1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
2 | /* |
3 | * Line 6 Linux USB driver |
4 | * |
5 | * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at) |
6 | */ |
7 | |
8 | /* |
9 | PCM interface to POD series devices. |
10 | */ |
11 | |
12 | #ifndef PCM_H |
13 | #define PCM_H |
14 | |
15 | #include <sound/pcm.h> |
16 | |
17 | #include "driver.h" |
18 | |
19 | /* |
20 | number of USB frames per URB |
21 | The Line 6 Windows driver always transmits two frames per packet, but |
22 | the Linux driver performs significantly better (i.e., lower latency) |
23 | with only one frame per packet. |
24 | */ |
25 | #define LINE6_ISO_PACKETS 1 |
26 | |
27 | /* in a "full speed" device (such as the PODxt Pro) this means 1ms, |
28 | * for "high speed" it's 1/8ms |
29 | */ |
30 | #define LINE6_ISO_INTERVAL 1 |
31 | |
32 | #define LINE6_IMPULSE_DEFAULT_PERIOD 100 |
33 | |
34 | /* |
35 | Get substream from Line 6 PCM data structure |
36 | */ |
37 | #define get_substream(line6pcm, stream) \ |
38 | (line6pcm->pcm->streams[stream].substream) |
39 | |
40 | /* |
41 | PCM mode bits. |
42 | |
43 | There are several features of the Line 6 USB driver which require PCM |
44 | data to be exchanged with the device: |
45 | *) PCM playback and capture via ALSA |
46 | *) software monitoring (for devices without hardware monitoring) |
47 | *) optional impulse response measurement |
48 | However, from the device's point of view, there is just a single |
49 | capture and playback stream, which must be shared between these |
50 | subsystems. It is therefore necessary to maintain the state of the |
51 | subsystems with respect to PCM usage. |
52 | |
53 | We define two bit flags, "opened" and "running", for each playback |
54 | or capture stream. Both can contain the bit flag corresponding to |
55 | LINE6_STREAM_* type, |
56 | LINE6_STREAM_PCM = ALSA PCM playback or capture |
57 | LINE6_STREAM_MONITOR = software monitoring |
58 | IMPULSE = optional impulse response measurement |
59 | The opened flag indicates whether the buffer is allocated while |
60 | the running flag indicates whether the stream is running. |
61 | |
62 | For monitor or impulse operations, the driver needs to call |
63 | line6_pcm_acquire() or line6_pcm_release() with the appropriate |
64 | LINE6_STREAM_* flag. |
65 | */ |
66 | |
67 | /* stream types */ |
68 | enum { |
69 | LINE6_STREAM_PCM, |
70 | LINE6_STREAM_MONITOR, |
71 | LINE6_STREAM_IMPULSE, |
72 | LINE6_STREAM_CAPTURE_HELPER, |
73 | }; |
74 | |
75 | /* misc bit flags for PCM operation */ |
76 | enum { |
77 | LINE6_FLAG_PAUSE_PLAYBACK, |
78 | LINE6_FLAG_PREPARED, |
79 | }; |
80 | |
81 | struct line6_pcm_properties { |
82 | struct snd_pcm_hardware playback_hw, capture_hw; |
83 | struct snd_pcm_hw_constraint_ratdens rates; |
84 | int bytes_per_channel; |
85 | }; |
86 | |
87 | struct line6_pcm_stream { |
88 | /* allocated URBs */ |
89 | struct urb **urbs; |
90 | |
91 | /* Temporary buffer; |
92 | * Since the packet size is not known in advance, this buffer is |
93 | * large enough to store maximum size packets. |
94 | */ |
95 | unsigned char *buffer; |
96 | |
97 | /* Free frame position in the buffer. */ |
98 | snd_pcm_uframes_t pos; |
99 | |
100 | /* Count processed bytes; |
101 | * This is modulo period size (to determine when a period is finished). |
102 | */ |
103 | unsigned bytes; |
104 | |
105 | /* Counter to create desired sample rate */ |
106 | unsigned count; |
107 | |
108 | /* period size in bytes */ |
109 | unsigned period; |
110 | |
111 | /* Processed frame position in the buffer; |
112 | * The contents of the ring buffer have been consumed by the USB |
113 | * subsystem (i.e., sent to the USB device) up to this position. |
114 | */ |
115 | snd_pcm_uframes_t pos_done; |
116 | |
117 | /* Bit mask of active URBs */ |
118 | unsigned long active_urbs; |
119 | |
120 | /* Bit mask of URBs currently being unlinked */ |
121 | unsigned long unlink_urbs; |
122 | |
123 | /* Spin lock to protect updates of the buffer positions (not contents) |
124 | */ |
125 | spinlock_t lock; |
126 | |
127 | /* Bit flags for operational stream types */ |
128 | unsigned long opened; |
129 | |
130 | /* Bit flags for running stream types */ |
131 | unsigned long running; |
132 | |
133 | int last_frame; |
134 | }; |
135 | |
136 | struct snd_line6_pcm { |
137 | /* Pointer back to the Line 6 driver data structure */ |
138 | struct usb_line6 *line6; |
139 | |
140 | /* Properties. */ |
141 | struct line6_pcm_properties *properties; |
142 | |
143 | /* ALSA pcm stream */ |
144 | struct snd_pcm *pcm; |
145 | |
146 | /* protection to state changes of in/out streams */ |
147 | struct mutex state_mutex; |
148 | |
149 | /* Capture and playback streams */ |
150 | struct line6_pcm_stream in; |
151 | struct line6_pcm_stream out; |
152 | |
153 | /* Previously captured frame (for software monitoring) */ |
154 | unsigned char *prev_fbuf; |
155 | |
156 | /* Size of previously captured frame (for software monitoring/sync) */ |
157 | int prev_fsize; |
158 | |
159 | /* Maximum size of USB packet */ |
160 | int max_packet_size_in; |
161 | int max_packet_size_out; |
162 | |
163 | /* PCM playback volume (left and right) */ |
164 | int volume_playback[2]; |
165 | |
166 | /* PCM monitor volume */ |
167 | int volume_monitor; |
168 | |
169 | /* Volume of impulse response test signal (if zero, test is disabled) */ |
170 | int impulse_volume; |
171 | |
172 | /* Period of impulse response test signal */ |
173 | int impulse_period; |
174 | |
175 | /* Counter for impulse response test signal */ |
176 | int impulse_count; |
177 | |
178 | /* Several status bits (see LINE6_FLAG_*) */ |
179 | unsigned long flags; |
180 | }; |
181 | |
182 | extern int line6_init_pcm(struct usb_line6 *line6, |
183 | struct line6_pcm_properties *properties); |
184 | extern int snd_line6_trigger(struct snd_pcm_substream *substream, int cmd); |
185 | extern int snd_line6_prepare(struct snd_pcm_substream *substream); |
186 | extern int snd_line6_hw_params(struct snd_pcm_substream *substream, |
187 | struct snd_pcm_hw_params *hw_params); |
188 | extern int snd_line6_hw_free(struct snd_pcm_substream *substream); |
189 | extern snd_pcm_uframes_t snd_line6_pointer(struct snd_pcm_substream *substream); |
190 | extern void line6_pcm_disconnect(struct snd_line6_pcm *line6pcm); |
191 | extern int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int type, |
192 | bool start); |
193 | extern void line6_pcm_release(struct snd_line6_pcm *line6pcm, int type); |
194 | |
195 | #endif |
196 | |