18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Line 6 Linux USB driver 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at) 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci/* 98c2ecf20Sopenharmony_ci PCM interface to POD series devices. 108c2ecf20Sopenharmony_ci*/ 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#ifndef PCM_H 138c2ecf20Sopenharmony_ci#define PCM_H 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#include <sound/pcm.h> 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci#include "driver.h" 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci/* 208c2ecf20Sopenharmony_ci number of USB frames per URB 218c2ecf20Sopenharmony_ci The Line 6 Windows driver always transmits two frames per packet, but 228c2ecf20Sopenharmony_ci the Linux driver performs significantly better (i.e., lower latency) 238c2ecf20Sopenharmony_ci with only one frame per packet. 248c2ecf20Sopenharmony_ci*/ 258c2ecf20Sopenharmony_ci#define LINE6_ISO_PACKETS 1 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci/* in a "full speed" device (such as the PODxt Pro) this means 1ms, 288c2ecf20Sopenharmony_ci * for "high speed" it's 1/8ms 298c2ecf20Sopenharmony_ci */ 308c2ecf20Sopenharmony_ci#define LINE6_ISO_INTERVAL 1 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci#define LINE6_IMPULSE_DEFAULT_PERIOD 100 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci/* 358c2ecf20Sopenharmony_ci Get substream from Line 6 PCM data structure 368c2ecf20Sopenharmony_ci*/ 378c2ecf20Sopenharmony_ci#define get_substream(line6pcm, stream) \ 388c2ecf20Sopenharmony_ci (line6pcm->pcm->streams[stream].substream) 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci/* 418c2ecf20Sopenharmony_ci PCM mode bits. 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci There are several features of the Line 6 USB driver which require PCM 448c2ecf20Sopenharmony_ci data to be exchanged with the device: 458c2ecf20Sopenharmony_ci *) PCM playback and capture via ALSA 468c2ecf20Sopenharmony_ci *) software monitoring (for devices without hardware monitoring) 478c2ecf20Sopenharmony_ci *) optional impulse response measurement 488c2ecf20Sopenharmony_ci However, from the device's point of view, there is just a single 498c2ecf20Sopenharmony_ci capture and playback stream, which must be shared between these 508c2ecf20Sopenharmony_ci subsystems. It is therefore necessary to maintain the state of the 518c2ecf20Sopenharmony_ci subsystems with respect to PCM usage. 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci We define two bit flags, "opened" and "running", for each playback 548c2ecf20Sopenharmony_ci or capture stream. Both can contain the bit flag corresponding to 558c2ecf20Sopenharmony_ci LINE6_STREAM_* type, 568c2ecf20Sopenharmony_ci LINE6_STREAM_PCM = ALSA PCM playback or capture 578c2ecf20Sopenharmony_ci LINE6_STREAM_MONITOR = software monitoring 588c2ecf20Sopenharmony_ci IMPULSE = optional impulse response measurement 598c2ecf20Sopenharmony_ci The opened flag indicates whether the buffer is allocated while 608c2ecf20Sopenharmony_ci the running flag indicates whether the stream is running. 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci For monitor or impulse operations, the driver needs to call 638c2ecf20Sopenharmony_ci line6_pcm_acquire() or line6_pcm_release() with the appropriate 648c2ecf20Sopenharmony_ci LINE6_STREAM_* flag. 658c2ecf20Sopenharmony_ci*/ 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci/* stream types */ 688c2ecf20Sopenharmony_cienum { 698c2ecf20Sopenharmony_ci LINE6_STREAM_PCM, 708c2ecf20Sopenharmony_ci LINE6_STREAM_MONITOR, 718c2ecf20Sopenharmony_ci LINE6_STREAM_IMPULSE, 728c2ecf20Sopenharmony_ci LINE6_STREAM_CAPTURE_HELPER, 738c2ecf20Sopenharmony_ci}; 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci/* misc bit flags for PCM operation */ 768c2ecf20Sopenharmony_cienum { 778c2ecf20Sopenharmony_ci LINE6_FLAG_PAUSE_PLAYBACK, 788c2ecf20Sopenharmony_ci LINE6_FLAG_PREPARED, 798c2ecf20Sopenharmony_ci}; 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_cistruct line6_pcm_properties { 828c2ecf20Sopenharmony_ci struct snd_pcm_hardware playback_hw, capture_hw; 838c2ecf20Sopenharmony_ci struct snd_pcm_hw_constraint_ratdens rates; 848c2ecf20Sopenharmony_ci int bytes_per_channel; 858c2ecf20Sopenharmony_ci}; 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_cistruct line6_pcm_stream { 888c2ecf20Sopenharmony_ci /* allocated URBs */ 898c2ecf20Sopenharmony_ci struct urb **urbs; 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci /* Temporary buffer; 928c2ecf20Sopenharmony_ci * Since the packet size is not known in advance, this buffer is 938c2ecf20Sopenharmony_ci * large enough to store maximum size packets. 948c2ecf20Sopenharmony_ci */ 958c2ecf20Sopenharmony_ci unsigned char *buffer; 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci /* Free frame position in the buffer. */ 988c2ecf20Sopenharmony_ci snd_pcm_uframes_t pos; 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci /* Count processed bytes; 1018c2ecf20Sopenharmony_ci * This is modulo period size (to determine when a period is finished). 1028c2ecf20Sopenharmony_ci */ 1038c2ecf20Sopenharmony_ci unsigned bytes; 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci /* Counter to create desired sample rate */ 1068c2ecf20Sopenharmony_ci unsigned count; 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci /* period size in bytes */ 1098c2ecf20Sopenharmony_ci unsigned period; 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci /* Processed frame position in the buffer; 1128c2ecf20Sopenharmony_ci * The contents of the ring buffer have been consumed by the USB 1138c2ecf20Sopenharmony_ci * subsystem (i.e., sent to the USB device) up to this position. 1148c2ecf20Sopenharmony_ci */ 1158c2ecf20Sopenharmony_ci snd_pcm_uframes_t pos_done; 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci /* Bit mask of active URBs */ 1188c2ecf20Sopenharmony_ci unsigned long active_urbs; 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci /* Bit mask of URBs currently being unlinked */ 1218c2ecf20Sopenharmony_ci unsigned long unlink_urbs; 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci /* Spin lock to protect updates of the buffer positions (not contents) 1248c2ecf20Sopenharmony_ci */ 1258c2ecf20Sopenharmony_ci spinlock_t lock; 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci /* Bit flags for operational stream types */ 1288c2ecf20Sopenharmony_ci unsigned long opened; 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci /* Bit flags for running stream types */ 1318c2ecf20Sopenharmony_ci unsigned long running; 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci int last_frame; 1348c2ecf20Sopenharmony_ci}; 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_cistruct snd_line6_pcm { 1378c2ecf20Sopenharmony_ci /* Pointer back to the Line 6 driver data structure */ 1388c2ecf20Sopenharmony_ci struct usb_line6 *line6; 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci /* Properties. */ 1418c2ecf20Sopenharmony_ci struct line6_pcm_properties *properties; 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci /* ALSA pcm stream */ 1448c2ecf20Sopenharmony_ci struct snd_pcm *pcm; 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci /* protection to state changes of in/out streams */ 1478c2ecf20Sopenharmony_ci struct mutex state_mutex; 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci /* Capture and playback streams */ 1508c2ecf20Sopenharmony_ci struct line6_pcm_stream in; 1518c2ecf20Sopenharmony_ci struct line6_pcm_stream out; 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci /* Previously captured frame (for software monitoring) */ 1548c2ecf20Sopenharmony_ci unsigned char *prev_fbuf; 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci /* Size of previously captured frame (for software monitoring/sync) */ 1578c2ecf20Sopenharmony_ci int prev_fsize; 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci /* Maximum size of USB packet */ 1608c2ecf20Sopenharmony_ci int max_packet_size_in; 1618c2ecf20Sopenharmony_ci int max_packet_size_out; 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci /* PCM playback volume (left and right) */ 1648c2ecf20Sopenharmony_ci int volume_playback[2]; 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ci /* PCM monitor volume */ 1678c2ecf20Sopenharmony_ci int volume_monitor; 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci /* Volume of impulse response test signal (if zero, test is disabled) */ 1708c2ecf20Sopenharmony_ci int impulse_volume; 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ci /* Period of impulse response test signal */ 1738c2ecf20Sopenharmony_ci int impulse_period; 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci /* Counter for impulse response test signal */ 1768c2ecf20Sopenharmony_ci int impulse_count; 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci /* Several status bits (see LINE6_FLAG_*) */ 1798c2ecf20Sopenharmony_ci unsigned long flags; 1808c2ecf20Sopenharmony_ci}; 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_ciextern int line6_init_pcm(struct usb_line6 *line6, 1838c2ecf20Sopenharmony_ci struct line6_pcm_properties *properties); 1848c2ecf20Sopenharmony_ciextern int snd_line6_trigger(struct snd_pcm_substream *substream, int cmd); 1858c2ecf20Sopenharmony_ciextern int snd_line6_prepare(struct snd_pcm_substream *substream); 1868c2ecf20Sopenharmony_ciextern int snd_line6_hw_params(struct snd_pcm_substream *substream, 1878c2ecf20Sopenharmony_ci struct snd_pcm_hw_params *hw_params); 1888c2ecf20Sopenharmony_ciextern int snd_line6_hw_free(struct snd_pcm_substream *substream); 1898c2ecf20Sopenharmony_ciextern snd_pcm_uframes_t snd_line6_pointer(struct snd_pcm_substream *substream); 1908c2ecf20Sopenharmony_ciextern void line6_pcm_disconnect(struct snd_line6_pcm *line6pcm); 1918c2ecf20Sopenharmony_ciextern int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int type, 1928c2ecf20Sopenharmony_ci bool start); 1938c2ecf20Sopenharmony_ciextern void line6_pcm_release(struct snd_line6_pcm *line6pcm, int type); 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci#endif 196