summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/sound/hdaudio.h28
-rw-r--r--sound/hda/hdac_device.c16
-rw-r--r--sound/hda/hdac_regmap.c8
-rw-r--r--sound/pci/hda/hda_codec.c8
-rw-r--r--sound/pci/hda/hda_codec.h2
-rw-r--r--sound/pci/hda/patch_ca0132.c12
-rw-r--r--sound/pci/hda/patch_hdmi.c4
7 files changed, 53 insertions, 25 deletions
diff --git a/include/sound/hdaudio.h b/include/sound/hdaudio.h
index 95acc33..30446f1 100644
--- a/include/sound/hdaudio.h
+++ b/include/sound/hdaudio.h
@@ -144,6 +144,34 @@ static inline void snd_hdac_power_up(struct hdac_device *codec) {}
static inline void snd_hdac_power_down(struct hdac_device *codec) {}
#endif
+/**
+ * snd_hdac_power_up_pm - power up the codec
+ * @codec: the codec object
+ *
+ * This function can be called in a recursive code path like init code
+ * which may be called by PM suspend/resume again. OTOH, if a power-up
+ * call must wake up the sleeper (e.g. in a kctl callback), use
+ * snd_hdac_power_up() instead.
+ */
+static inline void snd_hdac_power_up_pm(struct hdac_device *codec)
+{
+ if (!atomic_read(&codec->in_pm))
+ snd_hdac_power_up(codec);
+}
+
+/**
+ * snd_hdac_power_down_pm - power down the codec
+ * @codec: the codec object
+ *
+ * Like snd_hdac_power_up_pm(), this function is used in a recursive
+ * code path like init code which may be called by PM suspend/resume again.
+ */
+static inline void snd_hdac_power_down_pm(struct hdac_device *codec)
+{
+ if (!atomic_read(&codec->in_pm))
+ snd_hdac_power_down(codec);
+}
+
/*
* HD-audio codec base driver
*/
diff --git a/sound/hda/hdac_device.c b/sound/hda/hdac_device.c
index d4a0e72..92604bb 100644
--- a/sound/hda/hdac_device.c
+++ b/sound/hda/hdac_device.c
@@ -494,29 +494,27 @@ EXPORT_SYMBOL_GPL(snd_hdac_get_connections);
#ifdef CONFIG_PM
/**
- * snd_hdac_power_up - increment the runtime pm counter
+ * snd_hdac_power_up - power up the codec
* @codec: the codec object
+ *
+ * This function calls the runtime PM helper to power up the given codec.
+ * Unlike snd_hdac_power_up_pm(), you should call this only for the code
+ * path that isn't included in PM path. Otherwise it gets stuck.
*/
void snd_hdac_power_up(struct hdac_device *codec)
{
- struct device *dev = &codec->dev;
-
- if (atomic_read(&codec->in_pm))
- return;
- pm_runtime_get_sync(dev);
+ pm_runtime_get_sync(&codec->dev);
}
EXPORT_SYMBOL_GPL(snd_hdac_power_up);
/**
- * snd_hdac_power_up - decrement the runtime pm counter
+ * snd_hdac_power_down - power down the codec
* @codec: the codec object
*/
void snd_hdac_power_down(struct hdac_device *codec)
{
struct device *dev = &codec->dev;
- if (atomic_read(&codec->in_pm))
- return;
pm_runtime_mark_last_busy(dev);
pm_runtime_put_autosuspend(dev);
}
diff --git a/sound/hda/hdac_regmap.c b/sound/hda/hdac_regmap.c
index 1eb4320..64876fa 100644
--- a/sound/hda/hdac_regmap.c
+++ b/sound/hda/hdac_regmap.c
@@ -402,9 +402,9 @@ int snd_hdac_regmap_write_raw(struct hdac_device *codec, unsigned int reg,
err = reg_raw_write(codec, reg, val);
if (err == -EAGAIN) {
- snd_hdac_power_up(codec);
+ snd_hdac_power_up_pm(codec);
err = reg_raw_write(codec, reg, val);
- snd_hdac_power_down(codec);
+ snd_hdac_power_down_pm(codec);
}
return err;
}
@@ -434,9 +434,9 @@ int snd_hdac_regmap_read_raw(struct hdac_device *codec, unsigned int reg,
err = reg_raw_read(codec, reg, val);
if (err == -EAGAIN) {
- snd_hdac_power_up(codec);
+ snd_hdac_power_up_pm(codec);
err = reg_raw_read(codec, reg, val);
- snd_hdac_power_down(codec);
+ snd_hdac_power_down_pm(codec);
}
return err;
}
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 16dfa1e..e70a7fb 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -137,7 +137,7 @@ static int codec_exec_verb(struct hdac_device *dev, unsigned int cmd,
return -1;
again:
- snd_hda_power_up(codec);
+ snd_hda_power_up_pm(codec);
mutex_lock(&bus->core.cmd_mutex);
if (flags & HDA_RW_NO_RESPONSE_FALLBACK)
bus->no_response_fallback = 1;
@@ -145,7 +145,7 @@ static int codec_exec_verb(struct hdac_device *dev, unsigned int cmd,
cmd, res);
bus->no_response_fallback = 0;
mutex_unlock(&bus->core.cmd_mutex);
- snd_hda_power_down(codec);
+ snd_hda_power_down_pm(codec);
if (!codec_in_pm(codec) && res && err < 0 && bus->rirb_error) {
if (bus->response_reset) {
codec_dbg(codec,
@@ -3951,7 +3951,7 @@ int snd_hda_check_amp_list_power(struct hda_codec *codec,
if (!(v & HDA_AMP_MUTE) && v > 0) {
if (!check->power_on) {
check->power_on = 1;
- snd_hda_power_up(codec);
+ snd_hda_power_up_pm(codec);
}
return 1;
}
@@ -3959,7 +3959,7 @@ int snd_hda_check_amp_list_power(struct hda_codec *codec,
}
if (check->power_on) {
check->power_on = 0;
- snd_hda_power_down(codec);
+ snd_hda_power_down_pm(codec);
}
return 0;
}
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
index acf868c..9075ac2 100644
--- a/sound/pci/hda/hda_codec.h
+++ b/sound/pci/hda/hda_codec.h
@@ -508,7 +508,9 @@ const char *snd_hda_get_jack_location(u32 cfg);
* power saving
*/
#define snd_hda_power_up(codec) snd_hdac_power_up(&(codec)->core)
+#define snd_hda_power_up_pm(codec) snd_hdac_power_up_pm(&(codec)->core)
#define snd_hda_power_down(codec) snd_hdac_power_down(&(codec)->core)
+#define snd_hda_power_down_pm(codec) snd_hdac_power_down_pm(&(codec)->core)
#ifdef CONFIG_PM
void snd_hda_set_power_save(struct hda_bus *bus, int delay);
void snd_hda_update_power_acct(struct hda_codec *codec);
diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c
index 5aff35a..4a4e7b2 100644
--- a/sound/pci/hda/patch_ca0132.c
+++ b/sound/pci/hda/patch_ca0132.c
@@ -3131,7 +3131,7 @@ static int ca0132_select_out(struct hda_codec *codec)
codec_dbg(codec, "ca0132_select_out\n");
- snd_hda_power_up(codec);
+ snd_hda_power_up_pm(codec);
auto_jack = spec->vnode_lswitch[VNID_HP_ASEL - VNODE_START_NID];
@@ -3215,7 +3215,7 @@ static int ca0132_select_out(struct hda_codec *codec)
}
exit:
- snd_hda_power_down(codec);
+ snd_hda_power_down_pm(codec);
return err < 0 ? err : 0;
}
@@ -3293,7 +3293,7 @@ static int ca0132_select_mic(struct hda_codec *codec)
codec_dbg(codec, "ca0132_select_mic\n");
- snd_hda_power_up(codec);
+ snd_hda_power_up_pm(codec);
auto_jack = spec->vnode_lswitch[VNID_AMIC1_ASEL - VNODE_START_NID];
@@ -3326,7 +3326,7 @@ static int ca0132_select_mic(struct hda_codec *codec)
ca0132_effects_set(codec, VOICE_FOCUS, 0);
}
- snd_hda_power_down(codec);
+ snd_hda_power_down_pm(codec);
return 0;
}
@@ -4546,7 +4546,7 @@ static int ca0132_init(struct hda_codec *codec)
spec->dsp_state = DSP_DOWNLOAD_INIT;
spec->curr_chip_addx = INVALID_CHIP_ADDRESS;
- snd_hda_power_up(codec);
+ snd_hda_power_up_pm(codec);
ca0132_init_unsol(codec);
@@ -4577,7 +4577,7 @@ static int ca0132_init(struct hda_codec *codec)
snd_hda_jack_report_sync(codec);
- snd_hda_power_down(codec);
+ snd_hda_power_down_pm(codec);
return 0;
}
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index ca0c05e..5f44f60 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -1545,7 +1545,7 @@ static bool hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll)
bool eld_changed = false;
bool ret;
- snd_hda_power_up(codec);
+ snd_hda_power_up_pm(codec);
present = snd_hda_pin_sense(codec, pin_nid);
mutex_lock(&per_pin->lock);
@@ -1631,7 +1631,7 @@ static bool hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll)
jack->block_report = !ret;
mutex_unlock(&per_pin->lock);
- snd_hda_power_down(codec);
+ snd_hda_power_down_pm(codec);
return ret;
}