Does this patch make sense ? It adds two functions to rawmidi.c: snd_rawmidi_suspend() and snd_rawmidi_resume() and it adds a new ops callback. Those functions pause or restart the tasklet respectively and call the driver's ops->power(down/up) function. This patch also prevents driver's ops-> functions from being called while the card is supended. (tested ok with the Gina 3G) diff -dupr alsa-kernel__orig/core/rawmidi.c alsa-kernel/core/rawmidi.c --- alsa-kernel__orig/core/rawmidi.c 2006-05-17 23:17:58.000000000 +0200 +++ alsa-kernel/core/rawmidi.c 2006-05-31 23:47:16.000000000 +0200 @@ -155,17 +155,28 @@ static int snd_rawmidi_runtime_free(stru static inline void snd_rawmidi_output_trigger(struct snd_rawmidi_substream *substream,int up) { - if (up) { - tasklet_hi_schedule(&substream->runtime->tasklet); - } else { - tasklet_kill(&substream->runtime->tasklet); - substream->ops->trigger(substream, 0); + struct snd_card *card = substream->rmidi->card; + + snd_power_lock(card); + if (snd_power_wait(card, SNDRV_CTL_POWER_D0) >= 0) { + if (up) { + tasklet_hi_schedule(&substream->runtime->tasklet); + } else { + tasklet_kill(&substream->runtime->tasklet); + substream->ops->trigger(substream, 0); + } } + snd_power_unlock(card); } static void snd_rawmidi_input_trigger(struct snd_rawmidi_substream *substream, int up) { - substream->ops->trigger(substream, up); + struct snd_card *card = substream->rmidi->card; + + snd_power_lock(card); + if (snd_power_wait(card, SNDRV_CTL_POWER_D0) >= 0) + substream->ops->trigger(substream, up); + snd_power_unlock(card); if (!up && substream->runtime->event) tasklet_kill(&substream->runtime->tasklet); } @@ -204,9 +215,14 @@ int snd_rawmidi_drain_output(struct snd_ runtime->drain = 0; if (err != -ERESTARTSYS) { /* we need wait a while to make sure that Tx FIFOs are empty */ - if (substream->ops->drain) - substream->ops->drain(substream); - else + if (substream->ops->drain) { + struct snd_card *card = substream->rmidi->card; + + snd_power_lock(card); + if (snd_power_wait(card, SNDRV_CTL_POWER_D0) >= 0) + substream->ops->drain(substream); + snd_power_unlock(card); + } else msleep(50); snd_rawmidi_drop_output(substream); } @@ -1648,6 +1664,59 @@ void snd_rawmidi_set_ops(struct snd_rawm } } + +#ifdef CONFIG_PM + +/** + * snd_rawmidi_suspend + * @substream: the rawmidi substream + * + * Suspend the given substream. + */ +int snd_rawmidi_suspend(struct snd_rawmidi_substream *substream) +{ + int err; + struct snd_card *card = substream->rmidi->card; + +snd_printk("snd_rawmidi_suspend\n"); + err = 0; + snd_power_lock(card); + tasklet_disable(&substream->runtime->tasklet); + if (substream->ops->power) + err = substream->ops->power(substream, 0); + snd_power_unlock(card); + return err; +} + +EXPORT_SYMBOL(snd_rawmidi_suspend); + + +/** + * snd_rawmidi_resume + * @substream: the rawmidi substream + * + * Resume the given substream. + */ +int snd_rawmidi_resume(struct snd_rawmidi_substream *substream) +{ + int err; + struct snd_card *card = substream->rmidi->card; + +snd_printk("snd_rawmidi_resume\n"); + err = 0; + snd_power_lock(card); + if (substream->ops->power) + err = substream->ops->power(substream, 1); + tasklet_enable(&substream->runtime->tasklet); + snd_power_unlock(card); + return err; +} + +EXPORT_SYMBOL(snd_rawmidi_resume); + +#endif /* CONFIG_PM */ + + /* * ENTRY functions */ diff -dupr alsa-kernel__orig/include/rawmidi.h alsa-kernel/include/rawmidi.h --- alsa-kernel__orig/include/rawmidi.h 2006-05-17 23:17:58.000000000 +0200 +++ alsa-kernel/include/rawmidi.h 2006-05-28 19:57:49.000000000 +0200 @@ -53,6 +53,7 @@ struct snd_rawmidi_ops { int (*close) (struct snd_rawmidi_substream * substream); void (*trigger) (struct snd_rawmidi_substream * substream, int up); void (*drain) (struct snd_rawmidi_substream * substream); + int (*power) (struct snd_rawmidi_substream * substream, int state); }; struct snd_rawmidi_global_ops { @@ -182,5 +183,7 @@ long snd_rawmidi_kernel_read(struct snd_ unsigned char *buf, long count); long snd_rawmidi_kernel_write(struct snd_rawmidi_substream *substream, const unsigned char *buf, long count); +int snd_rawmidi_suspend(struct snd_rawmidi_substream *substream); +int snd_rawmidi_resume(struct snd_rawmidi_substream *substream); #endif /* __SOUND_RAWMIDI_H */ -- Giuliano. _______________________________________________ Alsa-devel mailing list Alsa-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.sourceforge.net/lists/listinfo/alsa-devel