mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 22:21:40 +00:00
ASoC: max9867: shutdown codec when changing filter type
Changing filter type without disabling codec results in filter malfunction. Disable codec when changing filter type. Signed-off-by: Pavel Dobias <dobias@2n.cz> Link: https://lore.kernel.org/r/20200827102528.29677-1-dobias@2n.cz Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
parent
f7660445c8
commit
a11ffbbac9
@ -15,6 +15,14 @@
|
||||
#include <sound/tlv.h>
|
||||
#include "max9867.h"
|
||||
|
||||
struct max9867_priv {
|
||||
struct regmap *regmap;
|
||||
const struct snd_pcm_hw_constraint_list *constraints;
|
||||
unsigned int sysclk, pclk;
|
||||
bool master, dsp_a;
|
||||
unsigned int adc_dac_active;
|
||||
};
|
||||
|
||||
static const char *const max9867_spmode[] = {
|
||||
"Stereo Diff", "Mono Diff",
|
||||
"Stereo Cap", "Mono Cap",
|
||||
@ -32,8 +40,102 @@ static const char *const max9867_adc_dac_filter_text[] = {
|
||||
"Butterworth/8-24"
|
||||
};
|
||||
|
||||
static SOC_ENUM_SINGLE_DECL(max9867_filter, MAX9867_CODECFLTR, 7,
|
||||
max9867_filter_text);
|
||||
enum max9867_adc_dac {
|
||||
MAX9867_ADC_LEFT,
|
||||
MAX9867_ADC_RIGHT,
|
||||
MAX9867_DAC_LEFT,
|
||||
MAX9867_DAC_RIGHT,
|
||||
};
|
||||
|
||||
static int max9867_adc_dac_event(struct snd_soc_dapm_widget *w,
|
||||
struct snd_kcontrol *kcontrol, int event)
|
||||
{
|
||||
struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
|
||||
struct max9867_priv *max9867 = snd_soc_component_get_drvdata(component);
|
||||
enum max9867_adc_dac adc_dac;
|
||||
|
||||
if (!strcmp(w->name, "ADCL"))
|
||||
adc_dac = MAX9867_ADC_LEFT;
|
||||
else if (!strcmp(w->name, "ADCR"))
|
||||
adc_dac = MAX9867_ADC_RIGHT;
|
||||
else if (!strcmp(w->name, "DACL"))
|
||||
adc_dac = MAX9867_DAC_LEFT;
|
||||
else if (!strcmp(w->name, "DACR"))
|
||||
adc_dac = MAX9867_DAC_RIGHT;
|
||||
else
|
||||
return 0;
|
||||
|
||||
if (SND_SOC_DAPM_EVENT_ON(event))
|
||||
max9867->adc_dac_active |= BIT(adc_dac);
|
||||
else if (SND_SOC_DAPM_EVENT_OFF(event))
|
||||
max9867->adc_dac_active &= ~BIT(adc_dac);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int max9867_filter_get(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
|
||||
struct max9867_priv *max9867 = snd_soc_component_get_drvdata(component);
|
||||
unsigned int reg;
|
||||
int ret;
|
||||
|
||||
ret = regmap_read(max9867->regmap, MAX9867_CODECFLTR, ®);
|
||||
if (ret)
|
||||
return -EINVAL;
|
||||
|
||||
if (reg & MAX9867_CODECFLTR_MODE)
|
||||
ucontrol->value.enumerated.item[0] = 1;
|
||||
else
|
||||
ucontrol->value.enumerated.item[0] = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int max9867_filter_set(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
|
||||
struct max9867_priv *max9867 = snd_soc_component_get_drvdata(component);
|
||||
unsigned int reg, mode = ucontrol->value.enumerated.item[0];
|
||||
int ret;
|
||||
|
||||
if (mode > 1)
|
||||
return -EINVAL;
|
||||
|
||||
/* don't allow change if ADC/DAC active */
|
||||
if (max9867->adc_dac_active)
|
||||
return -EBUSY;
|
||||
|
||||
/* read current filter mode */
|
||||
ret = regmap_read(max9867->regmap, MAX9867_CODECFLTR, ®);
|
||||
if (ret)
|
||||
return -EINVAL;
|
||||
|
||||
if (mode)
|
||||
mode = MAX9867_CODECFLTR_MODE;
|
||||
|
||||
/* check if change is needed */
|
||||
if ((reg & MAX9867_CODECFLTR_MODE) == mode)
|
||||
return 0;
|
||||
|
||||
/* shutdown codec before switching filter mode */
|
||||
regmap_update_bits(max9867->regmap, MAX9867_PWRMAN,
|
||||
MAX9867_PWRMAN_SHDN, 0);
|
||||
|
||||
/* switch filter mode */
|
||||
regmap_update_bits(max9867->regmap, MAX9867_CODECFLTR,
|
||||
MAX9867_CODECFLTR_MODE, mode);
|
||||
|
||||
/* out of shutdown now */
|
||||
regmap_update_bits(max9867->regmap, MAX9867_PWRMAN,
|
||||
MAX9867_PWRMAN_SHDN, MAX9867_PWRMAN_SHDN);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static SOC_ENUM_SINGLE_EXT_DECL(max9867_filter, max9867_filter_text);
|
||||
static SOC_ENUM_SINGLE_DECL(max9867_dac_filter, MAX9867_CODECFLTR, 0,
|
||||
max9867_adc_dac_filter_text);
|
||||
static SOC_ENUM_SINGLE_DECL(max9867_adc_filter, MAX9867_CODECFLTR, 4,
|
||||
@ -76,7 +178,7 @@ static const struct snd_kcontrol_new max9867_snd_controls[] = {
|
||||
SOC_ENUM("Speaker Mode", max9867_spkmode),
|
||||
SOC_SINGLE("Volume Smoothing Switch", MAX9867_MODECONFIG, 6, 1, 0),
|
||||
SOC_SINGLE("Line ZC Switch", MAX9867_MODECONFIG, 5, 1, 0),
|
||||
SOC_ENUM("DSP Filter", max9867_filter),
|
||||
SOC_ENUM_EXT("DSP Filter", max9867_filter, max9867_filter_get, max9867_filter_set),
|
||||
SOC_ENUM("ADC Filter", max9867_adc_filter),
|
||||
SOC_ENUM("DAC Filter", max9867_dac_filter),
|
||||
SOC_SINGLE("Mono Playback Switch", MAX9867_IFC1B, 3, 1, 0),
|
||||
@ -134,8 +236,12 @@ static const struct snd_soc_dapm_widget max9867_dapm_widgets[] = {
|
||||
&max9867_left_dmic_mux),
|
||||
SND_SOC_DAPM_MUX("DMICR Mux", SND_SOC_NOPM, 0, 0,
|
||||
&max9867_right_dmic_mux),
|
||||
SND_SOC_DAPM_ADC("ADCL", "HiFi Capture", SND_SOC_NOPM, 0, 0),
|
||||
SND_SOC_DAPM_ADC("ADCR", "HiFi Capture", SND_SOC_NOPM, 0, 0),
|
||||
SND_SOC_DAPM_ADC_E("ADCL", "HiFi Capture", SND_SOC_NOPM, 0, 0,
|
||||
max9867_adc_dac_event,
|
||||
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
|
||||
SND_SOC_DAPM_ADC_E("ADCR", "HiFi Capture", SND_SOC_NOPM, 0, 0,
|
||||
max9867_adc_dac_event,
|
||||
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
|
||||
|
||||
SND_SOC_DAPM_MIXER("Digital", SND_SOC_NOPM, 0, 0,
|
||||
max9867_sidetone_mixer_controls,
|
||||
@ -143,8 +249,12 @@ static const struct snd_soc_dapm_widget max9867_dapm_widgets[] = {
|
||||
SND_SOC_DAPM_MIXER_NAMED_CTL("Output Mixer", SND_SOC_NOPM, 0, 0,
|
||||
max9867_output_mixer_controls,
|
||||
ARRAY_SIZE(max9867_output_mixer_controls)),
|
||||
SND_SOC_DAPM_DAC("DACL", "HiFi Playback", SND_SOC_NOPM, 0, 0),
|
||||
SND_SOC_DAPM_DAC("DACR", "HiFi Playback", SND_SOC_NOPM, 0, 0),
|
||||
SND_SOC_DAPM_DAC_E("DACL", "HiFi Playback", SND_SOC_NOPM, 0, 0,
|
||||
max9867_adc_dac_event,
|
||||
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
|
||||
SND_SOC_DAPM_DAC_E("DACR", "HiFi Playback", SND_SOC_NOPM, 0, 0,
|
||||
max9867_adc_dac_event,
|
||||
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
|
||||
SND_SOC_DAPM_SWITCH("Master Playback", SND_SOC_NOPM, 0, 0,
|
||||
&max9867_line_out_control),
|
||||
SND_SOC_DAPM_OUTPUT("LOUT"),
|
||||
@ -197,13 +307,6 @@ static const struct snd_pcm_hw_constraint_list max9867_constraints_48k = {
|
||||
.count = ARRAY_SIZE(max9867_rates_48k),
|
||||
};
|
||||
|
||||
struct max9867_priv {
|
||||
struct regmap *regmap;
|
||||
const struct snd_pcm_hw_constraint_list *constraints;
|
||||
unsigned int sysclk, pclk;
|
||||
bool master, dsp_a;
|
||||
};
|
||||
|
||||
static int max9867_startup(struct snd_pcm_substream *substream,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
|
@ -45,6 +45,7 @@
|
||||
#define MAX9867_IFC1B_PCLK_8 0x06
|
||||
#define MAX9867_IFC1B_PCLK_16 0x07
|
||||
#define MAX9867_CODECFLTR 0x0a
|
||||
#define MAX9867_CODECFLTR_MODE (1<<7)
|
||||
#define MAX9867_SIDETONE 0x0b
|
||||
#define MAX9867_DACLEVEL 0x0c
|
||||
#define MAX9867_ADCLEVEL 0x0d
|
||||
@ -58,6 +59,7 @@
|
||||
#define MAX9867_MICCONFIG 0x15
|
||||
#define MAX9867_MODECONFIG 0x16
|
||||
#define MAX9867_PWRMAN 0x17
|
||||
#define MAX9867_PWRMAN_SHDN (1<<7)
|
||||
#define MAX9867_REVISION 0xff
|
||||
|
||||
#define MAX9867_CACHEREGNUM 10
|
||||
|
Loading…
Reference in New Issue
Block a user