123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197 |
- /*
- * 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
|