kernel_samsung_a34x-permissive/sound/soc/mediatek/mt6739/mtk-auddrv-clk.c
2024-04-28 15:51:13 +02:00

1479 lines
36 KiB
C

/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2019 MediaTek Inc.
*/
/*****************************************************************************
*
* Filename:
* ---------
* AudDrv_Clk.c
*
* Project:
* --------
* MT6739 Audio Driver clock control implement
*
* Description:
* ------------
* Audio register
*
* Author:
* -------
* Chipeng Chang (MTK02308)
*
*----------------------------------------------------------------------------
*
*
*****************************************************************************/
/*****************************************************************************
* C O M P I L E R F L A G S
*****************************************************************************/
/*****************************************************************************
* E X T E R N A L R E F E R E N C E S
*****************************************************************************/
#include <linux/clk.h>
#include "mtk-auddrv-afe.h"
#include "mtk-auddrv-clk.h"
#include "mtk-auddrv-common.h"
#include "mtk-soc-digital-type.h"
#include <linux/delay.h>
#include <linux/spinlock.h>
#if defined(_MT_IDLE_HEADER) && !defined(CONFIG_FPGA_EARLY_PORTING)
#include <mtk_idle.h>
#endif
#include <linux/err.h>
#include <linux/platform_device.h>
#define _MT_SPM_RESOURCE
#if defined(_MT_SPM_RESOURCE) && !defined(CONFIG_FPGA_EARLY_PORTING)
#include "mtk_spm_resource_req.h"
bool spm_resource_req(unsigned int user, unsigned int req_mask)
__attribute__((weak));
#endif
/*****************************************************************************
* D A T A T Y P E S
*****************************************************************************/
static int APLL1Counter;
static int APLL2Counter;
static int Aud_APLL_DIV_APLL1_cntr;
static int Aud_APLL_DIV_APLL2_cntr;
static unsigned int MCLKFS = 128;
static unsigned int MCLKFS_HDMI = 256;
int Aud_Core_Clk_cntr;
int Aud_AFE_Clk_cntr;
int Aud_I2S_Clk_cntr;
int Aud_TDM_Clk_cntr;
int Aud_ADC_Clk_cntr;
#ifdef _NON_COMMON_FEATURE_READY
int Aud_HDMI_Clk_cntr;
#endif
int Aud_APLL22M_Clk_cntr;
int Aud_APLL24M_Clk_cntr;
int Aud_APLL1_Tuner_cntr;
int Aud_APLL2_Tuner_cntr;
static int Aud_EMI_cntr;
static DEFINE_SPINLOCK(auddrv_Clk_lock);
/* amp mutex lock */
static DEFINE_MUTEX(auddrv_pmic_mutex);
static DEFINE_MUTEX(audEMI_Clk_mutex);
static DEFINE_MUTEX(auddrv_clk_mutex);
/* AUDIO_APLL_DIVIDER_GROUP may vary by chip!!! */
enum AUDIO_APLL_DIVIDER_GROUP {
AUDIO_APLL1_DIV0,
AUDIO_APLL2_DIV0,
AUDIO_APLL12_DIV0,
AUDIO_APLL12_DIV1,
AUDIO_APLL12_DIV2,
AUDIO_APLL12_DIV3,
AUDIO_APLL12_DIV4,
AUDIO_APLL12_DIVB,
AUDIO_APLL12_DIV5,
AUDIO_APLL_DIV_NUM
};
/* mI2SAPLLDivSelect may vary by chip!!! */
static const unsigned int mI2SAPLLDivSelect[Soc_Aud_I2S_CLKDIV_NUMBER] = {
AUDIO_APLL1_DIV0, AUDIO_APLL2_DIV0, AUDIO_APLL12_DIV0,
AUDIO_APLL12_DIV1, AUDIO_APLL12_DIV2, AUDIO_APLL12_DIV3,
AUDIO_APLL12_DIV4, AUDIO_APLL12_DIVB, AUDIO_APLL12_DIV5};
enum audio_system_clock_type {
CLOCK_AFE = 0,
CLOCK_DAC,
CLOCK_DAC_PREDIS,
CLOCK_ADC,
CLOCK_TML,
CLOCK_APLL22M,
CLOCK_APLL1_TUNER,
#ifdef MT6739_scp
CLOCK_SCP_SYS_AUD,
#endif
CLOCK_INFRA_SYS_AUDIO,
CLOCK_MTKAIF_26M_CLK,
CLOCK_MUX_AUDIO,
CLOCK_MUX_AUDIOINTBUS,
CLOCK_TOP_SYSPLL1_D4,
/* apll related mux */
CLOCK_TOP_MUX_AUD_1,
CLOCK_TOP_APLL1_CK,
CLOCK_TOP_MUX_AUD_ENG1,
CLOCK_TOP_APLL1_D8,
CLOCK_APMIXED_APLL1,
CLOCK_CLK26M,
CLOCK_NUM
};
struct audio_clock_attr {
const char *name;
bool clk_prepare;
bool clk_status;
struct clk *clock;
};
static struct audio_clock_attr aud_clks[CLOCK_NUM] = {
[CLOCK_AFE] = {"aud_afe_clk", false, false, NULL},
[CLOCK_DAC] = {"aud_dac_clk", false, false, NULL},
/* AudDrv_Clk_On only */
[CLOCK_DAC_PREDIS] = {"aud_dac_predis_clk", false, false, NULL},
/* AudDrv_Clk_On only */
[CLOCK_ADC] = {"aud_adc_clk", false, false, NULL},
/* AudDrv_ADC_Clk_On only */
[CLOCK_TML] = {"aud_tml_clk", false, false, NULL}, /* NOT USED */
[CLOCK_APLL22M] = {"aud_apll22m_clk", false, false, NULL},
[CLOCK_APLL1_TUNER] = {"aud_apll1_tuner_clk", false, false, NULL},
#ifdef MT6739_scp
[CLOCK_SCP_SYS_AUD] = {"scp_sys_audio", false, false, NULL},
#endif
[CLOCK_INFRA_SYS_AUDIO] = {"aud_infra_clk", false, false, NULL},
[CLOCK_MTKAIF_26M_CLK] = {"mtkaif_26m_clk", false, false, NULL},
[CLOCK_MUX_AUDIO] = {"top_mux_audio", false, false, NULL},
[CLOCK_MUX_AUDIOINTBUS] = {"top_mux_audio_int", false, false, NULL},
/* AudDrv_AUDINTBUS_Sel */
[CLOCK_TOP_SYSPLL1_D4] = {"top_sys_pll1_d4", false, false, NULL},
/* AudDrv_AUDINTBUS_Sel */
[CLOCK_TOP_MUX_AUD_1] = {"top_mux_aud_1", false, false, NULL},
[CLOCK_TOP_APLL1_CK] = {"top_apll1_ck", false, false, NULL},
[CLOCK_TOP_MUX_AUD_ENG1] = {"top_mux_aud_eng1", false, false, NULL},
[CLOCK_TOP_APLL1_D8] = {"top_apll1_d8", false, false, NULL},
[CLOCK_APMIXED_APLL1] = {"apmixed_apll1", false, false, NULL},
[CLOCK_CLK26M] = {"top_clk26m_clk", false, false, NULL}
};
static int apll1_mux_setting(bool enable);
static int apll2_mux_setting(bool enable);
#if !defined(CONFIG_FPGA_EARLY_PORTING)
static int aud_clk_enable(const struct audio_clock_attr *clk)
{
int ret;
if (clk->clk_prepare) {
ret = clk_enable(clk->clock);
if (ret) {
pr_debug("%s(), clk_enable %s fail, ret %d\n",
__func__,
clk->name, ret);
return -EPERM;
}
} else {
pr_debug("%s(), clk %s, not prepared\n", __func__, clk->name);
return -EINVAL;
}
return 0;
}
#endif
int AudDrv_Clk_probe(void *dev)
{
size_t i;
int ret = 0;
Aud_EMI_cntr = 0;
pr_debug("%s\n", __func__);
for (i = 0; i < ARRAY_SIZE(aud_clks); i++) {
aud_clks[i].clock = devm_clk_get(dev, aud_clks[i].name);
if (IS_ERR(aud_clks[i].clock)) {
ret = PTR_ERR(aud_clks[i].clock);
pr_debug("%s devm_clk_get %s fail %d\n", __func__,
aud_clks[i].name, ret);
} else {
aud_clks[i].clk_status = true;
}
}
if (ret)
return ret;
for (i = 0; i < ARRAY_SIZE(aud_clks); i++) {
#ifdef MT6739_scp
if (i == CLOCK_SCP_SYS_AUD) /* CLOCK_SCP_SYS_AUD is MTCMOS */
continue;
#endif
if (aud_clks[i].clk_status) {
ret = clk_prepare(aud_clks[i].clock);
if (ret) {
pr_debug("%s clk_prepare %s fail %d\n",
__func__,
aud_clks[i].name, ret);
} else {
aud_clks[i].clk_prepare = true;
}
}
}
return ret;
}
void AudDrv_Clk_Deinit(void *dev)
{
size_t i;
pr_debug("%s\n", __func__);
for (i = 0; i < ARRAY_SIZE(aud_clks); i++) {
#ifdef MT6739_scp
if (i == CLOCK_SCP_SYS_AUD) /* CLOCK_SCP_SYS_AUD is MTCMOS */
continue;
#endif
if (aud_clks[i].clock && !IS_ERR(aud_clks[i].clock) &&
aud_clks[i].clk_prepare) {
clk_unprepare(aud_clks[i].clock);
aud_clks[i].clk_prepare = false;
}
}
}
#if defined(_MT_IDLE_HEADER) && !defined(CONFIG_FPGA_EARLY_PORTING)
static int audio_idle_notify_call(struct notifier_block *nfb,
unsigned long id,
void *arg)
{
switch (id) {
case NOTIFY_DPIDLE_ENTER:
case NOTIFY_SOIDLE_ENTER:
/* intbus pll -> 26m */
if (aud_clk_enable(&aud_clks[CLOCK_MUX_AUDIOINTBUS]))
return NOTIFY_OK;
AudDrv_AUDINTBUS_Sel(0);
if (aud_clks[CLOCK_MUX_AUDIOINTBUS].clk_prepare)
clk_disable(aud_clks[CLOCK_MUX_AUDIOINTBUS].clock);
break;
case NOTIFY_DPIDLE_LEAVE:
case NOTIFY_SOIDLE_LEAVE:
/* Audio Clock: 26m -> pll */
if (aud_clk_enable(&aud_clks[CLOCK_MUX_AUDIOINTBUS]))
return NOTIFY_OK;
AudDrv_AUDINTBUS_Sel(1);
if (aud_clks[CLOCK_MUX_AUDIOINTBUS].clk_prepare)
clk_disable(aud_clks[CLOCK_MUX_AUDIOINTBUS].clock);
break;
case NOTIFY_SOIDLE3_ENTER:
case NOTIFY_SOIDLE3_LEAVE:
default:
break;
}
return NOTIFY_OK;
}
#endif
#if defined(_MT_IDLE_HEADER) && !defined(CONFIG_FPGA_EARLY_PORTING)
static struct notifier_block audio_idle_nfb = {
.notifier_call = audio_idle_notify_call,
};
#endif
void AudDrv_Clk_Global_Variable_Init(void)
{
APLL1Counter = 0;
APLL2Counter = 0;
Aud_APLL_DIV_APLL1_cntr = 0;
Aud_APLL_DIV_APLL2_cntr = 0;
MCLKFS = 128;
MCLKFS_HDMI = 256;
#if defined(_MT_IDLE_HEADER) && !defined(CONFIG_FPGA_EARLY_PORTING)
mtk_idle_notifier_register(&audio_idle_nfb);
#endif
}
void AudDrv_Bus_Init(void)
{
/* No need on 6759, system default set bit14 to 1 */
}
void AudDrv_AUDINTBUS_Sel(int parentidx)
{
#if !defined(CONFIG_FPGA_EARLY_PORTING)
int ret = 0;
if (!aud_clks[CLOCK_MUX_AUDIOINTBUS].clk_prepare ||
!aud_clks[CLOCK_TOP_SYSPLL1_D4].clk_prepare ||
!aud_clks[CLOCK_CLK26M].clk_prepare) {
pr_debug("%s(), clk_prepare = false\n", __func__);
goto EXIT;
}
/* pr_debug("+AudDrv_AUDINTBUS_Sel, parentidx = %d\n", parentidx); */
if (parentidx == 1) {
ret = clk_set_parent(aud_clks[CLOCK_MUX_AUDIOINTBUS].clock,
aud_clks[CLOCK_TOP_SYSPLL1_D4].clock);
if (ret) {
pr_debug("%s clk_set_parent %s-%s fail %d\n", __func__,
aud_clks[CLOCK_MUX_AUDIOINTBUS].name,
aud_clks[CLOCK_TOP_SYSPLL1_D4].name, ret);
goto EXIT;
}
} else if (parentidx == 0) {
ret = clk_set_parent(aud_clks[CLOCK_MUX_AUDIOINTBUS].clock,
aud_clks[CLOCK_CLK26M].clock);
if (ret) {
pr_debug("%s clk_set_parent %s-%s fail %d\n", __func__,
aud_clks[CLOCK_MUX_AUDIOINTBUS].name,
aud_clks[CLOCK_CLK26M].name, ret);
goto EXIT;
}
}
EXIT:
/* pr_debug("-%s()\n", __func__); */
return;
#endif /* #if !defined(CONFIG_FPGA_EARLY_PORTING) */
}
#if !defined(CONFIG_FPGA_EARLY_PORTING)
static int apll1_mux_setting(bool enable)
{
int ret = 0;
if (!aud_clks[CLOCK_TOP_MUX_AUD_1].clk_prepare ||
!aud_clks[CLOCK_TOP_APLL1_CK].clk_prepare ||
!aud_clks[CLOCK_TOP_MUX_AUD_ENG1].clk_prepare ||
!aud_clks[CLOCK_TOP_APLL1_D8].clk_prepare ||
!aud_clks[CLOCK_CLK26M].clk_prepare) {
pr_debug("%s(), clk_prepare = false\n", __func__);
return -EINVAL;
}
/* pr_debug("+%s(), enable %d\n", __func__, enable); */
if (enable) {
/* CLOCK_TOP_MUX_AUD_1 */
if (aud_clk_enable(&aud_clks[CLOCK_TOP_MUX_AUD_1]))
goto EXIT;
ret = clk_set_parent(aud_clks[CLOCK_TOP_MUX_AUD_1].clock,
aud_clks[CLOCK_TOP_APLL1_CK].clock);
if (ret) {
pr_debug("%s clk_set_parent %s-%s fail %d\n",
__func__, aud_clks[CLOCK_TOP_MUX_AUD_1].name,
aud_clks[CLOCK_TOP_APLL1_CK].name, ret);
goto EXIT;
}
/* CLOCK_TOP_MUX_AUD_ENG1 */
if (aud_clk_enable(&aud_clks[CLOCK_TOP_MUX_AUD_ENG1]))
goto EXIT;
ret = clk_set_parent(aud_clks[CLOCK_TOP_MUX_AUD_ENG1].clock,
aud_clks[CLOCK_TOP_APLL1_D8].clock);
if (ret) {
pr_debug("%s clk_set_parent %s-%s fail %d\n",
__func__,
aud_clks[CLOCK_TOP_MUX_AUD_ENG1].name,
aud_clks[CLOCK_TOP_APLL1_D8].name, ret);
goto EXIT;
}
} else {
/* CLOCK_TOP_MUX_AUD_ENG1 */
ret = clk_set_parent(aud_clks[CLOCK_TOP_MUX_AUD_ENG1].clock,
aud_clks[CLOCK_CLK26M].clock);
if (ret) {
pr_debug("%s clk_set_parent %s-%s fail %d\n",
__func__,
aud_clks[CLOCK_TOP_MUX_AUD_ENG1].name,
aud_clks[CLOCK_CLK26M].name, ret);
goto EXIT;
}
if (aud_clks[CLOCK_TOP_MUX_AUD_ENG1].clk_prepare)
clk_disable(aud_clks[CLOCK_TOP_MUX_AUD_ENG1].clock);
/* CLOCK_TOP_MUX_AUD_1 */
ret = clk_set_parent(aud_clks[CLOCK_TOP_MUX_AUD_1].clock,
aud_clks[CLOCK_CLK26M].clock);
if (ret) {
pr_debug("%s clk_set_parent %s-%s fail %d\n",
__func__, aud_clks[CLOCK_TOP_MUX_AUD_1].name,
aud_clks[CLOCK_CLK26M].name, ret);
goto EXIT;
}
if (aud_clks[CLOCK_TOP_MUX_AUD_1].clk_prepare)
clk_disable(aud_clks[CLOCK_TOP_MUX_AUD_1].clock);
}
EXIT:
return 0;
}
static int apll2_mux_setting(bool enable)
{
int ret = 0;
if (!aud_clks[CLOCK_TOP_MUX_AUD_1].clk_prepare ||
!aud_clks[CLOCK_TOP_APLL1_CK].clk_prepare ||
!aud_clks[CLOCK_TOP_MUX_AUD_ENG1].clk_prepare ||
!aud_clks[CLOCK_TOP_APLL1_D8].clk_prepare ||
!aud_clks[CLOCK_CLK26M].clk_prepare) {
pr_debug("%s(), clk_prepare = false\n", __func__);
return -EINVAL;
}
/* pr_debug("+%s(), enable %d\n", __func__, enable); */
if (enable) {
/* CLOCK_TOP_MUX_AUD_1 */
if (aud_clk_enable(&aud_clks[CLOCK_TOP_MUX_AUD_1]))
goto EXIT;
ret = clk_set_parent(aud_clks[CLOCK_TOP_MUX_AUD_1].clock,
aud_clks[CLOCK_TOP_APLL1_CK].clock);
if (ret) {
pr_debug("%s clk_set_parent %s-%s fail %d\n",
__func__, aud_clks[CLOCK_TOP_MUX_AUD_1].name,
aud_clks[CLOCK_TOP_APLL1_CK].name, ret);
goto EXIT;
}
/* CLOCK_TOP_MUX_AUD_ENG1 */
if (aud_clk_enable(&aud_clks[CLOCK_TOP_MUX_AUD_ENG1]))
goto EXIT;
ret = clk_set_parent(aud_clks[CLOCK_TOP_MUX_AUD_ENG1].clock,
aud_clks[CLOCK_TOP_APLL1_D8].clock);
if (ret) {
pr_debug("%s clk_set_parent %s-%s fail %d\n",
__func__,
aud_clks[CLOCK_TOP_MUX_AUD_ENG1].name,
aud_clks[CLOCK_TOP_APLL1_D8].name, ret);
goto EXIT;
}
} else {
/* CLOCK_TOP_MUX_AUD_ENG1 */
ret = clk_set_parent(aud_clks[CLOCK_TOP_MUX_AUD_ENG1].clock,
aud_clks[CLOCK_CLK26M].clock);
if (ret) {
pr_debug("%s clk_set_parent %s-%s fail %d\n",
__func__,
aud_clks[CLOCK_TOP_MUX_AUD_ENG1].name,
aud_clks[CLOCK_CLK26M].name, ret);
goto EXIT;
}
if (aud_clks[CLOCK_TOP_MUX_AUD_ENG1].clk_prepare)
clk_disable(aud_clks[CLOCK_TOP_MUX_AUD_ENG1].clock);
/* CLOCK_TOP_MUX_AUD_1 */
ret = clk_set_parent(aud_clks[CLOCK_TOP_MUX_AUD_1].clock,
aud_clks[CLOCK_CLK26M].clock);
if (ret) {
pr_debug("%s clk_set_parent %s-%s fail %d\n",
__func__, aud_clks[CLOCK_TOP_MUX_AUD_1].name,
aud_clks[CLOCK_CLK26M].name, ret);
goto EXIT;
}
if (aud_clks[CLOCK_TOP_MUX_AUD_1].clk_prepare)
clk_disable(aud_clks[CLOCK_TOP_MUX_AUD_1].clock);
}
EXIT:
return 0;
}
#endif
/*****************************************************************************
* FUNCTION
* AudDrv_Clk_On / AudDrv_Clk_Off
*
* DESCRIPTION
* Enable/Disable PLL(26M clock) \ AFE clock
*
****************************************************************************/
void AudDrv_Clk_On(void)
{
#if !defined(CONFIG_FPGA_EARLY_PORTING)
int ret = 0;
pr_debug("AudDrv_Clk_On, Aud_AFE_Clk_cntr:%d\n",
Aud_AFE_Clk_cntr);
mutex_lock(&auddrv_clk_mutex);
Aud_AFE_Clk_cntr++;
if (Aud_AFE_Clk_cntr == 1) {
#ifdef PM_MANAGER_API
#ifdef MT6739_scp
if (aud_clks[CLOCK_SCP_SYS_AUD].clk_status) {
ret = clk_prepare_enable(
aud_clks[CLOCK_SCP_SYS_AUD].clock);
if (ret) {
pr_debug("%s [CCF]Aud clk_prepare_enable %s fail\n",
__func__,
aud_clks[CLOCK_SCP_SYS_AUD].name);
goto EXIT;
}
}
#endif
if (aud_clk_enable(&aud_clks[CLOCK_INFRA_SYS_AUDIO]))
goto EXIT;
if (aud_clk_enable(&aud_clks[CLOCK_MUX_AUDIO]))
goto EXIT;
ret = clk_set_parent(aud_clks[CLOCK_MUX_AUDIO].clock,
aud_clks[CLOCK_CLK26M].clock);
if (ret) {
pr_debug("%s clk_set_parent %s-%s fail %d\n", __func__,
aud_clks[CLOCK_MUX_AUDIO].name,
aud_clks[CLOCK_CLK26M].name, ret);
}
/* AUD_INTBUS */
if (aud_clk_enable(&aud_clks[CLOCK_MUX_AUDIOINTBUS]))
goto EXIT;
AudDrv_AUDINTBUS_Sel(1);
if (aud_clk_enable(&aud_clks[CLOCK_AFE]))
goto EXIT;
if (aud_clk_enable(&aud_clks[CLOCK_DAC]))
goto EXIT;
if (aud_clk_enable(&aud_clks[CLOCK_DAC_PREDIS]))
goto EXIT;
if (aud_clk_enable(&aud_clks[CLOCK_MTKAIF_26M_CLK]))
goto EXIT;
/* enable audio sys DCM for power saving */
Afe_Set_Reg(AUDIO_TOP_CON0, 0x1 << 29, 0x1 << 29);
#else
SetInfraCfg(AUDIO_CG_CLR, 0x2000000, 0x2000000);
/* bit 25=0, without 133m master and 66m slave bus clock cg
* gating
*/
Afe_Set_Reg(AUDIO_TOP_CON0, 0x4000, 0x06004044);
#endif
}
EXIT:
mutex_unlock(&auddrv_clk_mutex);
#endif /* #if !defined(CONFIG_FPGA_EARLY_PORTING) */
}
EXPORT_SYMBOL(AudDrv_Clk_On);
void AudDrv_Clk_Off(void)
{
#if !defined(CONFIG_FPGA_EARLY_PORTING)
pr_debug("!! AudDrv_Clk_Off, Aud_AFE_Clk_cntr:%d\n",
Aud_AFE_Clk_cntr);
mutex_lock(&auddrv_clk_mutex);
Aud_AFE_Clk_cntr--;
if (Aud_AFE_Clk_cntr == 0) {
/* Disable AFE clock */
#ifdef PM_MANAGER_API
if (aud_clks[CLOCK_MTKAIF_26M_CLK].clk_prepare)
clk_disable(aud_clks[CLOCK_MTKAIF_26M_CLK].clock);
/* Make sure all IRQ status is cleared */
Afe_Set_Reg(AFE_IRQ_MCU_CLR, 0xffff, 0xffff);
Afe_Set_Reg(AFE_IRQ_MCU_CLR, 0xffff, 0xffff);
if (aud_clks[CLOCK_AFE].clk_prepare)
clk_disable(aud_clks[CLOCK_AFE].clock);
if (aud_clks[CLOCK_DAC].clk_prepare)
clk_disable(aud_clks[CLOCK_DAC].clock);
if (aud_clks[CLOCK_DAC_PREDIS].clk_prepare)
clk_disable(aud_clks[CLOCK_DAC_PREDIS].clock);
AudDrv_AUDINTBUS_Sel(0);
if (aud_clks[CLOCK_MUX_AUDIOINTBUS].clk_prepare)
clk_disable(aud_clks[CLOCK_MUX_AUDIOINTBUS].clock);
if (aud_clks[CLOCK_MUX_AUDIO].clk_prepare)
clk_disable(aud_clks[CLOCK_MUX_AUDIO].clock);
if (aud_clks[CLOCK_INFRA_SYS_AUDIO].clk_prepare)
clk_disable(aud_clks[CLOCK_INFRA_SYS_AUDIO].clock);
#ifdef MT6739_scp
if (aud_clks[CLOCK_SCP_SYS_AUD].clk_status)
clk_disable_unprepare(
aud_clks[CLOCK_SCP_SYS_AUD].clock);
#endif
#else
Afe_Set_Reg(AUDIO_TOP_CON0, 0x06000044, 0x06000044);
/* bit25=1, with 133m mastesr and 66m slave bus clock cg gating */
#endif
} else if (Aud_AFE_Clk_cntr < 0) {
pr_debug("!! AudDrv_Clk_Off, Aud_AFE_Clk_cntr<0 (%d)\n",
Aud_AFE_Clk_cntr);
Aud_AFE_Clk_cntr = 0;
}
mutex_unlock(&auddrv_clk_mutex);
#endif /* #if !defined(CONFIG_FPGA_EARLY_PORTING) */
}
EXPORT_SYMBOL(AudDrv_Clk_Off);
/*****************************************************************************
* FUNCTION
* AudDrv_ANA_Clk_On / AudDrv_ANA_Clk_Off
*
* DESCRIPTION
* Enable/Disable analog part clock
*
*****************************************************************************/
void AudDrv_ANA_Clk_On(void)
{
}
EXPORT_SYMBOL(AudDrv_ANA_Clk_On);
void AudDrv_ANA_Clk_Off(void)
{
}
EXPORT_SYMBOL(AudDrv_ANA_Clk_Off);
/*****************************************************************************
* FUNCTION
* AudDrv_ADC_Clk_On / AudDrv_ADC_Clk_Off
*
* DESCRIPTION
* Enable/Disable analog part clock
*
****************************************************************************
*/
void AudDrv_ADC_Clk_On(void)
{
int ret = 0;
unsigned long flags = 0;
spin_lock_irqsave(&auddrv_Clk_lock, flags);
if (Aud_ADC_Clk_cntr == 0) {
pr_debug("+%s enable_clock ADC clk(%x)\n", __func__,
Aud_ADC_Clk_cntr);
/* Afe_Set_Reg(AUDIO_TOP_CON0, 0 << 24 , 1 << 24); */
#ifdef PM_MANAGER_API
if (aud_clks[CLOCK_ADC].clk_prepare) {
ret = clk_enable(aud_clks[CLOCK_ADC].clock);
if (ret) {
pr_debug("%s [CCF]Aud enable_clock %s fail",
__func__, aud_clks[CLOCK_ADC].name);
goto EXIT;
}
} else {
pr_debug("%s [CCF]clk_prepare error %s fail", __func__,
aud_clks[CLOCK_ADC].name);
goto EXIT;
}
#else
Afe_Set_Reg(AUDIO_TOP_CON0, 0 << 24, 1 << 24);
#endif
}
Aud_ADC_Clk_cntr++;
EXIT:
spin_unlock_irqrestore(&auddrv_Clk_lock, flags);
}
void AudDrv_ADC_Clk_Off(void)
{
unsigned long flags = 0;
spin_lock_irqsave(&auddrv_Clk_lock, flags);
Aud_ADC_Clk_cntr--;
if (Aud_ADC_Clk_cntr == 0) {
pr_debug("+%s disable_clock ADC clk(%x)\n", __func__,
Aud_ADC_Clk_cntr);
#ifdef PM_MANAGER_API
if (aud_clks[CLOCK_ADC].clk_prepare)
clk_disable(aud_clks[CLOCK_ADC].clock);
#else
Afe_Set_Reg(AUDIO_TOP_CON0, 1 << 24, 1 << 24);
#endif
}
if (Aud_ADC_Clk_cntr < 0) {
pr_debug("!! %s, Aud_ADC_Clk_cntr<0 (%d)\n", __func__,
Aud_ADC_Clk_cntr);
Aud_ADC_Clk_cntr = 0;
}
spin_unlock_irqrestore(&auddrv_Clk_lock, flags);
}
/*****************************************************************************
* FUNCTION
* AudDrv_ADC2_Clk_On / AudDrv_ADC2_Clk_Off
*
* DESCRIPTION
* Enable/Disable clock
*
****************************************************************************
*/
void AudDrv_ADC2_Clk_On(void)
{
}
void AudDrv_ADC2_Clk_Off(void)
{
}
/*****************************************************************************
* FUNCTION
* AudDrv_ADC3_Clk_On / AudDrv_ADC3_Clk_Off
*
* DESCRIPTION
* Enable/Disable clock
*
****************************************************************************
*/
void AudDrv_ADC3_Clk_On(void)
{
}
void AudDrv_ADC3_Clk_Off(void)
{
}
/*****************************************************************************
* FUNCTION
* AudDrv_ADC_Hires_Clk_On / AudDrv_ADC_Hires_Clk_Off
*
* DESCRIPTION
* Enable/Disable analog part clock
*
****************************************************************************
*/
void AudDrv_ADC_Hires_Clk_On(void)
{
}
void AudDrv_ADC_Hires_Clk_Off(void)
{
}
/*****************************************************************************
* FUNCTION
* AudDrv_ADC2_Hires_Clk_On / AudDrv_ADC2_Hires_Clk_Off
*
* DESCRIPTION
* Enable/Disable analog part clock
*
****************************************************************************
*/
void AudDrv_ADC2_Hires_Clk_On(void)
{
}
void AudDrv_ADC2_Hires_Clk_Off(void)
{
}
/*****************************************************************************
* FUNCTION
* AudDrv_APLL22M_Clk_On / AudDrv_APLL22M_Clk_Off
*
* DESCRIPTION
* Enable/Disable clock
*
****************************************************************************
*/
void AudDrv_APLL22M_Clk_On(void)
{
int ret = 0;
mutex_lock(&auddrv_clk_mutex);
/* pr_debug("%s counter = %d\n", __func__, Aud_APLL22M_Clk_cntr); */
if (Aud_APLL22M_Clk_cntr == 0) {
#ifdef PM_MANAGER_API
if (aud_clks[CLOCK_APMIXED_APLL1].clk_prepare) {
ret = clk_set_rate(aud_clks[CLOCK_APMIXED_APLL1].clock,
180633600);
if (ret) {
pr_debug("%s clk_set_rate %s-180633600 fail %d\n",
__func__,
aud_clks[CLOCK_APMIXED_APLL1].name,
ret);
goto EXIT;
}
}
if (aud_clks[CLOCK_APLL22M].clk_prepare) {
ret = clk_enable(aud_clks[CLOCK_APLL22M].clock);
if (ret) {
pr_debug("%s [CCF]Aud enable_clock %s fail",
__func__,
aud_clks[CLOCK_APLL22M].name);
goto EXIT;
}
} else {
pr_debug("%s [CCF]clk_prepare error %s fail", __func__,
aud_clks[CLOCK_APLL22M].name);
goto EXIT;
}
#endif
}
Aud_APLL22M_Clk_cntr++;
EXIT:
mutex_unlock(&auddrv_clk_mutex);
}
void AudDrv_APLL22M_Clk_Off(void)
{
unsigned long flags = 0;
spin_lock_irqsave(&auddrv_Clk_lock, flags);
/* pr_debug("%s: counter = %d\n", __func__, Aud_APLL22M_Clk_cntr); */
Aud_APLL22M_Clk_cntr--;
if (Aud_APLL22M_Clk_cntr == 0) {
#ifdef PM_MANAGER_API
if (aud_clks[CLOCK_APLL22M].clk_prepare)
clk_disable(aud_clks[CLOCK_APLL22M].clock);
else {
pr_debug("%s [CCF]clk_prepare error %s fail", __func__,
aud_clks[CLOCK_APLL22M].name);
goto EXIT;
}
#endif
}
EXIT:
if (Aud_APLL22M_Clk_cntr < 0) {
pr_debug("err, %s <0 (%d)\n", __func__, Aud_APLL22M_Clk_cntr);
Aud_APLL22M_Clk_cntr = 0;
}
spin_unlock_irqrestore(&auddrv_Clk_lock, flags);
}
/*****************************************************************************
* FUNCTION
* AudDrv_APLL24M_Clk_On / AudDrv_APLL24M_Clk_Off
*
* DESCRIPTION
* Enable/Disable clock
*
****************************************************************************
*/
void AudDrv_APLL24M_Clk_On(void)
{
int ret = 0;
/* pr_debug("%s counter = %d\n", __func__, Aud_APLL24M_Clk_cntr); */
mutex_lock(&auddrv_clk_mutex);
if (Aud_APLL24M_Clk_cntr == 0) {
#ifdef PM_MANAGER_API
if (aud_clks[CLOCK_APMIXED_APLL1].clk_prepare) {
ret = clk_set_rate(aud_clks[CLOCK_APMIXED_APLL1].clock,
196608000);
if (ret) {
pr_debug("%s clk_set_rate %s-196608000 fail %d\n",
__func__,
aud_clks[CLOCK_APMIXED_APLL1].name,
ret);
goto EXIT;
}
}
if (aud_clks[CLOCK_APLL22M].clk_prepare) {
ret = clk_enable(aud_clks[CLOCK_APLL22M].clock);
if (ret) {
pr_debug("%s [CCF]Aud enable_clock %s fail",
__func__,
aud_clks[CLOCK_APLL22M].name);
goto EXIT;
}
} else {
pr_debug("%s [CCF]clk_prepare error %s fail",
__func__, aud_clks[CLOCK_APLL22M].name);
goto EXIT;
}
#endif
}
Aud_APLL24M_Clk_cntr++;
EXIT:
mutex_unlock(&auddrv_clk_mutex);
}
void AudDrv_APLL24M_Clk_Off(void)
{
unsigned long flags = 0;
pr_debug("+%s counter = %d\n", __func__, Aud_APLL24M_Clk_cntr);
spin_lock_irqsave(&auddrv_Clk_lock, flags);
Aud_APLL24M_Clk_cntr--;
if (Aud_APLL24M_Clk_cntr == 0) {
#ifdef PM_MANAGER_API
if (aud_clks[CLOCK_APLL22M].clk_prepare) {
clk_disable(aud_clks[CLOCK_APLL22M].clock);
} else {
pr_debug("%s [CCF]clk_prepare error %s fail",
__func__, aud_clks[CLOCK_APLL22M].name);
goto EXIT;
}
#endif
}
EXIT:
if (Aud_APLL24M_Clk_cntr < 0) {
pr_debug("%s <0 (%d)\n", __func__,
Aud_APLL24M_Clk_cntr);
Aud_APLL24M_Clk_cntr = 0;
}
spin_unlock_irqrestore(&auddrv_Clk_lock, flags);
}
/*****************************************************************************
* FUNCTION
* AudDrv_I2S_Clk_On / AudDrv_I2S_Clk_Off
*
* DESCRIPTION
* Enable I2S In clock (bck)
* This should be enabled in slave i2s mode.
*
****************************************************************************
*/
void aud_top_con_pdn_i2s(bool _pdn)
{
if (_pdn)
Afe_Set_Reg(AUDIO_TOP_CON0, 0x1 << 6,
0x1 << 6); /* power off I2S clock */
else
Afe_Set_Reg(AUDIO_TOP_CON0, 0x0 << 6,
0x1 << 6); /* power on I2S clock */
}
void AudDrv_I2S_Clk_On(void)
{
unsigned long flags = 0;
spin_lock_irqsave(&auddrv_Clk_lock, flags);
if (Aud_I2S_Clk_cntr == 0)
aud_top_con_pdn_i2s(false);
Aud_I2S_Clk_cntr++;
spin_unlock_irqrestore(&auddrv_Clk_lock, flags);
}
EXPORT_SYMBOL(AudDrv_I2S_Clk_On);
void AudDrv_I2S_Clk_Off(void)
{
unsigned long flags = 0;
spin_lock_irqsave(&auddrv_Clk_lock, flags);
Aud_I2S_Clk_cntr--;
if (Aud_I2S_Clk_cntr == 0) {
aud_top_con_pdn_i2s(true);
} else if (Aud_I2S_Clk_cntr < 0) {
pr_debug("!! AudDrv_I2S_Clk_Off, Aud_I2S_Clk_cntr<0 (%d)\n",
Aud_I2S_Clk_cntr);
Aud_I2S_Clk_cntr = 0;
}
spin_unlock_irqrestore(&auddrv_Clk_lock, flags);
}
EXPORT_SYMBOL(AudDrv_I2S_Clk_Off);
/*****************************************************************************
* FUNCTION
* AudDrv_TDM_Clk_On / AudDrv_TDM_Clk_Off
*
* DESCRIPTION
* Enable/Disable TDM clock
*
****************************************************************************
*/
void aud_top_con_pdn_tdm_ck(bool _pdn)
{
Afe_Set_Reg(AUDIO_TOP_CON0, _pdn << 20,
0x1 << 20); /* power on I2S clock */
}
void AudDrv_TDM_Clk_On(void)
{
unsigned long flags = 0;
spin_lock_irqsave(&auddrv_Clk_lock, flags);
if (Aud_TDM_Clk_cntr == 0)
aud_top_con_pdn_tdm_ck(false); /* enable HDMI CK */
Aud_TDM_Clk_cntr++;
spin_unlock_irqrestore(&auddrv_Clk_lock, flags);
}
EXPORT_SYMBOL(AudDrv_TDM_Clk_On);
void AudDrv_TDM_Clk_Off(void)
{
unsigned long flags = 0;
spin_lock_irqsave(&auddrv_Clk_lock, flags);
Aud_TDM_Clk_cntr--;
if (Aud_TDM_Clk_cntr == 0) {
aud_top_con_pdn_tdm_ck(true); /* disable HDMI CK */
} else if (Aud_TDM_Clk_cntr < 0) {
pr_debug("!! %s(), Aud_TDM_Clk_cntr<0 (%d)\n", __func__,
Aud_TDM_Clk_cntr);
Aud_TDM_Clk_cntr = 0;
}
spin_unlock_irqrestore(&auddrv_Clk_lock, flags);
}
EXPORT_SYMBOL(AudDrv_TDM_Clk_Off);
void AudDrv_APLL1Tuner_Clk_On(void)
{
unsigned long flags = 0;
int ret = 0;
spin_lock_irqsave(&auddrv_Clk_lock, flags);
if (Aud_APLL1_Tuner_cntr == 0) {
/* pr_debug("+%s, Aud_APLL1_Tuner_cntr:%d\n", __func__,
* Aud_APLL1_Tuner_cntr);
*/
#ifdef PM_MANAGER_API
if (aud_clks[CLOCK_APLL1_TUNER].clk_prepare) {
ret = clk_enable(aud_clks[CLOCK_APLL1_TUNER].clock);
if (ret) {
pr_debug("%s [CCF]Aud enable_clock %s fail\n",
__func__,
aud_clks[CLOCK_APLL1_TUNER].name);
goto EXIT;
}
} else {
pr_debug("%s [CCF]clk_prepare error %s fail\n",
__func__,
aud_clks[CLOCK_APLL1_TUNER].name);
goto EXIT;
}
#else
Afe_Set_Reg(AUDIO_TOP_CON0, 0x0 << 19, 0x1 << 19);
#endif
SetApmixedCfg(AP_PLL_CON5, 0x1, 0x1);
}
Aud_APLL1_Tuner_cntr++;
EXIT:
spin_unlock_irqrestore(&auddrv_Clk_lock, flags);
}
void AudDrv_APLL1Tuner_Clk_Off(void)
{
unsigned long flags = 0;
spin_lock_irqsave(&auddrv_Clk_lock, flags);
Aud_APLL1_Tuner_cntr--;
if (Aud_APLL1_Tuner_cntr == 0) {
SetApmixedCfg(AP_PLL_CON5, 0x0, 0x1);
#ifdef PM_MANAGER_API
if (aud_clks[CLOCK_APLL1_TUNER].clk_prepare)
clk_disable(aud_clks[CLOCK_APLL1_TUNER].clock);
#else
Afe_Set_Reg(AUDIO_TOP_CON0, 0x1 << 19, 0x1 << 19);
#endif
} else if (Aud_APLL1_Tuner_cntr < 0) {
pr_debug("!! %s, Aud_APLL1_Tuner_cntr<0 (%d)\n", __func__,
Aud_APLL1_Tuner_cntr);
Aud_APLL1_Tuner_cntr = 0;
}
spin_unlock_irqrestore(&auddrv_Clk_lock, flags);
}
void AudDrv_APLL2Tuner_Clk_On(void)
{
unsigned long flags = 0;
int ret = 0;
spin_lock_irqsave(&auddrv_Clk_lock, flags);
if (Aud_APLL2_Tuner_cntr == 0) {
/* pr_debug("+%s, Aud_APLL2_Tuner_cntr:%d\n", __func__,
* Aud_APLL2_Tuner_cntr);
*/
#ifdef PM_MANAGER_API
if (aud_clks[CLOCK_APLL1_TUNER].clk_prepare) {
ret = clk_enable(aud_clks[CLOCK_APLL1_TUNER].clock);
if (ret) {
pr_debug("%s [CCF]Aud enable_clock %s fail\n",
__func__,
aud_clks[CLOCK_APLL1_TUNER].name);
goto EXIT;
}
} else {
pr_debug("%s [CCF]clk_prepare error %s fail\n",
__func__, aud_clks[CLOCK_APLL1_TUNER].name);
goto EXIT;
}
#else
Afe_Set_Reg(AUDIO_TOP_CON0, 0x0 << 18, 0x1 << 18);
#endif
SetApmixedCfg(AP_PLL_CON5, 0x1, 0x1);
}
Aud_APLL2_Tuner_cntr++;
EXIT:
spin_unlock_irqrestore(&auddrv_Clk_lock, flags);
}
void AudDrv_APLL2Tuner_Clk_Off(void)
{
unsigned long flags = 0;
spin_lock_irqsave(&auddrv_Clk_lock, flags);
Aud_APLL2_Tuner_cntr--;
if (Aud_APLL2_Tuner_cntr == 0) {
SetApmixedCfg(AP_PLL_CON5, 0x0, 0x1);
#ifdef PM_MANAGER_API
if (aud_clks[CLOCK_APLL1_TUNER].clk_prepare)
clk_disable(aud_clks[CLOCK_APLL1_TUNER].clock);
#else
Afe_Set_Reg(AUDIO_TOP_CON0, 0x1 << 18, 0x1 << 18);
#endif
} else if (Aud_APLL2_Tuner_cntr < 0) {
pr_debug("!! %s, Aud_APLL1_Tuner_cntr<0 (%d)\n", __func__,
Aud_APLL2_Tuner_cntr);
Aud_APLL2_Tuner_cntr = 0;
}
spin_unlock_irqrestore(&auddrv_Clk_lock, flags);
}
/*****************************************************************************
* FUNCTION
* AudDrv_HDMI_Clk_On / AudDrv_HDMI_Clk_Off
*
* DESCRIPTION
* Enable/Disable analog part clock
*
****************************************************************************
*/
void AudDrv_HDMI_Clk_On(void)
{
#ifdef _NON_COMMON_FEATURE_READY
/* pr_debug("+AudDrv_HDMI_Clk_On, Aud_I2S_Clk_cntr:%d\n",
* Aud_HDMI_Clk_cntr);
*/
if (Aud_HDMI_Clk_cntr == 0) {
AudDrv_ANA_Clk_On();
AudDrv_Clk_On();
}
Aud_HDMI_Clk_cntr++;
#endif
}
void AudDrv_HDMI_Clk_Off(void)
{
#ifdef _NON_COMMON_FEATURE_READY
/* pr_debug("+AudDrv_HDMI_Clk_Off, Aud_I2S_Clk_cntr:%d\n",
* Aud_HDMI_Clk_cntr);
*/
Aud_HDMI_Clk_cntr--;
if (Aud_HDMI_Clk_cntr == 0) {
AudDrv_ANA_Clk_Off();
AudDrv_Clk_Off();
} else if (Aud_HDMI_Clk_cntr < 0) {
pr_debug("!! AudDrv_Linein_Clk_Off, Aud_I2S_Clk_cntr<0 (%d)\n",
Aud_HDMI_Clk_cntr);
Aud_HDMI_Clk_cntr = 0;
}
/* pr_debug("-AudDrv_I2S_Clk_Off, Aud_I2S_Clk_cntr:%d\n",
* Aud_HDMI_Clk_cntr);
*/
#endif
}
void AudDrv_Emi_Clk_On(void)
{
#if !defined(CONFIG_FPGA_EARLY_PORTING)
mutex_lock(&auddrv_pmic_mutex);
if (Aud_EMI_cntr == 0) {
#if defined(_MT_IDLE_HEADER)
/* mutex is used in these api */
spm_resource_req(SPM_RESOURCE_USER_AUDIO, SPM_RESOURCE_DRAM);
#endif
}
Aud_EMI_cntr++;
mutex_unlock(&auddrv_pmic_mutex);
#endif
}
void AudDrv_Emi_Clk_Off(void)
{
#if !defined(CONFIG_FPGA_EARLY_PORTING)
mutex_lock(&auddrv_pmic_mutex);
Aud_EMI_cntr--;
if (Aud_EMI_cntr == 0) {
#if defined(_MT_IDLE_HEADER)
/* mutex is used in these api */
spm_resource_req(SPM_RESOURCE_USER_AUDIO,
SPM_RESOURCE_RELEASE);
#endif
}
if (Aud_EMI_cntr < 0) {
Aud_EMI_cntr = 0;
pr_debug("Aud_EMI_cntr = %d\n", Aud_EMI_cntr);
}
mutex_unlock(&auddrv_pmic_mutex);
#endif
}
/*****************************************************************************
* FUNCTION
* AudDrv_ANC_Clk_On / AudDrv_ANC_Clk_Off
*
* DESCRIPTION
* Enable/Disable ANC clock
*
****************************************************************************
*/
void AudDrv_ANC_Clk_On(void)
{
/* MT6759 no ANC */
}
void AudDrv_ANC_Clk_Off(void)
{
/* MT6759 no ANC*/
}
unsigned int GetApllbySampleRate(unsigned int SampleRate)
{
if (SampleRate == 176400 || SampleRate == 88200 ||
SampleRate == 44100 || SampleRate == 22050 ||
SampleRate == 11025)
return Soc_Aud_APLL1;
else
return Soc_Aud_APLL2;
}
void SetckSel(unsigned int I2snum, unsigned int SampleRate)
{
/* always from APLL1 */
unsigned int ApllSource;
ApllSource = 0; /* mt6739 only has one apll */
switch (I2snum) {
case Soc_Aud_I2S0:
clksys_set_reg(CLK_AUDDIV_0, ApllSource << 8, 1 << 8);
break;
case Soc_Aud_I2S1:
clksys_set_reg(CLK_AUDDIV_0, ApllSource << 9, 1 << 9);
break;
case Soc_Aud_I2S2:
clksys_set_reg(CLK_AUDDIV_0, ApllSource << 10, 1 << 10);
break;
case Soc_Aud_I2S3:
clksys_set_reg(CLK_AUDDIV_0, ApllSource << 11, 1 << 11);
break;
default:
pr_debug("%s(), not support I2snum %u\n", __func__, I2snum);
break;
}
pr_debug("%s I2snum = %d ApllSource = %d\n", __func__, I2snum,
ApllSource);
}
void EnableALLbySampleRate(unsigned int SampleRate)
{
pr_debug("%s, APLL1Counter = %d, APLL2Counter = %d, SampleRate = %d\n",
__func__, APLL1Counter, APLL2Counter, SampleRate);
switch (GetApllbySampleRate(SampleRate)) {
case Soc_Aud_APLL1:
APLL1Counter++;
if (APLL1Counter == 1) {
EnableApll1(true);
AudDrv_APLL1Tuner_Clk_On();
}
break;
case Soc_Aud_APLL2:
APLL2Counter++;
if (APLL2Counter == 1) {
EnableApll2(true);
AudDrv_APLL2Tuner_Clk_On();
}
break;
default:
pr_debug("%s, invalid SampleRate %d\n", __func__, SampleRate);
break;
}
}
void DisableALLbySampleRate(unsigned int SampleRate)
{
pr_debug("%s, APLL1Counter = %d, APLL2Counter = %d, SampleRate = %d\n",
__func__, APLL1Counter, APLL2Counter, SampleRate);
switch (GetApllbySampleRate(SampleRate)) {
case Soc_Aud_APLL1:
APLL1Counter--;
if (APLL1Counter == 0) {
AudDrv_APLL1Tuner_Clk_Off();
EnableApll1(false);
} else if (APLL1Counter < 0) {
pr_debug("%s(), APLL1Counter %d < 0\n", __func__,
APLL1Counter);
APLL1Counter = 0;
}
break;
case Soc_Aud_APLL2:
APLL2Counter--;
if (APLL2Counter == 0) {
AudDrv_APLL2Tuner_Clk_Off();
EnableApll2(false);
} else if (APLL2Counter < 0) {
pr_debug("%s(), APLL2Counter %d < 0\n", __func__,
APLL2Counter);
APLL2Counter = 0;
}
break;
default:
pr_info("%s(), invalid SampleRate %d\n", __func__, SampleRate);
break;
}
}
void EnableI2SDivPower(unsigned int Diveder_name, bool bEnable)
{
pr_debug("%s bEnable = %d\n", __func__, bEnable);
if (Diveder_name < AUDIO_APLL12_DIV5)
clksys_set_reg(CLK_AUDDIV_0, !bEnable << Diveder_name,
1 << Diveder_name);
else
clksys_set_reg(CLK_AUDDIV_2,
!bEnable << 16 /*APLL_apll12_div5_pdn_POS*/,
1 << 16);
}
void EnableI2SCLKDiv(unsigned int I2snum, bool bEnable)
{
pr_debug("%s mI2SAPLLDivSelect = %d, i2snum = %d\n", __func__,
mI2SAPLLDivSelect[I2snum], I2snum);
EnableI2SDivPower(mI2SAPLLDivSelect[I2snum], bEnable);
}
void EnableApll1(bool enable)
{
pr_debug("%s enable = %d\n", __func__, enable);
if (enable) {
if (Aud_APLL_DIV_APLL1_cntr == 0) {
clksys_set_reg(CLK_AUDDIV_0, 7 << 24, 0xf << 24);
AudDrv_APLL22M_Clk_On();
apll1_mux_setting(true);
Afe_Set_Reg(AFE_HD_ENGEN_ENABLE, 0x1 << 0, 0x1 << 0);
}
Aud_APLL_DIV_APLL1_cntr++;
} else {
Aud_APLL_DIV_APLL1_cntr--;
if (Aud_APLL_DIV_APLL1_cntr == 0) {
Afe_Set_Reg(AFE_HD_ENGEN_ENABLE, 0x0 << 0, 0x1 << 0);
apll1_mux_setting(false);
AudDrv_APLL22M_Clk_Off();
}
}
}
void EnableApll2(bool enable)
{
/* pr_debug("%s enable = %d\n", __func__, enable); */
if (enable) {
if (Aud_APLL_DIV_APLL2_cntr == 0) {
clksys_set_reg(CLK_AUDDIV_0, 7 << 24, 0xf << 24);
AudDrv_APLL24M_Clk_On();
apll2_mux_setting(true);
Afe_Set_Reg(AFE_HD_ENGEN_ENABLE, 0x1 << 1, 0x1 << 1);
}
Aud_APLL_DIV_APLL2_cntr++;
} else {
Aud_APLL_DIV_APLL2_cntr--;
if (Aud_APLL_DIV_APLL2_cntr == 0) {
Afe_Set_Reg(AFE_HD_ENGEN_ENABLE, 0x0 << 1, 0x1 << 1);
apll2_mux_setting(false);
AudDrv_APLL24M_Clk_Off();
}
}
}
unsigned int SetCLkMclk(unsigned int I2snum, unsigned int SampleRate)
{
unsigned int I2S_APll = 0;
unsigned int I2s_ck_div = 0;
if (GetApllbySampleRate(SampleRate) == Soc_Aud_APLL1)
I2S_APll = APLL_44K_BASE;
else
I2S_APll = APLL_48K_BASE;
SetckSel(I2snum, SampleRate); /* set I2Sx mck source */
switch (I2snum) {
case Soc_Aud_I2S0:
I2s_ck_div = (I2S_APll / MCLKFS / SampleRate) - 1;
clksys_set_reg(CLK_AUDDIV_1, I2s_ck_div << 0, 0xff << 0);
break;
case Soc_Aud_I2S1:
I2s_ck_div = (I2S_APll / MCLKFS / SampleRate) - 1;
clksys_set_reg(CLK_AUDDIV_1, I2s_ck_div << 8, 0xff << 8);
break;
case Soc_Aud_I2S2:
I2s_ck_div = (I2S_APll / MCLKFS / SampleRate) - 1;
clksys_set_reg(CLK_AUDDIV_1, I2s_ck_div << 16, 0xff << 16);
break;
case Soc_Aud_I2S3:
I2s_ck_div = (I2S_APll / MCLKFS / SampleRate) - 1;
clksys_set_reg(CLK_AUDDIV_1, I2s_ck_div << 24, 0xff << 24);
break;
default:
pr_debug("[AudioWarn] SetCLkMclk: I2snum = %d not recognized\n",
I2snum);
break;
}
pr_debug("%s I2snum = %d I2s_ck_div = %d I2S_APll = %d\n", __func__,
I2snum, I2s_ck_div, I2S_APll);
return I2s_ck_div;
}
void SetCLkBclk(unsigned int MckDiv, unsigned int SampleRate,
unsigned int Channels, unsigned int Wlength)
{
}
void PowerDownAllI2SDiv(void)
{
int i = 0;
for (i = AUDIO_APLL1_DIV0; i < AUDIO_APLL_DIV_NUM; i++)
EnableI2SDivPower(i, false);
}