staging: line6: separate handling of buffer allocation and stream startup
[linux-2.6-block.git] / drivers / staging / line6 / pcm.h
index 47c6d6942b4f9911a1022cd191a2c043a326f875..5210ec8dbe168615a26fe19d14aaefc0dc2f1adb 100644 (file)
                (line6pcm->pcm->streams[stream].substream)
 
 /*
-       PCM mode bits and masks.
-       "ALSA": operations triggered by applications via ALSA
-       "MONITOR": software monitoring
-       "IMPULSE": optional impulse response operation
+       PCM mode bits.
+
+       There are several features of the Line6 USB driver which require PCM
+       data to be exchanged with the device:
+       *) PCM playback and capture via ALSA
+       *) software monitoring (for devices without hardware monitoring)
+       *) optional impulse response measurement
+       However, from the device's point of view, there is just a single
+       capture and playback stream, which must be shared between these
+       subsystems. It is therefore necessary to maintain the state of the
+       subsystems with respect to PCM usage. We define several constants of
+       the form LINE6_BIT_PCM_<subsystem>_<direction>_<resource> with the
+       following meanings:
+       *) <subsystem> is one of
+       -) ALSA: PCM playback and capture via ALSA
+       -) MONITOR: software monitoring
+       -) IMPULSE: optional impulse response measurement
+       *) <direction> is one of
+       -) PLAYBACK: audio output (from host to device)
+       -) CAPTURE: audio input (from device to host)
+       *) <resource> is one of
+       -) BUFFER: buffer required by PCM data stream
+       -) STREAM: actual PCM data stream
+
+       The subsystems call line6_pcm_acquire() to acquire the (shared)
+       resources needed for a particular operation (e.g., allocate the buffer
+       for ALSA playback or start the capture stream for software monitoring).
+       When a resource is no longer needed, it is released by calling
+       line6_pcm_release(). Buffer allocation and stream startup are handled
+       separately to allow the ALSA kernel driver to perform them at
+       appropriate places (since the callback which starts a PCM stream is not
+       allowed to sleep).
 */
 enum {
-       /* individual bits: */
-       BIT_PCM_ALSA_PLAYBACK,
-       BIT_PCM_ALSA_CAPTURE,
-       BIT_PCM_MONITOR_PLAYBACK,
-       BIT_PCM_MONITOR_CAPTURE,
+       /* individual bit indices: */
+       LINE6_INDEX_PCM_ALSA_PLAYBACK_BUFFER,
+       LINE6_INDEX_PCM_ALSA_PLAYBACK_STREAM,
+       LINE6_INDEX_PCM_ALSA_CAPTURE_BUFFER,
+       LINE6_INDEX_PCM_ALSA_CAPTURE_STREAM,
+       LINE6_INDEX_PCM_MONITOR_PLAYBACK_BUFFER,
+       LINE6_INDEX_PCM_MONITOR_PLAYBACK_STREAM,
+       LINE6_INDEX_PCM_MONITOR_CAPTURE_BUFFER,
+       LINE6_INDEX_PCM_MONITOR_CAPTURE_STREAM,
 #ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
-       BIT_PCM_IMPULSE_PLAYBACK,
-       BIT_PCM_IMPULSE_CAPTURE,
+       LINE6_INDEX_PCM_IMPULSE_PLAYBACK_BUFFER,
+       LINE6_INDEX_PCM_IMPULSE_PLAYBACK_STREAM,
+       LINE6_INDEX_PCM_IMPULSE_CAPTURE_BUFFER,
+       LINE6_INDEX_PCM_IMPULSE_CAPTURE_STREAM,
 #endif
-       BIT_PAUSE_PLAYBACK,
-       BIT_PREPARED,
-
-       /* individual masks: */
-/* *INDENT-OFF* */
-       MASK_PCM_ALSA_PLAYBACK    = 1 << BIT_PCM_ALSA_PLAYBACK,
-       MASK_PCM_ALSA_CAPTURE     = 1 << BIT_PCM_ALSA_CAPTURE,
-       MASK_PCM_MONITOR_PLAYBACK = 1 << BIT_PCM_MONITOR_PLAYBACK,
-       MASK_PCM_MONITOR_CAPTURE  = 1 << BIT_PCM_MONITOR_CAPTURE,
+       LINE6_INDEX_PAUSE_PLAYBACK,
+       LINE6_INDEX_PREPARED,
+
+       /* individual bit masks: */
+       LINE6_BIT(PCM_ALSA_PLAYBACK_BUFFER),
+       LINE6_BIT(PCM_ALSA_PLAYBACK_STREAM),
+       LINE6_BIT(PCM_ALSA_CAPTURE_BUFFER),
+       LINE6_BIT(PCM_ALSA_CAPTURE_STREAM),
+       LINE6_BIT(PCM_MONITOR_PLAYBACK_BUFFER),
+       LINE6_BIT(PCM_MONITOR_PLAYBACK_STREAM),
+       LINE6_BIT(PCM_MONITOR_CAPTURE_BUFFER),
+       LINE6_BIT(PCM_MONITOR_CAPTURE_STREAM),
 #ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
-       MASK_PCM_IMPULSE_PLAYBACK = 1 << BIT_PCM_IMPULSE_PLAYBACK,
-       MASK_PCM_IMPULSE_CAPTURE  = 1 << BIT_PCM_IMPULSE_CAPTURE,
+       LINE6_BIT(PCM_IMPULSE_PLAYBACK_BUFFER),
+       LINE6_BIT(PCM_IMPULSE_PLAYBACK_STREAM),
+       LINE6_BIT(PCM_IMPULSE_CAPTURE_BUFFER),
+       LINE6_BIT(PCM_IMPULSE_CAPTURE_STREAM),
 #endif
-       MASK_PAUSE_PLAYBACK       = 1 << BIT_PAUSE_PLAYBACK,
-       MASK_PREPARED             = 1 << BIT_PREPARED,
-/* *INDENT-ON* */
+       LINE6_BIT(PAUSE_PLAYBACK),
+       LINE6_BIT(PREPARED),
 
-       /* combined masks (by operation): */
-       MASK_PCM_ALSA = MASK_PCM_ALSA_PLAYBACK | MASK_PCM_ALSA_CAPTURE,
-       MASK_PCM_MONITOR = MASK_PCM_MONITOR_PLAYBACK | MASK_PCM_MONITOR_CAPTURE,
+       /* combined bit masks (by operation): */
+       LINE6_BITS_PCM_ALSA_BUFFER =
+           LINE6_BIT_PCM_ALSA_PLAYBACK_BUFFER |
+           LINE6_BIT_PCM_ALSA_CAPTURE_BUFFER,
+
+       LINE6_BITS_PCM_ALSA_STREAM =
+           LINE6_BIT_PCM_ALSA_PLAYBACK_STREAM |
+           LINE6_BIT_PCM_ALSA_CAPTURE_STREAM,
+
+       LINE6_BITS_PCM_MONITOR =
+           LINE6_BIT_PCM_MONITOR_PLAYBACK_BUFFER |
+           LINE6_BIT_PCM_MONITOR_PLAYBACK_STREAM |
+           LINE6_BIT_PCM_MONITOR_CAPTURE_BUFFER |
+           LINE6_BIT_PCM_MONITOR_CAPTURE_STREAM,
+
+#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
+       LINE6_BITS_PCM_IMPULSE =
+           LINE6_BIT_PCM_IMPULSE_PLAYBACK_BUFFER |
+           LINE6_BIT_PCM_IMPULSE_PLAYBACK_STREAM |
+           LINE6_BIT_PCM_IMPULSE_CAPTURE_BUFFER |
+           LINE6_BIT_PCM_IMPULSE_CAPTURE_STREAM,
+#endif
+
+       /* combined bit masks (by direction): */
+       LINE6_BITS_PLAYBACK_BUFFER =
+#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
+           LINE6_BIT_PCM_IMPULSE_PLAYBACK_BUFFER |
+#endif
+           LINE6_BIT_PCM_ALSA_PLAYBACK_BUFFER |
+           LINE6_BIT_PCM_MONITOR_PLAYBACK_BUFFER ,
+
+       LINE6_BITS_PLAYBACK_STREAM =
+#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
+           LINE6_BIT_PCM_IMPULSE_PLAYBACK_STREAM |
+#endif
+           LINE6_BIT_PCM_ALSA_PLAYBACK_STREAM |
+           LINE6_BIT_PCM_MONITOR_PLAYBACK_STREAM ,
+
+       LINE6_BITS_CAPTURE_BUFFER =
 #ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
-       MASK_PCM_IMPULSE = MASK_PCM_IMPULSE_PLAYBACK | MASK_PCM_IMPULSE_CAPTURE,
+           LINE6_BIT_PCM_IMPULSE_CAPTURE_BUFFER |
 #endif
+           LINE6_BIT_PCM_ALSA_CAPTURE_BUFFER |
+           LINE6_BIT_PCM_MONITOR_CAPTURE_BUFFER ,
 
-       /* combined masks (by direction): */
+       LINE6_BITS_CAPTURE_STREAM =
 #ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
-       MASK_PLAYBACK =
-           MASK_PCM_ALSA_PLAYBACK | MASK_PCM_MONITOR_PLAYBACK |
-           MASK_PCM_IMPULSE_PLAYBACK,
-       MASK_CAPTURE =
-           MASK_PCM_ALSA_CAPTURE | MASK_PCM_MONITOR_CAPTURE |
-           MASK_PCM_IMPULSE_CAPTURE
-#else
-       MASK_PLAYBACK = MASK_PCM_ALSA_PLAYBACK | MASK_PCM_MONITOR_PLAYBACK,
-       MASK_CAPTURE = MASK_PCM_ALSA_CAPTURE | MASK_PCM_MONITOR_CAPTURE
+           LINE6_BIT_PCM_IMPULSE_CAPTURE_STREAM |
 #endif
+           LINE6_BIT_PCM_ALSA_CAPTURE_STREAM |
+           LINE6_BIT_PCM_MONITOR_CAPTURE_STREAM,
+       
+       LINE6_BITS_STREAM =
+           LINE6_BITS_PLAYBACK_STREAM |
+           LINE6_BITS_CAPTURE_STREAM
 };
 
 struct line6_pcm_properties {
@@ -290,7 +364,7 @@ struct snd_line6_pcm {
 #endif
 
        /**
-                Several status bits (see BIT_*).
+                Several status bits (see LINE6_BIT_*).
        */
        unsigned long flags;
 
@@ -302,7 +376,7 @@ extern int line6_init_pcm(struct usb_line6 *line6,
 extern int snd_line6_trigger(struct snd_pcm_substream *substream, int cmd);
 extern int snd_line6_prepare(struct snd_pcm_substream *substream);
 extern void line6_pcm_disconnect(struct snd_line6_pcm *line6pcm);
-extern int line6_pcm_start(struct snd_line6_pcm *line6pcm, int channels);
-extern int line6_pcm_stop(struct snd_line6_pcm *line6pcm, int channels);
+extern int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int channels);
+extern int line6_pcm_release(struct snd_line6_pcm *line6pcm, int channels);
 
 #endif