Commit 78cfca32 authored by Mark Brown's avatar Mark Brown

Merge remote-tracking branches 'asoc/fix/arizona', 'asoc/fix/cs35l32',...

Merge remote-tracking branches 'asoc/fix/arizona', 'asoc/fix/cs35l32', 'asoc/fix/hdac', 'asoc/fix/nau8825' and 'asoc/fix/rt5616' into asoc-linus
...@@ -629,6 +629,7 @@ config SND_SOC_RT5514 ...@@ -629,6 +629,7 @@ config SND_SOC_RT5514
config SND_SOC_RT5616 config SND_SOC_RT5616
tristate "Realtek RT5616 CODEC" tristate "Realtek RT5616 CODEC"
depends on I2C
config SND_SOC_RT5631 config SND_SOC_RT5631
tristate "Realtek ALC5631/RT5631 CODEC" tristate "Realtek ALC5631/RT5631 CODEC"
......
...@@ -249,6 +249,18 @@ int arizona_init_spk(struct snd_soc_codec *codec) ...@@ -249,6 +249,18 @@ int arizona_init_spk(struct snd_soc_codec *codec)
} }
EXPORT_SYMBOL_GPL(arizona_init_spk); EXPORT_SYMBOL_GPL(arizona_init_spk);
int arizona_free_spk(struct snd_soc_codec *codec)
{
struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
struct arizona *arizona = priv->arizona;
arizona_free_irq(arizona, ARIZONA_IRQ_SPK_OVERHEAT_WARN, arizona);
arizona_free_irq(arizona, ARIZONA_IRQ_SPK_OVERHEAT, arizona);
return 0;
}
EXPORT_SYMBOL_GPL(arizona_free_spk);
static const struct snd_soc_dapm_route arizona_mono_routes[] = { static const struct snd_soc_dapm_route arizona_mono_routes[] = {
{ "OUT1R", NULL, "OUT1L" }, { "OUT1R", NULL, "OUT1L" },
{ "OUT2R", NULL, "OUT2L" }, { "OUT2R", NULL, "OUT2L" },
......
...@@ -307,6 +307,8 @@ extern int arizona_init_spk(struct snd_soc_codec *codec); ...@@ -307,6 +307,8 @@ extern int arizona_init_spk(struct snd_soc_codec *codec);
extern int arizona_init_gpio(struct snd_soc_codec *codec); extern int arizona_init_gpio(struct snd_soc_codec *codec);
extern int arizona_init_mono(struct snd_soc_codec *codec); extern int arizona_init_mono(struct snd_soc_codec *codec);
extern int arizona_free_spk(struct snd_soc_codec *codec);
extern int arizona_init_dai(struct arizona_priv *priv, int dai); extern int arizona_init_dai(struct arizona_priv *priv, int dai);
int arizona_set_output_mode(struct snd_soc_codec *codec, int output, int arizona_set_output_mode(struct snd_soc_codec *codec, int output,
......
...@@ -274,7 +274,9 @@ static int cs35l32_handle_of_data(struct i2c_client *i2c_client, ...@@ -274,7 +274,9 @@ static int cs35l32_handle_of_data(struct i2c_client *i2c_client,
if (of_property_read_u32(np, "cirrus,sdout-share", &val) >= 0) if (of_property_read_u32(np, "cirrus,sdout-share", &val) >= 0)
pdata->sdout_share = val; pdata->sdout_share = val;
of_property_read_u32(np, "cirrus,boost-manager", &val); if (of_property_read_u32(np, "cirrus,boost-manager", &val))
val = -1u;
switch (val) { switch (val) {
case CS35L32_BOOST_MGR_AUTO: case CS35L32_BOOST_MGR_AUTO:
case CS35L32_BOOST_MGR_AUTO_AUDIO: case CS35L32_BOOST_MGR_AUTO_AUDIO:
...@@ -282,13 +284,15 @@ static int cs35l32_handle_of_data(struct i2c_client *i2c_client, ...@@ -282,13 +284,15 @@ static int cs35l32_handle_of_data(struct i2c_client *i2c_client,
case CS35L32_BOOST_MGR_FIXED: case CS35L32_BOOST_MGR_FIXED:
pdata->boost_mng = val; pdata->boost_mng = val;
break; break;
case -1u:
default: default:
dev_err(&i2c_client->dev, dev_err(&i2c_client->dev,
"Wrong cirrus,boost-manager DT value %d\n", val); "Wrong cirrus,boost-manager DT value %d\n", val);
pdata->boost_mng = CS35L32_BOOST_MGR_BYPASS; pdata->boost_mng = CS35L32_BOOST_MGR_BYPASS;
} }
of_property_read_u32(np, "cirrus,sdout-datacfg", &val); if (of_property_read_u32(np, "cirrus,sdout-datacfg", &val))
val = -1u;
switch (val) { switch (val) {
case CS35L32_DATA_CFG_LR_VP: case CS35L32_DATA_CFG_LR_VP:
case CS35L32_DATA_CFG_LR_STAT: case CS35L32_DATA_CFG_LR_STAT:
...@@ -296,13 +300,15 @@ static int cs35l32_handle_of_data(struct i2c_client *i2c_client, ...@@ -296,13 +300,15 @@ static int cs35l32_handle_of_data(struct i2c_client *i2c_client,
case CS35L32_DATA_CFG_LR_VPSTAT: case CS35L32_DATA_CFG_LR_VPSTAT:
pdata->sdout_datacfg = val; pdata->sdout_datacfg = val;
break; break;
case -1u:
default: default:
dev_err(&i2c_client->dev, dev_err(&i2c_client->dev,
"Wrong cirrus,sdout-datacfg DT value %d\n", val); "Wrong cirrus,sdout-datacfg DT value %d\n", val);
pdata->sdout_datacfg = CS35L32_DATA_CFG_LR; pdata->sdout_datacfg = CS35L32_DATA_CFG_LR;
} }
of_property_read_u32(np, "cirrus,battery-threshold", &val); if (of_property_read_u32(np, "cirrus,battery-threshold", &val))
val = -1u;
switch (val) { switch (val) {
case CS35L32_BATT_THRESH_3_1V: case CS35L32_BATT_THRESH_3_1V:
case CS35L32_BATT_THRESH_3_2V: case CS35L32_BATT_THRESH_3_2V:
...@@ -310,13 +316,15 @@ static int cs35l32_handle_of_data(struct i2c_client *i2c_client, ...@@ -310,13 +316,15 @@ static int cs35l32_handle_of_data(struct i2c_client *i2c_client,
case CS35L32_BATT_THRESH_3_4V: case CS35L32_BATT_THRESH_3_4V:
pdata->batt_thresh = val; pdata->batt_thresh = val;
break; break;
case -1u:
default: default:
dev_err(&i2c_client->dev, dev_err(&i2c_client->dev,
"Wrong cirrus,battery-threshold DT value %d\n", val); "Wrong cirrus,battery-threshold DT value %d\n", val);
pdata->batt_thresh = CS35L32_BATT_THRESH_3_3V; pdata->batt_thresh = CS35L32_BATT_THRESH_3_3V;
} }
of_property_read_u32(np, "cirrus,battery-recovery", &val); if (of_property_read_u32(np, "cirrus,battery-recovery", &val))
val = -1u;
switch (val) { switch (val) {
case CS35L32_BATT_RECOV_3_1V: case CS35L32_BATT_RECOV_3_1V:
case CS35L32_BATT_RECOV_3_2V: case CS35L32_BATT_RECOV_3_2V:
...@@ -326,6 +334,7 @@ static int cs35l32_handle_of_data(struct i2c_client *i2c_client, ...@@ -326,6 +334,7 @@ static int cs35l32_handle_of_data(struct i2c_client *i2c_client,
case CS35L32_BATT_RECOV_3_6V: case CS35L32_BATT_RECOV_3_6V:
pdata->batt_recov = val; pdata->batt_recov = val;
break; break;
case -1u:
default: default:
dev_err(&i2c_client->dev, dev_err(&i2c_client->dev,
"Wrong cirrus,battery-recovery DT value %d\n", val); "Wrong cirrus,battery-recovery DT value %d\n", val);
......
...@@ -1108,6 +1108,9 @@ static int cs47l24_codec_remove(struct snd_soc_codec *codec) ...@@ -1108,6 +1108,9 @@ static int cs47l24_codec_remove(struct snd_soc_codec *codec)
priv->core.arizona->dapm = NULL; priv->core.arizona->dapm = NULL;
arizona_free_irq(arizona, ARIZONA_IRQ_DSP_IRQ1, priv); arizona_free_irq(arizona, ARIZONA_IRQ_DSP_IRQ1, priv);
arizona_free_spk(codec);
return 0; return 0;
} }
......
...@@ -1420,32 +1420,39 @@ static int hdmi_codec_remove(struct snd_soc_codec *codec) ...@@ -1420,32 +1420,39 @@ static int hdmi_codec_remove(struct snd_soc_codec *codec)
} }
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int hdmi_codec_resume(struct snd_soc_codec *codec) static int hdmi_codec_prepare(struct device *dev)
{ {
struct hdac_ext_device *edev = snd_soc_codec_get_drvdata(codec); struct hdac_ext_device *edev = to_hda_ext_device(dev);
struct hdac_device *hdac = &edev->hdac;
pm_runtime_get_sync(&edev->hdac.dev);
/*
* Power down afg.
* codec_read is preferred over codec_write to set the power state.
* This way verb is send to set the power state and response
* is received. So setting power state is ensured without using loop
* to read the state.
*/
snd_hdac_codec_read(hdac, hdac->afg, 0, AC_VERB_SET_POWER_STATE,
AC_PWRST_D3);
return 0;
}
static void hdmi_codec_complete(struct device *dev)
{
struct hdac_ext_device *edev = to_hda_ext_device(dev);
struct hdac_hdmi_priv *hdmi = edev->private_data; struct hdac_hdmi_priv *hdmi = edev->private_data;
struct hdac_hdmi_pin *pin; struct hdac_hdmi_pin *pin;
struct hdac_device *hdac = &edev->hdac; struct hdac_device *hdac = &edev->hdac;
struct hdac_bus *bus = hdac->bus;
int err;
unsigned long timeout;
hdac_hdmi_skl_enable_all_pins(&edev->hdac);
hdac_hdmi_skl_enable_dp12(&edev->hdac);
/* Power up afg */ /* Power up afg */
if (!snd_hdac_check_power_state(hdac, hdac->afg, AC_PWRST_D0)) { snd_hdac_codec_read(hdac, hdac->afg, 0, AC_VERB_SET_POWER_STATE,
AC_PWRST_D0);
snd_hdac_codec_write(hdac, hdac->afg, 0,
AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
/* Wait till power state is set to D0 */ hdac_hdmi_skl_enable_all_pins(&edev->hdac);
timeout = jiffies + msecs_to_jiffies(1000); hdac_hdmi_skl_enable_dp12(&edev->hdac);
while (!snd_hdac_check_power_state(hdac, hdac->afg, AC_PWRST_D0)
&& time_before(jiffies, timeout)) {
msleep(50);
}
}
/* /*
* As the ELD notify callback request is not entertained while the * As the ELD notify callback request is not entertained while the
...@@ -1455,28 +1462,16 @@ static int hdmi_codec_resume(struct snd_soc_codec *codec) ...@@ -1455,28 +1462,16 @@ static int hdmi_codec_resume(struct snd_soc_codec *codec)
list_for_each_entry(pin, &hdmi->pin_list, head) list_for_each_entry(pin, &hdmi->pin_list, head)
hdac_hdmi_present_sense(pin, 1); hdac_hdmi_present_sense(pin, 1);
/* pm_runtime_put_sync(&edev->hdac.dev);
* Codec power is turned ON during controller resume.
* Turn it OFF here
*/
err = snd_hdac_display_power(bus, false);
if (err < 0) {
dev_err(bus->dev,
"Cannot turn OFF display power on i915, err: %d\n",
err);
return err;
}
return 0;
} }
#else #else
#define hdmi_codec_resume NULL #define hdmi_codec_prepare NULL
#define hdmi_codec_complete NULL
#endif #endif
static struct snd_soc_codec_driver hdmi_hda_codec = { static struct snd_soc_codec_driver hdmi_hda_codec = {
.probe = hdmi_codec_probe, .probe = hdmi_codec_probe,
.remove = hdmi_codec_remove, .remove = hdmi_codec_remove,
.resume = hdmi_codec_resume,
.idle_bias_off = true, .idle_bias_off = true,
}; };
...@@ -1561,7 +1556,6 @@ static int hdac_hdmi_runtime_suspend(struct device *dev) ...@@ -1561,7 +1556,6 @@ static int hdac_hdmi_runtime_suspend(struct device *dev)
struct hdac_ext_device *edev = to_hda_ext_device(dev); struct hdac_ext_device *edev = to_hda_ext_device(dev);
struct hdac_device *hdac = &edev->hdac; struct hdac_device *hdac = &edev->hdac;
struct hdac_bus *bus = hdac->bus; struct hdac_bus *bus = hdac->bus;
unsigned long timeout;
int err; int err;
dev_dbg(dev, "Enter: %s\n", __func__); dev_dbg(dev, "Enter: %s\n", __func__);
...@@ -1570,20 +1564,15 @@ static int hdac_hdmi_runtime_suspend(struct device *dev) ...@@ -1570,20 +1564,15 @@ static int hdac_hdmi_runtime_suspend(struct device *dev)
if (!bus) if (!bus)
return 0; return 0;
/* Power down afg */ /*
if (!snd_hdac_check_power_state(hdac, hdac->afg, AC_PWRST_D3)) { * Power down afg.
snd_hdac_codec_write(hdac, hdac->afg, 0, * codec_read is preferred over codec_write to set the power state.
AC_VERB_SET_POWER_STATE, AC_PWRST_D3); * This way verb is send to set the power state and response
* is received. So setting power state is ensured without using loop
/* Wait till power state is set to D3 */ * to read the state.
timeout = jiffies + msecs_to_jiffies(1000); */
while (!snd_hdac_check_power_state(hdac, hdac->afg, AC_PWRST_D3) snd_hdac_codec_read(hdac, hdac->afg, 0, AC_VERB_SET_POWER_STATE,
&& time_before(jiffies, timeout)) { AC_PWRST_D3);
msleep(50);
}
}
err = snd_hdac_display_power(bus, false); err = snd_hdac_display_power(bus, false);
if (err < 0) { if (err < 0) {
dev_err(bus->dev, "Cannot turn on display power on i915\n"); dev_err(bus->dev, "Cannot turn on display power on i915\n");
...@@ -1616,9 +1605,8 @@ static int hdac_hdmi_runtime_resume(struct device *dev) ...@@ -1616,9 +1605,8 @@ static int hdac_hdmi_runtime_resume(struct device *dev)
hdac_hdmi_skl_enable_dp12(&edev->hdac); hdac_hdmi_skl_enable_dp12(&edev->hdac);
/* Power up afg */ /* Power up afg */
if (!snd_hdac_check_power_state(hdac, hdac->afg, AC_PWRST_D0)) snd_hdac_codec_read(hdac, hdac->afg, 0, AC_VERB_SET_POWER_STATE,
snd_hdac_codec_write(hdac, hdac->afg, 0, AC_PWRST_D0);
AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
return 0; return 0;
} }
...@@ -1629,6 +1617,8 @@ static int hdac_hdmi_runtime_resume(struct device *dev) ...@@ -1629,6 +1617,8 @@ static int hdac_hdmi_runtime_resume(struct device *dev)
static const struct dev_pm_ops hdac_hdmi_pm = { static const struct dev_pm_ops hdac_hdmi_pm = {
SET_RUNTIME_PM_OPS(hdac_hdmi_runtime_suspend, hdac_hdmi_runtime_resume, NULL) SET_RUNTIME_PM_OPS(hdac_hdmi_runtime_suspend, hdac_hdmi_runtime_resume, NULL)
.prepare = hdmi_codec_prepare,
.complete = hdmi_codec_complete,
}; };
static const struct hda_device_id hdmi_list[] = { static const struct hda_device_id hdmi_list[] = {
......
...@@ -343,9 +343,12 @@ static const struct snd_soc_dapm_widget nau8825_dapm_widgets[] = { ...@@ -343,9 +343,12 @@ static const struct snd_soc_dapm_widget nau8825_dapm_widgets[] = {
SND_SOC_DAPM_SUPPLY("ADC Power", NAU8825_REG_ANALOG_ADC_2, 6, 0, NULL, SND_SOC_DAPM_SUPPLY("ADC Power", NAU8825_REG_ANALOG_ADC_2, 6, 0, NULL,
0), 0),
/* ADC for button press detection */ /* ADC for button press detection. A dapm supply widget is used to
SND_SOC_DAPM_ADC("SAR", NULL, NAU8825_REG_SAR_CTRL, * prevent dapm_power_widgets keeping the codec at SND_SOC_BIAS_ON
NAU8825_SAR_ADC_EN_SFT, 0), * during suspend.
*/
SND_SOC_DAPM_SUPPLY("SAR", NAU8825_REG_SAR_CTRL,
NAU8825_SAR_ADC_EN_SFT, 0, NULL, 0),
SND_SOC_DAPM_PGA_S("ADACL", 2, NAU8825_REG_RDAC, 12, 0, NULL, 0), SND_SOC_DAPM_PGA_S("ADACL", 2, NAU8825_REG_RDAC, 12, 0, NULL, 0),
SND_SOC_DAPM_PGA_S("ADACR", 2, NAU8825_REG_RDAC, 13, 0, NULL, 0), SND_SOC_DAPM_PGA_S("ADACR", 2, NAU8825_REG_RDAC, 13, 0, NULL, 0),
...@@ -607,6 +610,16 @@ static bool nau8825_is_jack_inserted(struct regmap *regmap) ...@@ -607,6 +610,16 @@ static bool nau8825_is_jack_inserted(struct regmap *regmap)
static void nau8825_restart_jack_detection(struct regmap *regmap) static void nau8825_restart_jack_detection(struct regmap *regmap)
{ {
/* Chip needs one FSCLK cycle in order to generate interrupts,
* as we cannot guarantee one will be provided by the system. Turning
* master mode on then off enables us to generate that FSCLK cycle
* with a minimum of contention on the clock bus.
*/
regmap_update_bits(regmap, NAU8825_REG_I2S_PCM_CTRL2,
NAU8825_I2S_MS_MASK, NAU8825_I2S_MS_MASTER);
regmap_update_bits(regmap, NAU8825_REG_I2S_PCM_CTRL2,
NAU8825_I2S_MS_MASK, NAU8825_I2S_MS_SLAVE);
/* this will restart the entire jack detection process including MIC/GND /* this will restart the entire jack detection process including MIC/GND
* switching and create interrupts. We have to go from 0 to 1 and back * switching and create interrupts. We have to go from 0 to 1 and back
* to 0 to restart. * to 0 to restart.
...@@ -728,7 +741,10 @@ static irqreturn_t nau8825_interrupt(int irq, void *data) ...@@ -728,7 +741,10 @@ static irqreturn_t nau8825_interrupt(int irq, void *data)
struct regmap *regmap = nau8825->regmap; struct regmap *regmap = nau8825->regmap;
int active_irq, clear_irq = 0, event = 0, event_mask = 0; int active_irq, clear_irq = 0, event = 0, event_mask = 0;
regmap_read(regmap, NAU8825_REG_IRQ_STATUS, &active_irq); if (regmap_read(regmap, NAU8825_REG_IRQ_STATUS, &active_irq)) {
dev_err(nau8825->dev, "failed to read irq status\n");
return IRQ_NONE;
}
if ((active_irq & NAU8825_JACK_EJECTION_IRQ_MASK) == if ((active_irq & NAU8825_JACK_EJECTION_IRQ_MASK) ==
NAU8825_JACK_EJECTION_DETECTED) { NAU8825_JACK_EJECTION_DETECTED) {
...@@ -1141,33 +1157,74 @@ static int nau8825_set_bias_level(struct snd_soc_codec *codec, ...@@ -1141,33 +1157,74 @@ static int nau8825_set_bias_level(struct snd_soc_codec *codec,
return ret; return ret;
} }
} }
ret = regcache_sync(nau8825->regmap);
if (ret) {
dev_err(codec->dev,
"Failed to sync cache: %d\n", ret);
return ret;
}
} }
break; break;
case SND_SOC_BIAS_OFF: case SND_SOC_BIAS_OFF:
if (nau8825->mclk_freq) if (nau8825->mclk_freq)
clk_disable_unprepare(nau8825->mclk); clk_disable_unprepare(nau8825->mclk);
regcache_mark_dirty(nau8825->regmap);
break; break;
} }
return 0; return 0;
} }
#ifdef CONFIG_PM
static int nau8825_suspend(struct snd_soc_codec *codec)
{
struct nau8825 *nau8825 = snd_soc_codec_get_drvdata(codec);
disable_irq(nau8825->irq);
regcache_cache_only(nau8825->regmap, true);
regcache_mark_dirty(nau8825->regmap);
return 0;
}
static int nau8825_resume(struct snd_soc_codec *codec)
{
struct nau8825 *nau8825 = snd_soc_codec_get_drvdata(codec);
/* The chip may lose power and reset in S3. regcache_sync restores
* register values including configurations for sysclk, irq, and
* jack/button detection.
*/
regcache_cache_only(nau8825->regmap, false);
regcache_sync(nau8825->regmap);
/* Check the jack plug status directly. If the headset is unplugged
* during S3 when the chip has no power, there will be no jack
* detection irq even after the nau8825_restart_jack_detection below,
* because the chip just thinks no headset has ever been plugged in.
*/
if (!nau8825_is_jack_inserted(nau8825->regmap)) {
nau8825_eject_jack(nau8825);
snd_soc_jack_report(nau8825->jack, 0, SND_JACK_HEADSET);
}
enable_irq(nau8825->irq);
/* Run jack detection to check the type (OMTP or CTIA) of the headset
* if there is one. This handles the case where a different type of
* headset is plugged in during S3. This triggers an IRQ iff a headset
* is already plugged in.
*/
nau8825_restart_jack_detection(nau8825->regmap);
return 0;
}
#else
#define nau8825_suspend NULL
#define nau8825_resume NULL
#endif
static struct snd_soc_codec_driver nau8825_codec_driver = { static struct snd_soc_codec_driver nau8825_codec_driver = {
.probe = nau8825_codec_probe, .probe = nau8825_codec_probe,
.set_sysclk = nau8825_set_sysclk, .set_sysclk = nau8825_set_sysclk,
.set_pll = nau8825_set_pll, .set_pll = nau8825_set_pll,
.set_bias_level = nau8825_set_bias_level, .set_bias_level = nau8825_set_bias_level,
.suspend_bias_off = true, .suspend_bias_off = true,
.suspend = nau8825_suspend,
.resume = nau8825_resume,
.controls = nau8825_controls, .controls = nau8825_controls,
.num_controls = ARRAY_SIZE(nau8825_controls), .num_controls = ARRAY_SIZE(nau8825_controls),
...@@ -1277,16 +1334,6 @@ static int nau8825_setup_irq(struct nau8825 *nau8825) ...@@ -1277,16 +1334,6 @@ static int nau8825_setup_irq(struct nau8825 *nau8825)
regmap_update_bits(regmap, NAU8825_REG_ENA_CTRL, regmap_update_bits(regmap, NAU8825_REG_ENA_CTRL,
NAU8825_ENABLE_DACR, NAU8825_ENABLE_DACR); NAU8825_ENABLE_DACR, NAU8825_ENABLE_DACR);
/* Chip needs one FSCLK cycle in order to generate interrupts,
* as we cannot guarantee one will be provided by the system. Turning
* master mode on then off enables us to generate that FSCLK cycle
* with a minimum of contention on the clock bus.
*/
regmap_update_bits(regmap, NAU8825_REG_I2S_PCM_CTRL2,
NAU8825_I2S_MS_MASK, NAU8825_I2S_MS_MASTER);
regmap_update_bits(regmap, NAU8825_REG_I2S_PCM_CTRL2,
NAU8825_I2S_MS_MASK, NAU8825_I2S_MS_SLAVE);
ret = devm_request_threaded_irq(nau8825->dev, nau8825->irq, NULL, ret = devm_request_threaded_irq(nau8825->dev, nau8825->irq, NULL,
nau8825_interrupt, IRQF_TRIGGER_LOW | IRQF_ONESHOT, nau8825_interrupt, IRQF_TRIGGER_LOW | IRQF_ONESHOT,
"nau8825", nau8825); "nau8825", nau8825);
...@@ -1354,36 +1401,6 @@ static int nau8825_i2c_remove(struct i2c_client *client) ...@@ -1354,36 +1401,6 @@ static int nau8825_i2c_remove(struct i2c_client *client)
return 0; return 0;
} }
#ifdef CONFIG_PM_SLEEP
static int nau8825_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct nau8825 *nau8825 = dev_get_drvdata(dev);
disable_irq(client->irq);
regcache_cache_only(nau8825->regmap, true);
regcache_mark_dirty(nau8825->regmap);
return 0;
}
static int nau8825_resume(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct nau8825 *nau8825 = dev_get_drvdata(dev);
regcache_cache_only(nau8825->regmap, false);
regcache_sync(nau8825->regmap);
enable_irq(client->irq);
return 0;
}
#endif
static const struct dev_pm_ops nau8825_pm = {
SET_SYSTEM_SLEEP_PM_OPS(nau8825_suspend, nau8825_resume)
};
static const struct i2c_device_id nau8825_i2c_ids[] = { static const struct i2c_device_id nau8825_i2c_ids[] = {
{ "nau8825", 0 }, { "nau8825", 0 },
{ } { }
...@@ -1410,7 +1427,6 @@ static struct i2c_driver nau8825_driver = { ...@@ -1410,7 +1427,6 @@ static struct i2c_driver nau8825_driver = {
.name = "nau8825", .name = "nau8825",
.of_match_table = of_match_ptr(nau8825_of_ids), .of_match_table = of_match_ptr(nau8825_of_ids),
.acpi_match_table = ACPI_PTR(nau8825_acpi_match), .acpi_match_table = ACPI_PTR(nau8825_acpi_match),
.pm = &nau8825_pm,
}, },
.probe = nau8825_i2c_probe, .probe = nau8825_i2c_probe,
.remove = nau8825_i2c_remove, .remove = nau8825_i2c_remove,
......
...@@ -1955,11 +1955,16 @@ static int wm5102_codec_probe(struct snd_soc_codec *codec) ...@@ -1955,11 +1955,16 @@ static int wm5102_codec_probe(struct snd_soc_codec *codec)
static int wm5102_codec_remove(struct snd_soc_codec *codec) static int wm5102_codec_remove(struct snd_soc_codec *codec)
{ {
struct wm5102_priv *priv = snd_soc_codec_get_drvdata(codec); struct wm5102_priv *priv = snd_soc_codec_get_drvdata(codec);
struct arizona *arizona = priv->core.arizona;
wm_adsp2_codec_remove(&priv->core.adsp[0], codec); wm_adsp2_codec_remove(&priv->core.adsp[0], codec);
priv->core.arizona->dapm = NULL; priv->core.arizona->dapm = NULL;
arizona_free_irq(arizona, ARIZONA_IRQ_DSP_IRQ1, priv);
arizona_free_spk(codec);
return 0; return 0;
} }
......
...@@ -2298,6 +2298,8 @@ static int wm5110_codec_remove(struct snd_soc_codec *codec) ...@@ -2298,6 +2298,8 @@ static int wm5110_codec_remove(struct snd_soc_codec *codec)
arizona_free_irq(arizona, ARIZONA_IRQ_DSP_IRQ1, priv); arizona_free_irq(arizona, ARIZONA_IRQ_DSP_IRQ1, priv);
arizona_free_spk(codec);
return 0; return 0;
} }
......
...@@ -1072,6 +1072,8 @@ static int wm8997_codec_remove(struct snd_soc_codec *codec) ...@@ -1072,6 +1072,8 @@ static int wm8997_codec_remove(struct snd_soc_codec *codec)
priv->core.arizona->dapm = NULL; priv->core.arizona->dapm = NULL;
arizona_free_spk(codec);
return 0; return 0;
} }
......
...@@ -1324,6 +1324,8 @@ static int wm8998_codec_remove(struct snd_soc_codec *codec) ...@@ -1324,6 +1324,8 @@ static int wm8998_codec_remove(struct snd_soc_codec *codec)
priv->core.arizona->dapm = NULL; priv->core.arizona->dapm = NULL;
arizona_free_spk(codec);
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment