2009-02-28 06:43:04 +03:00
/*
2015-01-20 11:20:50 +03:00
* Line 6 Linux USB driver
2009-02-28 06:43:04 +03:00
*
2010-08-12 03:35:30 +04:00
* Copyright ( C ) 2004 - 2010 Markus Grabner ( grabner @ icg . tugraz . at )
2009-02-28 06:43:04 +03:00
*
* 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"
2009-02-28 08:09:55 +03:00
/* number of URBs */
2010-08-12 03:35:30 +04:00
# define LINE6_ISO_BUFFERS 2
2009-02-28 08:09:55 +03:00
2010-08-12 03:35:30 +04:00
/*
number of USB frames per URB
2015-01-20 11:20:49 +03:00
The Line 6 Windows driver always transmits two frames per packet , but
2010-08-12 03:35:30 +04:00
the Linux driver performs significantly better ( i . e . , lower latency )
with only one frame per packet .
*/
# define LINE6_ISO_PACKETS 1
2009-02-28 08:09:55 +03:00
/* in a "full speed" device (such as the PODxt Pro) this means 1ms */
# define LINE6_ISO_INTERVAL 1
2010-08-12 03:35:30 +04:00
# define LINE6_IMPULSE_DEFAULT_PERIOD 100
2009-02-28 06:43:04 +03:00
/*
2015-01-20 11:20:49 +03:00
Get substream from Line 6 PCM data structure
2009-02-28 06:43:04 +03:00
*/
2010-09-22 03:58:00 +04:00
# define get_substream(line6pcm, stream) \
( line6pcm - > pcm - > streams [ stream ] . substream )
2009-02-28 06:43:04 +03:00
2010-08-12 03:35:30 +04:00
/*
2012-01-20 03:09:09 +04:00
PCM mode bits .
2015-01-20 11:20:49 +03:00
There are several features of the Line 6 USB driver which require PCM
2012-01-20 03:09:09 +04:00
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
2015-01-27 17:24:09 +03:00
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
2015-01-28 16:43:11 +03:00
line6_pcm_acquire ( ) or line6_pcm_release ( ) with the appropriate
LINE6_STREAM_ * flag .
2010-08-12 03:35:30 +04:00
*/
2015-01-27 17:24:09 +03:00
/* stream types */
enum {
LINE6_STREAM_PCM ,
LINE6_STREAM_MONITOR ,
LINE6_STREAM_IMPULSE ,
} ;
/* misc bit flags for PCM operation */
2009-02-28 06:43:04 +03:00
enum {
2015-01-27 17:24:09 +03:00
LINE6_FLAG_PAUSE_PLAYBACK ,
LINE6_FLAG_PREPARED ,
2009-02-28 06:43:04 +03:00
} ;
struct line6_pcm_properties {
2015-01-28 17:08:59 +03:00
struct snd_pcm_hardware playback_hw , capture_hw ;
struct snd_pcm_hw_constraint_ratdens rates ;
2009-02-28 06:43:04 +03:00
int bytes_per_frame ;
} ;
2015-01-23 18:10:57 +03:00
struct line6_pcm_stream {
/* allocated URBs */
struct urb * urbs [ LINE6_ISO_BUFFERS ] ;
2009-02-28 06:43:04 +03:00
2015-01-23 18:10:57 +03:00
/* Temporary buffer;
* Since the packet size is not known in advance , this buffer is
* large enough to store maximum size packets .
*/
unsigned char * buffer ;
2009-02-28 06:43:04 +03:00
2015-01-23 18:10:57 +03:00
/* Free frame position in the buffer. */
snd_pcm_uframes_t pos ;
2009-02-28 06:43:04 +03:00
2015-01-23 18:10:57 +03:00
/* Count processed bytes;
* This is modulo period size ( to determine when a period is finished ) .
*/
unsigned bytes ;
2009-02-28 06:43:04 +03:00
2015-01-23 18:10:57 +03:00
/* Counter to create desired sample rate */
unsigned count ;
2009-02-28 06:43:04 +03:00
2015-01-23 18:10:57 +03:00
/* period size in bytes */
unsigned period ;
2009-02-28 06:43:04 +03:00
2015-01-23 18:10:57 +03:00
/* 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 ;
2009-02-28 06:43:04 +03:00
2015-01-23 18:10:57 +03:00
/* Bit mask of active URBs */
unsigned long active_urbs ;
2010-08-12 03:35:30 +04:00
2015-01-23 18:10:57 +03:00
/* Bit mask of URBs currently being unlinked */
unsigned long unlink_urbs ;
2009-02-28 06:43:04 +03:00
2015-01-23 18:10:57 +03:00
/* Spin lock to protect updates of the buffer positions (not contents)
*/
spinlock_t lock ;
2009-02-28 06:43:04 +03:00
2015-01-27 17:24:09 +03:00
/* Bit flags for operational stream types */
unsigned long opened ;
/* Bit flags for running stream types */
unsigned long running ;
2015-01-23 18:10:57 +03:00
int last_frame ;
} ;
2009-02-28 06:43:04 +03:00
2015-01-23 18:10:57 +03:00
struct snd_line6_pcm {
2015-01-28 16:43:11 +03:00
/* Pointer back to the Line 6 driver data structure */
2015-01-23 18:10:57 +03:00
struct usb_line6 * line6 ;
2009-02-28 06:43:04 +03:00
2015-01-28 16:43:11 +03:00
/* Properties. */
2015-01-23 18:10:57 +03:00
struct line6_pcm_properties * properties ;
2009-02-28 06:43:04 +03:00
2015-01-28 16:43:11 +03:00
/* ALSA pcm stream */
2015-01-23 18:10:57 +03:00
struct snd_pcm * pcm ;
2009-02-28 06:43:04 +03:00
2015-01-27 17:24:09 +03:00
/* protection to state changes of in/out streams */
struct mutex state_mutex ;
2015-01-23 18:10:57 +03:00
/* Capture and playback streams */
struct line6_pcm_stream in ;
struct line6_pcm_stream out ;
2009-02-28 06:43:04 +03:00
2015-01-28 16:43:11 +03:00
/* Previously captured frame (for software monitoring) */
2015-01-23 18:10:57 +03:00
unsigned char * prev_fbuf ;
2009-02-28 06:43:04 +03:00
2015-01-28 16:43:11 +03:00
/* Size of previously captured frame (for software monitoring) */
2015-01-23 18:10:57 +03:00
int prev_fsize ;
2009-02-28 06:43:04 +03:00
2015-01-28 16:43:11 +03:00
/* Maximum size of USB packet */
2009-02-28 06:43:04 +03:00
int max_packet_size ;
2015-01-28 16:43:11 +03:00
/* PCM playback volume (left and right) */
2010-08-12 03:35:30 +04:00
int volume_playback [ 2 ] ;
2015-01-28 16:43:11 +03:00
/* PCM monitor volume */
2010-08-12 03:35:30 +04:00
int volume_monitor ;
2015-01-28 16:43:11 +03:00
/* Volume of impulse response test signal (if zero, test is disabled) */
2010-08-12 03:35:30 +04:00
int impulse_volume ;
2015-01-28 16:43:11 +03:00
/* Period of impulse response test signal */
2010-08-12 03:35:30 +04:00
int impulse_period ;
2015-01-28 16:43:11 +03:00
/* Counter for impulse response test signal */
2010-08-12 03:35:30 +04:00
int impulse_count ;
2009-02-28 06:43:04 +03:00
2015-01-28 16:43:11 +03:00
/* Several status bits (see LINE6_FLAG_*) */
2009-02-28 06:43:04 +03:00
unsigned long flags ;
} ;
2009-02-28 08:09:55 +03:00
extern int line6_init_pcm ( struct usb_line6 * line6 ,
struct line6_pcm_properties * properties ) ;
2009-02-28 06:43:04 +03:00
extern int snd_line6_trigger ( struct snd_pcm_substream * substream , int cmd ) ;
extern int snd_line6_prepare ( struct snd_pcm_substream * substream ) ;
2015-01-27 17:24:09 +03:00
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 ) ;
2015-01-27 17:41:27 +03:00
extern snd_pcm_uframes_t snd_line6_pointer ( struct snd_pcm_substream * substream ) ;
2010-08-12 03:35:30 +04:00
extern void line6_pcm_disconnect ( struct snd_line6_pcm * line6pcm ) ;
2015-01-27 17:24:09 +03:00
extern int line6_pcm_acquire ( struct snd_line6_pcm * line6pcm , int type ) ;
extern void line6_pcm_release ( struct snd_line6_pcm * line6pcm , int type ) ;
2010-08-12 03:35:30 +04:00
2009-02-28 06:43:04 +03:00
# endif