blob: 17969c656648ee8c8c8b0c20356e95d3370e5bed [file] [log] [blame]
Markus Grabner705ecec2009-02-27 19:43:04 -08001/*
Markus Grabnere1a164d2010-08-23 01:08:25 +02002 * Line6 Linux USB driver - 0.9.1beta
Markus Grabner705ecec2009-02-27 19:43:04 -08003 *
Markus Grabner1027f4762010-08-12 01:35:30 +02004 * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
Markus Grabner705ecec2009-02-27 19:43:04 -08005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation, version 2.
9 *
10 */
11
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090012#include <linux/slab.h>
Markus Grabner705ecec2009-02-27 19:43:04 -080013#include <sound/core.h>
14#include <sound/control.h>
15#include <sound/pcm.h>
16#include <sound/pcm_params.h>
17
18#include "audio.h"
19#include "capture.h"
Markus Grabner1027f4762010-08-12 01:35:30 +020020#include "driver.h"
Markus Grabner705ecec2009-02-27 19:43:04 -080021#include "playback.h"
22#include "pod.h"
23
Markus Grabner1027f4762010-08-12 01:35:30 +020024#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
25
Markus Grabnere1a164d2010-08-23 01:08:25 +020026static struct snd_line6_pcm *dev2pcm(struct device *dev)
Markus Grabner1027f4762010-08-12 01:35:30 +020027{
28 struct usb_interface *interface = to_usb_interface(dev);
29 struct usb_line6 *line6 = usb_get_intfdata(interface);
30 struct snd_line6_pcm *line6pcm = line6->line6pcm;
31 return line6pcm;
32}
33
34/*
35 "read" request on "impulse_volume" special file.
36*/
37static ssize_t pcm_get_impulse_volume(struct device *dev,
Markus Grabnere1a164d2010-08-23 01:08:25 +020038 struct device_attribute *attr, char *buf)
Markus Grabner1027f4762010-08-12 01:35:30 +020039{
40 return sprintf(buf, "%d\n", dev2pcm(dev)->impulse_volume);
41}
42
43/*
44 "write" request on "impulse_volume" special file.
45*/
46static ssize_t pcm_set_impulse_volume(struct device *dev,
47 struct device_attribute *attr,
48 const char *buf, size_t count)
49{
50 struct snd_line6_pcm *line6pcm = dev2pcm(dev);
Johannes Thumshirncdf5e552012-08-06 14:08:50 +020051 int value;
Laurent Naveta3762902012-11-30 11:57:32 +010052 int ret;
Johannes Thumshirncdf5e552012-08-06 14:08:50 +020053
Laurent Naveta3762902012-11-30 11:57:32 +010054 ret = kstrtoint(buf, 10, &value);
55 if (ret < 0)
56 return ret;
Johannes Thumshirncdf5e552012-08-06 14:08:50 +020057
Markus Grabner1027f4762010-08-12 01:35:30 +020058 line6pcm->impulse_volume = value;
59
Markus Grabnere1a164d2010-08-23 01:08:25 +020060 if (value > 0)
Markus Grabner0ca54882012-01-20 00:09:09 +010061 line6_pcm_acquire(line6pcm, LINE6_BITS_PCM_IMPULSE);
Markus Grabner1027f4762010-08-12 01:35:30 +020062 else
Markus Grabner0ca54882012-01-20 00:09:09 +010063 line6_pcm_release(line6pcm, LINE6_BITS_PCM_IMPULSE);
Markus Grabner1027f4762010-08-12 01:35:30 +020064
65 return count;
66}
67
68/*
69 "read" request on "impulse_period" special file.
70*/
71static ssize_t pcm_get_impulse_period(struct device *dev,
Markus Grabnere1a164d2010-08-23 01:08:25 +020072 struct device_attribute *attr, char *buf)
Markus Grabner1027f4762010-08-12 01:35:30 +020073{
74 return sprintf(buf, "%d\n", dev2pcm(dev)->impulse_period);
75}
76
77/*
78 "write" request on "impulse_period" special file.
79*/
80static ssize_t pcm_set_impulse_period(struct device *dev,
81 struct device_attribute *attr,
82 const char *buf, size_t count)
83{
Laurent Naveta3762902012-11-30 11:57:32 +010084 int value;
85 int ret;
86
87 ret = kstrtoint(buf, 10, &value);
88 if (ret < 0)
89 return ret;
90
91 dev2pcm(dev)->impulse_period = value;
Markus Grabner1027f4762010-08-12 01:35:30 +020092 return count;
93}
94
Greg Kroah-Hartmana3a972a2010-11-18 11:21:04 -080095static DEVICE_ATTR(impulse_volume, S_IWUSR | S_IRUGO, pcm_get_impulse_volume,
Markus Grabnere1a164d2010-08-23 01:08:25 +020096 pcm_set_impulse_volume);
Greg Kroah-Hartmana3a972a2010-11-18 11:21:04 -080097static DEVICE_ATTR(impulse_period, S_IWUSR | S_IRUGO, pcm_get_impulse_period,
Markus Grabnere1a164d2010-08-23 01:08:25 +020098 pcm_set_impulse_period);
Markus Grabner1027f4762010-08-12 01:35:30 +020099
100#endif
101
Markus Grabner6b02a17e2011-12-10 02:12:32 +0100102static bool test_flags(unsigned long flags0, unsigned long flags1,
103 unsigned long mask)
104{
105 return ((flags0 & mask) == 0) && ((flags1 & mask) != 0);
106}
107
Markus Grabner0ca54882012-01-20 00:09:09 +0100108int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int channels)
Markus Grabner1027f4762010-08-12 01:35:30 +0200109{
Markus Grabnere1a164d2010-08-23 01:08:25 +0200110 unsigned long flags_old =
111 __sync_fetch_and_or(&line6pcm->flags, channels);
Markus Grabner1027f4762010-08-12 01:35:30 +0200112 unsigned long flags_new = flags_old | channels;
Markus Grabner0ca54882012-01-20 00:09:09 +0100113 unsigned long flags_final = flags_old;
Markus Grabner1027f4762010-08-12 01:35:30 +0200114 int err = 0;
Johannes Thumshirn82a74d42012-05-05 16:31:52 +0200115
Markus Grabner1027f4762010-08-12 01:35:30 +0200116 line6pcm->prev_fbuf = NULL;
Markus Grabnere1a164d2010-08-23 01:08:25 +0200117
Markus Grabner0ca54882012-01-20 00:09:09 +0100118 if (test_flags(flags_old, flags_new, LINE6_BITS_CAPTURE_BUFFER)) {
Stefan Hajnoczi928f25e2012-11-11 13:24:41 +0100119 /* Invoked multiple times in a row so allocate once only */
Markus Grabner0ca54882012-01-20 00:09:09 +0100120 if (!line6pcm->buffer_in) {
121 line6pcm->buffer_in =
122 kmalloc(LINE6_ISO_BUFFERS * LINE6_ISO_PACKETS *
123 line6pcm->max_packet_size, GFP_KERNEL);
124
125 if (!line6pcm->buffer_in) {
126 dev_err(line6pcm->line6->ifcdev,
127 "cannot malloc capture buffer\n");
128 err = -ENOMEM;
129 goto pcm_acquire_error;
130 }
131
132 flags_final |= channels & LINE6_BITS_CAPTURE_BUFFER;
133 }
134 }
135
136 if (test_flags(flags_old, flags_new, LINE6_BITS_CAPTURE_STREAM)) {
Markus Grabner1027f4762010-08-12 01:35:30 +0200137 /*
Markus Grabnere1a164d2010-08-23 01:08:25 +0200138 Waiting for completion of active URBs in the stop handler is
139 a bug, we therefore report an error if capturing is restarted
140 too soon.
141 */
Markus Grabner0ca54882012-01-20 00:09:09 +0100142 if (line6pcm->active_urb_in | line6pcm->unlink_urb_in) {
143 dev_err(line6pcm->line6->ifcdev, "Device not yet ready\n");
Markus Grabner1027f4762010-08-12 01:35:30 +0200144 return -EBUSY;
Markus Grabner6b02a17e2011-12-10 02:12:32 +0100145 }
146
Markus Grabner1027f4762010-08-12 01:35:30 +0200147 line6pcm->count_in = 0;
148 line6pcm->prev_fsize = 0;
149 err = line6_submit_audio_in_all_urbs(line6pcm);
Markus Grabnere1a164d2010-08-23 01:08:25 +0200150
Markus Grabner6b02a17e2011-12-10 02:12:32 +0100151 if (err < 0)
Markus Grabner0ca54882012-01-20 00:09:09 +0100152 goto pcm_acquire_error;
153
154 flags_final |= channels & LINE6_BITS_CAPTURE_STREAM;
Markus Grabner1027f4762010-08-12 01:35:30 +0200155 }
Markus Grabnere1a164d2010-08-23 01:08:25 +0200156
Markus Grabner0ca54882012-01-20 00:09:09 +0100157 if (test_flags(flags_old, flags_new, LINE6_BITS_PLAYBACK_BUFFER)) {
Stefan Hajnoczi928f25e2012-11-11 13:24:41 +0100158 /* Invoked multiple times in a row so allocate once only */
Markus Grabner0ca54882012-01-20 00:09:09 +0100159 if (!line6pcm->buffer_out) {
160 line6pcm->buffer_out =
161 kmalloc(LINE6_ISO_BUFFERS * LINE6_ISO_PACKETS *
162 line6pcm->max_packet_size, GFP_KERNEL);
163
164 if (!line6pcm->buffer_out) {
165 dev_err(line6pcm->line6->ifcdev,
166 "cannot malloc playback buffer\n");
167 err = -ENOMEM;
168 goto pcm_acquire_error;
169 }
170
171 flags_final |= channels & LINE6_BITS_PLAYBACK_BUFFER;
172 }
173 }
174
175 if (test_flags(flags_old, flags_new, LINE6_BITS_PLAYBACK_STREAM)) {
Markus Grabner1027f4762010-08-12 01:35:30 +0200176 /*
Markus Grabner0ca54882012-01-20 00:09:09 +0100177 See comment above regarding PCM restart.
178 */
179 if (line6pcm->active_urb_out | line6pcm->unlink_urb_out) {
180 dev_err(line6pcm->line6->ifcdev, "Device not yet ready\n");
Markus Grabner1027f4762010-08-12 01:35:30 +0200181 return -EBUSY;
Markus Grabner6b02a17e2011-12-10 02:12:32 +0100182 }
183
Markus Grabner1027f4762010-08-12 01:35:30 +0200184 line6pcm->count_out = 0;
185 err = line6_submit_audio_out_all_urbs(line6pcm);
Markus Grabnere1a164d2010-08-23 01:08:25 +0200186
Markus Grabner6b02a17e2011-12-10 02:12:32 +0100187 if (err < 0)
Markus Grabner0ca54882012-01-20 00:09:09 +0100188 goto pcm_acquire_error;
189
190 flags_final |= channels & LINE6_BITS_PLAYBACK_STREAM;
Markus Grabner1027f4762010-08-12 01:35:30 +0200191 }
Markus Grabnere1a164d2010-08-23 01:08:25 +0200192
Markus Grabner1027f4762010-08-12 01:35:30 +0200193 return 0;
Markus Grabner6b02a17e2011-12-10 02:12:32 +0100194
Markus Grabner0ca54882012-01-20 00:09:09 +0100195pcm_acquire_error:
196 /*
197 If not all requested resources/streams could be obtained, release
198 those which were successfully obtained (if any).
199 */
200 line6_pcm_release(line6pcm, flags_final & channels);
Markus Grabner6b02a17e2011-12-10 02:12:32 +0100201 return err;
Markus Grabner1027f4762010-08-12 01:35:30 +0200202}
203
Markus Grabner0ca54882012-01-20 00:09:09 +0100204int line6_pcm_release(struct snd_line6_pcm *line6pcm, int channels)
Markus Grabner1027f4762010-08-12 01:35:30 +0200205{
Markus Grabnere1a164d2010-08-23 01:08:25 +0200206 unsigned long flags_old =
207 __sync_fetch_and_and(&line6pcm->flags, ~channels);
Markus Grabner1027f4762010-08-12 01:35:30 +0200208 unsigned long flags_new = flags_old & ~channels;
209
Markus Grabner0ca54882012-01-20 00:09:09 +0100210 if (test_flags(flags_new, flags_old, LINE6_BITS_CAPTURE_STREAM))
Markus Grabner1027f4762010-08-12 01:35:30 +0200211 line6_unlink_audio_in_urbs(line6pcm);
Markus Grabner6b02a17e2011-12-10 02:12:32 +0100212
Markus Grabner0ca54882012-01-20 00:09:09 +0100213 if (test_flags(flags_new, flags_old, LINE6_BITS_CAPTURE_BUFFER)) {
214 line6_wait_clear_audio_in_urbs(line6pcm);
215 line6_free_capture_buffer(line6pcm);
Markus Grabner1027f4762010-08-12 01:35:30 +0200216 }
217
Markus Grabner0ca54882012-01-20 00:09:09 +0100218 if (test_flags(flags_new, flags_old, LINE6_BITS_PLAYBACK_STREAM))
Markus Grabner1027f4762010-08-12 01:35:30 +0200219 line6_unlink_audio_out_urbs(line6pcm);
Markus Grabner6b02a17e2011-12-10 02:12:32 +0100220
Markus Grabner0ca54882012-01-20 00:09:09 +0100221 if (test_flags(flags_new, flags_old, LINE6_BITS_PLAYBACK_BUFFER)) {
222 line6_wait_clear_audio_out_urbs(line6pcm);
223 line6_free_playback_buffer(line6pcm);
Markus Grabner1027f4762010-08-12 01:35:30 +0200224 }
Markus Grabner1027f4762010-08-12 01:35:30 +0200225
226 return 0;
227}
228
Markus Grabner705ecec2009-02-27 19:43:04 -0800229/* trigger callback */
230int snd_line6_trigger(struct snd_pcm_substream *substream, int cmd)
231{
232 struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
Markus Grabner705ecec2009-02-27 19:43:04 -0800233 struct snd_pcm_substream *s;
234 int err;
235 unsigned long flags;
236
237 spin_lock_irqsave(&line6pcm->lock_trigger, flags);
Markus Grabner0ca54882012-01-20 00:09:09 +0100238 clear_bit(LINE6_INDEX_PREPARED, &line6pcm->flags);
Markus Grabner705ecec2009-02-27 19:43:04 -0800239
Markus Grabner705ecec2009-02-27 19:43:04 -0800240 snd_pcm_group_for_each_entry(s, substream) {
Greg Kroah-Hartman68dc3dd2009-02-27 22:43:30 -0800241 switch (s->stream) {
Markus Grabner705ecec2009-02-27 19:43:04 -0800242 case SNDRV_PCM_STREAM_PLAYBACK:
Markus Grabner1027f4762010-08-12 01:35:30 +0200243 err = snd_line6_playback_trigger(line6pcm, cmd);
Markus Grabner705ecec2009-02-27 19:43:04 -0800244
Greg Kroah-Hartman68dc3dd2009-02-27 22:43:30 -0800245 if (err < 0) {
246 spin_unlock_irqrestore(&line6pcm->lock_trigger,
247 flags);
Markus Grabner705ecec2009-02-27 19:43:04 -0800248 return err;
249 }
250
251 break;
252
253 case SNDRV_PCM_STREAM_CAPTURE:
Markus Grabner1027f4762010-08-12 01:35:30 +0200254 err = snd_line6_capture_trigger(line6pcm, cmd);
Markus Grabner705ecec2009-02-27 19:43:04 -0800255
Greg Kroah-Hartman68dc3dd2009-02-27 22:43:30 -0800256 if (err < 0) {
257 spin_unlock_irqrestore(&line6pcm->lock_trigger,
258 flags);
Markus Grabner705ecec2009-02-27 19:43:04 -0800259 return err;
260 }
261
262 break;
263
264 default:
Markus Grabnere1a164d2010-08-23 01:08:25 +0200265 dev_err(line6pcm->line6->ifcdev,
266 "Unknown stream direction %d\n", s->stream);
Markus Grabner705ecec2009-02-27 19:43:04 -0800267 }
268 }
269
270 spin_unlock_irqrestore(&line6pcm->lock_trigger, flags);
271 return 0;
272}
273
274/* control info callback */
Markus Grabner1027f4762010-08-12 01:35:30 +0200275static int snd_line6_control_playback_info(struct snd_kcontrol *kcontrol,
276 struct snd_ctl_elem_info *uinfo)
Greg Kroah-Hartman68dc3dd2009-02-27 22:43:30 -0800277{
Markus Grabner705ecec2009-02-27 19:43:04 -0800278 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
279 uinfo->count = 2;
280 uinfo->value.integer.min = 0;
281 uinfo->value.integer.max = 256;
282 return 0;
283}
284
285/* control get callback */
Markus Grabner1027f4762010-08-12 01:35:30 +0200286static int snd_line6_control_playback_get(struct snd_kcontrol *kcontrol,
287 struct snd_ctl_elem_value *ucontrol)
Greg Kroah-Hartman68dc3dd2009-02-27 22:43:30 -0800288{
Markus Grabner705ecec2009-02-27 19:43:04 -0800289 int i;
290 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
291
Greg Kroah-Hartman68dc3dd2009-02-27 22:43:30 -0800292 for (i = 2; i--;)
Markus Grabner1027f4762010-08-12 01:35:30 +0200293 ucontrol->value.integer.value[i] = line6pcm->volume_playback[i];
Markus Grabner705ecec2009-02-27 19:43:04 -0800294
295 return 0;
296}
297
298/* control put callback */
Markus Grabner1027f4762010-08-12 01:35:30 +0200299static int snd_line6_control_playback_put(struct snd_kcontrol *kcontrol,
300 struct snd_ctl_elem_value *ucontrol)
Greg Kroah-Hartman68dc3dd2009-02-27 22:43:30 -0800301{
Markus Grabner705ecec2009-02-27 19:43:04 -0800302 int i, changed = 0;
303 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
304
Greg Kroah-Hartman68dc3dd2009-02-27 22:43:30 -0800305 for (i = 2; i--;)
Markus Grabnere1a164d2010-08-23 01:08:25 +0200306 if (line6pcm->volume_playback[i] !=
307 ucontrol->value.integer.value[i]) {
308 line6pcm->volume_playback[i] =
309 ucontrol->value.integer.value[i];
Markus Grabner705ecec2009-02-27 19:43:04 -0800310 changed = 1;
311 }
312
313 return changed;
314}
315
316/* control definition */
Markus Grabner1027f4762010-08-12 01:35:30 +0200317static struct snd_kcontrol_new line6_control_playback = {
Markus Grabner705ecec2009-02-27 19:43:04 -0800318 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
319 .name = "PCM Playback Volume",
320 .index = 0,
321 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
Markus Grabner1027f4762010-08-12 01:35:30 +0200322 .info = snd_line6_control_playback_info,
323 .get = snd_line6_control_playback_get,
324 .put = snd_line6_control_playback_put
Markus Grabner705ecec2009-02-27 19:43:04 -0800325};
326
327/*
328 Cleanup the PCM device.
329*/
330static void line6_cleanup_pcm(struct snd_pcm *pcm)
331{
332 int i;
333 struct snd_line6_pcm *line6pcm = snd_pcm_chip(pcm);
334
Markus Grabner1027f4762010-08-12 01:35:30 +0200335#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
336 device_remove_file(line6pcm->line6->ifcdev, &dev_attr_impulse_volume);
337 device_remove_file(line6pcm->line6->ifcdev, &dev_attr_impulse_period);
338#endif
339
Greg Kroah-Hartman68dc3dd2009-02-27 22:43:30 -0800340 for (i = LINE6_ISO_BUFFERS; i--;) {
341 if (line6pcm->urb_audio_out[i]) {
Markus Grabner705ecec2009-02-27 19:43:04 -0800342 usb_kill_urb(line6pcm->urb_audio_out[i]);
343 usb_free_urb(line6pcm->urb_audio_out[i]);
344 }
Greg Kroah-Hartman68dc3dd2009-02-27 22:43:30 -0800345 if (line6pcm->urb_audio_in[i]) {
Markus Grabner705ecec2009-02-27 19:43:04 -0800346 usb_kill_urb(line6pcm->urb_audio_in[i]);
347 usb_free_urb(line6pcm->urb_audio_in[i]);
348 }
349 }
350}
351
352/* create a PCM device */
353static int snd_line6_new_pcm(struct snd_line6_pcm *line6pcm)
354{
355 struct snd_pcm *pcm;
356 int err;
357
Greg Kroah-Hartman68dc3dd2009-02-27 22:43:30 -0800358 err = snd_pcm_new(line6pcm->line6->card,
Markus Grabnere1a164d2010-08-23 01:08:25 +0200359 (char *)line6pcm->line6->properties->name,
360 0, 1, 1, &pcm);
Greg Kroah-Hartman68dc3dd2009-02-27 22:43:30 -0800361 if (err < 0)
Markus Grabner705ecec2009-02-27 19:43:04 -0800362 return err;
363
364 pcm->private_data = line6pcm;
365 pcm->private_free = line6_cleanup_pcm;
366 line6pcm->pcm = pcm;
367 strcpy(pcm->name, line6pcm->line6->properties->name);
368
369 /* set operators */
Shawn Bohrerafb90912009-11-15 22:17:57 -0600370 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
371 &snd_line6_playback_ops);
Markus Grabnere1a164d2010-08-23 01:08:25 +0200372 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_line6_capture_ops);
Markus Grabner705ecec2009-02-27 19:43:04 -0800373
374 /* pre-allocation of buffers */
Greg Kroah-Hartman68dc3dd2009-02-27 22:43:30 -0800375 snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
Markus Grabnere1a164d2010-08-23 01:08:25 +0200376 snd_dma_continuous_data
377 (GFP_KERNEL), 64 * 1024,
378 128 * 1024);
Markus Grabner705ecec2009-02-27 19:43:04 -0800379
380 return 0;
381}
382
383/* PCM device destructor */
384static int snd_line6_pcm_free(struct snd_device *device)
385{
386 return 0;
387}
388
389/*
Markus Grabner1027f4762010-08-12 01:35:30 +0200390 Stop substream if still running.
391*/
392static void pcm_disconnect_substream(struct snd_pcm_substream *substream)
393{
Greg Kroah-Hartman027360c2010-09-21 16:58:00 -0700394 if (substream->runtime && snd_pcm_running(substream))
Markus Grabner1027f4762010-08-12 01:35:30 +0200395 snd_pcm_stop(substream, SNDRV_PCM_STATE_DISCONNECTED);
Markus Grabner1027f4762010-08-12 01:35:30 +0200396}
397
398/*
399 Stop PCM stream.
400*/
401void line6_pcm_disconnect(struct snd_line6_pcm *line6pcm)
402{
Markus Grabnere1a164d2010-08-23 01:08:25 +0200403 pcm_disconnect_substream(get_substream
404 (line6pcm, SNDRV_PCM_STREAM_CAPTURE));
405 pcm_disconnect_substream(get_substream
406 (line6pcm, SNDRV_PCM_STREAM_PLAYBACK));
Markus Grabner1027f4762010-08-12 01:35:30 +0200407 line6_unlink_wait_clear_audio_out_urbs(line6pcm);
408 line6_unlink_wait_clear_audio_in_urbs(line6pcm);
409}
410
411/*
Markus Grabner705ecec2009-02-27 19:43:04 -0800412 Create and register the PCM device and mixer entries.
413 Create URBs for playback and capture.
414*/
Greg Kroah-Hartman68dc3dd2009-02-27 22:43:30 -0800415int line6_init_pcm(struct usb_line6 *line6,
416 struct line6_pcm_properties *properties)
Markus Grabner705ecec2009-02-27 19:43:04 -0800417{
418 static struct snd_device_ops pcm_ops = {
419 .dev_free = snd_line6_pcm_free,
420 };
421
422 int err;
423 int ep_read = 0, ep_write = 0;
424 struct snd_line6_pcm *line6pcm;
425
Greg Kroah-Hartman68dc3dd2009-02-27 22:43:30 -0800426 if (!(line6->properties->capabilities & LINE6_BIT_PCM))
Markus Grabnere1a164d2010-08-23 01:08:25 +0200427 return 0; /* skip PCM initialization and report success */
Markus Grabner705ecec2009-02-27 19:43:04 -0800428
429 /* initialize PCM subsystem based on product id: */
Greg Kroah-Hartman68dc3dd2009-02-27 22:43:30 -0800430 switch (line6->product) {
Markus Grabner705ecec2009-02-27 19:43:04 -0800431 case LINE6_DEVID_BASSPODXT:
Greg Kroah-Hartman68dc3dd2009-02-27 22:43:30 -0800432 case LINE6_DEVID_BASSPODXTLIVE:
433 case LINE6_DEVID_BASSPODXTPRO:
434 case LINE6_DEVID_PODXT:
435 case LINE6_DEVID_PODXTLIVE:
436 case LINE6_DEVID_PODXTPRO:
Stefan Hajnoczi16dc1042011-11-23 08:20:42 +0000437 case LINE6_DEVID_PODHD300:
Markus Grabnere1a164d2010-08-23 01:08:25 +0200438 ep_read = 0x82;
Markus Grabner705ecec2009-02-27 19:43:04 -0800439 ep_write = 0x01;
440 break;
441
Markus Grabner4c6fb5f2011-12-05 23:51:53 +0100442 case LINE6_DEVID_PODHD500:
Greg Kroah-Hartman68dc3dd2009-02-27 22:43:30 -0800443 case LINE6_DEVID_PODX3:
444 case LINE6_DEVID_PODX3LIVE:
Markus Grabnere1a164d2010-08-23 01:08:25 +0200445 ep_read = 0x86;
Markus Grabner705ecec2009-02-27 19:43:04 -0800446 ep_write = 0x02;
447 break;
448
Greg Kroah-Hartman68dc3dd2009-02-27 22:43:30 -0800449 case LINE6_DEVID_POCKETPOD:
Markus Grabnere1a164d2010-08-23 01:08:25 +0200450 ep_read = 0x82;
Markus Grabner705ecec2009-02-27 19:43:04 -0800451 ep_write = 0x02;
452 break;
453
Greg Kroah-Hartman68dc3dd2009-02-27 22:43:30 -0800454 case LINE6_DEVID_GUITARPORT:
Markus Grabner1027f4762010-08-12 01:35:30 +0200455 case LINE6_DEVID_PODSTUDIO_GX:
456 case LINE6_DEVID_PODSTUDIO_UX1:
457 case LINE6_DEVID_PODSTUDIO_UX2:
Markus Grabner705ecec2009-02-27 19:43:04 -0800458 case LINE6_DEVID_TONEPORT_GX:
Markus Grabner1027f4762010-08-12 01:35:30 +0200459 case LINE6_DEVID_TONEPORT_UX1:
460 case LINE6_DEVID_TONEPORT_UX2:
Markus Grabnere1a164d2010-08-23 01:08:25 +0200461 ep_read = 0x82;
Markus Grabner705ecec2009-02-27 19:43:04 -0800462 ep_write = 0x01;
463 break;
464
Laurent Naveta3762902012-11-30 11:57:32 +0100465 /* this is for interface_number == 1:
466 case LINE6_DEVID_TONEPORT_UX2:
467 case LINE6_DEVID_PODSTUDIO_UX2:
468 ep_read = 0x87;
469 ep_write = 0x00;
470 break; */
Markus Grabner705ecec2009-02-27 19:43:04 -0800471
472 default:
473 MISSING_CASE;
474 }
475
476 line6pcm = kzalloc(sizeof(struct snd_line6_pcm), GFP_KERNEL);
477
Greg Kroah-Hartman68dc3dd2009-02-27 22:43:30 -0800478 if (line6pcm == NULL)
Markus Grabner705ecec2009-02-27 19:43:04 -0800479 return -ENOMEM;
480
Markus Grabner1027f4762010-08-12 01:35:30 +0200481 line6pcm->volume_playback[0] = line6pcm->volume_playback[1] = 255;
482 line6pcm->volume_monitor = 255;
Markus Grabner705ecec2009-02-27 19:43:04 -0800483 line6pcm->line6 = line6;
484 line6pcm->ep_audio_read = ep_read;
485 line6pcm->ep_audio_write = ep_write;
Stefan Hajnoczi3b08db32011-11-23 08:20:44 +0000486
487 /* Read and write buffers are sized identically, so choose minimum */
488 line6pcm->max_packet_size = min(
489 usb_maxpacket(line6->usbdev,
490 usb_rcvisocpipe(line6->usbdev, ep_read), 0),
491 usb_maxpacket(line6->usbdev,
492 usb_sndisocpipe(line6->usbdev, ep_write), 1));
493
Markus Grabner705ecec2009-02-27 19:43:04 -0800494 line6pcm->properties = properties;
495 line6->line6pcm = line6pcm;
496
497 /* PCM device: */
Greg Kroah-Hartman68dc3dd2009-02-27 22:43:30 -0800498 err = snd_device_new(line6->card, SNDRV_DEV_PCM, line6, &pcm_ops);
499 if (err < 0)
Markus Grabner705ecec2009-02-27 19:43:04 -0800500 return err;
501
502 snd_card_set_dev(line6->card, line6->ifcdev);
503
Greg Kroah-Hartman68dc3dd2009-02-27 22:43:30 -0800504 err = snd_line6_new_pcm(line6pcm);
505 if (err < 0)
Markus Grabner705ecec2009-02-27 19:43:04 -0800506 return err;
507
508 spin_lock_init(&line6pcm->lock_audio_out);
509 spin_lock_init(&line6pcm->lock_audio_in);
510 spin_lock_init(&line6pcm->lock_trigger);
511
Markus Grabner1027f4762010-08-12 01:35:30 +0200512 err = line6_create_audio_out_urbs(line6pcm);
Greg Kroah-Hartman68dc3dd2009-02-27 22:43:30 -0800513 if (err < 0)
Markus Grabner705ecec2009-02-27 19:43:04 -0800514 return err;
515
Markus Grabner1027f4762010-08-12 01:35:30 +0200516 err = line6_create_audio_in_urbs(line6pcm);
Greg Kroah-Hartman68dc3dd2009-02-27 22:43:30 -0800517 if (err < 0)
Markus Grabner705ecec2009-02-27 19:43:04 -0800518 return err;
519
520 /* mixer: */
Markus Grabnere1a164d2010-08-23 01:08:25 +0200521 err =
522 snd_ctl_add(line6->card,
523 snd_ctl_new1(&line6_control_playback, line6pcm));
Greg Kroah-Hartman68dc3dd2009-02-27 22:43:30 -0800524 if (err < 0)
Markus Grabner705ecec2009-02-27 19:43:04 -0800525 return err;
526
Markus Grabner1027f4762010-08-12 01:35:30 +0200527#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
528 /* impulse response test: */
529 err = device_create_file(line6->ifcdev, &dev_attr_impulse_volume);
530 if (err < 0)
531 return err;
532
533 err = device_create_file(line6->ifcdev, &dev_attr_impulse_period);
534 if (err < 0)
535 return err;
536
537 line6pcm->impulse_period = LINE6_IMPULSE_DEFAULT_PERIOD;
538#endif
539
Markus Grabner705ecec2009-02-27 19:43:04 -0800540 return 0;
541}
542
543/* prepare pcm callback */
544int snd_line6_prepare(struct snd_pcm_substream *substream)
545{
546 struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
547
Stefan Hajnoczi665f3f52011-12-10 02:12:31 +0100548 switch (substream->stream) {
549 case SNDRV_PCM_STREAM_PLAYBACK:
Markus Grabner0ca54882012-01-20 00:09:09 +0100550 if ((line6pcm->flags & LINE6_BITS_PLAYBACK_STREAM) == 0)
Markus Grabner6b02a17e2011-12-10 02:12:32 +0100551 line6_unlink_wait_clear_audio_out_urbs(line6pcm);
552
Stefan Hajnoczi665f3f52011-12-10 02:12:31 +0100553 break;
554
555 case SNDRV_PCM_STREAM_CAPTURE:
Markus Grabner0ca54882012-01-20 00:09:09 +0100556 if ((line6pcm->flags & LINE6_BITS_CAPTURE_STREAM) == 0)
Markus Grabner6b02a17e2011-12-10 02:12:32 +0100557 line6_unlink_wait_clear_audio_in_urbs(line6pcm);
558
Stefan Hajnoczi665f3f52011-12-10 02:12:31 +0100559 break;
560
561 default:
562 MISSING_CASE;
563 }
564
Markus Grabner0ca54882012-01-20 00:09:09 +0100565 if (!test_and_set_bit(LINE6_INDEX_PREPARED, &line6pcm->flags)) {
Markus Grabner1027f4762010-08-12 01:35:30 +0200566 line6pcm->count_out = 0;
Markus Grabner705ecec2009-02-27 19:43:04 -0800567 line6pcm->pos_out = 0;
568 line6pcm->pos_out_done = 0;
Markus Grabner705ecec2009-02-27 19:43:04 -0800569 line6pcm->bytes_out = 0;
Markus Grabner1027f4762010-08-12 01:35:30 +0200570 line6pcm->count_in = 0;
Markus Grabner705ecec2009-02-27 19:43:04 -0800571 line6pcm->pos_in_done = 0;
572 line6pcm->bytes_in = 0;
573 }
574
575 return 0;
576}