blob: 3097a75a9bec82b0271b14dfb022477362f8418e [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 * Emil Myhrman (emil.myhrman@gmail.com)
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation, version 2.
10 *
11 */
12
Markus Grabner1027f4762010-08-12 01:35:30 +020013#include <linux/wait.h>
Takashi Iwaiccddbe42015-01-15 08:22:31 +010014#include <linux/usb.h>
15#include <linux/slab.h>
16#include <linux/module.h>
17#include <sound/core.h>
Markus Grabner1027f4762010-08-12 01:35:30 +020018#include <sound/control.h>
Markus Grabner705ecec2009-02-27 19:43:04 -080019
Markus Grabner705ecec2009-02-27 19:43:04 -080020#include "capture.h"
Markus Grabner1027f4762010-08-12 01:35:30 +020021#include "driver.h"
Markus Grabner705ecec2009-02-27 19:43:04 -080022#include "playback.h"
Takashi Iwaiccddbe42015-01-15 08:22:31 +010023#include "usbdefs.h"
24
25enum line6_device_type {
26 LINE6_GUITARPORT,
27 LINE6_PODSTUDIO_GX,
28 LINE6_PODSTUDIO_UX1,
29 LINE6_PODSTUDIO_UX2,
30 LINE6_TONEPORT_GX,
31 LINE6_TONEPORT_UX1,
32 LINE6_TONEPORT_UX2,
33};
34
35struct usb_line6_toneport {
36 /**
37 Generic Line6 USB data.
38 */
39 struct usb_line6 line6;
40
41 /**
42 Source selector.
43 */
44 int source;
45
46 /**
47 Serial number of device.
48 */
49 int serial_number;
50
51 /**
52 Firmware version (x 100).
53 */
54 int firmware_version;
55
56 /**
57 Timer for delayed PCM startup.
58 */
59 struct timer_list timer;
60
61 /**
62 Device type.
63 */
64 enum line6_device_type type;
65};
Markus Grabner705ecec2009-02-27 19:43:04 -080066
Markus Grabner705ecec2009-02-27 19:43:04 -080067static int toneport_send_cmd(struct usb_device *usbdev, int cmd1, int cmd2);
68
Markus Grabner1027f4762010-08-12 01:35:30 +020069#define TONEPORT_PCM_DELAY 1
70
Markus Grabner705ecec2009-02-27 19:43:04 -080071static struct snd_ratden toneport_ratden = {
72 .num_min = 44100,
73 .num_max = 44100,
74 .num_step = 1,
75 .den = 1
76};
77
78static struct line6_pcm_properties toneport_pcm_properties = {
Shawn Bohrer63a4a8b2009-11-15 22:17:58 -060079 .snd_line6_playback_hw = {
Markus Grabnere1a164d2010-08-23 01:08:25 +020080 .info = (SNDRV_PCM_INFO_MMAP |
81 SNDRV_PCM_INFO_INTERLEAVED |
82 SNDRV_PCM_INFO_BLOCK_TRANSFER |
83 SNDRV_PCM_INFO_MMAP_VALID |
84 SNDRV_PCM_INFO_PAUSE |
Markus Grabnere1a164d2010-08-23 01:08:25 +020085 SNDRV_PCM_INFO_SYNC_START),
86 .formats = SNDRV_PCM_FMTBIT_S16_LE,
87 .rates = SNDRV_PCM_RATE_KNOT,
88 .rate_min = 44100,
89 .rate_max = 44100,
90 .channels_min = 2,
91 .channels_max = 2,
92 .buffer_bytes_max = 60000,
93 .period_bytes_min = 64,
94 .period_bytes_max = 8192,
95 .periods_min = 1,
96 .periods_max = 1024},
Shawn Bohrer63a4a8b2009-11-15 22:17:58 -060097 .snd_line6_capture_hw = {
Markus Grabnere1a164d2010-08-23 01:08:25 +020098 .info = (SNDRV_PCM_INFO_MMAP |
99 SNDRV_PCM_INFO_INTERLEAVED |
100 SNDRV_PCM_INFO_BLOCK_TRANSFER |
101 SNDRV_PCM_INFO_MMAP_VALID |
Markus Grabnere1a164d2010-08-23 01:08:25 +0200102 SNDRV_PCM_INFO_SYNC_START),
103 .formats = SNDRV_PCM_FMTBIT_S16_LE,
104 .rates = SNDRV_PCM_RATE_KNOT,
105 .rate_min = 44100,
106 .rate_max = 44100,
107 .channels_min = 2,
108 .channels_max = 2,
109 .buffer_bytes_max = 60000,
110 .period_bytes_min = 64,
111 .period_bytes_max = 8192,
112 .periods_min = 1,
113 .periods_max = 1024},
Markus Grabner705ecec2009-02-27 19:43:04 -0800114 .snd_line6_rates = {
Markus Grabnere1a164d2010-08-23 01:08:25 +0200115 .nrats = 1,
116 .rats = &toneport_ratden},
Markus Grabner705ecec2009-02-27 19:43:04 -0800117 .bytes_per_frame = 4
118};
119
120/*
121 For the led on Guitarport.
Greg Kroah-Hartman63537732009-02-27 22:43:45 -0800122 Brightness goes from 0x00 to 0x26. Set a value above this to have led
123 blink.
Markus Grabner705ecec2009-02-27 19:43:04 -0800124 (void cmd_0x02(byte red, byte green)
125*/
126static int led_red = 0x00;
127static int led_green = 0x26;
128
Stefan Hajnoczi709b2fa2013-01-11 23:08:13 +0100129static const struct {
Markus Grabner1027f4762010-08-12 01:35:30 +0200130 const char *name;
131 int code;
Stefan Hajnoczi709b2fa2013-01-11 23:08:13 +0100132} toneport_source_info[] = {
Markus Grabnere1a164d2010-08-23 01:08:25 +0200133 {"Microphone", 0x0a01},
134 {"Line", 0x0801},
135 {"Instrument", 0x0b01},
136 {"Inst & Mic", 0x0901}
Markus Grabner1027f4762010-08-12 01:35:30 +0200137};
138
Chris Rorvicka23a8bf2015-01-12 12:42:42 -0800139static bool toneport_has_led(enum line6_device_type type)
Markus Grabner1027f4762010-08-12 01:35:30 +0200140{
141 return
Chris Rorvicka23a8bf2015-01-12 12:42:42 -0800142 (type == LINE6_GUITARPORT) ||
143 (type == LINE6_TONEPORT_GX);
Markus Grabner1027f4762010-08-12 01:35:30 +0200144 /* add your device here if you are missing support for the LEDs */
145}
146
Greg Kroah-Hartman63537732009-02-27 22:43:45 -0800147static void toneport_update_led(struct device *dev)
148{
149 struct usb_interface *interface = to_usb_interface(dev);
150 struct usb_line6_toneport *tp = usb_get_intfdata(interface);
151 struct usb_line6 *line6;
Markus Grabner705ecec2009-02-27 19:43:04 -0800152
Greg Kroah-Hartman63537732009-02-27 22:43:45 -0800153 if (!tp)
154 return;
155
156 line6 = &tp->line6;
157 if (line6)
158 toneport_send_cmd(line6->usbdev, (led_red << 8) | 0x0002,
159 led_green);
Markus Grabner705ecec2009-02-27 19:43:04 -0800160}
Greg Kroah-Hartman63537732009-02-27 22:43:45 -0800161
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800162static ssize_t toneport_set_led_red(struct device *dev,
163 struct device_attribute *attr,
Greg Kroah-Hartman63537732009-02-27 22:43:45 -0800164 const char *buf, size_t count)
165{
Shawn Bohrerbb950a12009-11-15 22:17:59 -0600166 int retval;
Shawn Bohrerbb950a12009-11-15 22:17:59 -0600167
Stefan Hajnoczib07d9452012-11-11 13:24:44 +0100168 retval = kstrtoint(buf, 10, &led_red);
Shawn Bohrerbb950a12009-11-15 22:17:59 -0600169 if (retval)
170 return retval;
171
Markus Grabner705ecec2009-02-27 19:43:04 -0800172 toneport_update_led(dev);
173 return count;
174}
Greg Kroah-Hartman63537732009-02-27 22:43:45 -0800175
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800176static ssize_t toneport_set_led_green(struct device *dev,
177 struct device_attribute *attr,
Greg Kroah-Hartman63537732009-02-27 22:43:45 -0800178 const char *buf, size_t count)
179{
Shawn Bohrerbb950a12009-11-15 22:17:59 -0600180 int retval;
Shawn Bohrerbb950a12009-11-15 22:17:59 -0600181
Stefan Hajnoczib07d9452012-11-11 13:24:44 +0100182 retval = kstrtoint(buf, 10, &led_green);
Shawn Bohrerbb950a12009-11-15 22:17:59 -0600183 if (retval)
184 return retval;
185
Markus Grabner705ecec2009-02-27 19:43:04 -0800186 toneport_update_led(dev);
187 return count;
188}
189
Greg Kroah-Hartmana3a972a2010-11-18 11:21:04 -0800190static DEVICE_ATTR(led_red, S_IWUSR | S_IRUGO, line6_nop_read,
Shawn Bohrer63a4a8b2009-11-15 22:17:58 -0600191 toneport_set_led_red);
Greg Kroah-Hartmana3a972a2010-11-18 11:21:04 -0800192static DEVICE_ATTR(led_green, S_IWUSR | S_IRUGO, line6_nop_read,
Shawn Bohrer63a4a8b2009-11-15 22:17:58 -0600193 toneport_set_led_green);
Markus Grabner705ecec2009-02-27 19:43:04 -0800194
195static int toneport_send_cmd(struct usb_device *usbdev, int cmd1, int cmd2)
196{
197 int ret;
Markus Grabner705ecec2009-02-27 19:43:04 -0800198
Greg Kroah-Hartman63537732009-02-27 22:43:45 -0800199 ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0), 0x67,
200 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
201 cmd1, cmd2, NULL, 0, LINE6_TIMEOUT * HZ);
202
203 if (ret < 0) {
Greg Kroah-Hartmand86938f2012-04-20 16:53:32 -0700204 dev_err(&usbdev->dev, "send failed (error %d)\n", ret);
Markus Grabner705ecec2009-02-27 19:43:04 -0800205 return ret;
206 }
207
208 return 0;
209}
210
Markus Grabner1027f4762010-08-12 01:35:30 +0200211/* monitor info callback */
212static int snd_toneport_monitor_info(struct snd_kcontrol *kcontrol,
213 struct snd_ctl_elem_info *uinfo)
214{
215 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
216 uinfo->count = 1;
217 uinfo->value.integer.min = 0;
218 uinfo->value.integer.max = 256;
219 return 0;
220}
221
222/* monitor get callback */
223static int snd_toneport_monitor_get(struct snd_kcontrol *kcontrol,
224 struct snd_ctl_elem_value *ucontrol)
225{
226 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
Jerry Snitselaarf3c52612014-04-24 00:31:48 -0700227
Markus Grabner1027f4762010-08-12 01:35:30 +0200228 ucontrol->value.integer.value[0] = line6pcm->volume_monitor;
229 return 0;
230}
231
232/* monitor put callback */
233static int snd_toneport_monitor_put(struct snd_kcontrol *kcontrol,
234 struct snd_ctl_elem_value *ucontrol)
235{
236 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
237
Markus Grabnere1a164d2010-08-23 01:08:25 +0200238 if (ucontrol->value.integer.value[0] == line6pcm->volume_monitor)
Markus Grabner1027f4762010-08-12 01:35:30 +0200239 return 0;
240
241 line6pcm->volume_monitor = ucontrol->value.integer.value[0];
Markus Grabnere1a164d2010-08-23 01:08:25 +0200242
243 if (line6pcm->volume_monitor > 0)
Markus Grabner0ca54882012-01-20 00:09:09 +0100244 line6_pcm_acquire(line6pcm, LINE6_BITS_PCM_MONITOR);
Markus Grabnere1a164d2010-08-23 01:08:25 +0200245 else
Markus Grabner0ca54882012-01-20 00:09:09 +0100246 line6_pcm_release(line6pcm, LINE6_BITS_PCM_MONITOR);
Markus Grabnere1a164d2010-08-23 01:08:25 +0200247
Markus Grabner1027f4762010-08-12 01:35:30 +0200248 return 1;
249}
250
251/* source info callback */
252static int snd_toneport_source_info(struct snd_kcontrol *kcontrol,
253 struct snd_ctl_elem_info *uinfo)
254{
255 const int size = ARRAY_SIZE(toneport_source_info);
Fabian Mewesa6b46992014-03-24 23:46:31 +0100256
Markus Grabner1027f4762010-08-12 01:35:30 +0200257 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
258 uinfo->count = 1;
259 uinfo->value.enumerated.items = size;
260
Markus Grabnere1a164d2010-08-23 01:08:25 +0200261 if (uinfo->value.enumerated.item >= size)
Markus Grabner1027f4762010-08-12 01:35:30 +0200262 uinfo->value.enumerated.item = size - 1;
263
264 strcpy(uinfo->value.enumerated.name,
265 toneport_source_info[uinfo->value.enumerated.item].name);
266
267 return 0;
268}
269
270/* source get callback */
271static int snd_toneport_source_get(struct snd_kcontrol *kcontrol,
272 struct snd_ctl_elem_value *ucontrol)
273{
274 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
Markus Grabnere1a164d2010-08-23 01:08:25 +0200275 struct usb_line6_toneport *toneport =
276 (struct usb_line6_toneport *)line6pcm->line6;
Markus Grabner1027f4762010-08-12 01:35:30 +0200277 ucontrol->value.enumerated.item[0] = toneport->source;
278 return 0;
279}
280
281/* source put callback */
282static int snd_toneport_source_put(struct snd_kcontrol *kcontrol,
283 struct snd_ctl_elem_value *ucontrol)
284{
285 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
Markus Grabnere1a164d2010-08-23 01:08:25 +0200286 struct usb_line6_toneport *toneport =
287 (struct usb_line6_toneport *)line6pcm->line6;
Dan Carpenterc3cb7182013-09-13 11:07:13 +0300288 unsigned int source;
Markus Grabner1027f4762010-08-12 01:35:30 +0200289
Dan Carpenterc3cb7182013-09-13 11:07:13 +0300290 source = ucontrol->value.enumerated.item[0];
291 if (source >= ARRAY_SIZE(toneport_source_info))
292 return -EINVAL;
293 if (source == toneport->source)
Markus Grabner1027f4762010-08-12 01:35:30 +0200294 return 0;
295
Dan Carpenterc3cb7182013-09-13 11:07:13 +0300296 toneport->source = source;
Markus Grabnere1a164d2010-08-23 01:08:25 +0200297 toneport_send_cmd(toneport->line6.usbdev,
Dan Carpenterc3cb7182013-09-13 11:07:13 +0300298 toneport_source_info[source].code, 0x0000);
Markus Grabner1027f4762010-08-12 01:35:30 +0200299 return 1;
300}
301
302static void toneport_start_pcm(unsigned long arg)
303{
304 struct usb_line6_toneport *toneport = (struct usb_line6_toneport *)arg;
305 struct usb_line6 *line6 = &toneport->line6;
Jerry Snitselaarf3c52612014-04-24 00:31:48 -0700306
Markus Grabner0ca54882012-01-20 00:09:09 +0100307 line6_pcm_acquire(line6->line6pcm, LINE6_BITS_PCM_MONITOR);
Markus Grabner1027f4762010-08-12 01:35:30 +0200308}
309
310/* control definition */
311static struct snd_kcontrol_new toneport_control_monitor = {
312 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
313 .name = "Monitor Playback Volume",
314 .index = 0,
315 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
316 .info = snd_toneport_monitor_info,
317 .get = snd_toneport_monitor_get,
318 .put = snd_toneport_monitor_put
319};
320
321/* source selector definition */
322static struct snd_kcontrol_new toneport_control_source = {
323 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
324 .name = "PCM Capture Source",
325 .index = 0,
326 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
327 .info = snd_toneport_source_info,
328 .get = snd_toneport_source_get,
329 .put = snd_toneport_source_put
330};
331
Markus Grabner705ecec2009-02-27 19:43:04 -0800332/*
Markus Grabner1027f4762010-08-12 01:35:30 +0200333 Setup Toneport device.
Markus Grabner705ecec2009-02-27 19:43:04 -0800334*/
Markus Grabner1027f4762010-08-12 01:35:30 +0200335static void toneport_setup(struct usb_line6_toneport *toneport)
Markus Grabner705ecec2009-02-27 19:43:04 -0800336{
Markus Grabner1027f4762010-08-12 01:35:30 +0200337 int ticks;
Markus Grabner705ecec2009-02-27 19:43:04 -0800338 struct usb_line6 *line6 = &toneport->line6;
Markus Grabner1027f4762010-08-12 01:35:30 +0200339 struct usb_device *usbdev = line6->usbdev;
340
341 /* sync time on device with host: */
342 ticks = (int)get_seconds();
343 line6_write_data(line6, 0x80c6, &ticks, 4);
344
345 /* enable device: */
346 toneport_send_cmd(usbdev, 0x0301, 0x0000);
347
348 /* initialize source select: */
Takashi Iwaiccddbe42015-01-15 08:22:31 +0100349 switch (toneport->type) {
Chris Rorvicka23a8bf2015-01-12 12:42:42 -0800350 case LINE6_TONEPORT_UX1:
351 case LINE6_TONEPORT_UX2:
352 case LINE6_PODSTUDIO_UX1:
353 case LINE6_PODSTUDIO_UX2:
Markus Grabnere1a164d2010-08-23 01:08:25 +0200354 toneport_send_cmd(usbdev,
355 toneport_source_info[toneport->source].code,
356 0x0000);
Chris Rorvicka23a8bf2015-01-12 12:42:42 -0800357 default:
358 break;
Markus Grabner1027f4762010-08-12 01:35:30 +0200359 }
360
Takashi Iwaiccddbe42015-01-15 08:22:31 +0100361 if (toneport_has_led(toneport->type))
Markus Grabner1027f4762010-08-12 01:35:30 +0200362 toneport_update_led(&usbdev->dev);
363}
364
365/*
Chris Rorvickd29b8542015-01-12 12:43:00 -0800366 Toneport device disconnected.
367*/
368static void line6_toneport_disconnect(struct usb_interface *interface)
369{
370 struct usb_line6_toneport *toneport;
371 u16 idProduct;
372
373 if (interface == NULL)
374 return;
375
376 toneport = usb_get_intfdata(interface);
377 del_timer_sync(&toneport->timer);
378 idProduct = le16_to_cpu(toneport->line6.usbdev->descriptor.idProduct);
379
380 if (toneport_has_led(idProduct)) {
381 device_remove_file(&interface->dev, &dev_attr_led_red);
382 device_remove_file(&interface->dev, &dev_attr_led_green);
383 }
Chris Rorvickd29b8542015-01-12 12:43:00 -0800384}
385
386
387/*
Markus Grabner1027f4762010-08-12 01:35:30 +0200388 Try to init Toneport device.
389*/
Takashi Iwai85a93392015-01-19 15:54:00 +0100390static int toneport_init(struct usb_interface *interface,
391 struct usb_line6 *line6)
Markus Grabner1027f4762010-08-12 01:35:30 +0200392{
393 int err;
Chris Rorvicka221dd42015-01-12 12:42:56 -0800394 struct usb_line6_toneport *toneport = (struct usb_line6_toneport *) line6;
Markus Grabner705ecec2009-02-27 19:43:04 -0800395
Greg Kroah-Hartman63537732009-02-27 22:43:45 -0800396 if ((interface == NULL) || (toneport == NULL))
Markus Grabner705ecec2009-02-27 19:43:04 -0800397 return -ENODEV;
398
Chris Rorvicka46c4672015-01-12 12:42:59 -0800399 line6->disconnect = line6_toneport_disconnect;
400
Markus Grabner705ecec2009-02-27 19:43:04 -0800401 /* initialize PCM subsystem: */
Greg Kroah-Hartman63537732009-02-27 22:43:45 -0800402 err = line6_init_pcm(line6, &toneport_pcm_properties);
Greg Kroah-Hartman027360c2010-09-21 16:58:00 -0700403 if (err < 0)
Markus Grabner705ecec2009-02-27 19:43:04 -0800404 return err;
Markus Grabner705ecec2009-02-27 19:43:04 -0800405
Markus Grabner1027f4762010-08-12 01:35:30 +0200406 /* register monitor control: */
Greg Kroah-Hartman027360c2010-09-21 16:58:00 -0700407 err = snd_ctl_add(line6->card,
408 snd_ctl_new1(&toneport_control_monitor,
409 line6->line6pcm));
410 if (err < 0)
Markus Grabner1027f4762010-08-12 01:35:30 +0200411 return err;
Markus Grabner1027f4762010-08-12 01:35:30 +0200412
413 /* register source select control: */
Takashi Iwaiccddbe42015-01-15 08:22:31 +0100414 switch (toneport->type) {
Chris Rorvicka23a8bf2015-01-12 12:42:42 -0800415 case LINE6_TONEPORT_UX1:
416 case LINE6_TONEPORT_UX2:
417 case LINE6_PODSTUDIO_UX1:
418 case LINE6_PODSTUDIO_UX2:
Markus Grabnere1a164d2010-08-23 01:08:25 +0200419 err =
420 snd_ctl_add(line6->card,
421 snd_ctl_new1(&toneport_control_source,
422 line6->line6pcm));
Greg Kroah-Hartman027360c2010-09-21 16:58:00 -0700423 if (err < 0)
Markus Grabner1027f4762010-08-12 01:35:30 +0200424 return err;
Chris Rorvicka23a8bf2015-01-12 12:42:42 -0800425
426 default:
427 break;
Markus Grabner1027f4762010-08-12 01:35:30 +0200428 }
429
Markus Grabner705ecec2009-02-27 19:43:04 -0800430 line6_read_serial_number(line6, &toneport->serial_number);
431 line6_read_data(line6, 0x80c2, &toneport->firmware_version, 1);
432
Takashi Iwaiccddbe42015-01-15 08:22:31 +0100433 if (toneport_has_led(toneport->type)) {
Markus Grabnere1a164d2010-08-23 01:08:25 +0200434 CHECK_RETURN(device_create_file
435 (&interface->dev, &dev_attr_led_red));
436 CHECK_RETURN(device_create_file
437 (&interface->dev, &dev_attr_led_green));
Markus Grabner705ecec2009-02-27 19:43:04 -0800438 }
439
Markus Grabner1027f4762010-08-12 01:35:30 +0200440 toneport_setup(toneport);
441
Takashi Iwai0f2524b2015-01-19 11:44:40 +0100442 setup_timer(&toneport->timer, toneport_start_pcm,
443 (unsigned long)toneport);
444 mod_timer(&toneport->timer, jiffies + TONEPORT_PCM_DELAY * HZ);
Markus Grabner1027f4762010-08-12 01:35:30 +0200445
Takashi Iwai85a93392015-01-19 15:54:00 +0100446 /* register audio system: */
447 return snd_card_register(line6->card);
Markus Grabner1027f4762010-08-12 01:35:30 +0200448}
449
Takashi Iwaiccddbe42015-01-15 08:22:31 +0100450#ifdef CONFIG_PM
Markus Grabner1027f4762010-08-12 01:35:30 +0200451/*
452 Resume Toneport device after reset.
453*/
Takashi Iwaiccddbe42015-01-15 08:22:31 +0100454static int toneport_reset_resume(struct usb_interface *interface)
Markus Grabner1027f4762010-08-12 01:35:30 +0200455{
Takashi Iwaiccddbe42015-01-15 08:22:31 +0100456 toneport_setup(usb_get_intfdata(interface));
457 return line6_resume(interface);
Markus Grabner1027f4762010-08-12 01:35:30 +0200458}
Takashi Iwaiccddbe42015-01-15 08:22:31 +0100459#endif
460
461#define LINE6_DEVICE(prod) USB_DEVICE(0x0e41, prod)
462#define LINE6_IF_NUM(prod, n) USB_DEVICE_INTERFACE_NUMBER(0x0e41, prod, n)
463
464/* table of devices that work with this driver */
465static const struct usb_device_id toneport_id_table[] = {
466 { LINE6_DEVICE(0x4750), .driver_info = LINE6_GUITARPORT },
467 { LINE6_DEVICE(0x4153), .driver_info = LINE6_PODSTUDIO_GX },
468 { LINE6_DEVICE(0x4150), .driver_info = LINE6_PODSTUDIO_UX1 },
469 { LINE6_IF_NUM(0x4151, 0), .driver_info = LINE6_PODSTUDIO_UX2 },
470 { LINE6_DEVICE(0x4147), .driver_info = LINE6_TONEPORT_GX },
471 { LINE6_DEVICE(0x4141), .driver_info = LINE6_TONEPORT_UX1 },
472 { LINE6_IF_NUM(0x4142, 0), .driver_info = LINE6_TONEPORT_UX2 },
473 {}
474};
475
476MODULE_DEVICE_TABLE(usb, toneport_id_table);
477
478static const struct line6_properties toneport_properties_table[] = {
479 [LINE6_GUITARPORT] = {
480 .id = "GuitarPort",
481 .name = "GuitarPort",
482 .capabilities = LINE6_CAP_PCM,
483 .altsetting = 2, /* 1..4 seem to be ok */
484 /* no control channel */
485 .ep_audio_r = 0x82,
486 .ep_audio_w = 0x01,
487 },
488 [LINE6_PODSTUDIO_GX] = {
489 .id = "PODStudioGX",
490 .name = "POD Studio GX",
491 .capabilities = LINE6_CAP_PCM,
492 .altsetting = 2, /* 1..4 seem to be ok */
493 /* no control channel */
494 .ep_audio_r = 0x82,
495 .ep_audio_w = 0x01,
496 },
497 [LINE6_PODSTUDIO_UX1] = {
498 .id = "PODStudioUX1",
499 .name = "POD Studio UX1",
500 .capabilities = LINE6_CAP_PCM,
501 .altsetting = 2, /* 1..4 seem to be ok */
502 /* no control channel */
503 .ep_audio_r = 0x82,
504 .ep_audio_w = 0x01,
505 },
506 [LINE6_PODSTUDIO_UX2] = {
507 .id = "PODStudioUX2",
508 .name = "POD Studio UX2",
509 .capabilities = LINE6_CAP_PCM,
510 .altsetting = 2, /* defaults to 44.1kHz, 16-bit */
511 /* no control channel */
512 .ep_audio_r = 0x82,
513 .ep_audio_w = 0x01,
514 },
515 [LINE6_TONEPORT_GX] = {
516 .id = "TonePortGX",
517 .name = "TonePort GX",
518 .capabilities = LINE6_CAP_PCM,
519 .altsetting = 2, /* 1..4 seem to be ok */
520 /* no control channel */
521 .ep_audio_r = 0x82,
522 .ep_audio_w = 0x01,
523 },
524 [LINE6_TONEPORT_UX1] = {
525 .id = "TonePortUX1",
526 .name = "TonePort UX1",
527 .capabilities = LINE6_CAP_PCM,
528 .altsetting = 2, /* 1..4 seem to be ok */
529 /* no control channel */
530 .ep_audio_r = 0x82,
531 .ep_audio_w = 0x01,
532 },
533 [LINE6_TONEPORT_UX2] = {
534 .id = "TonePortUX2",
535 .name = "TonePort UX2",
536 .capabilities = LINE6_CAP_PCM,
537 .altsetting = 2, /* defaults to 44.1kHz, 16-bit */
538 /* no control channel */
539 .ep_audio_r = 0x82,
540 .ep_audio_w = 0x01,
541 },
542};
543
544/*
545 Probe USB device.
546*/
547static int toneport_probe(struct usb_interface *interface,
548 const struct usb_device_id *id)
549{
550 struct usb_line6_toneport *toneport;
Takashi Iwaiccddbe42015-01-15 08:22:31 +0100551
552 toneport = kzalloc(sizeof(*toneport), GFP_KERNEL);
553 if (!toneport)
554 return -ENODEV;
555 toneport->type = id->driver_info;
Takashi Iwai85a93392015-01-19 15:54:00 +0100556 return line6_probe(interface, &toneport->line6,
557 &toneport_properties_table[id->driver_info],
558 toneport_init);
Takashi Iwaiccddbe42015-01-15 08:22:31 +0100559}
560
561static struct usb_driver toneport_driver = {
562 .name = KBUILD_MODNAME,
563 .probe = toneport_probe,
564 .disconnect = line6_disconnect,
565#ifdef CONFIG_PM
566 .suspend = line6_suspend,
567 .resume = line6_resume,
568 .reset_resume = toneport_reset_resume,
569#endif
570 .id_table = toneport_id_table,
571};
572
573module_usb_driver(toneport_driver);
574
575MODULE_DESCRIPTION("TonePort USB driver");
576MODULE_LICENSE("GPL");