summaryrefslogtreecommitdiff
path: root/sound/soc/codecs/wm8962.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/codecs/wm8962.c')
-rw-r--r--sound/soc/codecs/wm8962.c111
1 files changed, 68 insertions, 43 deletions
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c
index 68ea15be7330..e9e317ce6898 100644
--- a/sound/soc/codecs/wm8962.c
+++ b/sound/soc/codecs/wm8962.c
@@ -82,6 +82,7 @@ struct wm8962_priv {
#endif
int irq;
+ bool master_flag;
};
/* We can't use the same notifier block for more than one supply and
@@ -1544,7 +1545,7 @@ static int wm8962_dsp2_ena_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
int shift = kcontrol->private_value;
- struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
+ struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
struct wm8962_priv *wm8962 = snd_soc_component_get_drvdata(component);
ucontrol->value.integer.value[0] = !!(wm8962->dsp2_ena & 1 << shift);
@@ -1556,7 +1557,7 @@ static int wm8962_dsp2_ena_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
int shift = kcontrol->private_value;
- struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
+ struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
struct wm8962_priv *wm8962 = snd_soc_component_get_drvdata(component);
int old = wm8962->dsp2_ena;
int ret = 0;
@@ -1594,7 +1595,7 @@ out:
static int wm8962_put_hp_sw(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
+ struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
int ret;
/* Apply the update (if any) */
@@ -1624,7 +1625,7 @@ static int wm8962_put_hp_sw(struct snd_kcontrol *kcontrol,
static int wm8962_put_spk_sw(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
+ struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
int ret;
/* Apply the update (if any) */
@@ -1854,10 +1855,10 @@ static int tp_event(struct snd_soc_dapm_widget *w,
reg = WM8962_ADDITIONAL_CONTROL_4;
- if (!strcmp(w->name, "TEMP_HP")) {
+ if (!snd_soc_dapm_widget_name_cmp(w, "TEMP_HP")) {
mask = WM8962_TEMP_ENA_HP_MASK;
val = WM8962_TEMP_ENA_HP;
- } else if (!strcmp(w->name, "TEMP_SPK")) {
+ } else if (!snd_soc_dapm_widget_name_cmp(w, "TEMP_SPK")) {
mask = WM8962_TEMP_ENA_SPK_MASK;
val = WM8962_TEMP_ENA_SPK;
} else {
@@ -2229,6 +2230,9 @@ SND_SOC_DAPM_PGA_E("HPOUT", SND_SOC_NOPM, 0, 0, NULL, 0, hp_event,
SND_SOC_DAPM_OUTPUT("HPOUTL"),
SND_SOC_DAPM_OUTPUT("HPOUTR"),
+
+SND_SOC_DAPM_PGA("SPKOUTL Output", WM8962_CLASS_D_CONTROL_1, 6, 0, NULL, 0),
+SND_SOC_DAPM_PGA("SPKOUTR Output", WM8962_CLASS_D_CONTROL_1, 7, 0, NULL, 0),
};
static const struct snd_soc_dapm_widget wm8962_dapm_spk_mono_widgets[] = {
@@ -2236,7 +2240,6 @@ SND_SOC_DAPM_MIXER("Speaker Mixer", WM8962_MIXER_ENABLES, 1, 0,
spkmixl, ARRAY_SIZE(spkmixl)),
SND_SOC_DAPM_MUX_E("Speaker PGA", WM8962_PWR_MGMT_2, 4, 0, &spkoutl_mux,
out_pga_event, SND_SOC_DAPM_POST_PMU),
-SND_SOC_DAPM_PGA("Speaker Output", WM8962_CLASS_D_CONTROL_1, 7, 0, NULL, 0),
SND_SOC_DAPM_OUTPUT("SPKOUT"),
};
@@ -2251,9 +2254,6 @@ SND_SOC_DAPM_MUX_E("SPKOUTL PGA", WM8962_PWR_MGMT_2, 4, 0, &spkoutl_mux,
SND_SOC_DAPM_MUX_E("SPKOUTR PGA", WM8962_PWR_MGMT_2, 3, 0, &spkoutr_mux,
out_pga_event, SND_SOC_DAPM_POST_PMU),
-SND_SOC_DAPM_PGA("SPKOUTR Output", WM8962_CLASS_D_CONTROL_1, 7, 0, NULL, 0),
-SND_SOC_DAPM_PGA("SPKOUTL Output", WM8962_CLASS_D_CONTROL_1, 6, 0, NULL, 0),
-
SND_SOC_DAPM_OUTPUT("SPKOUTL"),
SND_SOC_DAPM_OUTPUT("SPKOUTR"),
};
@@ -2366,12 +2366,18 @@ static const struct snd_soc_dapm_route wm8962_spk_mono_intercon[] = {
{ "Speaker PGA", "Mixer", "Speaker Mixer" },
{ "Speaker PGA", "DAC", "DACL" },
- { "Speaker Output", NULL, "Speaker PGA" },
- { "Speaker Output", NULL, "SYSCLK" },
- { "Speaker Output", NULL, "TOCLK" },
- { "Speaker Output", NULL, "TEMP_SPK" },
+ { "SPKOUTL Output", NULL, "Speaker PGA" },
+ { "SPKOUTL Output", NULL, "SYSCLK" },
+ { "SPKOUTL Output", NULL, "TOCLK" },
+ { "SPKOUTL Output", NULL, "TEMP_SPK" },
- { "SPKOUT", NULL, "Speaker Output" },
+ { "SPKOUTR Output", NULL, "Speaker PGA" },
+ { "SPKOUTR Output", NULL, "SYSCLK" },
+ { "SPKOUTR Output", NULL, "TOCLK" },
+ { "SPKOUTR Output", NULL, "TEMP_SPK" },
+
+ { "SPKOUT", NULL, "SPKOUTL Output" },
+ { "SPKOUT", NULL, "SPKOUTR Output" },
};
static const struct snd_soc_dapm_route wm8962_spk_stereo_intercon[] = {
@@ -2413,7 +2419,7 @@ static int wm8962_add_widgets(struct snd_soc_component *component)
{
struct wm8962_priv *wm8962 = snd_soc_component_get_drvdata(component);
struct wm8962_pdata *pdata = &wm8962->pdata;
- struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
+ struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component);
snd_soc_add_component_controls(component, wm8962_snd_controls,
ARRAY_SIZE(wm8962_snd_controls));
@@ -2460,6 +2466,7 @@ static const int sysclk_rates[] = {
static void wm8962_configure_bclk(struct snd_soc_component *component)
{
+ struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component);
struct wm8962_priv *wm8962 = snd_soc_component_get_drvdata(component);
int best, min_diff, diff;
int dspclk, i;
@@ -2499,7 +2506,7 @@ static void wm8962_configure_bclk(struct snd_soc_component *component)
* So we here provisionally enable it and then disable it afterward
* if current bias_level hasn't reached SND_SOC_BIAS_ON.
*/
- if (snd_soc_component_get_bias_level(component) != SND_SOC_BIAS_ON)
+ if (snd_soc_dapm_get_bias_level(dapm) != SND_SOC_BIAS_ON)
snd_soc_component_update_bits(component, WM8962_CLOCKING2,
WM8962_SYSCLK_ENA_MASK, WM8962_SYSCLK_ENA);
@@ -2513,7 +2520,7 @@ static void wm8962_configure_bclk(struct snd_soc_component *component)
usleep_range(500, 1000);
dspclk = snd_soc_component_read(component, WM8962_CLOCKING1);
- if (snd_soc_component_get_bias_level(component) != SND_SOC_BIAS_ON)
+ if (snd_soc_dapm_get_bias_level(dapm) != SND_SOC_BIAS_ON)
snd_soc_component_update_bits(component, WM8962_CLOCKING2,
WM8962_SYSCLK_ENA_MASK, 0);
@@ -2573,6 +2580,8 @@ static void wm8962_configure_bclk(struct snd_soc_component *component)
static int wm8962_set_bias_level(struct snd_soc_component *component,
enum snd_soc_bias_level level)
{
+ struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component);
+
switch (level) {
case SND_SOC_BIAS_ON:
break;
@@ -2590,7 +2599,7 @@ static int wm8962_set_bias_level(struct snd_soc_component *component,
snd_soc_component_update_bits(component, WM8962_PWR_MGMT_1,
WM8962_VMID_SEL_MASK, 0x100);
- if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF)
+ if (snd_soc_dapm_get_bias_level(dapm) == SND_SOC_BIAS_OFF)
msleep(100);
break;
@@ -2623,6 +2632,7 @@ static int wm8962_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_component *component = dai->component;
+ struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component);
struct wm8962_priv *wm8962 = snd_soc_component_get_drvdata(component);
int i;
int aif0 = 0;
@@ -2673,7 +2683,7 @@ static int wm8962_hw_params(struct snd_pcm_substream *substream,
dev_dbg(component->dev, "hw_params set BCLK %dHz LRCLK %dHz\n",
wm8962->bclk, wm8962->lrclk);
- if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_ON)
+ if (snd_soc_dapm_get_bias_level(dapm) == SND_SOC_BIAS_ON)
wm8962_configure_bclk(component);
return 0;
@@ -2710,6 +2720,7 @@ static int wm8962_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id,
static int wm8962_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
{
struct snd_soc_component *component = dai->component;
+ struct wm8962_priv *wm8962 = snd_soc_component_get_drvdata(component);
int aif0 = 0;
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
@@ -2756,11 +2767,13 @@ static int wm8962_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
return -EINVAL;
}
+ wm8962->master_flag = false;
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
- case SND_SOC_DAIFMT_CBM_CFM:
+ case SND_SOC_DAIFMT_CBP_CFP:
aif0 |= WM8962_MSTR;
+ wm8962->master_flag = true;
break;
- case SND_SOC_DAIFMT_CBS_CFS:
+ case SND_SOC_DAIFMT_CBC_CFC:
break;
default:
return -EINVAL;
@@ -2881,7 +2894,7 @@ static int wm8962_set_fll(struct snd_soc_component *component, int fll_id, int s
{
struct wm8962_priv *wm8962 = snd_soc_component_get_drvdata(component);
struct _fll_div fll_div;
- unsigned long timeout;
+ unsigned long time_left;
int ret;
int fll1 = 0;
@@ -2914,8 +2927,12 @@ static int wm8962_set_fll(struct snd_soc_component *component, int fll_id, int s
switch (fll_id) {
case WM8962_FLL_MCLK:
case WM8962_FLL_BCLK:
+ fll1 |= (fll_id - 1) << WM8962_FLL_REFCLK_SRC_SHIFT;
+ break;
case WM8962_FLL_OSC:
fll1 |= (fll_id - 1) << WM8962_FLL_REFCLK_SRC_SHIFT;
+ snd_soc_component_update_bits(component, WM8962_PLL2,
+ WM8962_OSC_ENA, WM8962_OSC_ENA);
break;
case WM8962_FLL_INT:
snd_soc_component_update_bits(component, WM8962_FLL_CONTROL_1,
@@ -2924,7 +2941,7 @@ static int wm8962_set_fll(struct snd_soc_component *component, int fll_id, int s
WM8962_FLL_FRC_NCO, WM8962_FLL_FRC_NCO);
break;
default:
- dev_err(component->dev, "Unknown FLL source %d\n", ret);
+ dev_err(component->dev, "Unknown FLL source %d\n", source);
return -EINVAL;
}
@@ -2965,14 +2982,14 @@ static int wm8962_set_fll(struct snd_soc_component *component, int fll_id, int s
* higher if we'll error out
*/
if (wm8962->irq)
- timeout = msecs_to_jiffies(5);
+ time_left = msecs_to_jiffies(5);
else
- timeout = msecs_to_jiffies(1);
+ time_left = msecs_to_jiffies(1);
- timeout = wait_for_completion_timeout(&wm8962->fll_lock,
- timeout);
+ time_left = wait_for_completion_timeout(&wm8962->fll_lock,
+ time_left);
- if (timeout == 0 && wm8962->irq) {
+ if (time_left == 0 && wm8962->irq) {
dev_err(component->dev, "FLL lock timed out");
snd_soc_component_update_bits(component, WM8962_FLL_CONTROL_1,
WM8962_FLL_ENA, 0);
@@ -3180,7 +3197,7 @@ static irqreturn_t wm8962_irq(int irq, void *data)
int wm8962_mic_detect(struct snd_soc_component *component, struct snd_soc_jack *jack)
{
struct wm8962_priv *wm8962 = snd_soc_component_get_drvdata(component);
- struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
+ struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component);
int irq_mask, enable;
wm8962->jack = jack;
@@ -3226,7 +3243,7 @@ static void wm8962_beep_work(struct work_struct *work)
struct wm8962_priv *wm8962 =
container_of(work, struct wm8962_priv, beep_work);
struct snd_soc_component *component = wm8962->component;
- struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
+ struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component);
int i;
int reg = 0;
int best = 0;
@@ -3398,13 +3415,16 @@ static int wm8962_gpio_request(struct gpio_chip *chip, unsigned offset)
return 0;
}
-static void wm8962_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+static int wm8962_gpio_set(struct gpio_chip *chip, unsigned int offset,
+ int value)
{
struct wm8962_priv *wm8962 = gpiochip_get_data(chip);
struct snd_soc_component *component = wm8962->component;
- snd_soc_component_update_bits(component, WM8962_GPIO_BASE + offset,
- WM8962_GP2_LVL, !!value << WM8962_GP2_LVL_SHIFT);
+ return snd_soc_component_update_bits(component,
+ WM8962_GPIO_BASE + offset,
+ WM8962_GP2_LVL,
+ !!value << WM8962_GP2_LVL_SHIFT);
}
static int wm8962_gpio_direction_out(struct gpio_chip *chip,
@@ -3472,7 +3492,7 @@ static void wm8962_free_gpio(struct snd_soc_component *component)
static int wm8962_probe(struct snd_soc_component *component)
{
- struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
+ struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component);
int ret;
struct wm8962_priv *wm8962 = snd_soc_component_get_drvdata(component);
int i;
@@ -3527,7 +3547,7 @@ static int wm8962_probe(struct snd_soc_component *component)
}
if (!dmicclk || !dmicdat) {
dev_dbg(component->dev, "DMIC not in use, disabling\n");
- snd_soc_dapm_nc_pin(dapm, "DMICDAT");
+ snd_soc_dapm_disable_pin(dapm, "DMICDAT");
}
if (dmicclk != dmicdat)
dev_warn(component->dev, "DMIC GPIOs partially configured\n");
@@ -3573,7 +3593,7 @@ static const struct regmap_config wm8962_regmap = {
.num_reg_defaults = ARRAY_SIZE(wm8962_reg),
.volatile_reg = wm8962_volatile_register,
.readable_reg = wm8962_readable_register,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
};
static int wm8962_set_pdata_from_of(struct i2c_client *i2c,
@@ -3841,7 +3861,6 @@ static void wm8962_i2c_remove(struct i2c_client *client)
pm_runtime_disable(&client->dev);
}
-#ifdef CONFIG_PM
static int wm8962_runtime_resume(struct device *dev)
{
struct wm8962_priv *wm8962 = dev_get_drvdata(dev);
@@ -3892,6 +3911,9 @@ static int wm8962_runtime_resume(struct device *dev)
WM8962_BIAS_ENA | WM8962_VMID_SEL_MASK,
WM8962_BIAS_ENA | 0x180);
+ if (wm8962->master_flag)
+ regmap_update_bits(wm8962->regmap, WM8962_AUDIO_INTERFACE_0,
+ WM8962_MSTR, WM8962_MSTR);
msleep(5);
return 0;
@@ -3905,6 +3927,10 @@ static int wm8962_runtime_suspend(struct device *dev)
{
struct wm8962_priv *wm8962 = dev_get_drvdata(dev);
+ if (wm8962->master_flag)
+ regmap_update_bits(wm8962->regmap, WM8962_AUDIO_INTERFACE_0,
+ WM8962_MSTR, 0);
+
regmap_update_bits(wm8962->regmap, WM8962_PWR_MGMT_1,
WM8962_VMID_SEL_MASK | WM8962_BIAS_ENA, 0);
@@ -3921,15 +3947,14 @@ static int wm8962_runtime_suspend(struct device *dev)
return 0;
}
-#endif
static const struct dev_pm_ops wm8962_pm = {
- SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume)
- SET_RUNTIME_PM_OPS(wm8962_runtime_suspend, wm8962_runtime_resume, NULL)
+ SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume)
+ RUNTIME_PM_OPS(wm8962_runtime_suspend, wm8962_runtime_resume, NULL)
};
static const struct i2c_device_id wm8962_i2c_id[] = {
- { "wm8962", 0 },
+ { "wm8962" },
{ }
};
MODULE_DEVICE_TABLE(i2c, wm8962_i2c_id);
@@ -3944,7 +3969,7 @@ static struct i2c_driver wm8962_i2c_driver = {
.driver = {
.name = "wm8962",
.of_match_table = wm8962_of_match,
- .pm = &wm8962_pm,
+ .pm = pm_ptr(&wm8962_pm),
},
.probe = wm8962_i2c_probe,
.remove = wm8962_i2c_remove,