aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/line6/toneport.c
diff options
context:
space:
mode:
authorMarkus Grabner <grabner@icg.tugraz.at>2010-08-11 19:35:30 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2010-08-31 18:28:15 -0400
commit1027f476f507ef7ed9919cd3e3d32310f3985da1 (patch)
tree5f0da58a5bc15338c71e848693a5ae259b97a207 /drivers/staging/line6/toneport.c
parent4498dbcd2d85b67e9f46790bcfee5860d2dd1762 (diff)
staging: line6: sync with upstream
Big upstream sync. Signed-off-by: Markus Grabner <grabner@icg.tugraz.at> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/staging/line6/toneport.c')
-rw-r--r--drivers/staging/line6/toneport.c337
1 files changed, 268 insertions, 69 deletions
diff --git a/drivers/staging/line6/toneport.c b/drivers/staging/line6/toneport.c
index e6770ea1793..0e7e871507c 100644
--- a/drivers/staging/line6/toneport.c
+++ b/drivers/staging/line6/toneport.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * Line6 Linux USB driver - 0.8.0 2 * Line6 Linux USB driver - 0.9.0
3 * 3 *
4 * Copyright (C) 2004-2009 Markus Grabner (grabner@icg.tugraz.at) 4 * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
5 * Emil Myhrman (emil.myhrman@gmail.com) 5 * Emil Myhrman (emil.myhrman@gmail.com)
6 * 6 *
7 * This program is free software; you can redistribute it and/or 7 * This program is free software; you can redistribute it and/or
@@ -10,15 +10,22 @@
10 * 10 *
11 */ 11 */
12 12
13#include "driver.h" 13#include <linux/wait.h>
14#include <sound/control.h>
14 15
15#include "audio.h" 16#include "audio.h"
16#include "capture.h" 17#include "capture.h"
18#include "driver.h"
17#include "playback.h" 19#include "playback.h"
18#include "toneport.h" 20#include "toneport.h"
19 21
22
20static int toneport_send_cmd(struct usb_device *usbdev, int cmd1, int cmd2); 23static int toneport_send_cmd(struct usb_device *usbdev, int cmd1, int cmd2);
21 24
25
26#define TONEPORT_PCM_DELAY 1
27
28
22static struct snd_ratden toneport_ratden = { 29static struct snd_ratden toneport_ratden = {
23 .num_min = 44100, 30 .num_min = 44100,
24 .num_max = 44100, 31 .num_max = 44100,
@@ -28,43 +35,52 @@ static struct snd_ratden toneport_ratden = {
28 35
29static struct line6_pcm_properties toneport_pcm_properties = { 36static struct line6_pcm_properties toneport_pcm_properties = {
30 .snd_line6_playback_hw = { 37 .snd_line6_playback_hw = {
31 .info = (SNDRV_PCM_INFO_MMAP | 38 .info = (SNDRV_PCM_INFO_MMAP |
32 SNDRV_PCM_INFO_INTERLEAVED | 39 SNDRV_PCM_INFO_INTERLEAVED |
33 SNDRV_PCM_INFO_BLOCK_TRANSFER | 40 SNDRV_PCM_INFO_BLOCK_TRANSFER |
34 SNDRV_PCM_INFO_MMAP_VALID | 41 SNDRV_PCM_INFO_MMAP_VALID |
35 SNDRV_PCM_INFO_PAUSE | 42 SNDRV_PCM_INFO_PAUSE |
36 SNDRV_PCM_INFO_SYNC_START), 43#ifdef CONFIG_PM
37 .formats = SNDRV_PCM_FMTBIT_S16_LE, 44 SNDRV_PCM_INFO_RESUME |
38 .rates = SNDRV_PCM_RATE_KNOT, 45#endif
39 .rate_min = 44100, 46 SNDRV_PCM_INFO_SYNC_START),
40 .rate_max = 44100, 47 .formats = SNDRV_PCM_FMTBIT_S16_LE,
41 .channels_min = 2, 48 .rates = SNDRV_PCM_RATE_KNOT,
42 .channels_max = 2, 49 .rate_min = 44100,
43 .buffer_bytes_max = 60000, 50 .rate_max = 44100,
44 .period_bytes_min = 180 * 4, 51 .channels_min = 2,
45 .period_bytes_max = 8192, 52 .channels_max = 2,
46 .periods_min = 1, 53 .buffer_bytes_max = 60000,
47 .periods_max = 1024}, 54 .period_bytes_min = 64,
55 .period_bytes_max = 8192,
56 .periods_min = 1,
57 .periods_max = 1024
58 },
48 .snd_line6_capture_hw = { 59 .snd_line6_capture_hw = {
49 .info = (SNDRV_PCM_INFO_MMAP | 60 .info = (SNDRV_PCM_INFO_MMAP |
50 SNDRV_PCM_INFO_INTERLEAVED | 61 SNDRV_PCM_INFO_INTERLEAVED |
51 SNDRV_PCM_INFO_BLOCK_TRANSFER | 62 SNDRV_PCM_INFO_BLOCK_TRANSFER |
52 SNDRV_PCM_INFO_MMAP_VALID | 63 SNDRV_PCM_INFO_MMAP_VALID |
53 SNDRV_PCM_INFO_SYNC_START), 64#ifdef CONFIG_PM
54 .formats = SNDRV_PCM_FMTBIT_S16_LE, 65 SNDRV_PCM_INFO_RESUME |
55 .rates = SNDRV_PCM_RATE_KNOT, 66#endif
56 .rate_min = 44100, 67 SNDRV_PCM_INFO_SYNC_START),
57 .rate_max = 44100, 68 .formats = SNDRV_PCM_FMTBIT_S16_LE,
58 .channels_min = 2, 69 .rates = SNDRV_PCM_RATE_KNOT,
59 .channels_max = 2, 70 .rate_min = 44100,
60 .buffer_bytes_max = 60000, 71 .rate_max = 44100,
61 .period_bytes_min = 188 * 4, 72 .channels_min = 2,
62 .period_bytes_max = 8192, 73 .channels_max = 2,
63 .periods_min = 1, 74 .buffer_bytes_max = 60000,
64 .periods_max = 1024}, 75 .period_bytes_min = 64,
76 .period_bytes_max = 8192,
77 .periods_min = 1,
78 .periods_max = 1024
79 },
65 .snd_line6_rates = { 80 .snd_line6_rates = {
66 .nrats = 1, 81 .nrats = 1,
67 .rats = &toneport_ratden}, 82 .rats = &toneport_ratden
83 },
68 .bytes_per_frame = 4 84 .bytes_per_frame = 4
69}; 85};
70 86
@@ -77,6 +93,27 @@ static struct line6_pcm_properties toneport_pcm_properties = {
77static int led_red = 0x00; 93static int led_red = 0x00;
78static int led_green = 0x26; 94static int led_green = 0x26;
79 95
96struct ToneportSourceInfo
97{
98 const char *name;
99 int code;
100};
101
102static const struct ToneportSourceInfo toneport_source_info[] = {
103 { "Microphone", 0x0a01 },
104 { "Line" , 0x0801 },
105 { "Instrument", 0x0b01 },
106 { "Inst & Mic", 0x0901 }
107};
108
109static bool toneport_has_led(short product)
110{
111 return
112 (product == LINE6_DEVID_GUITARPORT) ||
113 (product == LINE6_DEVID_TONEPORT_GX);
114 /* add your device here if you are missing support for the LEDs */
115}
116
80static void toneport_update_led(struct device *dev) 117static void toneport_update_led(struct device *dev)
81{ 118{
82 struct usb_interface *interface = to_usb_interface(dev); 119 struct usb_interface *interface = to_usb_interface(dev);
@@ -129,6 +166,7 @@ static DEVICE_ATTR(led_red, S_IWUGO | S_IRUGO, line6_nop_read,
129static DEVICE_ATTR(led_green, S_IWUGO | S_IRUGO, line6_nop_read, 166static DEVICE_ATTR(led_green, S_IWUGO | S_IRUGO, line6_nop_read,
130 toneport_set_led_green); 167 toneport_set_led_green);
131 168
169
132static int toneport_send_cmd(struct usb_device *usbdev, int cmd1, int cmd2) 170static int toneport_send_cmd(struct usb_device *usbdev, int cmd1, int cmd2)
133{ 171{
134 int ret; 172 int ret;
@@ -145,6 +183,111 @@ static int toneport_send_cmd(struct usb_device *usbdev, int cmd1, int cmd2)
145 return 0; 183 return 0;
146} 184}
147 185
186/* monitor info callback */
187static int snd_toneport_monitor_info(struct snd_kcontrol *kcontrol,
188 struct snd_ctl_elem_info *uinfo)
189{
190 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
191 uinfo->count = 1;
192 uinfo->value.integer.min = 0;
193 uinfo->value.integer.max = 256;
194 return 0;
195}
196
197/* monitor get callback */
198static int snd_toneport_monitor_get(struct snd_kcontrol *kcontrol,
199 struct snd_ctl_elem_value *ucontrol)
200{
201 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
202 ucontrol->value.integer.value[0] = line6pcm->volume_monitor;
203 return 0;
204}
205
206/* monitor put callback */
207static int snd_toneport_monitor_put(struct snd_kcontrol *kcontrol,
208 struct snd_ctl_elem_value *ucontrol)
209{
210 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
211
212 if(ucontrol->value.integer.value[0] == line6pcm->volume_monitor)
213 return 0;
214
215 line6pcm->volume_monitor = ucontrol->value.integer.value[0];
216 return 1;
217}
218
219/* source info callback */
220static int snd_toneport_source_info(struct snd_kcontrol *kcontrol,
221 struct snd_ctl_elem_info *uinfo)
222{
223 const int size = ARRAY_SIZE(toneport_source_info);
224 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
225 uinfo->count = 1;
226 uinfo->value.enumerated.items = size;
227
228 if(uinfo->value.enumerated.item >= size)
229 uinfo->value.enumerated.item = size - 1;
230
231 strcpy(uinfo->value.enumerated.name,
232 toneport_source_info[uinfo->value.enumerated.item].name);
233
234 return 0;
235}
236
237/* source get callback */
238static int snd_toneport_source_get(struct snd_kcontrol *kcontrol,
239 struct snd_ctl_elem_value *ucontrol)
240{
241 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
242 struct usb_line6_toneport *toneport = (struct usb_line6_toneport *)line6pcm->line6;
243 ucontrol->value.enumerated.item[0] = toneport->source;
244 return 0;
245}
246
247/* source put callback */
248static int snd_toneport_source_put(struct snd_kcontrol *kcontrol,
249 struct snd_ctl_elem_value *ucontrol)
250{
251 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
252 struct usb_line6_toneport *toneport = (struct usb_line6_toneport *)line6pcm->line6;
253
254 if(ucontrol->value.enumerated.item[0] == toneport->source)
255 return 0;
256
257 toneport->source = ucontrol->value.enumerated.item[0];
258 toneport_send_cmd(toneport->line6.usbdev, toneport_source_info[toneport->source].code, 0x0000);
259 return 1;
260}
261
262static void toneport_start_pcm(unsigned long arg)
263{
264 struct usb_line6_toneport *toneport = (struct usb_line6_toneport *)arg;
265 struct usb_line6 *line6 = &toneport->line6;
266 line6_pcm_start(line6->line6pcm, MASK_PCM_MONITOR);
267}
268
269/* control definition */
270static struct snd_kcontrol_new toneport_control_monitor = {
271 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
272 .name = "Monitor Playback Volume",
273 .index = 0,
274 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
275 .info = snd_toneport_monitor_info,
276 .get = snd_toneport_monitor_get,
277 .put = snd_toneport_monitor_put
278};
279
280/* source selector definition */
281static struct snd_kcontrol_new toneport_control_source = {
282 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
283 .name = "PCM Capture Source",
284 .index = 0,
285 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
286 .info = snd_toneport_source_info,
287 .get = snd_toneport_source_get,
288 .put = snd_toneport_source_put
289};
290
148/* 291/*
149 Toneport destructor. 292 Toneport destructor.
150*/ 293*/
@@ -162,14 +305,41 @@ static void toneport_destruct(struct usb_interface *interface)
162} 305}
163 306
164/* 307/*
165 Init Toneport device. 308 Setup Toneport device.
166*/ 309*/
167int toneport_init(struct usb_interface *interface, 310static void toneport_setup(struct usb_line6_toneport *toneport)
168 struct usb_line6_toneport *toneport)
169{ 311{
170 int err, ticks; 312 int ticks;
171 struct usb_line6 *line6 = &toneport->line6; 313 struct usb_line6 *line6 = &toneport->line6;
172 struct usb_device *usbdev; 314 struct usb_device *usbdev = line6->usbdev;
315
316 /* sync time on device with host: */
317 ticks = (int)get_seconds();
318 line6_write_data(line6, 0x80c6, &ticks, 4);
319
320 /* enable device: */
321 toneport_send_cmd(usbdev, 0x0301, 0x0000);
322
323 /* initialize source select: */
324 switch(usbdev->descriptor.idProduct) {
325 case LINE6_DEVID_TONEPORT_UX1:
326 case LINE6_DEVID_PODSTUDIO_UX1:
327 toneport_send_cmd(usbdev, toneport_source_info[toneport->source].code, 0x0000);
328 }
329
330 if (toneport_has_led(usbdev->descriptor.idProduct))
331 toneport_update_led(&usbdev->dev);
332}
333
334/*
335 Try to init Toneport device.
336*/
337static int toneport_try_init(struct usb_interface *interface,
338 struct usb_line6_toneport *toneport)
339{
340 int err;
341 struct usb_line6 *line6 = &toneport->line6;
342 struct usb_device *usbdev = line6->usbdev;
173 343
174 if ((interface == NULL) || (toneport == NULL)) 344 if ((interface == NULL) || (toneport == NULL))
175 return -ENODEV; 345 return -ENODEV;
@@ -177,64 +347,93 @@ int toneport_init(struct usb_interface *interface,
177 /* initialize audio system: */ 347 /* initialize audio system: */
178 err = line6_init_audio(line6); 348 err = line6_init_audio(line6);
179 if (err < 0) { 349 if (err < 0) {
180 toneport_destruct(interface);
181 return err; 350 return err;
182 } 351 }
183 352
184 /* initialize PCM subsystem: */ 353 /* initialize PCM subsystem: */
185 err = line6_init_pcm(line6, &toneport_pcm_properties); 354 err = line6_init_pcm(line6, &toneport_pcm_properties);
186 if (err < 0) { 355 if (err < 0) {
187 toneport_destruct(interface);
188 return err; 356 return err;
189 } 357 }
190 358
359 /* register monitor control: */
360 err = snd_ctl_add(line6->card, snd_ctl_new1(&toneport_control_monitor, line6->line6pcm));
361 if (err < 0) {
362 return err;
363 }
364
365 /* register source select control: */
366 switch(usbdev->descriptor.idProduct) {
367 case LINE6_DEVID_TONEPORT_UX1:
368 case LINE6_DEVID_PODSTUDIO_UX1:
369 err = snd_ctl_add(line6->card, snd_ctl_new1(&toneport_control_source, line6->line6pcm));
370 if (err < 0) {
371 return err;
372 }
373 }
374
191 /* register audio system: */ 375 /* register audio system: */
192 err = line6_register_audio(line6); 376 err = line6_register_audio(line6);
193 if (err < 0) { 377 if (err < 0) {
194 toneport_destruct(interface);
195 return err; 378 return err;
196 } 379 }
197 380
198 usbdev = line6->usbdev;
199 line6_read_serial_number(line6, &toneport->serial_number); 381 line6_read_serial_number(line6, &toneport->serial_number);
200 line6_read_data(line6, 0x80c2, &toneport->firmware_version, 1); 382 line6_read_data(line6, 0x80c2, &toneport->firmware_version, 1);
201 383
202 /* sync time on device with host: */ 384 if (toneport_has_led(usbdev->descriptor.idProduct)) {
203 ticks = (int)get_seconds(); 385 CHECK_RETURN(device_create_file(&interface->dev, &dev_attr_led_red));
204 line6_write_data(line6, 0x80c6, &ticks, 4); 386 CHECK_RETURN(device_create_file(&interface->dev, &dev_attr_led_green));
387 }
205 388
206 /* 389 toneport_setup(toneport);
207 seems to work without the first two...
208 */
209 /* toneport_send_cmd(usbdev, 0x0201, 0x0002); */
210 /* toneport_send_cmd(usbdev, 0x0801, 0x0000); */
211 /* only one that works for me; on GP, TP might be different? */
212 toneport_send_cmd(usbdev, 0x0301, 0x0000);
213 390
214 if (usbdev->descriptor.idProduct != LINE6_DEVID_GUITARPORT) { 391 init_timer(&toneport->timer);
215 CHECK_RETURN(device_create_file 392 toneport->timer.expires = jiffies + TONEPORT_PCM_DELAY * HZ;
216 (&interface->dev, &dev_attr_led_red)); 393 toneport->timer.function = toneport_start_pcm;
217 CHECK_RETURN(device_create_file 394 toneport->timer.data = (unsigned long)toneport;
218 (&interface->dev, &dev_attr_led_green)); 395 add_timer(&toneport->timer);
219 toneport_update_led(&usbdev->dev);
220 }
221 396
222 return 0; 397 return 0;
223} 398}
224 399
225/* 400/*
401 Init Toneport device (and clean up in case of failure).
402*/
403int line6_toneport_init(struct usb_interface *interface,
404 struct usb_line6_toneport *toneport)
405{
406 int err = toneport_try_init(interface, toneport);
407
408 if (err < 0) {
409 toneport_destruct(interface);
410 }
411
412 return err;
413}
414
415/*
416 Resume Toneport device after reset.
417*/
418void line6_toneport_reset_resume(struct usb_line6_toneport *toneport)
419{
420 toneport_setup(toneport);
421}
422
423/*
226 Toneport device disconnected. 424 Toneport device disconnected.
227*/ 425*/
228void toneport_disconnect(struct usb_interface *interface) 426void line6_toneport_disconnect(struct usb_interface *interface)
229{ 427{
230 struct usb_line6_toneport *toneport; 428 struct usb_line6_toneport *toneport;
231 429
232 if (interface == NULL) 430 if (interface == NULL)
233 return; 431 return;
432
234 toneport = usb_get_intfdata(interface); 433 toneport = usb_get_intfdata(interface);
434 del_timer_sync(&toneport->timer);
235 435
236 if (toneport->line6.usbdev->descriptor.idProduct != 436 if (toneport_has_led(toneport->line6.usbdev->descriptor.idProduct)) {
237 LINE6_DEVID_GUITARPORT) {
238 device_remove_file(&interface->dev, &dev_attr_led_red); 437 device_remove_file(&interface->dev, &dev_attr_led_red);
239 device_remove_file(&interface->dev, &dev_attr_led_green); 438 device_remove_file(&interface->dev, &dev_attr_led_green);
240 } 439 }
@@ -243,8 +442,8 @@ void toneport_disconnect(struct usb_interface *interface)
243 struct snd_line6_pcm *line6pcm = toneport->line6.line6pcm; 442 struct snd_line6_pcm *line6pcm = toneport->line6.line6pcm;
244 443
245 if (line6pcm != NULL) { 444 if (line6pcm != NULL) {
246 unlink_wait_clear_audio_out_urbs(line6pcm); 445 line6_pcm_stop(line6pcm, MASK_PCM_MONITOR);
247 unlink_wait_clear_audio_in_urbs(line6pcm); 446 line6_pcm_disconnect(line6pcm);
248 } 447 }
249 } 448 }
250 449