Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / sound / usb / line6 / pcm.h
diff --git a/kernel/sound/usb/line6/pcm.h b/kernel/sound/usb/line6/pcm.h
new file mode 100644 (file)
index 0000000..508410a
--- /dev/null
@@ -0,0 +1,197 @@
+/*
+ * Line 6 Linux USB driver
+ *
+ * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation, version 2.
+ *
+ */
+
+/*
+       PCM interface to POD series devices.
+*/
+
+#ifndef PCM_H
+#define PCM_H
+
+#include <sound/pcm.h>
+
+#include "driver.h"
+
+/* number of URBs */
+#define LINE6_ISO_BUFFERS      2
+
+/*
+       number of USB frames per URB
+       The Line 6 Windows driver always transmits two frames per packet, but
+       the Linux driver performs significantly better (i.e., lower latency)
+       with only one frame per packet.
+*/
+#define LINE6_ISO_PACKETS      1
+
+/* in a "full speed" device (such as the PODxt Pro) this means 1ms */
+#define LINE6_ISO_INTERVAL     1
+
+#define LINE6_IMPULSE_DEFAULT_PERIOD 100
+
+/*
+       Get substream from Line 6 PCM data structure
+*/
+#define get_substream(line6pcm, stream)        \
+               (line6pcm->pcm->streams[stream].substream)
+
+/*
+       PCM mode bits.
+
+       There are several features of the Line 6 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 two bit flags, "opened" and "running", for each playback
+       or capture stream.  Both can contain the bit flag corresponding to
+       LINE6_STREAM_* type,
+         LINE6_STREAM_PCM = ALSA PCM playback or capture
+         LINE6_STREAM_MONITOR = software monitoring
+         IMPULSE = optional impulse response measurement
+       The opened flag indicates whether the buffer is allocated while
+       the running flag indicates whether the stream is running.
+
+       For monitor or impulse operations, the driver needs to call
+       line6_pcm_acquire() or line6_pcm_release() with the appropriate
+       LINE6_STREAM_* flag.
+*/
+
+/* stream types */
+enum {
+       LINE6_STREAM_PCM,
+       LINE6_STREAM_MONITOR,
+       LINE6_STREAM_IMPULSE,
+};
+
+/* misc bit flags for PCM operation */
+enum {
+       LINE6_FLAG_PAUSE_PLAYBACK,
+       LINE6_FLAG_PREPARED,
+};
+
+struct line6_pcm_properties {
+       struct snd_pcm_hardware playback_hw, capture_hw;
+       struct snd_pcm_hw_constraint_ratdens rates;
+       int bytes_per_frame;
+};
+
+struct line6_pcm_stream {
+       /* allocated URBs */
+       struct urb *urbs[LINE6_ISO_BUFFERS];
+
+       /* Temporary buffer;
+        * Since the packet size is not known in advance, this buffer is
+        * large enough to store maximum size packets.
+        */
+       unsigned char *buffer;
+
+       /* Free frame position in the buffer. */
+       snd_pcm_uframes_t pos;
+
+       /* Count processed bytes;
+        * This is modulo period size (to determine when a period is finished).
+        */
+       unsigned bytes;
+
+       /* Counter to create desired sample rate */
+       unsigned count;
+
+       /* period size in bytes */
+       unsigned period;
+
+       /* Processed frame position in the buffer;
+        * The contents of the ring buffer have been consumed by the USB
+        * subsystem (i.e., sent to the USB device) up to this position.
+        */
+       snd_pcm_uframes_t pos_done;
+
+       /* Bit mask of active URBs */
+       unsigned long active_urbs;
+
+       /* Bit mask of URBs currently being unlinked */
+       unsigned long unlink_urbs;
+
+       /* Spin lock to protect updates of the buffer positions (not contents)
+        */
+       spinlock_t lock;
+
+       /* Bit flags for operational stream types */
+       unsigned long opened;
+
+       /* Bit flags for running stream types */
+       unsigned long running;
+
+       int last_frame;
+};
+
+struct snd_line6_pcm {
+       /* Pointer back to the Line 6 driver data structure */
+       struct usb_line6 *line6;
+
+       /* Properties. */
+       struct line6_pcm_properties *properties;
+
+       /* ALSA pcm stream */
+       struct snd_pcm *pcm;
+
+       /* protection to state changes of in/out streams */
+       struct mutex state_mutex;
+
+       /* Capture and playback streams */
+       struct line6_pcm_stream in;
+       struct line6_pcm_stream out;
+
+       /* Previously captured frame (for software monitoring) */
+       unsigned char *prev_fbuf;
+
+       /* Size of previously captured frame (for software monitoring) */
+       int prev_fsize;
+
+       /* Maximum size of USB packet */
+       int max_packet_size;
+
+       /* PCM playback volume (left and right) */
+       int volume_playback[2];
+
+       /* PCM monitor volume */
+       int volume_monitor;
+
+       /* Volume of impulse response test signal (if zero, test is disabled) */
+       int impulse_volume;
+
+       /* Period of impulse response test signal */
+       int impulse_period;
+
+       /* Counter for impulse response test signal */
+       int impulse_count;
+
+       /* Several status bits (see LINE6_FLAG_*) */
+       unsigned long flags;
+};
+
+extern int line6_init_pcm(struct usb_line6 *line6,
+                         struct line6_pcm_properties *properties);
+extern int snd_line6_trigger(struct snd_pcm_substream *substream, int cmd);
+extern int snd_line6_prepare(struct snd_pcm_substream *substream);
+extern int snd_line6_hw_params(struct snd_pcm_substream *substream,
+                              struct snd_pcm_hw_params *hw_params);
+extern int snd_line6_hw_free(struct snd_pcm_substream *substream);
+extern snd_pcm_uframes_t snd_line6_pointer(struct snd_pcm_substream *substream);
+extern void line6_pcm_disconnect(struct snd_line6_pcm *line6pcm);
+extern int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int type);
+extern void line6_pcm_release(struct snd_line6_pcm *line6pcm, int type);
+
+#endif