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
return;
#ifdef CONFIG_SND_HDA_POWER_SAVE
cancel_delayed_work(&codec->power_work);
+ flush_scheduled_work();
#endif
list_del(&codec->list);
codec->bus->caddr_tbl[codec->addr] = NULL;
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);
}
#ifdef CONFIG_SND_HDA_POWER_SAVE
cancel_delayed_work(&codec->power_work);
codec->power_on = 0;
+ codec->power_transition = 0;
#endif
}
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)
void snd_hda_power_up(struct hda_codec *codec)
{
codec->power_count++;
- if (codec->power_on)
+ if (codec->power_on || codec->power_transition)
return;
codec->power_on = 1;
codec->bus->ops.pm_notify(codec);
hda_call_codec_resume(codec);
cancel_delayed_work(&codec->power_work);
+ codec->power_transition = 0;
}
void snd_hda_power_down(struct hda_codec *codec)
{
--codec->power_count;
- if (!codec->power_on)
+ if (!codec->power_on || codec->power_count || codec->power_transition)
return;
- if (power_save)
+ if (power_save) {
+ codec->power_transition = 1; /* avoid reentrance */
schedule_delayed_work(&codec->power_work,
msecs_to_jiffies(power_save * 1000));
+ }
}
int snd_hda_check_amp_list_power(struct hda_codec *codec,
struct hda_codec *codec;
list_for_each_entry(codec, &bus->codec_list, list) {
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+ if (!codec->power_on)
+ continue;
+#endif
hda_call_codec_suspend(codec);
}
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