blob: c3509e2b489a76b6540b0af98eb1f5cc432a33dd [file]
// SPDX-License-Identifier: GPL-2.0
/*
* mt8532-afe-utils.c -- Mediatek 8532 audio utility
*
* Copyright (c) 2022 MediaTek Inc.
* Author: Wen Cai <wen.cai@mediatek.com>
*/
#include "mt8532-afe-utils.h"
#include "mt8532-afe-common.h"
#include "mt8532-reg.h"
#include "../common/mtk-base-afe.h"
#include <linux/device.h>
#ifdef COMMON_CLOCK_FRAMEWORK_API
static const char *aud_clks[MT8532_CLK_NUM] = {
//[MT8532_CLK_TOP_SYSPLL1_D8] = "syspll1_d8",
//[MT8532_CLK_TOP_AXI_SEL] = "axi_sel",
[MT8532_CLK_TOP_AUDIO_26MSEL] = "audio_26msel",
[MT8532_CLK_TOP_AUDIO_SEL] = "audio_sel",
[MT8532_CLK_TOP_AUD_INTBUSSEL] = "aud_intbussel",
[MT8532_CLK_INFRA_IPSYS] = "infra_ipsys",
[MT8532_CLK_TOP_A1SYSHP_SEL] = "a1syshp_sel",
[MT8532_CLK_TOP_INTDIR_SEL] = "intdir_sel",
[MT8532_CLK_TOP_A2SYSHP_SEL] = "a2syshp_sel",
[MT8532_CLK_TOP_A3SYSHP_SEL] = "a3syshp_sel",
[MT8532_CLK_TOP_A4SYSHP_SEL] = "a4syshp_sel",
[MT8532_CLK_TOP_APLL3_D4] = "apll3_d4",
[MT8532_CLK_TOP_APLL4_D4] = "apll4_d4",
[MT8532_CLK_TOP_APLL5_D4] = "apll5_d4",
[MT8532_CLK_TOP_HDMIRX_APLL_D6] = "hdmirx_apll_d6",
[MT8532_CLK_TOP_APLL_SEL] = "apll_sel",
[MT8532_CLK_TOP_APLL2_SEL] = "apll2_sel",
[MT8532_CLK_TOP_APLL3_SEL] = "apll3_sel",
[MT8532_CLK_TOP_APLL4_SEL] = "apll4_sel",
[MT8532_CLK_TOP_APLL5_SEL] = "apll5_sel",
[MT8532_CLK_TOP_APLL1_D8] = "apll1_d8",
[MT8532_CLK_TOP_APLL2_D8] = "apll2_d8",
[MT8532_CLK_TOP_APLL3_D8] = "apll3_d8",
[MT8532_CLK_TOP_APLL4_D8] = "apll4_d8",
[MT8532_CLK_TOP_APLL5_D8] = "apll5_d8",
[MT8532_CLK_TOP_ASML_SEL] = "asml_sel",
[MT8532_CLK_TOP_ASMM_SEL] = "asmm_sel",
[MT8532_CLK_TOP_ASMH_SEL] = "asmh_sel",
[MT8532_CLK_TOP_APLL12_DIV4] = "apll12_div4",
[MT8532_CLK_TOP_APLL12_DIV0] = "apll12_div0",
[MT8532_CLK_TOP_APLL12_DIV1] = "apll12_div1",
[MT8532_CLK_TOP_APLL12_DIV2] = "apll12_div2",
[MT8532_CLK_TOP_APLL12_DIV3] = "apll12_div3",
[MT8532_CLK_TOP_AUD_IEC] = "hf_faud_iec_ck",
[MT8532_CLK_TOP_I2SI1_M] = "hf_fi2si1_m_ck",
[MT8532_CLK_TOP_I2SI2_M] = "hf_fi2si2_m_ck",
[MT8532_CLK_TOP_I2SO1_M] = "hf_fi2so1_m_ck",
[MT8532_CLK_TOP_I2SO2_M] = "hf_fi2so2_m_ck",
[MT8532_CLK_TOP_I2SI1_SEL] = "i2si1_sel",
[MT8532_CLK_TOP_I2SI2_SEL] = "i2si2_sel",
[MT8532_CLK_TOP_I2SO1_SEL] = "i2so1_sel",
[MT8532_CLK_TOP_I2SO2_SEL] = "i2so2_sel",
[MT8532_CLK_APMIXED_APLL1] = "apll1",
[MT8532_CLK_APMIXED_APLL2] = "apll2",
[MT8532_CLK_APMIXED_APLL3] = "apll3",
[MT8532_CLK_APMIXED_APLL4] = "apll4",
[MT8532_CLK_APMIXED_APLL5] = "apll5",
};
#endif
int mt8532_afe_init_audio_clk(struct mtk_base_afe *afe)
{
#ifdef COMMON_CLOCK_FRAMEWORK_API
size_t i;
struct mt8532_afe_private *afe_priv = afe->platform_priv;
for (i = 0; i < ARRAY_SIZE(aud_clks); i++) {
afe_priv->clocks[i] = devm_clk_get(afe->dev, aud_clks[i]);
if (IS_ERR(afe_priv->clocks[i])) {
dev_dbg(afe->dev, "%s devm_clk_get %s fail\n",
__func__, aud_clks[i]);
return PTR_ERR(afe_priv->clocks[i]);
}
}
#endif
return 0;
}
int mt8532_afe_enable_clk(struct mtk_base_afe *afe, struct clk *clk)
{
#ifdef COMMON_CLOCK_FRAMEWORK_API
int ret;
if (clk) {
ret = clk_prepare_enable(clk);
if (ret) {
dev_dbg(afe->dev, "Failed to enable clk\n");
return ret;
}
} else {
dev_dbg(afe->dev, "null clk\n");
}
#endif
return 0;
}
void mt8532_afe_disable_clk(struct mtk_base_afe *afe, struct clk *clk)
{
#ifdef COMMON_CLOCK_FRAMEWORK_API
if (clk)
clk_disable_unprepare(clk);
else
dev_dbg(afe->dev, "null clk\n");
#endif
}
int mt8532_afe_set_clk_rate(struct mtk_base_afe *afe, struct clk *clk,
unsigned int rate)
{
#ifdef COMMON_CLOCK_FRAMEWORK_API
int ret;
if (clk) {
ret = clk_set_rate(clk, rate);
if (ret) {
dev_dbg(afe->dev, "Failed to set rate\n");
return ret;
}
}
#endif
return 0;
}
int mt8532_afe_set_clk_parent(struct mtk_base_afe *afe, struct clk *clk,
struct clk *parent)
{
#ifdef COMMON_CLOCK_FRAMEWORK_API
int ret;
if (clk && parent) {
ret = clk_set_parent(clk, parent);
if (ret) {
dev_dbg(afe->dev, "Failed to set parent\n");
return ret;
}
}
#endif
return 0;
}
static unsigned int get_top_cg_reg(unsigned int cg_type)
{
switch (cg_type) {
case MT8532_TOP_CG_AFE:
case MT8532_TOP_CG_SPDIFIN_TUNER_APLL:
case MT8532_TOP_CG_SPDIFIN_TUNER_DBG:
case MT8532_TOP_CG_APLL_TUNER:
case MT8532_TOP_CG_APLL2_TUNER:
case MT8532_TOP_CG_SPDIF_OUT:
case MT8532_TOP_CG_APLL:
case MT8532_TOP_CG_APLL2:
case MT8532_TOP_CG_TML:
return AUDIO_TOP_CON0;
case MT8532_TOP_CG_26M_DMIC_TM:
case MT8532_TOP_CG_26M_DMIC4:
case MT8532_TOP_CG_26M_DMIC3:
case MT8532_TOP_CG_26M_DMIC2:
case MT8532_TOP_CG_26M_DMIC1:
case MT8532_TOP_CG_A1SYS_HP:
return AUDIO_TOP_CON1;
case MT8532_TOP_CG_LINEIN_TUNER:
case MT8532_TOP_CG_EARC_TUNER:
return AUDIO_TOP_CON3;
case MT8532_TOP_CG_I2S_IN:
case MT8532_TOP_CG_TDM_IN:
case MT8532_TOP_CG_I2S_OUT:
case MT8532_TOP_CG_TDM_OUT:
case MT8532_TOP_CG_HDMI_OUT:
case MT8532_TOP_CG_ASRC11:
case MT8532_TOP_CG_ASRC12:
case MT8532_TOP_CG_MULTI_IN:
case MT8532_TOP_CG_INTDIR:
case MT8532_TOP_CG_A1SYS:
case MT8532_TOP_CG_A2SYS:
case MT8532_TOP_CG_AFE_CONN:
case MT8532_TOP_CG_PCMIF:
case MT8532_TOP_CG_A3SYS:
case MT8532_TOP_CG_A4SYS:
return AUDIO_TOP_CON4;
case MT8532_TOP_CG_GASRC0:
case MT8532_TOP_CG_GASRC1:
case MT8532_TOP_CG_GASRC2:
case MT8532_TOP_CG_GASRC3:
case MT8532_TOP_CG_GASRC4:
case MT8532_TOP_CG_GASRC5:
case MT8532_TOP_CG_GASRC6:
case MT8532_TOP_CG_GASRC7:
case MT8532_TOP_CG_GASRC8:
case MT8532_TOP_CG_GASRC9:
case MT8532_TOP_CG_GASRC10:
case MT8532_TOP_CG_GASRC11:
case MT8532_TOP_CG_GASRC12:
case MT8532_TOP_CG_GASRC13:
case MT8532_TOP_CG_GASRC14:
case MT8532_TOP_CG_GASRC15:
case MT8532_TOP_CG_GASRC16:
case MT8532_TOP_CG_GASRC17:
case MT8532_TOP_CG_GASRC18:
case MT8532_TOP_CG_GASRC19:
return AUDIO_TOP_CON6;
case MT8532_TOP_CG_DMIC0:
case MT8532_TOP_CG_DMIC1:
case MT8532_TOP_CG_DMIC2:
case MT8532_TOP_CG_DMIC3:
return PWR2_TOP_CON0;
case MT8532_TOP_CG_A1SYS_TIMING:
case MT8532_TOP_CG_A2SYS_TIMING:
case MT8532_TOP_CG_A3SYS_TIMING:
case MT8532_TOP_CG_A4SYS_TIMING:
case MT8532_TOP_CG_LP_MOD:
case MT8532_TOP_CG_LP_26M_ENGEN:
return ASYS_TOP_CON;
default:
return 0;
}
}
static unsigned int get_top_cg_mask(unsigned int cg_type)
{
switch (cg_type) {
case MT8532_TOP_CG_AFE:
return AUD_TCON0_PDN_AFE;
case MT8532_TOP_CG_SPDIFIN_TUNER_APLL:
return AUD_TCON0_PDN_SPDIFIN_TUNER_APLL;
case MT8532_TOP_CG_SPDIFIN_TUNER_DBG:
return AUD_TCON0_PDN_SPDIFIN_TUNER_DBG;
case MT8532_TOP_CG_SPDIF_OUT:
return AUD_TCON0_PDN_SPDIF_OUT;
case MT8532_TOP_CG_APLL_TUNER:
return AUD_TCON0_PDN_APLL_TUNER;
case MT8532_TOP_CG_APLL2_TUNER:
return AUD_TCON0_PDN_APLL2_TUNER;
case MT8532_TOP_CG_APLL:
return AUD_TCON0_PDN_APLL;
case MT8532_TOP_CG_APLL2:
return AUD_TCON0_PDN_APLL2;
case MT8532_TOP_CG_TML:
return AUD_TCON0_PDN_TML;
case MT8532_TOP_CG_26M_DMIC_TM:
return AUD_TCON1_PDN_26M_DMIC_TM;
case MT8532_TOP_CG_26M_DMIC4:
return AUD_TCON1_PDN_DMIC4_26M_UL_HOP_BCLK;
case MT8532_TOP_CG_26M_DMIC3:
return AUD_TCON1_PDN_DMIC3_26M_UL_HOP_BCLK;
case MT8532_TOP_CG_26M_DMIC2:
return AUD_TCON1_PDN_DMIC2_26M_UL_HOP_BCLK;
case MT8532_TOP_CG_26M_DMIC1:
return AUD_TCON1_PDN_DMIC1_26M_UL_HOP_BCLK;
case MT8532_TOP_CG_A1SYS_HP:
return AUD_TCON1_PDN_A1SYS_HP;
case MT8532_TOP_CG_LINEIN_TUNER:
return AUD_TCON3_PDN_LINEIN_TUNER;
case MT8532_TOP_CG_EARC_TUNER:
return AUD_TCON3_PDN_EARC_TUNER;
case MT8532_TOP_CG_I2S_IN:
return AUD_TCON4_PDN_I2S_IN;
case MT8532_TOP_CG_TDM_IN:
return AUD_TCON4_PDN_TDM_IN;
case MT8532_TOP_CG_I2S_OUT:
return AUD_TCON4_PDN_I2S_OUT;
case MT8532_TOP_CG_TDM_OUT:
return AUD_TCON4_PDN_TDM_OUT;
case MT8532_TOP_CG_HDMI_OUT:
return AUD_TCON4_PDN_HDMI_OUT;
case MT8532_TOP_CG_ASRC11:
return AUD_TCON4_PDN_ASRC11;
case MT8532_TOP_CG_ASRC12:
return AUD_TCON4_PDN_ASRC12;
case MT8532_TOP_CG_MULTI_IN:
return AUD_TCON4_PDN_MULTI_IN;
case MT8532_TOP_CG_INTDIR:
return AUD_TCON4_PDN_INTDIR;
case MT8532_TOP_CG_A1SYS:
return AUD_TCON4_PDN_A1SYS;
case MT8532_TOP_CG_A2SYS:
return AUD_TCON4_PDN_A2SYS;
case MT8532_TOP_CG_AFE_CONN:
return AUD_TCON4_PDN_AFE_CONN;
case MT8532_TOP_CG_PCMIF:
return AUD_TCON4_PDN_PCMIF;
case MT8532_TOP_CG_A3SYS:
return AUD_TCON4_PDN_A3SYS;
case MT8532_TOP_CG_A4SYS:
return AUD_TCON4_PDN_A4SYS;
case MT8532_TOP_CG_GASRC0:
return AUD_TCON6_PDN_GASRC0;
case MT8532_TOP_CG_GASRC1:
return AUD_TCON6_PDN_GASRC1;
case MT8532_TOP_CG_GASRC2:
return AUD_TCON6_PDN_GASRC2;
case MT8532_TOP_CG_GASRC3:
return AUD_TCON6_PDN_GASRC3;
case MT8532_TOP_CG_GASRC4:
return AUD_TCON6_PDN_GASRC4;
case MT8532_TOP_CG_GASRC5:
return AUD_TCON6_PDN_GASRC5;
case MT8532_TOP_CG_GASRC6:
return AUD_TCON6_PDN_GASRC6;
case MT8532_TOP_CG_GASRC7:
return AUD_TCON6_PDN_GASRC7;
case MT8532_TOP_CG_GASRC8:
return AUD_TCON6_PDN_GASRC8;
case MT8532_TOP_CG_GASRC9:
return AUD_TCON6_PDN_GASRC9;
case MT8532_TOP_CG_GASRC10:
return AUD_TCON6_PDN_GASRC10;
case MT8532_TOP_CG_GASRC11:
return AUD_TCON6_PDN_GASRC11;
case MT8532_TOP_CG_GASRC12:
return AUD_TCON6_PDN_GASRC12;
case MT8532_TOP_CG_GASRC13:
return AUD_TCON6_PDN_GASRC13;
case MT8532_TOP_CG_GASRC14:
return AUD_TCON6_PDN_GASRC14;
case MT8532_TOP_CG_GASRC15:
return AUD_TCON6_PDN_GASRC15;
case MT8532_TOP_CG_GASRC16:
return AUD_TCON6_PDN_GASRC16;
case MT8532_TOP_CG_GASRC17:
return AUD_TCON6_PDN_GASRC17;
case MT8532_TOP_CG_GASRC18:
return AUD_TCON6_PDN_GASRC18;
case MT8532_TOP_CG_GASRC19:
return AUD_TCON6_PDN_GASRC19;
case MT8532_TOP_CG_DMIC0:
return PWR2_TOP_CON_PDN_DMIC0;
case MT8532_TOP_CG_DMIC1:
return PWR2_TOP_CON_PDN_DMIC1;
case MT8532_TOP_CG_DMIC2:
return PWR2_TOP_CON_PDN_DMIC2;
case MT8532_TOP_CG_DMIC3:
return PWR2_TOP_CON_PDN_DMIC3;
case MT8532_TOP_CG_A1SYS_TIMING:
return ASYS_TCON_A1SYS_TIMING_ON;
case MT8532_TOP_CG_A2SYS_TIMING:
return ASYS_TCON_A2SYS_TIMING_ON;
case MT8532_TOP_CG_A3SYS_TIMING:
return ASYS_TCON_A3SYS_TIMING_ON;
case MT8532_TOP_CG_A4SYS_TIMING:
return ASYS_TCON_A4SYS_TIMING_ON;
case MT8532_TOP_CG_LP_MOD:
return ASYS_TCON_LP_MOD_ON;
case MT8532_TOP_CG_LP_26M_ENGEN:
return ASYS_TCON_LP_26M_ENGEN_ON;
default:
return 0;
}
}
static unsigned int get_top_cg_on_val(unsigned int cg_type)
{
switch (cg_type) {
case MT8532_TOP_CG_A1SYS_TIMING:
case MT8532_TOP_CG_A2SYS_TIMING:
case MT8532_TOP_CG_A3SYS_TIMING:
case MT8532_TOP_CG_A4SYS_TIMING:
case MT8532_TOP_CG_LP_MOD:
case MT8532_TOP_CG_LP_26M_ENGEN:
return get_top_cg_mask(cg_type);
default:
return 0;
}
}
static unsigned int get_top_cg_off_val(unsigned int cg_type)
{
switch (cg_type) {
case MT8532_TOP_CG_A1SYS_TIMING:
case MT8532_TOP_CG_A2SYS_TIMING:
case MT8532_TOP_CG_A3SYS_TIMING:
case MT8532_TOP_CG_A4SYS_TIMING:
case MT8532_TOP_CG_LP_MOD:
case MT8532_TOP_CG_LP_26M_ENGEN:
return 0;
default:
return get_top_cg_mask(cg_type);
}
}
int mt8532_afe_enable_top_cg(struct mtk_base_afe *afe, unsigned int cg_type)
{
struct mt8532_afe_private *afe_priv = afe->platform_priv;
unsigned int reg = get_top_cg_reg(cg_type);
unsigned int mask = get_top_cg_mask(cg_type);
unsigned int val = get_top_cg_on_val(cg_type);
unsigned long flags;
bool need_update = false;
spin_lock_irqsave(&afe_priv->afe_ctrl_lock, flags);
afe_priv->top_cg_ref_cnt[cg_type]++;
if (afe_priv->top_cg_ref_cnt[cg_type] == 1)
need_update = true;
spin_unlock_irqrestore(&afe_priv->afe_ctrl_lock, flags);
if (need_update)
regmap_update_bits(afe->regmap, reg, mask, val);
return 0;
}
int mt8532_afe_disable_top_cg(struct mtk_base_afe *afe, unsigned int cg_type)
{
struct mt8532_afe_private *afe_priv = afe->platform_priv;
unsigned int reg = get_top_cg_reg(cg_type);
unsigned int mask = get_top_cg_mask(cg_type);
unsigned int val = get_top_cg_off_val(cg_type);
unsigned long flags;
bool need_update = false;
spin_lock_irqsave(&afe_priv->afe_ctrl_lock, flags);
afe_priv->top_cg_ref_cnt[cg_type]--;
if (afe_priv->top_cg_ref_cnt[cg_type] == 0)
need_update = true;
else if (afe_priv->top_cg_ref_cnt[cg_type] < 0)
afe_priv->top_cg_ref_cnt[cg_type] = 0;
spin_unlock_irqrestore(&afe_priv->afe_ctrl_lock, flags);
if (need_update)
regmap_update_bits(afe->regmap, reg, mask, val);
return 0;
}
int mt8532_afe_enable_main_clk(struct mtk_base_afe *afe)
{
struct mt8532_afe_private *afe_priv = afe->platform_priv;
//mt8532_afe_enable_clk(afe,
// afe_priv->clocks[MT8532_CLK_TOP_SYSPLL1_D8]);
//mt8532_afe_enable_clk(afe,
// afe_priv->clocks[MT8532_CLK_TOP_AXI_SEL]);
mt8532_afe_enable_clk(afe,
afe_priv->clocks[MT8532_CLK_INFRA_IPSYS]);
mt8532_afe_enable_clk(afe,
afe_priv->clocks[MT8532_CLK_TOP_AUD_INTBUSSEL]);
mt8532_afe_enable_clk(afe,
afe_priv->clocks[MT8532_CLK_TOP_AUDIO_26MSEL]);
mt8532_afe_enable_clk(afe,
afe_priv->clocks[MT8532_CLK_TOP_AUDIO_SEL]);
mt8532_afe_enable_clk(afe,
afe_priv->clocks[MT8532_CLK_TOP_A1SYSHP_SEL]);
mt8532_afe_enable_clk(afe,
afe_priv->clocks[MT8532_CLK_TOP_A2SYSHP_SEL]);
mt8532_afe_enable_clk(afe,
afe_priv->clocks[MT8532_CLK_TOP_A3SYSHP_SEL]);
mt8532_afe_enable_clk(afe,
afe_priv->clocks[MT8532_CLK_TOP_A4SYSHP_SEL]);
mt8532_afe_enable_top_cg(afe, MT8532_TOP_CG_A1SYS_HP);
mt8532_afe_enable_top_cg(afe, MT8532_TOP_CG_A1SYS);
mt8532_afe_enable_top_cg(afe, MT8532_TOP_CG_A2SYS);
mt8532_afe_enable_top_cg(afe, MT8532_TOP_CG_A3SYS);
mt8532_afe_enable_top_cg(afe, MT8532_TOP_CG_A4SYS);
mt8532_afe_enable_top_cg(afe, MT8532_TOP_CG_AFE);
mt8532_afe_enable_top_cg(afe, MT8532_TOP_CG_AFE_CONN);
mt8532_afe_enable_top_cg(afe, MT8532_TOP_CG_A1SYS_TIMING);
mt8532_afe_enable_top_cg(afe, MT8532_TOP_CG_A2SYS_TIMING);
mt8532_afe_enable_top_cg(afe, MT8532_TOP_CG_LP_26M_ENGEN);
mt8532_afe_enable_top_cg(afe, MT8532_TOP_CG_A3SYS_TIMING);
mt8532_afe_enable_top_cg(afe, MT8532_TOP_CG_A4SYS_TIMING);
mt8532_afe_enable_afe_on(afe);
return 0;
}
int mt8532_afe_disable_main_clk(struct mtk_base_afe *afe)
{
struct mt8532_afe_private *afe_priv = afe->platform_priv;
mt8532_afe_disable_afe_on(afe);
mt8532_afe_disable_top_cg(afe, MT8532_TOP_CG_A4SYS_TIMING);
mt8532_afe_disable_top_cg(afe, MT8532_TOP_CG_A3SYS_TIMING);
mt8532_afe_disable_top_cg(afe, MT8532_TOP_CG_LP_26M_ENGEN);
mt8532_afe_disable_top_cg(afe, MT8532_TOP_CG_A2SYS_TIMING);
mt8532_afe_disable_top_cg(afe, MT8532_TOP_CG_A1SYS_TIMING);
mt8532_afe_disable_top_cg(afe, MT8532_TOP_CG_AFE_CONN);
mt8532_afe_disable_top_cg(afe, MT8532_TOP_CG_AFE);
mt8532_afe_disable_top_cg(afe, MT8532_TOP_CG_A4SYS);
mt8532_afe_disable_top_cg(afe, MT8532_TOP_CG_A3SYS);
mt8532_afe_disable_top_cg(afe, MT8532_TOP_CG_A2SYS);
mt8532_afe_disable_top_cg(afe, MT8532_TOP_CG_A1SYS);
mt8532_afe_disable_top_cg(afe, MT8532_TOP_CG_A1SYS_HP);
mt8532_afe_disable_clk(afe,
afe_priv->clocks[MT8532_CLK_TOP_A4SYSHP_SEL]);
mt8532_afe_disable_clk(afe,
afe_priv->clocks[MT8532_CLK_TOP_A3SYSHP_SEL]);
mt8532_afe_disable_clk(afe,
afe_priv->clocks[MT8532_CLK_TOP_A2SYSHP_SEL]);
mt8532_afe_disable_clk(afe,
afe_priv->clocks[MT8532_CLK_TOP_A1SYSHP_SEL]);
mt8532_afe_disable_clk(afe,
afe_priv->clocks[MT8532_CLK_TOP_AUDIO_SEL]);
mt8532_afe_disable_clk(afe,
afe_priv->clocks[MT8532_CLK_TOP_AUDIO_26MSEL]);
mt8532_afe_disable_clk(afe,
afe_priv->clocks[MT8532_CLK_TOP_AUD_INTBUSSEL]);
mt8532_afe_disable_clk(afe,
afe_priv->clocks[MT8532_CLK_INFRA_IPSYS]);
//mt8532_afe_disable_clk(afe,
// afe_priv->clocks[MT8532_CLK_TOP_AUD_INTBUSSEL]);
//mt8532_afe_disable_clk(afe,
// afe_priv->clocks[MT8532_CLK_TOP_SYSPLL1_D8]);
return 0;
}
int mt8532_afe_enable_reg_rw_clk(struct mtk_base_afe *afe)
{
struct mt8532_afe_private *afe_priv = afe->platform_priv;
mt8532_afe_enable_clk(afe,
afe_priv->clocks[MT8532_CLK_INFRA_IPSYS]);
mt8532_afe_enable_clk(afe,
afe_priv->clocks[MT8532_CLK_TOP_AUD_INTBUSSEL]);
mt8532_afe_enable_clk(afe,
afe_priv->clocks[MT8532_CLK_TOP_AUDIO_26MSEL]);
mt8532_afe_enable_clk(afe,
afe_priv->clocks[MT8532_CLK_TOP_AUDIO_SEL]);
mt8532_afe_enable_clk(afe,
afe_priv->clocks[MT8532_CLK_TOP_A1SYSHP_SEL]);
mt8532_afe_enable_top_cg(afe, MT8532_TOP_CG_A1SYS_HP);
mt8532_afe_enable_top_cg(afe, MT8532_TOP_CG_A1SYS);
mt8532_afe_enable_top_cg(afe, MT8532_TOP_CG_AFE);
//mt8532_afe_enable_top_cg(afe, MT8532_TOP_CG_AFE_CONN);
return 0;
}
EXPORT_SYMBOL(mt8532_afe_enable_reg_rw_clk);
int mt8532_afe_disable_reg_rw_clk(struct mtk_base_afe *afe)
{
struct mt8532_afe_private *afe_priv = afe->platform_priv;
//mt8532_afe_disable_top_cg(afe, MT8532_TOP_CG_AFE_CONN);
mt8532_afe_disable_top_cg(afe, MT8532_TOP_CG_AFE);
mt8532_afe_disable_top_cg(afe, MT8532_TOP_CG_A1SYS);
mt8532_afe_disable_top_cg(afe, MT8532_TOP_CG_A1SYS_HP);
mt8532_afe_disable_clk(afe,
afe_priv->clocks[MT8532_CLK_TOP_A1SYSHP_SEL]);
mt8532_afe_disable_clk(afe,
afe_priv->clocks[MT8532_CLK_TOP_AUDIO_SEL]);
mt8532_afe_disable_clk(afe,
afe_priv->clocks[MT8532_CLK_TOP_AUDIO_26MSEL]);
mt8532_afe_disable_clk(afe,
afe_priv->clocks[MT8532_CLK_TOP_AUD_INTBUSSEL]);
mt8532_afe_disable_clk(afe,
afe_priv->clocks[MT8532_CLK_INFRA_IPSYS]);
return 0;
}
EXPORT_SYMBOL(mt8532_afe_disable_reg_rw_clk);
int mt8532_afe_enable_afe_on(struct mtk_base_afe *afe)
{
struct mt8532_afe_private *afe_priv = afe->platform_priv;
unsigned long flags;
bool need_update = false;
spin_lock_irqsave(&afe_priv->afe_ctrl_lock, flags);
afe_priv->afe_on_ref_cnt++;
if (afe_priv->afe_on_ref_cnt == 1)
need_update = true;
spin_unlock_irqrestore(&afe_priv->afe_ctrl_lock, flags);
if (need_update)
regmap_update_bits(afe->regmap, AFE_DAC_CON0, 0x1, 0x1);
return 0;
}
int mt8532_afe_disable_afe_on(struct mtk_base_afe *afe)
{
struct mt8532_afe_private *afe_priv = afe->platform_priv;
unsigned long flags;
bool need_update = false;
spin_lock_irqsave(&afe_priv->afe_ctrl_lock, flags);
afe_priv->afe_on_ref_cnt--;
if (afe_priv->afe_on_ref_cnt == 0)
need_update = true;
else if (afe_priv->afe_on_ref_cnt < 0)
afe_priv->afe_on_ref_cnt = 0;
spin_unlock_irqrestore(&afe_priv->afe_ctrl_lock, flags);
if (need_update)
regmap_update_bits(afe->regmap, AFE_DAC_CON0, 0x1, 0x0);
return 0;
}
static const struct mtk_base_irq_data *mt8532_get_irq_data(
struct mtk_base_afe *afe, unsigned int irq_id)
{
int i;
for (i = 0; i < afe->irqs_size; i++) {
if (irq_id == afe->irqs->irq_data[i].id)
return &afe->irqs->irq_data[i];
}
return NULL;
}
int mt8532_afe_enable_irq(struct mtk_base_afe *afe, unsigned int irq_id)
{
const struct mtk_base_irq_data *data;
data = mt8532_get_irq_data(afe, irq_id);
if (!data)
return -EINVAL;
regmap_update_bits(afe->regmap,
data->irq_en_reg,
1 << data->irq_en_shift,
1 << data->irq_en_shift);
return 0;
}
int mt8532_afe_disable_irq(struct mtk_base_afe *afe, unsigned int irq_id)
{
const struct mtk_base_irq_data *data;
data = mt8532_get_irq_data(afe, irq_id);
if (!data)
return -EINVAL;
regmap_update_bits(afe->regmap,
data->irq_en_reg,
1 << data->irq_en_shift,
0 << data->irq_en_shift);
return 0;
}
static int mt8532_afe_enable_spdif_in(struct mtk_base_afe *afe)
{
struct mt8532_afe_private *afe_priv = afe->platform_priv;
unsigned int port_sel;
unsigned int mux_sel;
unsigned int port = afe_priv->spdif_in_data.port;
switch (port) {
case SPDIF_IN_PORT_OPT:
case SPDIF_IN_PORT_COAXIAL:
case SPDIF_IN_PORT_ARC:
mux_sel = afe_priv->spdif_in_data.ports_mux[port];
break;
case SPDIF_IN_PORT_NONE:
default:
dev_notice(afe->dev, "%s unexpected port %u\n",
__func__, port);
return -EINVAL;
}
switch (mux_sel) {
case SPDIF_IN_MUX_0:
port_sel = AFE_SPDIFIN_INT_EXT_SEL_OPTICAL;
break;
case SPDIF_IN_MUX_1:
port_sel = AFE_SPDIFIN_INT_EXT_SEL_COAXIAL;
break;
case SPDIF_IN_MUX_2:
port_sel = AFE_SPDIFIN_INT_EXT_SEL_ARC;
break;
default:
dev_notice(afe->dev, "%s unexpected mux_sel %u\n",
__func__, mux_sel);
return -EINVAL;
}
mt8532_afe_enable_main_clk(afe);
mt8532_afe_enable_clk(afe, afe_priv->clocks[MT8532_CLK_TOP_INTDIR_SEL]);
mt8532_afe_enable_top_cg(afe, MT8532_TOP_CG_INTDIR);
regmap_write(afe->regmap, SPDIFIN_FREQ_INFO, 0x00877986);
regmap_write(afe->regmap, SPDIFIN_FREQ_INFO_2, 0x006596e8);
regmap_write(afe->regmap, SPDIFIN_FREQ_INFO_3, 0x000005a5);
regmap_write(afe->regmap, AFE_SPDIFIN_BR, 0x00039000);
regmap_update_bits(afe->regmap,
AFE_SPDIFIN_INT_EXT2,
SPDIFIN_594MODE_MASK,
SPDIFIN_594MODE_EN);
regmap_update_bits(afe->regmap,
AFE_SPDIFIN_CFG1,
AFE_SPDIFIN_CFG1_SET_MASK,
AFE_SPDIFIN_CFG1_INT_BITS |
AFE_SPDIFIN_CFG1_SEL_BCK_SPDIFIN |
AFE_SPDIFIN_CFG1_FIFOSTART_5POINTS |
AFE_SPDIFIN_CFG1_SEL_DEC0_CLK_EN |
AFE_SPDIFIN_CFG1_SEL_DEC0_DATA_EN);
regmap_update_bits(afe->regmap,
AFE_SPDIFIN_INT_EXT,
AFE_SPDIFIN_INT_EXT_SET_MASK,
AFE_SPDIFIN_INT_EXT_DATALAT_ERR_EN |
AFE_SPDIFIN_INT_EXT_DERR_NEW_RETEN |
port_sel);
regmap_update_bits(afe->regmap,
AFE_SPDIFIN_CFG0,
AFE_SPDIFIN_CFG0_SET_MASK,
AFE_SPDIFIN_CFG0_FLIP |
AFE_SPDIFIN_CFG0_GMAT_BC_256_CYCLES |
AFE_SPDIFIN_CFG0_DPERR2IDLE_EN |
AFE_SPDIFIN_CFG0_DERR2IDLE_EN |
AFE_SPDIFIN_CFG0_INT_EN |
AFE_SPDIFIN_CFG0_TIMEOUT2IDLE_EN |
AFE_SPDIFIN_CFG0_DE_CNT(4) |
AFE_SPDIFIN_CFG0_DE_SEL_CNT |
AFE_SPDIFIN_CFG0_MAX_LEN_NUM(237));
mt8532_afe_enable_irq(afe, MT8532_AFE_IRQ2);
regmap_update_bits(afe->regmap,
AFE_SPDIFIN_CFG0,
AFE_SPDIFIN_CFG0_EN,
AFE_SPDIFIN_CFG0_EN);
return 0;
}
static int mt8532_afe_disable_spdif_in(struct mtk_base_afe *afe)
{
struct mt8532_afe_private *afe_priv = afe->platform_priv;
unsigned long flags;
dev_dbg(afe->dev, "%s\n", __func__);
spin_lock_irqsave(&afe_priv->spdifin_ctrl_lock, flags);
regmap_update_bits(afe->regmap,
AFE_SPDIFIN_CFG0,
AFE_SPDIFIN_CFG0_EN,
0x0);
mt8532_afe_disable_irq(afe, MT8532_AFE_IRQ2);
mt8532_afe_disable_top_cg(afe, MT8532_TOP_CG_INTDIR);
spin_unlock_irqrestore(&afe_priv->spdifin_ctrl_lock, flags);
mt8532_afe_disable_clk(afe,
afe_priv->clocks[MT8532_CLK_TOP_INTDIR_SEL]);
mt8532_afe_disable_main_clk(afe);
return 0;
}
int mt8532_afe_handle_spdif_in_port_change(struct mtk_base_afe *afe,
unsigned int port)
{
struct mt8532_afe_private *afe_priv = afe->platform_priv;
struct mt8532_spdif_in_data *spdif_in = &afe_priv->spdif_in_data;
int ret = 0;
if (port != SPDIF_IN_PORT_NONE &&
port != SPDIF_IN_PORT_OPT &&
port != SPDIF_IN_PORT_COAXIAL &&
port != SPDIF_IN_PORT_ARC)
return -EINVAL;
dev_info(afe->dev, "%s, spdif_in->port:%d, port:%d\n",
__func__, spdif_in->port, port);
if (spdif_in->port != port) {
if (spdif_in->port != SPDIF_IN_PORT_NONE)
ret = mt8532_afe_disable_spdif_in(afe);
if (port == SPDIF_IN_PORT_NONE) {
/* sample rate */
spdif_in->subdata.rate = 0;
/* usercode */
memset((void *)spdif_in->subdata.user_code,
0xff, sizeof(spdif_in->subdata.user_code));
/* channel status */
memset((void *)spdif_in->subdata.ch_status,
0xff, sizeof(spdif_in->subdata.ch_status));
/* stream type */
spdif_in->subdata.stream_type = 0xff;
}
spdif_in->port = port;
if (spdif_in->port != SPDIF_IN_PORT_NONE)
ret = mt8532_afe_enable_spdif_in(afe);
}
return ret;
}
int mt8532_afe_block_dpidle(struct mtk_base_afe *afe)
{
struct mt8532_afe_private *afe_priv = afe->platform_priv;
mutex_lock(&afe_priv->block_dpidle_mutex);
if (afe_priv->block_dpidle_ref_cnt == 0) {
//regmap_update_bits(afe_priv->scpsys,
// BLOCK_DPIDLE_REG,
// BLOCK_DPIDLE_REG_MASK,
// BLOCK_DPIDLE_REG_BIT_ON);
}
afe_priv->block_dpidle_ref_cnt++;
mutex_unlock(&afe_priv->block_dpidle_mutex);
return 0;
}
int mt8532_afe_unblock_dpidle(struct mtk_base_afe *afe)
{
struct mt8532_afe_private *afe_priv = afe->platform_priv;
mutex_lock(&afe_priv->block_dpidle_mutex);
afe_priv->block_dpidle_ref_cnt--;
if (afe_priv->block_dpidle_ref_cnt == 0) {
//regmap_update_bits(afe_priv->scpsys,
// BLOCK_DPIDLE_REG,
// BLOCK_DPIDLE_REG_MASK,
// BLOCK_DPIDLE_REG_BIT_OFF);
} else if (afe_priv->block_dpidle_ref_cnt < 0) {
afe_priv->block_dpidle_ref_cnt = 0;
}
mutex_unlock(&afe_priv->block_dpidle_mutex);
return 0;
}
int mt8532_afe_get_be_idx(int id)
{
int index;
if (id < MT8532_AFE_BACKEND_BASE || id >= MT8532_AFE_BACKEND_END)
return -EINVAL;
index = id - MT8532_AFE_BACKEND_BASE;
return index;
}
int mt8532_afe_set_be_active(struct mtk_base_afe *afe, int id)
{
struct mt8532_afe_private *afe_priv = afe->platform_priv;
int index;
index = mt8532_afe_get_be_idx(id);
if (index < 0)
return -EINVAL;
afe_priv->be_active_status |= BIT(index);
return 0;
}
int mt8532_afe_clear_be_active(struct mtk_base_afe *afe, int id)
{
struct mt8532_afe_private *afe_priv = afe->platform_priv;
int index;
index = mt8532_afe_get_be_idx(id);
if (index < 0)
return -EINVAL;
afe_priv->be_active_status &= ~BIT(index);
return 0;
}
bool mt8532_afe_is_be_active(struct mtk_base_afe *afe, int id)
{
struct mt8532_afe_private *afe_priv = afe->platform_priv;
int index;
index = mt8532_afe_get_be_idx(id);
if (index < 0)
return false;
if (afe_priv->be_active_status & BIT(index))
return true;
return false;
}