mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-05 16:54:27 +00:00
ASoC: da7213: Add new kcontrol for tonegen
Add new kcontrol for tone generator Signed-off-by: David Rau <David.Rau.opensource@dm.renesas.com> Link: https://lore.kernel.org/r/20231018064444.23186-1-David.Rau.opensource@dm.renesas.com Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
parent
9a4bf1f0be
commit
64c3259b5f
2 changed files with 233 additions and 2 deletions
|
@ -55,6 +55,7 @@ static const DECLARE_TLV_DB_SCALE(hp_vol_tlv, -5700, 100, 0);
|
|||
static const DECLARE_TLV_DB_SCALE(lineout_vol_tlv, -4800, 100, 0);
|
||||
static const DECLARE_TLV_DB_SCALE(alc_threshold_tlv, -9450, 150, 0);
|
||||
static const DECLARE_TLV_DB_SCALE(alc_gain_tlv, 0, 600, 0);
|
||||
static const DECLARE_TLV_DB_SCALE(da7213_tonegen_gain_tlv, -4500, 300, 0);
|
||||
|
||||
/* ADC and DAC voice mode (8kHz) high pass cutoff value */
|
||||
static const char * const da7213_voice_hpf_corner_txt[] = {
|
||||
|
@ -86,6 +87,23 @@ static SOC_ENUM_SINGLE_DECL(da7213_adc_audio_hpf_corner,
|
|||
DA7213_AUDIO_HPF_CORNER_SHIFT,
|
||||
da7213_audio_hpf_corner_txt);
|
||||
|
||||
static const char * const da7213_tonegen_dtmf_key_txt[] = {
|
||||
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D",
|
||||
"*", "#"
|
||||
};
|
||||
|
||||
static const struct soc_enum da7213_tonegen_dtmf_key =
|
||||
SOC_ENUM_SINGLE(DA7213_TONE_GEN_CFG1, DA7213_DTMF_REG_SHIFT,
|
||||
DA7213_DTMF_REG_MAX, da7213_tonegen_dtmf_key_txt);
|
||||
|
||||
static const char * const da7213_tonegen_swg_sel_txt[] = {
|
||||
"Sum", "SWG1", "SWG2", "Sum"
|
||||
};
|
||||
|
||||
static const struct soc_enum da7213_tonegen_swg_sel =
|
||||
SOC_ENUM_SINGLE(DA7213_TONE_GEN_CFG2, DA7213_SWG_SEL_SHIFT,
|
||||
DA7213_SWG_SEL_MAX, da7213_tonegen_swg_sel_txt);
|
||||
|
||||
/* Gain ramping rate value */
|
||||
static const char * const da7213_gain_ramp_rate_txt[] = {
|
||||
"nominal rate * 8", "nominal rate * 16", "nominal rate / 16",
|
||||
|
@ -191,6 +209,64 @@ static SOC_ENUM_SINGLE_DECL(da7213_alc_integ_release_rate,
|
|||
* Control Functions
|
||||
*/
|
||||
|
||||
/* Locked Kcontrol calls */
|
||||
static int da7213_volsw_locked_get(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
|
||||
struct da7213_priv *da7213 = snd_soc_component_get_drvdata(component);
|
||||
int ret;
|
||||
|
||||
mutex_lock(&da7213->ctrl_lock);
|
||||
ret = snd_soc_get_volsw(kcontrol, ucontrol);
|
||||
mutex_unlock(&da7213->ctrl_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int da7213_volsw_locked_put(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
|
||||
struct da7213_priv *da7213 = snd_soc_component_get_drvdata(component);
|
||||
int ret;
|
||||
|
||||
mutex_lock(&da7213->ctrl_lock);
|
||||
ret = snd_soc_put_volsw(kcontrol, ucontrol);
|
||||
mutex_unlock(&da7213->ctrl_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int da7213_enum_locked_get(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
|
||||
struct da7213_priv *da7213 = snd_soc_component_get_drvdata(component);
|
||||
int ret;
|
||||
|
||||
mutex_lock(&da7213->ctrl_lock);
|
||||
ret = snd_soc_get_enum_double(kcontrol, ucontrol);
|
||||
mutex_unlock(&da7213->ctrl_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int da7213_enum_locked_put(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
|
||||
struct da7213_priv *da7213 = snd_soc_component_get_drvdata(component);
|
||||
int ret;
|
||||
|
||||
mutex_lock(&da7213->ctrl_lock);
|
||||
ret = snd_soc_put_enum_double(kcontrol, ucontrol);
|
||||
mutex_unlock(&da7213->ctrl_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* ALC */
|
||||
static int da7213_get_alc_data(struct snd_soc_component *component, u8 reg_val)
|
||||
{
|
||||
int mid_data, top_data;
|
||||
|
@ -376,6 +452,64 @@ static int da7213_put_alc_sw(struct snd_kcontrol *kcontrol,
|
|||
return snd_soc_put_volsw(kcontrol, ucontrol);
|
||||
}
|
||||
|
||||
/* ToneGen */
|
||||
static int da7213_tonegen_freq_get(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
|
||||
struct da7213_priv *da7213 = snd_soc_component_get_drvdata(component);
|
||||
struct soc_mixer_control *mixer_ctrl =
|
||||
(struct soc_mixer_control *) kcontrol->private_value;
|
||||
unsigned int reg = mixer_ctrl->reg;
|
||||
__le16 val;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&da7213->ctrl_lock);
|
||||
ret = regmap_raw_read(da7213->regmap, reg, &val, sizeof(val));
|
||||
mutex_unlock(&da7213->ctrl_lock);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* Frequency value spans two 8-bit registers, lower then upper byte.
|
||||
* Therefore we need to convert to host endianness here.
|
||||
*/
|
||||
ucontrol->value.integer.value[0] = le16_to_cpu(val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int da7213_tonegen_freq_put(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
|
||||
struct da7213_priv *da7213 = snd_soc_component_get_drvdata(component);
|
||||
struct soc_mixer_control *mixer_ctrl =
|
||||
(struct soc_mixer_control *) kcontrol->private_value;
|
||||
unsigned int reg = mixer_ctrl->reg;
|
||||
__le16 val_new, val_old;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Frequency value spans two 8-bit registers, lower then upper byte.
|
||||
* Therefore we need to convert to little endian here to align with
|
||||
* HW registers.
|
||||
*/
|
||||
val_new = cpu_to_le16(ucontrol->value.integer.value[0]);
|
||||
|
||||
mutex_lock(&da7213->ctrl_lock);
|
||||
ret = regmap_raw_read(da7213->regmap, reg, &val_old, sizeof(val_old));
|
||||
if (ret == 0 && (val_old != val_new))
|
||||
ret = regmap_raw_write(da7213->regmap, reg,
|
||||
&val_new, sizeof(val_new));
|
||||
mutex_unlock(&da7213->ctrl_lock);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return val_old != val_new;
|
||||
}
|
||||
|
||||
/*
|
||||
* KControls
|
||||
|
@ -477,6 +611,37 @@ static const struct snd_kcontrol_new da7213_snd_controls[] = {
|
|||
SOC_DOUBLE_R("Headphone ZC Switch", DA7213_HP_L_CTRL, DA7213_HP_R_CTRL,
|
||||
DA7213_ZC_EN_SHIFT, DA7213_ZC_EN_MAX, DA7213_NO_INVERT),
|
||||
|
||||
/* Tone Generator */
|
||||
SOC_SINGLE_EXT_TLV("ToneGen Volume", DA7213_TONE_GEN_CFG2,
|
||||
DA7213_TONE_GEN_GAIN_SHIFT, DA7213_TONE_GEN_GAIN_MAX,
|
||||
DA7213_NO_INVERT, da7213_volsw_locked_get,
|
||||
da7213_volsw_locked_put, da7213_tonegen_gain_tlv),
|
||||
SOC_ENUM_EXT("ToneGen DTMF Key", da7213_tonegen_dtmf_key,
|
||||
da7213_enum_locked_get, da7213_enum_locked_put),
|
||||
SOC_SINGLE_EXT("ToneGen DTMF Switch", DA7213_TONE_GEN_CFG1,
|
||||
DA7213_DTMF_EN_SHIFT, DA7213_SWITCH_EN_MAX,
|
||||
DA7213_NO_INVERT, da7213_volsw_locked_get,
|
||||
da7213_volsw_locked_put),
|
||||
SOC_SINGLE_EXT("ToneGen Start", DA7213_TONE_GEN_CFG1,
|
||||
DA7213_START_STOPN_SHIFT, DA7213_SWITCH_EN_MAX,
|
||||
DA7213_NO_INVERT, da7213_volsw_locked_get,
|
||||
da7213_volsw_locked_put),
|
||||
SOC_ENUM_EXT("ToneGen Sinewave Gen Type", da7213_tonegen_swg_sel,
|
||||
da7213_enum_locked_get, da7213_enum_locked_put),
|
||||
SOC_SINGLE_EXT("ToneGen Sinewave1 Freq", DA7213_TONE_GEN_FREQ1_L,
|
||||
DA7213_FREQ1_L_SHIFT, DA7213_FREQ_MAX, DA7213_NO_INVERT,
|
||||
da7213_tonegen_freq_get, da7213_tonegen_freq_put),
|
||||
SOC_SINGLE_EXT("ToneGen Sinewave2 Freq", DA7213_TONE_GEN_FREQ2_L,
|
||||
DA7213_FREQ2_L_SHIFT, DA7213_FREQ_MAX, DA7213_NO_INVERT,
|
||||
da7213_tonegen_freq_get, da7213_tonegen_freq_put),
|
||||
SOC_SINGLE_EXT("ToneGen On Time", DA7213_TONE_GEN_ON_PER,
|
||||
DA7213_BEEP_ON_PER_SHIFT, DA7213_BEEP_ON_OFF_MAX,
|
||||
DA7213_NO_INVERT, da7213_volsw_locked_get,
|
||||
da7213_volsw_locked_put),
|
||||
SOC_SINGLE("ToneGen Off Time", DA7213_TONE_GEN_OFF_PER,
|
||||
DA7213_BEEP_OFF_PER_SHIFT, DA7213_BEEP_ON_OFF_MAX,
|
||||
DA7213_NO_INVERT),
|
||||
|
||||
/* Gain Ramping controls */
|
||||
SOC_DOUBLE_R("Aux Gain Ramping Switch", DA7213_AUX_L_CTRL,
|
||||
DA7213_AUX_R_CTRL, DA7213_GAIN_RAMP_EN_SHIFT,
|
||||
|
@ -765,7 +930,7 @@ static int da7213_dai_event(struct snd_soc_dapm_widget *w,
|
|||
/* Check SRM has locked */
|
||||
do {
|
||||
pll_status = snd_soc_component_read(component, DA7213_PLL_STATUS);
|
||||
if (pll_status & DA7219_PLL_SRM_LOCK) {
|
||||
if (pll_status & DA7213_PLL_SRM_LOCK) {
|
||||
srm_lock = true;
|
||||
} else {
|
||||
++i;
|
||||
|
@ -1949,6 +2114,9 @@ static int da7213_probe(struct snd_soc_component *component)
|
|||
da7213->fixed_clk_auto_pll = true;
|
||||
}
|
||||
|
||||
/* Default infinite tone gen, start/stop by Kcontrol */
|
||||
snd_soc_component_write(component, DA7213_TONE_GEN_CYCLES, DA7213_BEEP_CYCLES_MASK);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2096,4 +2264,5 @@ module_i2c_driver(da7213_i2c_driver);
|
|||
|
||||
MODULE_DESCRIPTION("ASoC DA7213 Codec driver");
|
||||
MODULE_AUTHOR("Adam Thomson <Adam.Thomson.Opensource@diasemi.com>");
|
||||
MODULE_AUTHOR("David Rau <David.Rau.opensource@dm.renesas.com>");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
* Copyright (c) 2013 Dialog Semiconductor
|
||||
*
|
||||
* Author: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
|
||||
* Author: David Rau <David.Rau.opensource@dm.renesas.com>
|
||||
*/
|
||||
|
||||
#ifndef _DA7213_H
|
||||
|
@ -135,13 +136,24 @@
|
|||
#define DA7213_DAC_NG_ON_THRESHOLD 0xB1
|
||||
#define DA7213_DAC_NG_CTRL 0xB2
|
||||
|
||||
#define DA7213_TONE_GEN_CFG1 0xB4
|
||||
#define DA7213_TONE_GEN_CFG2 0xB5
|
||||
#define DA7213_TONE_GEN_CYCLES 0xB6
|
||||
#define DA7213_TONE_GEN_FREQ1_L 0xB7
|
||||
#define DA7213_TONE_GEN_FREQ1_U 0xB8
|
||||
#define DA7213_TONE_GEN_FREQ2_L 0xB9
|
||||
#define DA7213_TONE_GEN_FREQ2_U 0xBA
|
||||
#define DA7213_TONE_GEN_ON_PER 0xBB
|
||||
#define DA7213_TONE_GEN_OFF_PER 0xBC
|
||||
|
||||
/*
|
||||
* Bit fields
|
||||
*/
|
||||
|
||||
#define DA7213_SWITCH_EN_MAX 0x1
|
||||
|
||||
/* DA7213_PLL_STATUS = 0x03 */
|
||||
#define DA7219_PLL_SRM_LOCK (0x1 << 1)
|
||||
#define DA7213_PLL_SRM_LOCK (0x1 << 1)
|
||||
|
||||
/* DA7213_SR = 0x22 */
|
||||
#define DA7213_SR_8000 (0x1 << 0)
|
||||
|
@ -484,6 +496,55 @@
|
|||
#define DA7213_DAC_NG_EN_SHIFT 7
|
||||
#define DA7213_DAC_NG_EN_MAX 0x1
|
||||
|
||||
/* DA7213_TONE_GEN_CFG1 = 0xB4 */
|
||||
#define DA7213_DTMF_REG_SHIFT 0
|
||||
#define DA7213_DTMF_REG_MASK (0xF << 0)
|
||||
#define DA7213_DTMF_REG_MAX 16
|
||||
#define DA7213_DTMF_EN_SHIFT 4
|
||||
#define DA7213_DTMF_EN_MASK (0x1 << 4)
|
||||
#define DA7213_START_STOPN_SHIFT 7
|
||||
#define DA7213_START_STOPN_MASK (0x1 << 7)
|
||||
|
||||
/* DA7213_TONE_GEN_CFG2 = 0xB5 */
|
||||
#define DA7213_SWG_SEL_SHIFT 0
|
||||
#define DA7213_SWG_SEL_MASK (0x3 << 0)
|
||||
#define DA7213_SWG_SEL_MAX 4
|
||||
#define DA7213_SWG_SEL_SRAMP (0x3 << 0)
|
||||
#define DA7213_TONE_GEN_GAIN_SHIFT 4
|
||||
#define DA7213_TONE_GEN_GAIN_MASK (0xF << 4)
|
||||
#define DA7213_TONE_GEN_GAIN_MAX 0xF
|
||||
#define DA7213_TONE_GEN_GAIN_MINUS_9DB (0x3 << 4)
|
||||
#define DA7213_TONE_GEN_GAIN_MINUS_15DB (0x5 << 4)
|
||||
|
||||
/* DA7213_TONE_GEN_CYCLES = 0xB6 */
|
||||
#define DA7213_BEEP_CYCLES_SHIFT 0
|
||||
#define DA7213_BEEP_CYCLES_MASK (0x7 << 0)
|
||||
|
||||
/* DA7213_TONE_GEN_FREQ1_L = 0xB7 */
|
||||
#define DA7213_FREQ1_L_SHIFT 0
|
||||
#define DA7213_FREQ1_L_MASK (0xFF << 0)
|
||||
#define DA7213_FREQ_MAX 0xFFFF
|
||||
|
||||
/* DA7213_TONE_GEN_FREQ1_U = 0xB8 */
|
||||
#define DA7213_FREQ1_U_SHIFT 0
|
||||
#define DA7213_FREQ1_U_MASK (0xFF << 0)
|
||||
|
||||
/* DA7213_TONE_GEN_FREQ2_L = 0xB9 */
|
||||
#define DA7213_FREQ2_L_SHIFT 0
|
||||
#define DA7213_FREQ2_L_MASK (0xFF << 0)
|
||||
|
||||
/* DA7213_TONE_GEN_FREQ2_U = 0xBA */
|
||||
#define DA7213_FREQ2_U_SHIFT 0
|
||||
#define DA7213_FREQ2_U_MASK (0xFF << 0)
|
||||
|
||||
/* DA7213_TONE_GEN_ON_PER = 0xBB */
|
||||
#define DA7213_BEEP_ON_PER_SHIFT 0
|
||||
#define DA7213_BEEP_ON_PER_MASK (0x3F << 0)
|
||||
#define DA7213_BEEP_ON_OFF_MAX 0x3F
|
||||
|
||||
/* DA7213_TONE_GEN_OFF_PER = 0xBC */
|
||||
#define DA7213_BEEP_OFF_PER_SHIFT 0
|
||||
#define DA7213_BEEP_OFF_PER_MASK (0x3F << 0)
|
||||
|
||||
/*
|
||||
* General defines
|
||||
|
@ -534,6 +595,7 @@ enum da7213_supplies {
|
|||
/* Codec private data */
|
||||
struct da7213_priv {
|
||||
struct regmap *regmap;
|
||||
struct mutex ctrl_lock;
|
||||
struct regulator_bulk_data supplies[DA7213_NUM_SUPPLIES];
|
||||
struct clk *mclk;
|
||||
unsigned int mclk_rate;
|
||||
|
|
Loading…
Add table
Reference in a new issue