162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Line 6 Linux USB driver 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at) 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci/* 962306a36Sopenharmony_ci PCM interface to POD series devices. 1062306a36Sopenharmony_ci*/ 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#ifndef PCM_H 1362306a36Sopenharmony_ci#define PCM_H 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#include <sound/pcm.h> 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci#include "driver.h" 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci/* 2062306a36Sopenharmony_ci number of USB frames per URB 2162306a36Sopenharmony_ci The Line 6 Windows driver always transmits two frames per packet, but 2262306a36Sopenharmony_ci the Linux driver performs significantly better (i.e., lower latency) 2362306a36Sopenharmony_ci with only one frame per packet. 2462306a36Sopenharmony_ci*/ 2562306a36Sopenharmony_ci#define LINE6_ISO_PACKETS 1 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci/* in a "full speed" device (such as the PODxt Pro) this means 1ms, 2862306a36Sopenharmony_ci * for "high speed" it's 1/8ms 2962306a36Sopenharmony_ci */ 3062306a36Sopenharmony_ci#define LINE6_ISO_INTERVAL 1 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci#define LINE6_IMPULSE_DEFAULT_PERIOD 100 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci/* 3562306a36Sopenharmony_ci Get substream from Line 6 PCM data structure 3662306a36Sopenharmony_ci*/ 3762306a36Sopenharmony_ci#define get_substream(line6pcm, stream) \ 3862306a36Sopenharmony_ci (line6pcm->pcm->streams[stream].substream) 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci/* 4162306a36Sopenharmony_ci PCM mode bits. 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci There are several features of the Line 6 USB driver which require PCM 4462306a36Sopenharmony_ci data to be exchanged with the device: 4562306a36Sopenharmony_ci *) PCM playback and capture via ALSA 4662306a36Sopenharmony_ci *) software monitoring (for devices without hardware monitoring) 4762306a36Sopenharmony_ci *) optional impulse response measurement 4862306a36Sopenharmony_ci However, from the device's point of view, there is just a single 4962306a36Sopenharmony_ci capture and playback stream, which must be shared between these 5062306a36Sopenharmony_ci subsystems. It is therefore necessary to maintain the state of the 5162306a36Sopenharmony_ci subsystems with respect to PCM usage. 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci We define two bit flags, "opened" and "running", for each playback 5462306a36Sopenharmony_ci or capture stream. Both can contain the bit flag corresponding to 5562306a36Sopenharmony_ci LINE6_STREAM_* type, 5662306a36Sopenharmony_ci LINE6_STREAM_PCM = ALSA PCM playback or capture 5762306a36Sopenharmony_ci LINE6_STREAM_MONITOR = software monitoring 5862306a36Sopenharmony_ci IMPULSE = optional impulse response measurement 5962306a36Sopenharmony_ci The opened flag indicates whether the buffer is allocated while 6062306a36Sopenharmony_ci the running flag indicates whether the stream is running. 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci For monitor or impulse operations, the driver needs to call 6362306a36Sopenharmony_ci line6_pcm_acquire() or line6_pcm_release() with the appropriate 6462306a36Sopenharmony_ci LINE6_STREAM_* flag. 6562306a36Sopenharmony_ci*/ 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci/* stream types */ 6862306a36Sopenharmony_cienum { 6962306a36Sopenharmony_ci LINE6_STREAM_PCM, 7062306a36Sopenharmony_ci LINE6_STREAM_MONITOR, 7162306a36Sopenharmony_ci LINE6_STREAM_IMPULSE, 7262306a36Sopenharmony_ci LINE6_STREAM_CAPTURE_HELPER, 7362306a36Sopenharmony_ci}; 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci/* misc bit flags for PCM operation */ 7662306a36Sopenharmony_cienum { 7762306a36Sopenharmony_ci LINE6_FLAG_PAUSE_PLAYBACK, 7862306a36Sopenharmony_ci LINE6_FLAG_PREPARED, 7962306a36Sopenharmony_ci}; 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_cistruct line6_pcm_properties { 8262306a36Sopenharmony_ci struct snd_pcm_hardware playback_hw, capture_hw; 8362306a36Sopenharmony_ci struct snd_pcm_hw_constraint_ratdens rates; 8462306a36Sopenharmony_ci int bytes_per_channel; 8562306a36Sopenharmony_ci}; 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_cistruct line6_pcm_stream { 8862306a36Sopenharmony_ci /* allocated URBs */ 8962306a36Sopenharmony_ci struct urb **urbs; 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci /* Temporary buffer; 9262306a36Sopenharmony_ci * Since the packet size is not known in advance, this buffer is 9362306a36Sopenharmony_ci * large enough to store maximum size packets. 9462306a36Sopenharmony_ci */ 9562306a36Sopenharmony_ci unsigned char *buffer; 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci /* Free frame position in the buffer. */ 9862306a36Sopenharmony_ci snd_pcm_uframes_t pos; 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci /* Count processed bytes; 10162306a36Sopenharmony_ci * This is modulo period size (to determine when a period is finished). 10262306a36Sopenharmony_ci */ 10362306a36Sopenharmony_ci unsigned bytes; 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci /* Counter to create desired sample rate */ 10662306a36Sopenharmony_ci unsigned count; 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci /* period size in bytes */ 10962306a36Sopenharmony_ci unsigned period; 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci /* Processed frame position in the buffer; 11262306a36Sopenharmony_ci * The contents of the ring buffer have been consumed by the USB 11362306a36Sopenharmony_ci * subsystem (i.e., sent to the USB device) up to this position. 11462306a36Sopenharmony_ci */ 11562306a36Sopenharmony_ci snd_pcm_uframes_t pos_done; 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci /* Bit mask of active URBs */ 11862306a36Sopenharmony_ci unsigned long active_urbs; 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci /* Bit mask of URBs currently being unlinked */ 12162306a36Sopenharmony_ci unsigned long unlink_urbs; 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci /* Spin lock to protect updates of the buffer positions (not contents) 12462306a36Sopenharmony_ci */ 12562306a36Sopenharmony_ci spinlock_t lock; 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci /* Bit flags for operational stream types */ 12862306a36Sopenharmony_ci unsigned long opened; 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci /* Bit flags for running stream types */ 13162306a36Sopenharmony_ci unsigned long running; 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci int last_frame; 13462306a36Sopenharmony_ci}; 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_cistruct snd_line6_pcm { 13762306a36Sopenharmony_ci /* Pointer back to the Line 6 driver data structure */ 13862306a36Sopenharmony_ci struct usb_line6 *line6; 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci /* Properties. */ 14162306a36Sopenharmony_ci struct line6_pcm_properties *properties; 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci /* ALSA pcm stream */ 14462306a36Sopenharmony_ci struct snd_pcm *pcm; 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci /* protection to state changes of in/out streams */ 14762306a36Sopenharmony_ci struct mutex state_mutex; 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci /* Capture and playback streams */ 15062306a36Sopenharmony_ci struct line6_pcm_stream in; 15162306a36Sopenharmony_ci struct line6_pcm_stream out; 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci /* Previously captured frame (for software monitoring) */ 15462306a36Sopenharmony_ci unsigned char *prev_fbuf; 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci /* Size of previously captured frame (for software monitoring/sync) */ 15762306a36Sopenharmony_ci int prev_fsize; 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci /* Maximum size of USB packet */ 16062306a36Sopenharmony_ci int max_packet_size_in; 16162306a36Sopenharmony_ci int max_packet_size_out; 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ci /* PCM playback volume (left and right) */ 16462306a36Sopenharmony_ci int volume_playback[2]; 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ci /* PCM monitor volume */ 16762306a36Sopenharmony_ci int volume_monitor; 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_ci /* Volume of impulse response test signal (if zero, test is disabled) */ 17062306a36Sopenharmony_ci int impulse_volume; 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci /* Period of impulse response test signal */ 17362306a36Sopenharmony_ci int impulse_period; 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci /* Counter for impulse response test signal */ 17662306a36Sopenharmony_ci int impulse_count; 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci /* Several status bits (see LINE6_FLAG_*) */ 17962306a36Sopenharmony_ci unsigned long flags; 18062306a36Sopenharmony_ci}; 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_ciextern int line6_init_pcm(struct usb_line6 *line6, 18362306a36Sopenharmony_ci struct line6_pcm_properties *properties); 18462306a36Sopenharmony_ciextern int snd_line6_trigger(struct snd_pcm_substream *substream, int cmd); 18562306a36Sopenharmony_ciextern int snd_line6_prepare(struct snd_pcm_substream *substream); 18662306a36Sopenharmony_ciextern int snd_line6_hw_params(struct snd_pcm_substream *substream, 18762306a36Sopenharmony_ci struct snd_pcm_hw_params *hw_params); 18862306a36Sopenharmony_ciextern int snd_line6_hw_free(struct snd_pcm_substream *substream); 18962306a36Sopenharmony_ciextern snd_pcm_uframes_t snd_line6_pointer(struct snd_pcm_substream *substream); 19062306a36Sopenharmony_ciextern void line6_pcm_disconnect(struct snd_line6_pcm *line6pcm); 19162306a36Sopenharmony_ciextern int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int type, 19262306a36Sopenharmony_ci bool start); 19362306a36Sopenharmony_ciextern void line6_pcm_release(struct snd_line6_pcm *line6pcm, int type); 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_ci#endif 196