ASoC: nau8825: add programmable biquad filter control

Add programmable biquad filter configuration control for user space.
The filter is configurable for low pass filters, high pass filters,
Notch filter, etc in the ADC and DAC path.

Signed-off-by: John Hsu <KCHSU0@nuvoton.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
John Hsu 2016-05-31 11:57:41 +08:00 committed by Mark Brown
parent ffd72505b0
commit 18d8306d7e
2 changed files with 61 additions and 0 deletions

View File

@ -217,6 +217,7 @@ static bool nau8825_volatile_reg(struct device *dev, unsigned int reg)
case NAU8825_REG_SARDOUT_RAM_STATUS:
case NAU8825_REG_CHARGE_PUMP_INPUT_READ:
case NAU8825_REG_GENERAL_STATUS:
case NAU8825_REG_BIQ_CTRL ... NAU8825_REG_BIQ_COF10:
return true;
default:
return false;
@ -293,6 +294,54 @@ static int nau8825_output_dac_event(struct snd_soc_dapm_widget *w,
return 0;
}
static int nau8825_biq_coeff_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
struct soc_bytes_ext *params = (void *)kcontrol->private_value;
if (!component->regmap)
return -EINVAL;
regmap_raw_read(component->regmap, NAU8825_REG_BIQ_COF1,
ucontrol->value.bytes.data, params->max);
return 0;
}
static int nau8825_biq_coeff_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
struct soc_bytes_ext *params = (void *)kcontrol->private_value;
void *data;
if (!component->regmap)
return -EINVAL;
data = kmemdup(ucontrol->value.bytes.data,
params->max, GFP_KERNEL | GFP_DMA);
if (!data)
return -ENOMEM;
regmap_update_bits(component->regmap, NAU8825_REG_BIQ_CTRL,
NAU8825_BIQ_WRT_EN, 0);
regmap_raw_write(component->regmap, NAU8825_REG_BIQ_COF1,
data, params->max);
regmap_update_bits(component->regmap, NAU8825_REG_BIQ_CTRL,
NAU8825_BIQ_WRT_EN, NAU8825_BIQ_WRT_EN);
kfree(data);
return 0;
}
static const char * const nau8825_biq_path[] = {
"ADC", "DAC"
};
static const struct soc_enum nau8825_biq_path_enum =
SOC_ENUM_SINGLE(NAU8825_REG_BIQ_CTRL, NAU8825_BIQ_PATH_SFT,
ARRAY_SIZE(nau8825_biq_path), nau8825_biq_path);
static const char * const nau8825_adc_decimation[] = {
"32", "64", "128", "256"
};
@ -329,6 +378,10 @@ static const struct snd_kcontrol_new nau8825_controls[] = {
SOC_ENUM("ADC Decimation Rate", nau8825_adc_decimation_enum),
SOC_ENUM("DAC Oversampling Rate", nau8825_dac_oversampl_enum),
/* programmable biquad filter */
SOC_ENUM("BIQ Path Select", nau8825_biq_path_enum),
SND_SOC_BYTES_EXT("BIQ Coefficeints", 20,
nau8825_biq_coeff_get, nau8825_biq_coeff_put),
};
/* DAC Mux 0x33[9] and 0x34[9] */

View File

@ -231,6 +231,14 @@
#define NAU8825_I2S_MS_MASTER (1 << NAU8825_I2S_MS_SFT)
#define NAU8825_I2S_MS_SLAVE (0 << NAU8825_I2S_MS_SFT)
/* BIQ_CTRL (0x20) */
#define NAU8825_BIQ_WRT_SFT 4
#define NAU8825_BIQ_WRT_EN (1 << NAU8825_BIQ_WRT_SFT)
#define NAU8825_BIQ_PATH_SFT 0
#define NAU8825_BIQ_PATH_MASK (1 << NAU8825_BIQ_PATH_SFT)
#define NAU8825_BIQ_PATH_ADC (0 << NAU8825_BIQ_PATH_SFT)
#define NAU8825_BIQ_PATH_DAC (1 << NAU8825_BIQ_PATH_SFT)
/* ADC_RATE (0x2b) */
#define NAU8825_ADC_SYNC_DOWN_SFT 0
#define NAU8825_ADC_SYNC_DOWN_MASK 0x3