aboutsummaryrefslogtreecommitdiffstats
path: root/sound/usb/line6
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2015-01-23 10:10:57 -0500
committerTakashi Iwai <tiwai@suse.de>2015-01-28 01:21:18 -0500
commitad0119abe29fe3d506486a789de4c4619fa7602c (patch)
treeebbb5c893a11998437fba5bbfd0b22a63f70fe71 /sound/usb/line6
parentab5cdcbab2efb833b4c199d0b0a6603af080eaa2 (diff)
ALSA: line6: Rearrange PCM structure
Introduce a new line6_pcm_stream structure and group individual fields of snd_line6_pcm struct to playback and capture groups. This patch itself just does rename and nothing else. More meaningful cleanups based on these fields shuffling will follow. Tested-by: Chris Rorvick <chris@rorvick.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/usb/line6')
-rw-r--r--sound/usb/line6/capture.c64
-rw-r--r--sound/usb/line6/pcm.c50
-rw-r--r--sound/usb/line6/pcm.h158
-rw-r--r--sound/usb/line6/playback.c78
4 files changed, 142 insertions, 208 deletions
diff --git a/sound/usb/line6/capture.c b/sound/usb/line6/capture.c
index bad1b5b02786..439f1941eb56 100644
--- a/sound/usb/line6/capture.c
+++ b/sound/usb/line6/capture.c
@@ -29,17 +29,17 @@ static int submit_audio_in_urb(struct snd_line6_pcm *line6pcm)
29 int ret; 29 int ret;
30 struct urb *urb_in; 30 struct urb *urb_in;
31 31
32 spin_lock_irqsave(&line6pcm->lock_audio_in, flags); 32 spin_lock_irqsave(&line6pcm->in.lock, flags);
33 index = 33 index =
34 find_first_zero_bit(&line6pcm->active_urb_in, LINE6_ISO_BUFFERS); 34 find_first_zero_bit(&line6pcm->in.active_urbs, LINE6_ISO_BUFFERS);
35 35
36 if (index < 0 || index >= LINE6_ISO_BUFFERS) { 36 if (index < 0 || index >= LINE6_ISO_BUFFERS) {
37 spin_unlock_irqrestore(&line6pcm->lock_audio_in, flags); 37 spin_unlock_irqrestore(&line6pcm->in.lock, flags);
38 dev_err(line6pcm->line6->ifcdev, "no free URB found\n"); 38 dev_err(line6pcm->line6->ifcdev, "no free URB found\n");
39 return -EINVAL; 39 return -EINVAL;
40 } 40 }
41 41
42 urb_in = line6pcm->urb_audio_in[index]; 42 urb_in = line6pcm->in.urbs[index];
43 urb_size = 0; 43 urb_size = 0;
44 44
45 for (i = 0; i < LINE6_ISO_PACKETS; ++i) { 45 for (i = 0; i < LINE6_ISO_PACKETS; ++i) {
@@ -51,7 +51,7 @@ static int submit_audio_in_urb(struct snd_line6_pcm *line6pcm)
51 } 51 }
52 52
53 urb_in->transfer_buffer = 53 urb_in->transfer_buffer =
54 line6pcm->buffer_in + 54 line6pcm->in.buffer +
55 index * LINE6_ISO_PACKETS * line6pcm->max_packet_size; 55 index * LINE6_ISO_PACKETS * line6pcm->max_packet_size;
56 urb_in->transfer_buffer_length = urb_size; 56 urb_in->transfer_buffer_length = urb_size;
57 urb_in->context = line6pcm; 57 urb_in->context = line6pcm;
@@ -59,12 +59,12 @@ static int submit_audio_in_urb(struct snd_line6_pcm *line6pcm)
59 ret = usb_submit_urb(urb_in, GFP_ATOMIC); 59 ret = usb_submit_urb(urb_in, GFP_ATOMIC);
60 60
61 if (ret == 0) 61 if (ret == 0)
62 set_bit(index, &line6pcm->active_urb_in); 62 set_bit(index, &line6pcm->in.active_urbs);
63 else 63 else
64 dev_err(line6pcm->line6->ifcdev, 64 dev_err(line6pcm->line6->ifcdev,
65 "URB in #%d submission failed (%d)\n", index, ret); 65 "URB in #%d submission failed (%d)\n", index, ret);
66 66
67 spin_unlock_irqrestore(&line6pcm->lock_audio_in, flags); 67 spin_unlock_irqrestore(&line6pcm->in.lock, flags);
68 return 0; 68 return 0;
69} 69}
70 70
@@ -92,9 +92,9 @@ void line6_unlink_audio_in_urbs(struct snd_line6_pcm *line6pcm)
92 unsigned int i; 92 unsigned int i;
93 93
94 for (i = 0; i < LINE6_ISO_BUFFERS; i++) { 94 for (i = 0; i < LINE6_ISO_BUFFERS; i++) {
95 if (test_bit(i, &line6pcm->active_urb_in)) { 95 if (test_bit(i, &line6pcm->in.active_urbs)) {
96 if (!test_and_set_bit(i, &line6pcm->unlink_urb_in)) { 96 if (!test_and_set_bit(i, &line6pcm->in.unlink_urbs)) {
97 struct urb *u = line6pcm->urb_audio_in[i]; 97 struct urb *u = line6pcm->in.urbs[i];
98 98
99 usb_unlink_urb(u); 99 usb_unlink_urb(u);
100 } 100 }
@@ -115,7 +115,7 @@ void line6_wait_clear_audio_in_urbs(struct snd_line6_pcm *line6pcm)
115 do { 115 do {
116 alive = 0; 116 alive = 0;
117 for (i = 0; i < LINE6_ISO_BUFFERS; i++) { 117 for (i = 0; i < LINE6_ISO_BUFFERS; i++) {
118 if (test_bit(i, &line6pcm->active_urb_in)) 118 if (test_bit(i, &line6pcm->in.active_urbs))
119 alive++; 119 alive++;
120 } 120 }
121 if (!alive) 121 if (!alive)
@@ -150,18 +150,18 @@ void line6_capture_copy(struct snd_line6_pcm *line6pcm, char *fbuf, int fsize)
150 if (runtime == NULL) 150 if (runtime == NULL)
151 return; 151 return;
152 152
153 if (line6pcm->pos_in_done + frames > runtime->buffer_size) { 153 if (line6pcm->in.pos_done + frames > runtime->buffer_size) {
154 /* 154 /*
155 The transferred area goes over buffer boundary, 155 The transferred area goes over buffer boundary,
156 copy two separate chunks. 156 copy two separate chunks.
157 */ 157 */
158 int len; 158 int len;
159 159
160 len = runtime->buffer_size - line6pcm->pos_in_done; 160 len = runtime->buffer_size - line6pcm->in.pos_done;
161 161
162 if (len > 0) { 162 if (len > 0) {
163 memcpy(runtime->dma_area + 163 memcpy(runtime->dma_area +
164 line6pcm->pos_in_done * bytes_per_frame, fbuf, 164 line6pcm->in.pos_done * bytes_per_frame, fbuf,
165 len * bytes_per_frame); 165 len * bytes_per_frame);
166 memcpy(runtime->dma_area, fbuf + len * bytes_per_frame, 166 memcpy(runtime->dma_area, fbuf + len * bytes_per_frame,
167 (frames - len) * bytes_per_frame); 167 (frames - len) * bytes_per_frame);
@@ -173,12 +173,12 @@ void line6_capture_copy(struct snd_line6_pcm *line6pcm, char *fbuf, int fsize)
173 } else { 173 } else {
174 /* copy single chunk */ 174 /* copy single chunk */
175 memcpy(runtime->dma_area + 175 memcpy(runtime->dma_area +
176 line6pcm->pos_in_done * bytes_per_frame, fbuf, fsize); 176 line6pcm->in.pos_done * bytes_per_frame, fbuf, fsize);
177 } 177 }
178 178
179 line6pcm->pos_in_done += frames; 179 line6pcm->in.pos_done += frames;
180 if (line6pcm->pos_in_done >= runtime->buffer_size) 180 if (line6pcm->in.pos_done >= runtime->buffer_size)
181 line6pcm->pos_in_done -= runtime->buffer_size; 181 line6pcm->in.pos_done -= runtime->buffer_size;
182} 182}
183 183
184void line6_capture_check_period(struct snd_line6_pcm *line6pcm, int length) 184void line6_capture_check_period(struct snd_line6_pcm *line6pcm, int length)
@@ -186,17 +186,17 @@ void line6_capture_check_period(struct snd_line6_pcm *line6pcm, int length)
186 struct snd_pcm_substream *substream = 186 struct snd_pcm_substream *substream =
187 get_substream(line6pcm, SNDRV_PCM_STREAM_CAPTURE); 187 get_substream(line6pcm, SNDRV_PCM_STREAM_CAPTURE);
188 188
189 line6pcm->bytes_in += length; 189 line6pcm->in.bytes += length;
190 if (line6pcm->bytes_in >= line6pcm->period_in) { 190 if (line6pcm->in.bytes >= line6pcm->in.period) {
191 line6pcm->bytes_in %= line6pcm->period_in; 191 line6pcm->in.bytes %= line6pcm->in.period;
192 snd_pcm_period_elapsed(substream); 192 snd_pcm_period_elapsed(substream);
193 } 193 }
194} 194}
195 195
196void line6_free_capture_buffer(struct snd_line6_pcm *line6pcm) 196void line6_free_capture_buffer(struct snd_line6_pcm *line6pcm)
197{ 197{
198 kfree(line6pcm->buffer_in); 198 kfree(line6pcm->in.buffer);
199 line6pcm->buffer_in = NULL; 199 line6pcm->in.buffer = NULL;
200} 200}
201 201
202/* 202/*
@@ -209,14 +209,14 @@ static void audio_in_callback(struct urb *urb)
209 209
210 struct snd_line6_pcm *line6pcm = (struct snd_line6_pcm *)urb->context; 210 struct snd_line6_pcm *line6pcm = (struct snd_line6_pcm *)urb->context;
211 211
212 line6pcm->last_frame_in = urb->start_frame; 212 line6pcm->in.last_frame = urb->start_frame;
213 213
214 /* find index of URB */ 214 /* find index of URB */
215 for (index = 0; index < LINE6_ISO_BUFFERS; ++index) 215 for (index = 0; index < LINE6_ISO_BUFFERS; ++index)
216 if (urb == line6pcm->urb_audio_in[index]) 216 if (urb == line6pcm->in.urbs[index])
217 break; 217 break;
218 218
219 spin_lock_irqsave(&line6pcm->lock_audio_in, flags); 219 spin_lock_irqsave(&line6pcm->in.lock, flags);
220 220
221 for (i = 0; i < LINE6_ISO_PACKETS; ++i) { 221 for (i = 0; i < LINE6_ISO_PACKETS; ++i) {
222 char *fbuf; 222 char *fbuf;
@@ -249,12 +249,12 @@ static void audio_in_callback(struct urb *urb)
249 line6_capture_copy(line6pcm, fbuf, fsize); 249 line6_capture_copy(line6pcm, fbuf, fsize);
250 } 250 }
251 251
252 clear_bit(index, &line6pcm->active_urb_in); 252 clear_bit(index, &line6pcm->in.active_urbs);
253 253
254 if (test_and_clear_bit(index, &line6pcm->unlink_urb_in)) 254 if (test_and_clear_bit(index, &line6pcm->in.unlink_urbs))
255 shutdown = 1; 255 shutdown = 1;
256 256
257 spin_unlock_irqrestore(&line6pcm->lock_audio_in, flags); 257 spin_unlock_irqrestore(&line6pcm->in.lock, flags);
258 258
259 if (!shutdown) { 259 if (!shutdown) {
260 submit_audio_in_urb(line6pcm); 260 submit_audio_in_urb(line6pcm);
@@ -309,7 +309,7 @@ static int snd_line6_capture_hw_params(struct snd_pcm_substream *substream,
309 return ret; 309 return ret;
310 } 310 }
311 311
312 line6pcm->period_in = params_period_bytes(hw_params); 312 line6pcm->in.period = params_period_bytes(hw_params);
313 return 0; 313 return 0;
314} 314}
315 315
@@ -361,7 +361,7 @@ snd_line6_capture_pointer(struct snd_pcm_substream *substream)
361{ 361{
362 struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream); 362 struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
363 363
364 return line6pcm->pos_in_done; 364 return line6pcm->in.pos_done;
365} 365}
366 366
367/* capture operators */ 367/* capture operators */
@@ -386,7 +386,7 @@ int line6_create_audio_in_urbs(struct snd_line6_pcm *line6pcm)
386 struct urb *urb; 386 struct urb *urb;
387 387
388 /* URB for audio in: */ 388 /* URB for audio in: */
389 urb = line6pcm->urb_audio_in[i] = 389 urb = line6pcm->in.urbs[i] =
390 usb_alloc_urb(LINE6_ISO_PACKETS, GFP_KERNEL); 390 usb_alloc_urb(LINE6_ISO_PACKETS, GFP_KERNEL);
391 391
392 if (urb == NULL) 392 if (urb == NULL)
diff --git a/sound/usb/line6/pcm.c b/sound/usb/line6/pcm.c
index 43474c4ebb6b..738bfd82cecd 100644
--- a/sound/usb/line6/pcm.c
+++ b/sound/usb/line6/pcm.c
@@ -112,11 +112,11 @@ int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int channels)
112 112
113 if (test_flags(flags_old, flags_new, LINE6_BITS_CAPTURE_BUFFER)) { 113 if (test_flags(flags_old, flags_new, LINE6_BITS_CAPTURE_BUFFER)) {
114 /* Invoked multiple times in a row so allocate once only */ 114 /* Invoked multiple times in a row so allocate once only */
115 if (!line6pcm->buffer_in) { 115 if (!line6pcm->in.buffer) {
116 line6pcm->buffer_in = 116 line6pcm->in.buffer =
117 kmalloc(LINE6_ISO_BUFFERS * LINE6_ISO_PACKETS * 117 kmalloc(LINE6_ISO_BUFFERS * LINE6_ISO_PACKETS *
118 line6pcm->max_packet_size, GFP_KERNEL); 118 line6pcm->max_packet_size, GFP_KERNEL);
119 if (!line6pcm->buffer_in) { 119 if (!line6pcm->in.buffer) {
120 err = -ENOMEM; 120 err = -ENOMEM;
121 goto pcm_acquire_error; 121 goto pcm_acquire_error;
122 } 122 }
@@ -131,13 +131,13 @@ int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int channels)
131 a bug, we therefore report an error if capturing is restarted 131 a bug, we therefore report an error if capturing is restarted
132 too soon. 132 too soon.
133 */ 133 */
134 if (line6pcm->active_urb_in || line6pcm->unlink_urb_in) { 134 if (line6pcm->in.active_urbs || line6pcm->in.unlink_urbs) {
135 dev_err(line6pcm->line6->ifcdev, "Device not yet ready\n"); 135 dev_err(line6pcm->line6->ifcdev, "Device not yet ready\n");
136 err = -EBUSY; 136 err = -EBUSY;
137 goto pcm_acquire_error; 137 goto pcm_acquire_error;
138 } 138 }
139 139
140 line6pcm->count_in = 0; 140 line6pcm->in.count = 0;
141 line6pcm->prev_fsize = 0; 141 line6pcm->prev_fsize = 0;
142 err = line6_submit_audio_in_all_urbs(line6pcm); 142 err = line6_submit_audio_in_all_urbs(line6pcm);
143 143
@@ -149,11 +149,11 @@ int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int channels)
149 149
150 if (test_flags(flags_old, flags_new, LINE6_BITS_PLAYBACK_BUFFER)) { 150 if (test_flags(flags_old, flags_new, LINE6_BITS_PLAYBACK_BUFFER)) {
151 /* Invoked multiple times in a row so allocate once only */ 151 /* Invoked multiple times in a row so allocate once only */
152 if (!line6pcm->buffer_out) { 152 if (!line6pcm->out.buffer) {
153 line6pcm->buffer_out = 153 line6pcm->out.buffer =
154 kmalloc(LINE6_ISO_BUFFERS * LINE6_ISO_PACKETS * 154 kmalloc(LINE6_ISO_BUFFERS * LINE6_ISO_PACKETS *
155 line6pcm->max_packet_size, GFP_KERNEL); 155 line6pcm->max_packet_size, GFP_KERNEL);
156 if (!line6pcm->buffer_out) { 156 if (!line6pcm->out.buffer) {
157 err = -ENOMEM; 157 err = -ENOMEM;
158 goto pcm_acquire_error; 158 goto pcm_acquire_error;
159 } 159 }
@@ -166,12 +166,12 @@ int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int channels)
166 /* 166 /*
167 See comment above regarding PCM restart. 167 See comment above regarding PCM restart.
168 */ 168 */
169 if (line6pcm->active_urb_out || line6pcm->unlink_urb_out) { 169 if (line6pcm->out.active_urbs || line6pcm->out.unlink_urbs) {
170 dev_err(line6pcm->line6->ifcdev, "Device not yet ready\n"); 170 dev_err(line6pcm->line6->ifcdev, "Device not yet ready\n");
171 return -EBUSY; 171 return -EBUSY;
172 } 172 }
173 173
174 line6pcm->count_out = 0; 174 line6pcm->out.count = 0;
175 err = line6_submit_audio_out_all_urbs(line6pcm); 175 err = line6_submit_audio_out_all_urbs(line6pcm);
176 176
177 if (err < 0) 177 if (err < 0)
@@ -331,13 +331,13 @@ static void line6_cleanup_pcm(struct snd_pcm *pcm)
331 struct snd_line6_pcm *line6pcm = snd_pcm_chip(pcm); 331 struct snd_line6_pcm *line6pcm = snd_pcm_chip(pcm);
332 332
333 for (i = 0; i < LINE6_ISO_BUFFERS; i++) { 333 for (i = 0; i < LINE6_ISO_BUFFERS; i++) {
334 if (line6pcm->urb_audio_out[i]) { 334 if (line6pcm->out.urbs[i]) {
335 usb_kill_urb(line6pcm->urb_audio_out[i]); 335 usb_kill_urb(line6pcm->out.urbs[i]);
336 usb_free_urb(line6pcm->urb_audio_out[i]); 336 usb_free_urb(line6pcm->out.urbs[i]);
337 } 337 }
338 if (line6pcm->urb_audio_in[i]) { 338 if (line6pcm->in.urbs[i]) {
339 usb_kill_urb(line6pcm->urb_audio_in[i]); 339 usb_kill_urb(line6pcm->in.urbs[i]);
340 usb_free_urb(line6pcm->urb_audio_in[i]); 340 usb_free_urb(line6pcm->in.urbs[i]);
341 } 341 }
342 } 342 }
343 kfree(line6pcm); 343 kfree(line6pcm);
@@ -415,8 +415,8 @@ int line6_init_pcm(struct usb_line6 *line6,
415 usb_maxpacket(line6->usbdev, 415 usb_maxpacket(line6->usbdev,
416 usb_sndisocpipe(line6->usbdev, ep_write), 1)); 416 usb_sndisocpipe(line6->usbdev, ep_write), 1));
417 417
418 spin_lock_init(&line6pcm->lock_audio_out); 418 spin_lock_init(&line6pcm->out.lock);
419 spin_lock_init(&line6pcm->lock_audio_in); 419 spin_lock_init(&line6pcm->in.lock);
420 line6pcm->impulse_period = LINE6_IMPULSE_DEFAULT_PERIOD; 420 line6pcm->impulse_period = LINE6_IMPULSE_DEFAULT_PERIOD;
421 421
422 line6->line6pcm = line6pcm; 422 line6->line6pcm = line6pcm;
@@ -464,13 +464,13 @@ int snd_line6_prepare(struct snd_pcm_substream *substream)
464 } 464 }
465 465
466 if (!test_and_set_bit(LINE6_INDEX_PREPARED, &line6pcm->flags)) { 466 if (!test_and_set_bit(LINE6_INDEX_PREPARED, &line6pcm->flags)) {
467 line6pcm->count_out = 0; 467 line6pcm->out.count = 0;
468 line6pcm->pos_out = 0; 468 line6pcm->out.pos = 0;
469 line6pcm->pos_out_done = 0; 469 line6pcm->out.pos_done = 0;
470 line6pcm->bytes_out = 0; 470 line6pcm->out.bytes = 0;
471 line6pcm->count_in = 0; 471 line6pcm->in.count = 0;
472 line6pcm->pos_in_done = 0; 472 line6pcm->in.pos_done = 0;
473 line6pcm->bytes_in = 0; 473 line6pcm->in.bytes = 0;
474 } 474 }
475 475
476 return 0; 476 return 0;
diff --git a/sound/usb/line6/pcm.h b/sound/usb/line6/pcm.h
index a84753ee0fa2..4c74f4e85074 100644
--- a/sound/usb/line6/pcm.h
+++ b/sound/usb/line6/pcm.h
@@ -165,115 +165,78 @@ struct line6_pcm_properties {
165 int bytes_per_frame; 165 int bytes_per_frame;
166}; 166};
167 167
168struct snd_line6_pcm { 168struct line6_pcm_stream {
169 /** 169 /* allocated URBs */
170 Pointer back to the Line 6 driver data structure. 170 struct urb *urbs[LINE6_ISO_BUFFERS];
171 */
172 struct usb_line6 *line6;
173 171
174 /** 172 /* Temporary buffer;
175 Properties. 173 * Since the packet size is not known in advance, this buffer is
176 */ 174 * large enough to store maximum size packets.
177 struct line6_pcm_properties *properties; 175 */
176 unsigned char *buffer;
178 177
179 /** 178 /* Free frame position in the buffer. */
180 ALSA pcm stream 179 snd_pcm_uframes_t pos;
181 */
182 struct snd_pcm *pcm;
183 180
184 /** 181 /* Count processed bytes;
185 URBs for audio playback. 182 * This is modulo period size (to determine when a period is finished).
186 */ 183 */
187 struct urb *urb_audio_out[LINE6_ISO_BUFFERS]; 184 unsigned bytes;
188 185
189 /** 186 /* Counter to create desired sample rate */
190 URBs for audio capture. 187 unsigned count;
191 */
192 struct urb *urb_audio_in[LINE6_ISO_BUFFERS];
193 188
194 /** 189 /* period size in bytes */
195 Temporary buffer for playback. 190 unsigned period;
196 Since the packet size is not known in advance, this buffer is
197 large enough to store maximum size packets.
198 */
199 unsigned char *buffer_out;
200 191
201 /** 192 /* Processed frame position in the buffer;
202 Temporary buffer for capture. 193 * The contents of the ring buffer have been consumed by the USB
203 Since the packet size is not known in advance, this buffer is 194 * subsystem (i.e., sent to the USB device) up to this position.
204 large enough to store maximum size packets. 195 */
205 */ 196 snd_pcm_uframes_t pos_done;
206 unsigned char *buffer_in;
207 197
208 /** 198 /* Bit mask of active URBs */
209 Previously captured frame (for software monitoring). 199 unsigned long active_urbs;
210 */
211 unsigned char *prev_fbuf;
212 200
213 /** 201 /* Bit mask of URBs currently being unlinked */
214 Size of previously captured frame (for software monitoring). 202 unsigned long unlink_urbs;
215 */
216 int prev_fsize;
217
218 /**
219 Free frame position in the playback buffer.
220 */
221 snd_pcm_uframes_t pos_out;
222 203
223 /** 204 /* Spin lock to protect updates of the buffer positions (not contents)
224 Count processed bytes for playback. 205 */
225 This is modulo period size (to determine when a period is 206 spinlock_t lock;
226 finished).
227 */
228 unsigned bytes_out;
229 207
230 /** 208 int last_frame;
231 Counter to create desired playback sample rate. 209};
232 */
233 unsigned count_out;
234
235 /**
236 Playback period size in bytes
237 */
238 unsigned period_out;
239 210
211struct snd_line6_pcm {
240 /** 212 /**
241 Processed frame position in the playback buffer. 213 Pointer back to the Line 6 driver data structure.
242 The contents of the output ring buffer have been consumed by
243 the USB subsystem (i.e., sent to the USB device) up to this
244 position.
245 */ 214 */
246 snd_pcm_uframes_t pos_out_done; 215 struct usb_line6 *line6;
247 216
248 /** 217 /**
249 Count processed bytes for capture. 218 Properties.
250 This is modulo period size (to determine when a period is
251 finished).
252 */ 219 */
253 unsigned bytes_in; 220 struct line6_pcm_properties *properties;
254 221
255 /** 222 /**
256 Counter to create desired capture sample rate. 223 ALSA pcm stream
257 */ 224 */
258 unsigned count_in; 225 struct snd_pcm *pcm;
259 226
260 /** 227 /* Capture and playback streams */
261 Capture period size in bytes 228 struct line6_pcm_stream in;
262 */ 229 struct line6_pcm_stream out;
263 unsigned period_in;
264 230
265 /** 231 /**
266 Processed frame position in the capture buffer. 232 Previously captured frame (for software monitoring).
267 The contents of the output ring buffer have been consumed by
268 the USB subsystem (i.e., sent to the USB device) up to this
269 position.
270 */ 233 */
271 snd_pcm_uframes_t pos_in_done; 234 unsigned char *prev_fbuf;
272 235
273 /** 236 /**
274 Bit mask of active playback URBs. 237 Size of previously captured frame (for software monitoring).
275 */ 238 */
276 unsigned long active_urb_out; 239 int prev_fsize;
277 240
278 /** 241 /**
279 Maximum size of USB packet. 242 Maximum size of USB packet.
@@ -281,33 +244,6 @@ struct snd_line6_pcm {
281 int max_packet_size; 244 int max_packet_size;
282 245
283 /** 246 /**
284 Bit mask of active capture URBs.
285 */
286 unsigned long active_urb_in;
287
288 /**
289 Bit mask of playback URBs currently being unlinked.
290 */
291 unsigned long unlink_urb_out;
292
293 /**
294 Bit mask of capture URBs currently being unlinked.
295 */
296 unsigned long unlink_urb_in;
297
298 /**
299 Spin lock to protect updates of the playback buffer positions (not
300 contents!)
301 */
302 spinlock_t lock_audio_out;
303
304 /**
305 Spin lock to protect updates of the capture buffer positions (not
306 contents!)
307 */
308 spinlock_t lock_audio_in;
309
310 /**
311 PCM playback volume (left and right). 247 PCM playback volume (left and right).
312 */ 248 */
313 int volume_playback[2]; 249 int volume_playback[2];
@@ -336,8 +272,6 @@ struct snd_line6_pcm {
336 Several status bits (see LINE6_BIT_*). 272 Several status bits (see LINE6_BIT_*).
337 */ 273 */
338 unsigned long flags; 274 unsigned long flags;
339
340 int last_frame_in, last_frame_out;
341}; 275};
342 276
343extern int line6_init_pcm(struct usb_line6 *line6, 277extern int line6_init_pcm(struct usb_line6 *line6,
diff --git a/sound/usb/line6/playback.c b/sound/usb/line6/playback.c
index 7e031b1761aa..d619c1718306 100644
--- a/sound/usb/line6/playback.c
+++ b/sound/usb/line6/playback.c
@@ -145,17 +145,17 @@ static int submit_audio_out_urb(struct snd_line6_pcm *line6pcm)
145 (USB_INTERVALS_PER_SECOND / LINE6_ISO_INTERVAL); 145 (USB_INTERVALS_PER_SECOND / LINE6_ISO_INTERVAL);
146 struct urb *urb_out; 146 struct urb *urb_out;
147 147
148 spin_lock_irqsave(&line6pcm->lock_audio_out, flags); 148 spin_lock_irqsave(&line6pcm->out.lock, flags);
149 index = 149 index =
150 find_first_zero_bit(&line6pcm->active_urb_out, LINE6_ISO_BUFFERS); 150 find_first_zero_bit(&line6pcm->out.active_urbs, LINE6_ISO_BUFFERS);
151 151
152 if (index < 0 || index >= LINE6_ISO_BUFFERS) { 152 if (index < 0 || index >= LINE6_ISO_BUFFERS) {
153 spin_unlock_irqrestore(&line6pcm->lock_audio_out, flags); 153 spin_unlock_irqrestore(&line6pcm->out.lock, flags);
154 dev_err(line6pcm->line6->ifcdev, "no free URB found\n"); 154 dev_err(line6pcm->line6->ifcdev, "no free URB found\n");
155 return -EINVAL; 155 return -EINVAL;
156 } 156 }
157 157
158 urb_out = line6pcm->urb_audio_out[index]; 158 urb_out = line6pcm->out.urbs[index];
159 urb_size = 0; 159 urb_size = 0;
160 160
161 for (i = 0; i < LINE6_ISO_PACKETS; ++i) { 161 for (i = 0; i < LINE6_ISO_PACKETS; ++i) {
@@ -170,9 +170,9 @@ static int submit_audio_out_urb(struct snd_line6_pcm *line6pcm)
170 if (fsize == 0) { 170 if (fsize == 0) {
171 int n; 171 int n;
172 172
173 line6pcm->count_out += frame_increment; 173 line6pcm->out.count += frame_increment;
174 n = line6pcm->count_out / frame_factor; 174 n = line6pcm->out.count / frame_factor;
175 line6pcm->count_out -= n * frame_factor; 175 line6pcm->out.count -= n * frame_factor;
176 fsize = n * bytes_per_frame; 176 fsize = n * bytes_per_frame;
177 } 177 }
178 178
@@ -183,14 +183,14 @@ static int submit_audio_out_urb(struct snd_line6_pcm *line6pcm)
183 183
184 if (urb_size == 0) { 184 if (urb_size == 0) {
185 /* can't determine URB size */ 185 /* can't determine URB size */
186 spin_unlock_irqrestore(&line6pcm->lock_audio_out, flags); 186 spin_unlock_irqrestore(&line6pcm->out.lock, flags);
187 dev_err(line6pcm->line6->ifcdev, "driver bug: urb_size = 0\n"); 187 dev_err(line6pcm->line6->ifcdev, "driver bug: urb_size = 0\n");
188 return -EINVAL; 188 return -EINVAL;
189 } 189 }
190 190
191 urb_frames = urb_size / bytes_per_frame; 191 urb_frames = urb_size / bytes_per_frame;
192 urb_out->transfer_buffer = 192 urb_out->transfer_buffer =
193 line6pcm->buffer_out + 193 line6pcm->out.buffer +
194 index * LINE6_ISO_PACKETS * line6pcm->max_packet_size; 194 index * LINE6_ISO_PACKETS * line6pcm->max_packet_size;
195 urb_out->transfer_buffer_length = urb_size; 195 urb_out->transfer_buffer_length = urb_size;
196 urb_out->context = line6pcm; 196 urb_out->context = line6pcm;
@@ -200,19 +200,19 @@ static int submit_audio_out_urb(struct snd_line6_pcm *line6pcm)
200 struct snd_pcm_runtime *runtime = 200 struct snd_pcm_runtime *runtime =
201 get_substream(line6pcm, SNDRV_PCM_STREAM_PLAYBACK)->runtime; 201 get_substream(line6pcm, SNDRV_PCM_STREAM_PLAYBACK)->runtime;
202 202
203 if (line6pcm->pos_out + urb_frames > runtime->buffer_size) { 203 if (line6pcm->out.pos + urb_frames > runtime->buffer_size) {
204 /* 204 /*
205 The transferred area goes over buffer boundary, 205 The transferred area goes over buffer boundary,
206 copy the data to the temp buffer. 206 copy the data to the temp buffer.
207 */ 207 */
208 int len; 208 int len;
209 209
210 len = runtime->buffer_size - line6pcm->pos_out; 210 len = runtime->buffer_size - line6pcm->out.pos;
211 211
212 if (len > 0) { 212 if (len > 0) {
213 memcpy(urb_out->transfer_buffer, 213 memcpy(urb_out->transfer_buffer,
214 runtime->dma_area + 214 runtime->dma_area +
215 line6pcm->pos_out * bytes_per_frame, 215 line6pcm->out.pos * bytes_per_frame,
216 len * bytes_per_frame); 216 len * bytes_per_frame);
217 memcpy(urb_out->transfer_buffer + 217 memcpy(urb_out->transfer_buffer +
218 len * bytes_per_frame, runtime->dma_area, 218 len * bytes_per_frame, runtime->dma_area,
@@ -223,13 +223,13 @@ static int submit_audio_out_urb(struct snd_line6_pcm *line6pcm)
223 } else { 223 } else {
224 memcpy(urb_out->transfer_buffer, 224 memcpy(urb_out->transfer_buffer,
225 runtime->dma_area + 225 runtime->dma_area +
226 line6pcm->pos_out * bytes_per_frame, 226 line6pcm->out.pos * bytes_per_frame,
227 urb_out->transfer_buffer_length); 227 urb_out->transfer_buffer_length);
228 } 228 }
229 229
230 line6pcm->pos_out += urb_frames; 230 line6pcm->out.pos += urb_frames;
231 if (line6pcm->pos_out >= runtime->buffer_size) 231 if (line6pcm->out.pos >= runtime->buffer_size)
232 line6pcm->pos_out -= runtime->buffer_size; 232 line6pcm->out.pos -= runtime->buffer_size;
233 } else { 233 } else {
234 memset(urb_out->transfer_buffer, 0, 234 memset(urb_out->transfer_buffer, 0,
235 urb_out->transfer_buffer_length); 235 urb_out->transfer_buffer_length);
@@ -265,12 +265,12 @@ static int submit_audio_out_urb(struct snd_line6_pcm *line6pcm)
265 ret = usb_submit_urb(urb_out, GFP_ATOMIC); 265 ret = usb_submit_urb(urb_out, GFP_ATOMIC);
266 266
267 if (ret == 0) 267 if (ret == 0)
268 set_bit(index, &line6pcm->active_urb_out); 268 set_bit(index, &line6pcm->out.active_urbs);
269 else 269 else
270 dev_err(line6pcm->line6->ifcdev, 270 dev_err(line6pcm->line6->ifcdev,
271 "URB out #%d submission failed (%d)\n", index, ret); 271 "URB out #%d submission failed (%d)\n", index, ret);
272 272
273 spin_unlock_irqrestore(&line6pcm->lock_audio_out, flags); 273 spin_unlock_irqrestore(&line6pcm->out.lock, flags);
274 return 0; 274 return 0;
275} 275}
276 276
@@ -298,9 +298,9 @@ void line6_unlink_audio_out_urbs(struct snd_line6_pcm *line6pcm)
298 unsigned int i; 298 unsigned int i;
299 299
300 for (i = 0; i < LINE6_ISO_BUFFERS; i++) { 300 for (i = 0; i < LINE6_ISO_BUFFERS; i++) {
301 if (test_bit(i, &line6pcm->active_urb_out)) { 301 if (test_bit(i, &line6pcm->out.active_urbs)) {
302 if (!test_and_set_bit(i, &line6pcm->unlink_urb_out)) { 302 if (!test_and_set_bit(i, &line6pcm->out.unlink_urbs)) {
303 struct urb *u = line6pcm->urb_audio_out[i]; 303 struct urb *u = line6pcm->out.urbs[i];
304 304
305 usb_unlink_urb(u); 305 usb_unlink_urb(u);
306 } 306 }
@@ -321,7 +321,7 @@ void line6_wait_clear_audio_out_urbs(struct snd_line6_pcm *line6pcm)
321 do { 321 do {
322 alive = 0; 322 alive = 0;
323 for (i = 0; i < LINE6_ISO_BUFFERS; i++) { 323 for (i = 0; i < LINE6_ISO_BUFFERS; i++) {
324 if (test_bit(i, &line6pcm->active_urb_out)) 324 if (test_bit(i, &line6pcm->out.active_urbs))
325 alive++; 325 alive++;
326 } 326 }
327 if (!alive) 327 if (!alive)
@@ -344,8 +344,8 @@ void line6_unlink_wait_clear_audio_out_urbs(struct snd_line6_pcm *line6pcm)
344 344
345void line6_free_playback_buffer(struct snd_line6_pcm *line6pcm) 345void line6_free_playback_buffer(struct snd_line6_pcm *line6pcm)
346{ 346{
347 kfree(line6pcm->buffer_out); 347 kfree(line6pcm->out.buffer);
348 line6pcm->buffer_out = NULL; 348 line6pcm->out.buffer = NULL;
349} 349}
350 350
351/* 351/*
@@ -363,11 +363,11 @@ static void audio_out_callback(struct urb *urb)
363 memset(urb->transfer_buffer, 0, urb->transfer_buffer_length); 363 memset(urb->transfer_buffer, 0, urb->transfer_buffer_length);
364#endif 364#endif
365 365
366 line6pcm->last_frame_out = urb->start_frame; 366 line6pcm->out.last_frame = urb->start_frame;
367 367
368 /* find index of URB */ 368 /* find index of URB */
369 for (index = 0; index < LINE6_ISO_BUFFERS; index++) 369 for (index = 0; index < LINE6_ISO_BUFFERS; index++)
370 if (urb == line6pcm->urb_audio_out[index]) 370 if (urb == line6pcm->out.urbs[index])
371 break; 371 break;
372 372
373 if (index >= LINE6_ISO_BUFFERS) 373 if (index >= LINE6_ISO_BUFFERS)
@@ -376,19 +376,19 @@ static void audio_out_callback(struct urb *urb)
376 for (i = 0; i < LINE6_ISO_PACKETS; i++) 376 for (i = 0; i < LINE6_ISO_PACKETS; i++)
377 length += urb->iso_frame_desc[i].length; 377 length += urb->iso_frame_desc[i].length;
378 378
379 spin_lock_irqsave(&line6pcm->lock_audio_out, flags); 379 spin_lock_irqsave(&line6pcm->out.lock, flags);
380 380
381 if (test_bit(LINE6_INDEX_PCM_ALSA_PLAYBACK_STREAM, &line6pcm->flags)) { 381 if (test_bit(LINE6_INDEX_PCM_ALSA_PLAYBACK_STREAM, &line6pcm->flags)) {
382 struct snd_pcm_runtime *runtime = substream->runtime; 382 struct snd_pcm_runtime *runtime = substream->runtime;
383 383
384 line6pcm->pos_out_done += 384 line6pcm->out.pos_done +=
385 length / line6pcm->properties->bytes_per_frame; 385 length / line6pcm->properties->bytes_per_frame;
386 386
387 if (line6pcm->pos_out_done >= runtime->buffer_size) 387 if (line6pcm->out.pos_done >= runtime->buffer_size)
388 line6pcm->pos_out_done -= runtime->buffer_size; 388 line6pcm->out.pos_done -= runtime->buffer_size;
389 } 389 }
390 390
391 clear_bit(index, &line6pcm->active_urb_out); 391 clear_bit(index, &line6pcm->out.active_urbs);
392 392
393 for (i = 0; i < LINE6_ISO_PACKETS; i++) 393 for (i = 0; i < LINE6_ISO_PACKETS; i++)
394 if (urb->iso_frame_desc[i].status == -EXDEV) { 394 if (urb->iso_frame_desc[i].status == -EXDEV) {
@@ -396,19 +396,19 @@ static void audio_out_callback(struct urb *urb)
396 break; 396 break;
397 } 397 }
398 398
399 if (test_and_clear_bit(index, &line6pcm->unlink_urb_out)) 399 if (test_and_clear_bit(index, &line6pcm->out.unlink_urbs))
400 shutdown = 1; 400 shutdown = 1;
401 401
402 spin_unlock_irqrestore(&line6pcm->lock_audio_out, flags); 402 spin_unlock_irqrestore(&line6pcm->out.lock, flags);
403 403
404 if (!shutdown) { 404 if (!shutdown) {
405 submit_audio_out_urb(line6pcm); 405 submit_audio_out_urb(line6pcm);
406 406
407 if (test_bit(LINE6_INDEX_PCM_ALSA_PLAYBACK_STREAM, 407 if (test_bit(LINE6_INDEX_PCM_ALSA_PLAYBACK_STREAM,
408 &line6pcm->flags)) { 408 &line6pcm->flags)) {
409 line6pcm->bytes_out += length; 409 line6pcm->out.bytes += length;
410 if (line6pcm->bytes_out >= line6pcm->period_out) { 410 if (line6pcm->out.bytes >= line6pcm->out.period) {
411 line6pcm->bytes_out %= line6pcm->period_out; 411 line6pcm->out.bytes %= line6pcm->out.period;
412 snd_pcm_period_elapsed(substream); 412 snd_pcm_period_elapsed(substream);
413 } 413 }
414 } 414 }
@@ -457,7 +457,7 @@ static int snd_line6_playback_hw_params(struct snd_pcm_substream *substream,
457 return ret; 457 return ret;
458 } 458 }
459 459
460 line6pcm->period_out = params_period_bytes(hw_params); 460 line6pcm->out.period = params_period_bytes(hw_params);
461 return 0; 461 return 0;
462} 462}
463 463
@@ -517,7 +517,7 @@ snd_line6_playback_pointer(struct snd_pcm_substream *substream)
517{ 517{
518 struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream); 518 struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
519 519
520 return line6pcm->pos_out_done; 520 return line6pcm->out.pos_done;
521} 521}
522 522
523/* playback operators */ 523/* playback operators */
@@ -542,7 +542,7 @@ int line6_create_audio_out_urbs(struct snd_line6_pcm *line6pcm)
542 struct urb *urb; 542 struct urb *urb;
543 543
544 /* URB for audio out: */ 544 /* URB for audio out: */
545 urb = line6pcm->urb_audio_out[i] = 545 urb = line6pcm->out.urbs[i] =
546 usb_alloc_urb(LINE6_ISO_PACKETS, GFP_KERNEL); 546 usb_alloc_urb(LINE6_ISO_PACKETS, GFP_KERNEL);
547 547
548 if (urb == NULL) 548 if (urb == NULL)