blob: 2165fbe3a5f138a79cb5ffeab8862b8ce4e0d94f [file] [log] [blame]
/*
* mt8167-codec-utils.c -- MT8167 codec driver utility functions
*
* Copyright (c) 2016 MediaTek Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <sound/soc.h>
#include <linux/delay.h>
#include <linux/dma-mapping.h>
#include "mt8167-codec.h"
#include "mt8167-codec-utils.h"
#ifdef CONFIG_MTK_SPEAKER
#include "mt6392-codec.h"
#endif
#ifdef CONFIG_MTK_AUXADC
#include "mtk_auxadc.h"
#endif
enum auxadc_channel_id {
AUXADC_CH_AU_HPL = 7,
AUXADC_CH_AU_HPR,
};
struct reg_setting {
uint32_t reg;
uint32_t mask;
uint32_t val;
};
static const struct reg_setting mt8167_codec_cali_setup_regs[] = {
{
.reg = AUDIO_TOP_CON0,
.mask = GENMASK(26, 25),
.val = 0x0,
},
{
.reg = AUDIO_TOP_CON0,
.mask = BIT(2),
.val = 0x0,
},
{
.reg = AFE_MEMIF_PBUF_SIZE,
.mask = GENMASK(17, 16),
.val = 0x0,
},
{
.reg = AFE_CONN_24BIT,
.mask = GENMASK(4, 3),
.val = 0x0,
},
{
.reg = AFE_DAC_CON1,
.mask = GENMASK(3, 0),
.val = 0x9,
},
{
.reg = AFE_CONN1,
.mask = BIT(21),
.val = BIT(21),
},
{
.reg = AFE_CONN2,
.mask = BIT(6),
.val = BIT(6),
},
{
.reg = AFE_DAC_CON0,
.mask = BIT(1),
.val = BIT(1),
},
{
.reg = AFE_ADDA_PREDIS_CON0,
.mask = GENMASK(31, 0),
.val = 0x0,
},
{
.reg = AFE_ADDA_PREDIS_CON1,
.mask = GENMASK(31, 0),
.val = 0x0,
},
{
.reg = AFE_ADDA_DL_SRC2_CON0,
.mask = GENMASK(31, 0),
.val = (0x7 << 28) | (0x03 << 24) | (0x03 << 11) | BIT(1),
},
{
.reg = AFE_ADDA_DL_SRC2_CON1,
.mask = GENMASK(31, 0),
.val = 0xf74f0000,
},
{ /* I2S2_OUT_MODE (44.1khz) */
.reg = AFE_I2S_CON1,
.mask = (0x9 << 8),
.val = (0x9 << 8),
},
{
.reg = AFE_ADDA_DL_SRC2_CON0,
.mask = BIT(0),
.val = BIT(0),
},
{
.reg = AFE_I2S_CON1,
.mask = BIT(0),
.val = BIT(0),
},
{
.reg = AFE_ADDA_UL_DL_CON0,
.mask = BIT(0),
.val = BIT(0),
},
{
.reg = AFE_DAC_CON0,
.mask = BIT(0),
.val = BIT(0),
},
{ /* ADA_HPLO_TO_AUXADC */
.reg = AUDIO_CODEC_CON02,
.mask = BIT(15),
.val = BIT(15),
},
{ /* ADA_HPRO_TO_AUXADC */
.reg = AUDIO_CODEC_CON02,
.mask = BIT(14),
.val = BIT(14),
},
};
static const struct reg_setting mt8167_codec_cali_cleanup_regs[] = {
{ /* ADA_HPLO_TO_AUXADC */
.reg = AUDIO_CODEC_CON02,
.mask = BIT(15),
.val = 0x0,
},
{ /* ADA_HPRO_TO_AUXADC */
.reg = AUDIO_CODEC_CON02,
.mask = 0x0,
.val = BIT(14),
},
{
.reg = AFE_DAC_CON0,
.mask = BIT(1),
.val = 0x0,
},
{
.reg = AFE_ADDA_DL_SRC2_CON0,
.mask = BIT(0),
.val = 0x0,
},
{
.reg = AFE_I2S_CON1,
.mask = BIT(0),
.val = 0x0,
},
{
.reg = AFE_ADDA_UL_DL_CON0,
.mask = BIT(0),
.val = 0x0,
},
{
.reg = AFE_DAC_CON0,
.mask = BIT(0),
.val = 0x0,
},
{
.reg = AUDIO_TOP_CON0,
.mask = BIT(2),
.val = BIT(2),
},
{
.reg = AUDIO_TOP_CON0,
.mask = GENMASK(26, 25),
.val = (0x3 << 25),
},
};
static const struct reg_setting mt8167_codec_cali_enable_regs[] = {
{ /* dl_rate (44.1khz) */
.reg = ABB_AFE_CON1,
.mask = GENMASK(3, 0),
.val = 9,
},
{ /* toggle top_ctrl */
.reg = ABB_AFE_CON11,
.mask = ABB_AFE_CON11_TOP_CTRL,
.val = ABB_AFE_CON11_TOP_CTRL,
},
{ /* toggle top_ctrl */
.reg = ABB_AFE_CON11,
.mask = ABB_AFE_CON11_TOP_CTRL,
.val = 0x0,
},
{
.reg = ABB_AFE_CON3,
.mask = GENMASK(31, 0),
.val = 0x0,
},
{
.reg = ABB_AFE_CON4,
.mask = GENMASK(31, 0),
.val = 0x0,
},
{
.reg = ABB_AFE_CON10,
.mask = BIT(0),
.val = BIT(0),
},
{
.reg = ABB_AFE_CON0,
.mask = BIT(0),
.val = BIT(0),
},
{
.reg = AUDIO_CODEC_CON02,
.mask = BIT(27) | BIT(17) | BIT(16),
.val = BIT(27) | BIT(17) | BIT(16),
},
{
.reg = AUDIO_CODEC_CON00,
.mask = BIT(19),
.val = BIT(19),
},
{
.reg = AUDIO_CODEC_CON01,
.mask = BIT(15) | BIT(14) | BIT(13) | BIT(12) | BIT(11),
.val = BIT(15) | BIT(14) | BIT(13) | BIT(12) | BIT(11),
},
{
.reg = AUDIO_CODEC_CON02,
.mask = BIT(28) | BIT(25) | BIT(22),
.val = BIT(28),
},
};
static const struct reg_setting mt8167_codec_cali_disable_regs[] = {
{
.reg = AUDIO_CODEC_CON02,
.mask = BIT(28) | BIT(25) | BIT(22),
.val = BIT(25) | BIT(22),
},
{
.reg = AUDIO_CODEC_CON01,
.mask = BIT(15) | BIT(14) | BIT(13) | BIT(12) | BIT(11),
.val = 0x0,
},
{
.reg = AUDIO_CODEC_CON00,
.mask = BIT(19),
.val = 0x0,
},
{
.reg = AUDIO_CODEC_CON02,
.mask = BIT(27) | BIT(17) | BIT(16),
.val = 0x0,
},
{
.reg = ABB_AFE_CON0,
.mask = BIT(0),
.val = 0x0,
},
};
static int mt8167_codec_apply_reg_setting(struct snd_soc_component *codec,
const struct reg_setting regs[], uint32_t reg_nums)
{
int i;
for (i = 0 ; i < reg_nums ; i++)
snd_soc_component_update_bits(codec,
regs[i].reg, regs[i].mask, regs[i].val);
return 0;
}
#define AFIFO_SIZE (48 * 1024)
static int mt8167_codec_setup_cali_path(struct snd_soc_component *codec,
struct snd_dma_buffer *buf)
{
/* enable power */
snd_soc_component_update_bits(codec, AUDIO_CODEC_CON01, BIT(20), BIT(20));
/* enable clock */
snd_soc_component_update_bits(codec, AUDIO_CODEC_CON03, BIT(30), BIT(30));
snd_soc_component_update_bits(codec, AUDIO_CODEC_CON04, BIT(15), BIT(15));
/* allocate buffer */
buf->area = dma_alloc_coherent(codec->dev, AFIFO_SIZE,
&buf->addr, GFP_KERNEL | __GFP_ZERO);
snd_soc_component_update_bits(codec,
AFE_DL1_BASE,
GENMASK(31, 0),
buf->addr);
snd_soc_component_update_bits(codec,
AFE_DL1_END,
GENMASK(31, 0),
buf->addr + (AFIFO_SIZE - 1));
/* setup */
return mt8167_codec_apply_reg_setting(codec,
mt8167_codec_cali_setup_regs,
ARRAY_SIZE(mt8167_codec_cali_setup_regs));
}
static int mt8167_codec_cleanup_cali_path(struct snd_soc_component *codec,
struct snd_dma_buffer *buf)
{
int ret = 0;
/* cleanup */
ret = mt8167_codec_apply_reg_setting(codec,
mt8167_codec_cali_cleanup_regs,
ARRAY_SIZE(mt8167_codec_cali_cleanup_regs));
/* free buffer */
dma_free_coherent(codec->dev, AFIFO_SIZE, buf->area,
buf->addr);
/* disable clock */
snd_soc_component_update_bits(codec, AUDIO_CODEC_CON04, BIT(15), 0x0);
snd_soc_component_update_bits(codec, AUDIO_CODEC_CON03, BIT(30), 0x0);
/* disable power */
snd_soc_component_update_bits(codec, AUDIO_CODEC_CON01, BIT(20), 0x0);
return ret;
}
static int mt8167_codec_enable_cali_path(struct snd_soc_component *codec)
{
/* enable */
return mt8167_codec_apply_reg_setting(codec,
mt8167_codec_cali_enable_regs,
ARRAY_SIZE(mt8167_codec_cali_enable_regs));
}
static int mt8167_codec_disable_cali_path(struct snd_soc_component *codec)
{
/* disable */
return mt8167_codec_apply_reg_setting(codec,
mt8167_codec_cali_disable_regs,
ARRAY_SIZE(mt8167_codec_cali_disable_regs));
}
static int32_t mt8167_codec_get_hp_cali_val(struct snd_soc_component *codec,
uint32_t auxadc_channel)
{
int32_t cali_val = 0;
struct snd_dma_buffer dma_buf;
#ifdef CONFIG_MTK_AUXADC
int32_t auxadc_on_val = 0;
int32_t auxadc_off_val = 0;
int32_t auxadc_val_sum = 0;
int32_t auxadc_val_avg = 0;
int32_t count = 0;
int32_t countlimit = 5;
#endif
dev_dbg(codec->dev, "%s\n", __func__);
mt8167_codec_setup_cali_path(codec, &dma_buf);
usleep_range(10 * 1000, 15 * 1000);
#ifdef CONFIG_MTK_AUXADC
IMM_GetOneChannelValue_Cali(auxadc_channel, &auxadc_off_val);
dev_dbg(codec->dev, "%s auxadc_off_val: %d\n",
__func__, auxadc_off_val);
#endif
mt8167_codec_enable_cali_path(codec);
usleep_range(10 * 1000, 15 * 1000);
#ifdef CONFIG_MTK_AUXADC
for (count = 0 ; count < countlimit ; count++) {
IMM_GetOneChannelValue_Cali(auxadc_channel, &auxadc_on_val);
auxadc_val_sum += auxadc_on_val;
dev_dbg(codec->dev, "%s auxadc_on_val: %d, auxadc_val_sum: %d\n",
__func__, auxadc_on_val, auxadc_val_sum);
}
auxadc_val_avg = auxadc_val_sum / countlimit;
cali_val = auxadc_off_val - auxadc_val_avg;
cali_val = cali_val/1000; /* mV */
#endif
mt8167_codec_disable_cali_path(codec);
mt8167_codec_cleanup_cali_path(codec, &dma_buf);
return cali_val;
}
uint32_t mt8167_codec_conv_dc_offset_to_comp_val(int32_t dc_offset)
{
uint32_t dccomp_val = 0;
bool invert = false;
if (!dc_offset)
return 0;
if (dc_offset > 0)
invert = true;
else
dc_offset *= (-1);
/* transform to 1.8V scale */
dc_offset = (dc_offset * 18) / 10;
/*
* ABB_AFE_CON3, 1 step is (1/32768) * 1800 mV = 0.0549
* dccomp_val = dc_cali_value/0.0549 = dc_cali_value * 18
*/
dccomp_val = dc_offset * 18;
/* two's complement to change the direction of dc compensation value */
if (invert)
dccomp_val = 0xFFFFFFFF - dccomp_val + 1;
return dccomp_val;
}
EXPORT_SYMBOL_GPL(mt8167_codec_conv_dc_offset_to_comp_val);
int mt8167_codec_get_hpl_cali_val(struct snd_soc_component *codec,
uint32_t *dccomp_val, int32_t *dc_offset)
{
*dc_offset = mt8167_codec_get_hp_cali_val(codec, AUXADC_CH_AU_HPL);
*dccomp_val = mt8167_codec_conv_dc_offset_to_comp_val(*dc_offset);
dev_dbg(codec->dev, "%s dc_offset %d, dccomp_val %d\n",
__func__, *dc_offset, *dccomp_val);
return 0;
}
EXPORT_SYMBOL_GPL(mt8167_codec_get_hpl_cali_val);
int mt8167_codec_get_hpr_cali_val(struct snd_soc_component *codec,
uint32_t *dccomp_val, int32_t *dc_offset)
{
*dc_offset = mt8167_codec_get_hp_cali_val(codec, AUXADC_CH_AU_HPR);
*dccomp_val = mt8167_codec_conv_dc_offset_to_comp_val(*dc_offset);
dev_dbg(codec->dev, "%s dc_offset %d, dccomp_val %d\n",
__func__, *dc_offset, *dccomp_val);
return 0;
}
EXPORT_SYMBOL_GPL(mt8167_codec_get_hpr_cali_val);
static bool ul_is_builtin_mic(uint32_t type)
{
bool ret = false;
switch (type) {
case CODEC_LOOPBACK_AMIC_TO_SPK:
case CODEC_LOOPBACK_AMIC_TO_HP:
ret = true;
break;
default:
ret = false;
break;
}
return ret;
}
static bool ul_is_headset_mic(uint32_t type)
{
bool ret = false;
switch (type) {
case CODEC_LOOPBACK_HEADSET_MIC_TO_SPK:
case CODEC_LOOPBACK_HEADSET_MIC_TO_HP:
ret = true;
break;
default:
ret = false;
break;
}
return ret;
}
static bool ul_is_amic(uint32_t type)
{
return ul_is_builtin_mic(type) ||
ul_is_headset_mic(type);
}
static bool ul_is_dmic(uint32_t type)
{
bool ret = false;
switch (type) {
case CODEC_LOOPBACK_DMIC_TO_SPK:
case CODEC_LOOPBACK_DMIC_TO_HP:
ret = true;
break;
default:
ret = false;
break;
}
return ret;
}
static bool dl_is_spk(uint32_t type)
{
bool ret = false;
switch (type) {
case CODEC_LOOPBACK_AMIC_TO_SPK:
case CODEC_LOOPBACK_DMIC_TO_SPK:
case CODEC_LOOPBACK_HEADSET_MIC_TO_SPK:
ret = true;
break;
default:
ret = false;
break;
}
return ret;
}
static bool dl_is_hp(uint32_t type)
{
bool ret = false;
switch (type) {
case CODEC_LOOPBACK_AMIC_TO_HP:
case CODEC_LOOPBACK_DMIC_TO_HP:
case CODEC_LOOPBACK_HEADSET_MIC_TO_HP:
ret = true;
break;
default:
ret = false;
break;
}
return ret;
}
static const struct reg_setting mt8167_codec_ul_rate_32000_setup_regs[] = {
{ /* ul_rate (32khz) */
.reg = ABB_AFE_CON1,
.mask = GENMASK(7, 4),
.val = 0x0,
},
{ /* toggle top_ctrl */
.reg = ABB_AFE_CON11,
.mask = ABB_AFE_CON11_TOP_CTRL,
.val = ABB_AFE_CON11_TOP_CTRL,
},
{ /* toggle top_ctrl */
.reg = ABB_AFE_CON11,
.mask = ABB_AFE_CON11_TOP_CTRL,
.val = 0x0,
},
};
static const struct reg_setting mt8167_codec_ul_rate_48000_setup_regs[] = {
{ /* ul_rate (48khz) */
.reg = ABB_AFE_CON1,
.mask = GENMASK(7, 4),
.val = (0x1 << 4),
},
{ /* toggle top_ctrl */
.reg = ABB_AFE_CON11,
.mask = ABB_AFE_CON11_TOP_CTRL,
.val = ABB_AFE_CON11_TOP_CTRL,
},
{ /* toggle top_ctrl */
.reg = ABB_AFE_CON11,
.mask = ABB_AFE_CON11_TOP_CTRL,
.val = 0x0,
},
};
static const struct reg_setting mt8167_codec_dl_rate_32000_setup_regs[] = {
{ /* dl_rate (32khz) */
.reg = ABB_AFE_CON1,
.mask = GENMASK(3, 0),
.val = 8,
},
{ /* toggle top_ctrl */
.reg = ABB_AFE_CON11,
.mask = ABB_AFE_CON11_TOP_CTRL,
.val = ABB_AFE_CON11_TOP_CTRL,
},
{ /* toggle top_ctrl */
.reg = ABB_AFE_CON11,
.mask = ABB_AFE_CON11_TOP_CTRL,
.val = 0x0,
},
};
static const struct reg_setting mt8167_codec_dl_rate_48000_setup_regs[] = {
{ /* dl_rate (48khz) */
.reg = ABB_AFE_CON1,
.mask = GENMASK(3, 0),
.val = 10,
},
{ /* toggle top_ctrl */
.reg = ABB_AFE_CON11,
.mask = ABB_AFE_CON11_TOP_CTRL,
.val = ABB_AFE_CON11_TOP_CTRL,
},
{ /* toggle top_ctrl */
.reg = ABB_AFE_CON11,
.mask = ABB_AFE_CON11_TOP_CTRL,
.val = 0x0,
},
};
static const struct reg_setting mt8167_codec_builtin_amic_enable_regs[] = {
{ /* micbias0 */
.reg = AUDIO_CODEC_CON03,
.mask = BIT(17),
.val = BIT(17),
},
{ /* left pga mux <- AU_VIN0 */
.reg = AUDIO_CODEC_CON00,
.mask = GENMASK(31, 28),
.val = 0x0,
},
{ /* right pga mux <- AU_VIN2 */
.reg = AUDIO_CODEC_CON00,
.mask = GENMASK(13, 10),
.val = 0x0,
},
};
static const struct reg_setting mt8167_codec_headset_amic_enable_regs[] = {
{ /* micbias1 */
.reg = AUDIO_CODEC_CON01,
.mask = BIT(21),
.val = BIT(21),
},
{ /* left pga mux <- AU_VIN1 */
.reg = AUDIO_CODEC_CON00,
.mask = GENMASK(31, 28),
.val = BIT(28),
},
{ /* right pga mux <- AU_VIN1 */
.reg = AUDIO_CODEC_CON00,
.mask = GENMASK(13, 10),
.val = BIT(10),
},
};
static const struct reg_setting mt8167_codec_amic_enable_regs[] = {
{ /* CLKLDO power on */
.reg = AUDIO_CODEC_CON01,
.mask = BIT(20),
.val = BIT(20),
},
{ /* Audio Codec CLK on */
.reg = AUDIO_CODEC_CON03,
.mask = BIT(30),
.val = BIT(30),
},
{ /* UL CLK on */
.reg = AUDIO_CODEC_CON03,
.mask = BIT(21),
.val = BIT(21),
},
{ /* vcm14 */
.reg = AUDIO_CODEC_CON00,
.mask = AUDIO_CODEC_CON00_AUDULL_VCM14_EN,
.val = AUDIO_CODEC_CON00_AUDULL_VCM14_EN,
},
{ /* vcm14 */
.reg = AUDIO_CODEC_CON00,
.mask = AUDIO_CODEC_CON00_AUDULR_VCM14_EN,
.val = AUDIO_CODEC_CON00_AUDULR_VCM14_EN,
},
{ /* vref24 */
.reg = AUDIO_CODEC_CON00,
.mask = AUDIO_CODEC_CON00_AUDULL_VREF24_EN,
.val = AUDIO_CODEC_CON00_AUDULL_VREF24_EN,
},
{ /* vref24 */
.reg = AUDIO_CODEC_CON00,
.mask = AUDIO_CODEC_CON00_AUDULR_VREF24_EN,
.val = AUDIO_CODEC_CON00_AUDULR_VREF24_EN,
},
{ /* ul_en */
.reg = ABB_AFE_CON0,
.mask = BIT(1),
.val = BIT(1),
},
{ /* left pga */
.reg = AUDIO_CODEC_CON00,
.mask = BIT(24),
.val = BIT(24),
},
{ /* right pga */
.reg = AUDIO_CODEC_CON00,
.mask = BIT(6),
.val = BIT(6),
},
{ /* left adc */
.reg = AUDIO_CODEC_CON00,
.mask = BIT(23),
.val = BIT(23),
},
{ /* right adc */
.reg = AUDIO_CODEC_CON00,
.mask = BIT(5),
.val = BIT(5),
},
};
static const struct reg_setting mt8167_codec_amic_disable_regs[] = {
{ /* left adc */
.reg = AUDIO_CODEC_CON00,
.mask = BIT(23),
.val = 0x0,
},
{ /* right adc */
.reg = AUDIO_CODEC_CON00,
.mask = BIT(5),
.val = 0x0,
},
{ /* left pga */
.reg = AUDIO_CODEC_CON00,
.mask = BIT(24),
.val = 0x0,
},
{ /* right pga */
.reg = AUDIO_CODEC_CON00,
.mask = BIT(6),
.val = 0x0,
},
{ /* micbias0 */
.reg = AUDIO_CODEC_CON03,
.mask = BIT(17),
.val = 0x0,
},
{ /* micbias1 */
.reg = AUDIO_CODEC_CON01,
.mask = BIT(21),
.val = 0x0,
},
{ /* left pga mux <- OPEN */
.reg = AUDIO_CODEC_CON00,
.mask = BIT(28),
.val = (0x2 << 28),
},
{ /* right pga mux <- OPEN */
.reg = AUDIO_CODEC_CON00,
.mask = BIT(10),
.val = (0x2 << 10),
},
{ /* ul_en */
.reg = ABB_AFE_CON0,
.mask = BIT(1),
.val = 0x0,
},
{ /* vref24 */
.reg = AUDIO_CODEC_CON00,
.mask = AUDIO_CODEC_CON00_AUDULL_VREF24_EN,
.val = 0x0,
},
{ /* vref24 */
.reg = AUDIO_CODEC_CON00,
.mask = AUDIO_CODEC_CON00_AUDULR_VREF24_EN,
.val = 0x0,
},
{ /* vcm14 */
.reg = AUDIO_CODEC_CON00,
.mask = AUDIO_CODEC_CON00_AUDULL_VCM14_EN,
.val = 0x0,
},
{ /* vcm14 */
.reg = AUDIO_CODEC_CON00,
.mask = AUDIO_CODEC_CON00_AUDULR_VCM14_EN,
.val = 0x0,
},
{ /* UL CLK off */
.reg = AUDIO_CODEC_CON03,
.mask = BIT(21),
.val = 0x0,
},
{ /* Audio Codec CLK off */
.reg = AUDIO_CODEC_CON03,
.mask = BIT(30),
.val = 0x0,
},
{ /* CLKLDO power off */
.reg = AUDIO_CODEC_CON01,
.mask = BIT(20),
.val = 0x0,
},
};
static const struct reg_setting mt8167_codec_dmic_enable_regs[] = {
{ /* vcm14 */
.reg = AUDIO_CODEC_CON00,
.mask = AUDIO_CODEC_CON00_AUDULL_VCM14_EN,
.val = AUDIO_CODEC_CON00_AUDULL_VCM14_EN,
},
{ /* vcm14 */
.reg = AUDIO_CODEC_CON00,
.mask = AUDIO_CODEC_CON00_AUDULR_VCM14_EN,
.val = AUDIO_CODEC_CON00_AUDULR_VCM14_EN,
},
{ /* micbias0 */
.reg = AUDIO_CODEC_CON03,
.mask = BIT(17),
.val = BIT(17),
},
{ /* ul_en */
.reg = ABB_AFE_CON0,
.mask = BIT(1),
.val = BIT(1),
},
{ /* dig_mic_en (one-wire) */
.reg = ABB_AFE_CON9,
.mask = ABB_AFE_CON9_DIG_MIC_EN,
.val = ABB_AFE_CON9_DIG_MIC_EN,
},
{ /* Digital microphone enable */
.reg = AUDIO_CODEC_CON03,
.mask = AUDIO_CODEC_CON03_DIG_MIC_EN,
.val = AUDIO_CODEC_CON03_DIG_MIC_EN,
},
};
static const struct reg_setting mt8167_codec_dmic_disable_regs[] = {
{ /* Digital microphone enable */
.reg = AUDIO_CODEC_CON03,
.mask = AUDIO_CODEC_CON03_DIG_MIC_EN,
.val = 0x0,
},
{ /* dig_mic_en (one-wire) */
.reg = ABB_AFE_CON9,
.mask = ABB_AFE_CON9_DIG_MIC_EN,
.val = 0x0,
},
{ /* micbias0 */
.reg = AUDIO_CODEC_CON03,
.mask = BIT(17),
.val = 0x0,
},
{ /* ul_en */
.reg = ABB_AFE_CON0,
.mask = BIT(1),
.val = 0x0,
},
{ /* vcm14 */
.reg = AUDIO_CODEC_CON00,
.mask = AUDIO_CODEC_CON00_AUDULL_VCM14_EN,
.val = 0x0,
},
{ /* vcm14 */
.reg = AUDIO_CODEC_CON00,
.mask = AUDIO_CODEC_CON00_AUDULR_VCM14_EN,
.val = 0x0,
},
};
static const struct reg_setting mt8167_codec_spk_enable_regs[] = {
{ /* DL CLK on */
.reg = AUDIO_CODEC_CON04,
.mask = BIT(15),
.val = BIT(15),
},
{ /* dl_vef24 */
.reg = AUDIO_CODEC_CON02,
.mask = BIT(16),
.val = BIT(16),
},
{ /* dac_clk */
.reg = AUDIO_CODEC_CON02,
.mask = BIT(27),
.val = BIT(27),
},
{ /* dl_vcm1 */
.reg = AUDIO_CODEC_CON01,
.mask = BIT(13),
.val = BIT(13),
},
{ /* dl_vcm2 */
.reg = AUDIO_CODEC_CON02,
.mask = BIT(17),
.val = BIT(17),
},
{ /* dl_en */
.reg = ABB_AFE_CON0,
.mask = BIT(0),
.val = BIT(0),
},
{ /* left dac */
.reg = AUDIO_CODEC_CON01,
.mask = BIT(15),
.val = BIT(15),
},
{ /* voice amp */
.reg = AUDIO_CODEC_CON02,
.mask = BIT(8),
.val = BIT(8),
},
};
static const struct reg_setting mt8167_codec_spk_disable_regs[] = {
{ /* voice amp */
.reg = AUDIO_CODEC_CON02,
.mask = BIT(8),
.val = 0x0,
},
{ /* left dac */
.reg = AUDIO_CODEC_CON01,
.mask = BIT(15),
.val = 0x0,
},
{ /* dl_en */
.reg = ABB_AFE_CON0,
.mask = BIT(0),
.val = 0x0,
},
{ /* dl_vcm2 */
.reg = AUDIO_CODEC_CON02,
.mask = BIT(17),
.val = 0x0,
},
{ /* dl_vcm1 */
.reg = AUDIO_CODEC_CON01,
.mask = BIT(13),
.val = 0x0,
},
{ /* dac_clk */
.reg = AUDIO_CODEC_CON02,
.mask = BIT(27),
.val = 0x0,
},
{ /* dl_vef24 */
.reg = AUDIO_CODEC_CON02,
.mask = BIT(16),
.val = 0x0,
},
{ /* DL CLK off */
.reg = AUDIO_CODEC_CON04,
.mask = BIT(15),
.val = 0x0,
},
};
static const struct reg_setting mt8167_codec_hp_enable_regs[] = {
{ /* DL CLK on */
.reg = AUDIO_CODEC_CON04,
.mask = BIT(15),
.val = BIT(15),
},
{ /* dl_vef24 */
.reg = AUDIO_CODEC_CON02,
.mask = BIT(16),
.val = BIT(16),
},
{ /* dac_clk */
.reg = AUDIO_CODEC_CON02,
.mask = BIT(27),
.val = BIT(27),
},
{ /* dl_vcm1 */
.reg = AUDIO_CODEC_CON01,
.mask = BIT(13),
.val = BIT(13),
},
{ /* dl_vcm2 */
.reg = AUDIO_CODEC_CON02,
.mask = BIT(17),
.val = BIT(17),
},
{ /* dl_en */
.reg = ABB_AFE_CON0,
.mask = BIT(0),
.val = BIT(0),
},
{ /* left dac */
.reg = AUDIO_CODEC_CON01,
.mask = BIT(15),
.val = BIT(15),
},
{ /* right dac */
.reg = AUDIO_CODEC_CON01,
.mask = BIT(14),
.val = BIT(14),
},
{ /* left audio amp */
.reg = AUDIO_CODEC_CON01,
.mask = BIT(12),
.val = BIT(12),
},
{ /* right audio amp */
.reg = AUDIO_CODEC_CON01,
.mask = BIT(11),
.val = BIT(11),
},
{ /* HP Pre-charge function release */
.reg = AUDIO_CODEC_CON02,
.mask = BIT(28),
.val = BIT(28),
},
{ /* Disable the depop mux of HP drivers */
.reg = AUDIO_CODEC_CON02,
.mask = BIT(25),
.val = 0x0,
},
{ /* Disable the depop VCM gen */
.reg = AUDIO_CODEC_CON02,
.mask = BIT(22),
.val = 0x0,
},
};
static const struct reg_setting mt8167_codec_hp_disable_regs[] = {
{ /* Reset HP Pre-charge function */
.reg = AUDIO_CODEC_CON02,
.mask = BIT(28),
.val = 0x0,
},
{ /* Enable the depop mux of HP drivers */
.reg = AUDIO_CODEC_CON02,
.mask = BIT(25),
.val = BIT(25),
},
{ /* Enable depop VCM gen */
.reg = AUDIO_CODEC_CON02,
.mask = BIT(22),
.val = BIT(22),
},
{ /* left audio amp */
.reg = AUDIO_CODEC_CON01,
.mask = BIT(12),
.val = 0x0,
},
{ /* right audio amp */
.reg = AUDIO_CODEC_CON01,
.mask = BIT(11),
.val = 0x0,
},
{ /* left dac */
.reg = AUDIO_CODEC_CON01,
.mask = BIT(15),
.val = 0x0,
},
{ /* right dac */
.reg = AUDIO_CODEC_CON01,
.mask = BIT(14),
.val = 0x0,
},
{ /* dl_en */
.reg = ABB_AFE_CON0,
.mask = BIT(0),
.val = 0x0,
},
{ /* dl_vcm2 */
.reg = AUDIO_CODEC_CON02,
.mask = BIT(17),
.val = 0x0,
},
{ /* dl_vcm1 */
.reg = AUDIO_CODEC_CON01,
.mask = BIT(13),
.val = 0x0,
},
{ /* dac_clk */
.reg = AUDIO_CODEC_CON02,
.mask = BIT(27),
.val = 0x0,
},
{ /* dl_vef24 */
.reg = AUDIO_CODEC_CON02,
.mask = BIT(16),
.val = 0x0,
},
{ /* DL CLK off */
.reg = AUDIO_CODEC_CON04,
.mask = BIT(15),
.val = 0x0,
},
};
static void mt8167_codec_turn_on_ul_amic_path(struct snd_soc_component *codec,
uint32_t lpbk_type)
{
dev_dbg(codec->dev, "%s %s\n", __func__,
ul_is_builtin_mic(lpbk_type) ? "built-in mic" : "headset mic");
if (ul_is_builtin_mic(lpbk_type))
mt8167_codec_apply_reg_setting(codec,
mt8167_codec_builtin_amic_enable_regs,
ARRAY_SIZE(mt8167_codec_builtin_amic_enable_regs));
else if (ul_is_headset_mic(lpbk_type))
mt8167_codec_apply_reg_setting(codec,
mt8167_codec_headset_amic_enable_regs,
ARRAY_SIZE(mt8167_codec_headset_amic_enable_regs));
mt8167_codec_apply_reg_setting(codec,
mt8167_codec_amic_enable_regs,
ARRAY_SIZE(mt8167_codec_amic_enable_regs));
}
static void mt8167_codec_turn_on_ul_dmic_path(struct snd_soc_component *codec)
{
dev_dbg(codec->dev, "%s\n", __func__);
mt8167_codec_apply_reg_setting(codec,
mt8167_codec_dmic_enable_regs,
ARRAY_SIZE(mt8167_codec_dmic_enable_regs));
}
static void mt8167_codec_turn_off_ul_amic_path(struct snd_soc_component *codec)
{
dev_dbg(codec->dev, "%s\n", __func__);
mt8167_codec_apply_reg_setting(codec,
mt8167_codec_amic_disable_regs,
ARRAY_SIZE(mt8167_codec_amic_disable_regs));
}
static void mt8167_codec_turn_off_ul_dmic_path(struct snd_soc_component *codec)
{
dev_dbg(codec->dev, "%s\n", __func__);
mt8167_codec_apply_reg_setting(codec,
mt8167_codec_dmic_disable_regs,
ARRAY_SIZE(mt8167_codec_dmic_disable_regs));
}
static void mt8167_codec_turn_on_dl_spk_path(struct snd_soc_component *codec)
{
dev_dbg(codec->dev, "%s\n", __func__);
mt8167_codec_apply_reg_setting(codec,
mt8167_codec_spk_enable_regs,
ARRAY_SIZE(mt8167_codec_spk_enable_regs));
}
static void mt8167_codec_turn_on_dl_hp_path(struct snd_soc_component *codec)
{
dev_dbg(codec->dev, "%s\n", __func__);
mt8167_codec_apply_reg_setting(codec,
mt8167_codec_hp_enable_regs,
ARRAY_SIZE(mt8167_codec_hp_enable_regs));
}
static void mt8167_codec_turn_off_dl_spk_path(struct snd_soc_component *codec)
{
dev_dbg(codec->dev, "%s\n", __func__);
mt8167_codec_apply_reg_setting(codec,
mt8167_codec_spk_disable_regs,
ARRAY_SIZE(mt8167_codec_spk_disable_regs));
}
static void mt8167_codec_turn_off_dl_hp_path(struct snd_soc_component *codec)
{
dev_dbg(codec->dev, "%s\n", __func__);
mt8167_codec_apply_reg_setting(codec,
mt8167_codec_hp_disable_regs,
ARRAY_SIZE(mt8167_codec_hp_disable_regs));
}
static void mt8167_codec_setup_ul_rate(struct snd_soc_component *codec,
uint32_t lpbk_type)
{
if (ul_is_amic(lpbk_type))
mt8167_codec_apply_reg_setting(codec,
mt8167_codec_ul_rate_48000_setup_regs,
ARRAY_SIZE(mt8167_codec_ul_rate_48000_setup_regs));
else if (ul_is_dmic(lpbk_type))
mt8167_codec_apply_reg_setting(codec,
mt8167_codec_ul_rate_32000_setup_regs,
ARRAY_SIZE(mt8167_codec_ul_rate_32000_setup_regs));
}
static void mt8167_codec_turn_on_ul_path(struct snd_soc_component *codec,
uint32_t lpbk_type)
{
mt8167_codec_setup_ul_rate(codec, lpbk_type);
if (ul_is_amic(lpbk_type))
mt8167_codec_turn_on_ul_amic_path(codec, lpbk_type);
else if (ul_is_dmic(lpbk_type))
mt8167_codec_turn_on_ul_dmic_path(codec);
}
static void mt8167_codec_turn_off_ul_path(struct snd_soc_component *codec,
uint32_t lpbk_type)
{
if (ul_is_amic(lpbk_type))
mt8167_codec_turn_off_ul_amic_path(codec);
else if (ul_is_dmic(lpbk_type))
mt8167_codec_turn_off_ul_dmic_path(codec);
}
static void mt8167_codec_setup_dl_rate(struct snd_soc_component *codec,
uint32_t lpbk_type)
{
if (ul_is_amic(lpbk_type))
mt8167_codec_apply_reg_setting(codec,
mt8167_codec_dl_rate_48000_setup_regs,
ARRAY_SIZE(mt8167_codec_dl_rate_48000_setup_regs));
else if (ul_is_dmic(lpbk_type))
mt8167_codec_apply_reg_setting(codec,
mt8167_codec_dl_rate_32000_setup_regs,
ARRAY_SIZE(mt8167_codec_dl_rate_32000_setup_regs));
}
static void mt8167_codec_turn_on_dl_path(struct snd_soc_component *codec,
uint32_t lpbk_type)
{
mt8167_codec_setup_dl_rate(codec, lpbk_type);
if (dl_is_spk(lpbk_type)) {
mt8167_codec_turn_on_dl_spk_path(codec);
#ifdef CONFIG_MTK_SPEAKER
mt6392_int_spk_turn_on(codec);
#endif
} else if (dl_is_hp(lpbk_type))
mt8167_codec_turn_on_dl_hp_path(codec);
}
static void mt8167_codec_turn_off_dl_path(struct snd_soc_component *codec,
uint32_t lpbk_type)
{
if (dl_is_spk(lpbk_type)) {
#ifdef CONFIG_MTK_SPEAKER
mt6392_int_spk_turn_off(codec);
#endif
mt8167_codec_turn_off_dl_spk_path(codec);
} else if (dl_is_hp(lpbk_type))
mt8167_codec_turn_off_dl_hp_path(codec);
}
void mt8167_codec_turn_on_lpbk_path(struct snd_soc_component *codec,
uint32_t lpbk_type)
{
mt8167_codec_turn_on_ul_path(codec, lpbk_type);
mt8167_codec_turn_on_dl_path(codec, lpbk_type);
}
EXPORT_SYMBOL_GPL(mt8167_codec_turn_on_lpbk_path);
void mt8167_codec_turn_off_lpbk_path(struct snd_soc_component *codec,
uint32_t lpbk_type)
{
mt8167_codec_turn_off_dl_path(codec, lpbk_type);
mt8167_codec_turn_off_ul_path(codec, lpbk_type);
}
EXPORT_SYMBOL_GPL(mt8167_codec_turn_off_lpbk_path);