[RFC] rawmidi suspend/resume support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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

[Index of Archives]     [ALSA User]     [Linux Audio Users]     [Kernel Archive]     [Asterisk PBX]     [Photo Sharing]     [Linux Sound]     [Video 4 Linux]     [Gimp]     [Yosemite News]

  Powered by Linux