#ifdef CONFIG_SND_HDA_POWER_SAVE
/* define this option here to hide as static */
-static int power_save = 10;
+static int power_save = CONFIG_SND_HDA_POWER_SAVE_DEFAULT;
module_param(power_save, int, 0644);
MODULE_PARM_DESC(power_save, "Automatic power-saving timeout "
"(in second, 0 = disable).");
unsigned int parm;
parm = snd_hda_param_read(codec, nid, AC_PAR_NODE_COUNT);
+ if (parm == -1)
+ return 0;
*start_id = (parm >> 16) & 0x7fff;
return (int)(parm & 0x7fff);
}
static void init_hda_cache(struct hda_cache_rec *cache,
unsigned int record_size);
-static inline void free_hda_cache(struct hda_cache_rec *cache);
+static void free_hda_cache(struct hda_cache_rec *cache);
/*
* codec destructor
snd_hda_get_codec_name(codec, bus->card->mixername,
sizeof(bus->card->mixername));
-#ifdef CONFIG_SND_HDA_GENERIC
if (is_generic_config(codec)) {
err = snd_hda_parse_generic_codec(codec);
goto patched;
}
-#endif
if (codec->preset && codec->preset->patch) {
err = codec->preset->patch(codec);
goto patched;
}
/* call the default parser */
-#ifdef CONFIG_SND_HDA_GENERIC
err = snd_hda_parse_generic_codec(codec);
-#else
- printk(KERN_ERR "hda-codec: No codec parser is available\n");
- err = -ENODEV;
-#endif
+ if (err < 0)
+ printk(KERN_ERR "hda-codec: No codec parser is available\n");
patched:
if (err < 0) {
cache->record_size = record_size;
}
-static inline void free_hda_cache(struct hda_cache_rec *cache)
+static void free_hda_cache(struct hda_cache_rec *cache)
{
kfree(cache->buffer);
}
nid = codec->start_nid;
for (i = 0; i < codec->num_nodes; i++, nid++) {
- if (get_wcaps(codec, nid) & AC_WCAP_POWER)
+ unsigned int wcaps = get_wcaps(codec, nid);
+ if (wcaps & AC_WCAP_POWER) {
+ unsigned int wid_type = (wcaps & AC_WCAP_TYPE) >>
+ AC_WCAP_TYPE_SHIFT;
+ if (wid_type == AC_WID_PIN) {
+ unsigned int pincap;
+ /*
+ * don't power down the widget if it controls
+ * eapd and EAPD_BTLENABLE is set.
+ */
+ pincap = snd_hda_param_read(codec, nid,
+ AC_PAR_PIN_CAP);
+ if (pincap & AC_PINCAP_EAPD) {
+ int eapd = snd_hda_codec_read(codec,
+ nid, 0,
+ AC_VERB_GET_EAPD_BTLENABLE, 0);
+ eapd &= 0x02;
+ if (power_state == AC_PWRST_D3 && eapd)
+ continue;
+ }
+ }
snd_hda_codec_write(codec, nid, 0,
AC_VERB_SET_POWER_STATE,
power_state);
+ }
}
if (power_state == AC_PWRST_D0) {
struct hda_codec *codec =
container_of(work, struct hda_codec, power_work.work);
- if (!codec->power_on || codec->power_count)
+ if (!codec->power_on || codec->power_count) {
+ codec->power_transition = 0;
return;
+ }
hda_call_codec_suspend(codec);
if (codec->bus->ops.pm_notify)
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
uinfo->count = 1;
uinfo->value.enumerated.items = imux->num_items;
+ if (!imux->num_items)
+ return 0;
index = uinfo->value.enumerated.item;
if (index >= imux->num_items)
index = imux->num_items - 1;
{
unsigned int idx;
+ if (!imux->num_items)
+ return 0;
idx = ucontrol->value.enumerated.item[0];
if (idx >= imux->num_items)
idx = imux->num_items - 1;
/* front */
snd_hda_codec_setup_stream(codec, nids[HDA_FRONT], stream_tag,
0, format);
- if (mout->hp_nid && mout->hp_nid != nids[HDA_FRONT])
+ if (!mout->no_share_stream &&
+ mout->hp_nid && mout->hp_nid != nids[HDA_FRONT])
/* headphone out will just decode front left/right (stereo) */
snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag,
0, format);
/* extra outputs copied from front */
for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++)
- if (mout->extra_out_nid[i])
+ if (!mout->no_share_stream && mout->extra_out_nid[i])
snd_hda_codec_setup_stream(codec,
mout->extra_out_nid[i],
stream_tag, 0, format);
if (chs >= (i + 1) * 2) /* independent out */
snd_hda_codec_setup_stream(codec, nids[i], stream_tag,
i * 2, format);
- else /* copy front */
+ else if (!mout->no_share_stream) /* copy front */
snd_hda_codec_setup_stream(codec, nids[i], stream_tag,
0, format);
}
return 0;
}
-#ifndef CONFIG_SND_HDA_POWER_SAVE
/**
* snd_hda_resume - resume the codecs
* @bus: the HDA bus
struct hda_codec *codec;
list_for_each_entry(codec, &bus->codec_list, list) {
- hda_call_codec_resume(codec);
+ if (snd_hda_codec_needs_resume(codec))
+ hda_call_codec_resume(codec);
}
return 0;
}
-#endif /* !CONFIG_SND_HDA_POWER_SAVE */
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+int snd_hda_codecs_inuse(struct hda_bus *bus)
+{
+ struct hda_codec *codec;
+ list_for_each_entry(codec, &bus->codec_list, list) {
+ if (snd_hda_codec_needs_resume(codec))
+ return 1;
+ }
+ return 0;
+}
+#endif
#endif