blob: 7766f5349324275b004661bdbb8e2c49968e178a [file] [log] [blame]
Markus Grabner705ecec2009-02-27 19:43:04 -08001/*
Chris Rorvickc6fffce2015-01-20 02:20:49 -06002 * Line 6 Linux USB driver - 0.9.1beta
Markus Grabner705ecec2009-02-27 19:43:04 -08003 *
Markus Grabner1027f472010-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 Grabner1027f472010-08-12 01:35:30 +020013#include <linux/wait.h>
Takashi Iwaiccddbe42015-01-15 08:22:31 +010014#include <linux/interrupt.h>
15#include <linux/module.h>
16#include <linux/usb.h>
17
18#include <sound/core.h>
Markus Grabner1027f472010-08-12 01:35:30 +020019#include <sound/control.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090020
Markus Grabner705ecec2009-02-27 19:43:04 -080021#include "capture.h"
Markus Grabner1027f472010-08-12 01:35:30 +020022#include "driver.h"
Markus Grabner705ecec2009-02-27 19:43:04 -080023#include "playback.h"
Takashi Iwaiccddbe42015-01-15 08:22:31 +010024#include "usbdefs.h"
25
26/*
27 Locate name in binary program dump
28*/
29#define POD_NAME_OFFSET 0
30#define POD_NAME_LENGTH 16
31
32/*
33 Other constants
34*/
35#define POD_CONTROL_SIZE 0x80
36#define POD_BUFSIZE_DUMPREQ 7
37#define POD_STARTUP_DELAY 1000
38
39/*
40 Stages of POD startup procedure
41*/
42enum {
43 POD_STARTUP_INIT = 1,
44 POD_STARTUP_VERSIONREQ,
45 POD_STARTUP_WORKQUEUE,
46 POD_STARTUP_SETUP,
47 POD_STARTUP_LAST = POD_STARTUP_SETUP - 1
48};
49
50enum {
51 LINE6_BASSPODXT,
52 LINE6_BASSPODXTLIVE,
53 LINE6_BASSPODXTPRO,
54 LINE6_POCKETPOD,
55 LINE6_PODXT,
56 LINE6_PODXTLIVE_POD,
57 LINE6_PODXTPRO,
58};
59
60struct usb_line6_pod {
61 /**
Chris Rorvickc6fffce2015-01-20 02:20:49 -060062 Generic Line 6 USB data.
Takashi Iwaiccddbe42015-01-15 08:22:31 +010063 */
64 struct usb_line6 line6;
65
66 /**
67 Instrument monitor level.
68 */
69 int monitor_level;
70
71 /**
72 Timer for device initializaton.
73 */
74 struct timer_list startup_timer;
75
76 /**
77 Work handler for device initializaton.
78 */
79 struct work_struct startup_work;
80
81 /**
82 Current progress in startup procedure.
83 */
84 int startup_progress;
85
86 /**
87 Serial number of device.
88 */
89 int serial_number;
90
91 /**
92 Firmware version (x 100).
93 */
94 int firmware_version;
95
96 /**
97 Device ID.
98 */
99 int device_id;
100};
Markus Grabner705ecec2009-02-27 19:43:04 -0800101
Markus Grabner705ecec2009-02-27 19:43:04 -0800102#define POD_SYSEX_CODE 3
Markus Grabnere1a164d2010-08-23 01:08:25 +0200103#define POD_BYTES_PER_FRAME 6 /* 24bit audio (stereo) */
Markus Grabner705ecec2009-02-27 19:43:04 -0800104
Markus Grabnere1a164d2010-08-23 01:08:25 +0200105/* *INDENT-OFF* */
Markus Grabner705ecec2009-02-27 19:43:04 -0800106
107enum {
Markus Grabner705ecec2009-02-27 19:43:04 -0800108 POD_SYSEX_SAVE = 0x24,
109 POD_SYSEX_SYSTEM = 0x56,
110 POD_SYSEX_SYSTEMREQ = 0x57,
111 /* POD_SYSEX_UPDATE = 0x6c, */ /* software update! */
112 POD_SYSEX_STORE = 0x71,
113 POD_SYSEX_FINISH = 0x72,
114 POD_SYSEX_DUMPMEM = 0x73,
115 POD_SYSEX_DUMP = 0x74,
116 POD_SYSEX_DUMPREQ = 0x75
Stefan Hajnoczi0a1eb4e2013-01-11 23:08:12 +0100117
118 /* dumps entire internal memory of PODxt Pro */
119 /* POD_SYSEX_DUMPMEM2 = 0x76 */
Markus Grabner705ecec2009-02-27 19:43:04 -0800120};
121
122enum {
Stefan Hajnoczi79360952013-01-11 23:08:14 +0100123 POD_MONITOR_LEVEL = 0x04,
124 POD_SYSTEM_INVALID = 0x10000
Markus Grabner705ecec2009-02-27 19:43:04 -0800125};
126
Markus Grabnere1a164d2010-08-23 01:08:25 +0200127/* *INDENT-ON* */
128
Markus Grabner705ecec2009-02-27 19:43:04 -0800129enum {
130 POD_DUMP_MEMORY = 2
131};
132
133enum {
134 POD_BUSY_READ,
135 POD_BUSY_WRITE,
136 POD_CHANNEL_DIRTY,
137 POD_SAVE_PRESSED,
138 POD_BUSY_MIDISEND
139};
140
Markus Grabner705ecec2009-02-27 19:43:04 -0800141static struct snd_ratden pod_ratden = {
142 .num_min = 78125,
143 .num_max = 78125,
144 .num_step = 1,
145 .den = 2
146};
147
148static struct line6_pcm_properties pod_pcm_properties = {
Markus Grabner1027f472010-08-12 01:35:30 +0200149 .snd_line6_playback_hw = {
Markus Grabnere1a164d2010-08-23 01:08:25 +0200150 .info = (SNDRV_PCM_INFO_MMAP |
151 SNDRV_PCM_INFO_INTERLEAVED |
152 SNDRV_PCM_INFO_BLOCK_TRANSFER |
153 SNDRV_PCM_INFO_MMAP_VALID |
154 SNDRV_PCM_INFO_PAUSE |
Markus Grabnere1a164d2010-08-23 01:08:25 +0200155 SNDRV_PCM_INFO_SYNC_START),
156 .formats = SNDRV_PCM_FMTBIT_S24_3LE,
157 .rates = SNDRV_PCM_RATE_KNOT,
158 .rate_min = 39062,
159 .rate_max = 39063,
160 .channels_min = 2,
161 .channels_max = 2,
162 .buffer_bytes_max = 60000,
163 .period_bytes_min = 64,
164 .period_bytes_max = 8192,
165 .periods_min = 1,
166 .periods_max = 1024},
Markus Grabner1027f472010-08-12 01:35:30 +0200167 .snd_line6_capture_hw = {
Markus Grabnere1a164d2010-08-23 01:08:25 +0200168 .info = (SNDRV_PCM_INFO_MMAP |
169 SNDRV_PCM_INFO_INTERLEAVED |
170 SNDRV_PCM_INFO_BLOCK_TRANSFER |
171 SNDRV_PCM_INFO_MMAP_VALID |
Markus Grabnere1a164d2010-08-23 01:08:25 +0200172 SNDRV_PCM_INFO_SYNC_START),
173 .formats = SNDRV_PCM_FMTBIT_S24_3LE,
174 .rates = SNDRV_PCM_RATE_KNOT,
175 .rate_min = 39062,
176 .rate_max = 39063,
177 .channels_min = 2,
178 .channels_max = 2,
179 .buffer_bytes_max = 60000,
180 .period_bytes_min = 64,
181 .period_bytes_max = 8192,
182 .periods_min = 1,
183 .periods_max = 1024},
Markus Grabner705ecec2009-02-27 19:43:04 -0800184 .snd_line6_rates = {
Markus Grabnere1a164d2010-08-23 01:08:25 +0200185 .nrats = 1,
186 .rats = &pod_ratden},
Markus Grabner705ecec2009-02-27 19:43:04 -0800187 .bytes_per_frame = POD_BYTES_PER_FRAME
188};
189
Markus Grabnere1a164d2010-08-23 01:08:25 +0200190static const char pod_version_header[] = {
Markus Grabner1027f472010-08-12 01:35:30 +0200191 0xf2, 0x7e, 0x7f, 0x06, 0x02
192};
193
Markus Grabner1027f472010-08-12 01:35:30 +0200194/* forward declarations: */
195static void pod_startup2(unsigned long data);
196static void pod_startup3(struct usb_line6_pod *pod);
Markus Grabner705ecec2009-02-27 19:43:04 -0800197
Markus Grabnere1a164d2010-08-23 01:08:25 +0200198static char *pod_alloc_sysex_buffer(struct usb_line6_pod *pod, int code,
199 int size)
Markus Grabner705ecec2009-02-27 19:43:04 -0800200{
Markus Grabnere1a164d2010-08-23 01:08:25 +0200201 return line6_alloc_sysex_buffer(&pod->line6, POD_SYSEX_CODE, code,
202 size);
Markus Grabner705ecec2009-02-27 19:43:04 -0800203}
204
205/*
Markus Grabner705ecec2009-02-27 19:43:04 -0800206 Process a completely received message.
207*/
Chris Rorvick01f6b2b2015-01-12 12:42:58 -0800208static void line6_pod_process_message(struct usb_line6 *line6)
Markus Grabner705ecec2009-02-27 19:43:04 -0800209{
Chris Rorvick1cad3e82015-01-12 12:42:57 -0800210 struct usb_line6_pod *pod = (struct usb_line6_pod *) line6;
Markus Grabner705ecec2009-02-27 19:43:04 -0800211 const unsigned char *buf = pod->line6.buffer_message;
212
Stefan Hajnoczi4e6a8ff2013-01-19 11:18:43 +0100213 if (memcmp(buf, pod_version_header, sizeof(pod_version_header)) == 0) {
214 pod->firmware_version = buf[13] * 100 + buf[14] * 10 + buf[15];
215 pod->device_id = ((int)buf[8] << 16) | ((int)buf[9] << 8) |
216 (int) buf[10];
217 pod_startup3(pod);
218 return;
Markus Grabner705ecec2009-02-27 19:43:04 -0800219 }
220
Stefan Hajnoczi4e6a8ff2013-01-19 11:18:43 +0100221 /* Only look for sysex messages from this device */
222 if (buf[0] != (LINE6_SYSEX_BEGIN | LINE6_CHANNEL_DEVICE) &&
223 buf[0] != (LINE6_SYSEX_BEGIN | LINE6_CHANNEL_UNKNOWN)) {
224 return;
225 }
Laurent Navetc19e9462013-02-25 14:08:49 +0100226 if (memcmp(buf + 1, line6_midi_id, sizeof(line6_midi_id)) != 0)
Stefan Hajnoczi4e6a8ff2013-01-19 11:18:43 +0100227 return;
Markus Grabner705ecec2009-02-27 19:43:04 -0800228
Stefan Hajnoczi4e6a8ff2013-01-19 11:18:43 +0100229 if (buf[5] == POD_SYSEX_SYSTEM && buf[6] == POD_MONITOR_LEVEL) {
230 short value = ((int)buf[7] << 12) | ((int)buf[8] << 8) |
231 ((int)buf[9] << 4) | (int)buf[10];
232 pod->monitor_level = value;
Markus Grabner705ecec2009-02-27 19:43:04 -0800233 }
234}
235
236/*
Markus Grabner1027f472010-08-12 01:35:30 +0200237 Send system parameter (from integer).
Markus Grabner705ecec2009-02-27 19:43:04 -0800238*/
Markus Grabnere1a164d2010-08-23 01:08:25 +0200239static int pod_set_system_param_int(struct usb_line6_pod *pod, int value,
240 int code)
Markus Grabner705ecec2009-02-27 19:43:04 -0800241{
242 char *sysex;
243 static const int size = 5;
Markus Grabner705ecec2009-02-27 19:43:04 -0800244
Markus Grabner705ecec2009-02-27 19:43:04 -0800245 sysex = pod_alloc_sysex_buffer(pod, POD_SYSEX_SYSTEM, size);
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800246 if (!sysex)
Markus Grabner1027f472010-08-12 01:35:30 +0200247 return -ENOMEM;
Markus Grabner705ecec2009-02-27 19:43:04 -0800248 sysex[SYSEX_DATA_OFS] = code;
249 sysex[SYSEX_DATA_OFS + 1] = (value >> 12) & 0x0f;
Markus Grabnere1a164d2010-08-23 01:08:25 +0200250 sysex[SYSEX_DATA_OFS + 2] = (value >> 8) & 0x0f;
251 sysex[SYSEX_DATA_OFS + 3] = (value >> 4) & 0x0f;
252 sysex[SYSEX_DATA_OFS + 4] = (value) & 0x0f;
Markus Grabner705ecec2009-02-27 19:43:04 -0800253 line6_send_sysex_message(&pod->line6, sysex, size);
254 kfree(sysex);
Markus Grabner1027f472010-08-12 01:35:30 +0200255 return 0;
256}
257
258/*
Markus Grabner705ecec2009-02-27 19:43:04 -0800259 "read" request on "serial_number" special file.
260*/
Greg Kroah-Hartmane7c8a7e2013-08-24 10:36:49 -0700261static ssize_t serial_number_show(struct device *dev,
262 struct device_attribute *attr, char *buf)
Markus Grabner705ecec2009-02-27 19:43:04 -0800263{
264 struct usb_interface *interface = to_usb_interface(dev);
265 struct usb_line6_pod *pod = usb_get_intfdata(interface);
Jerry Snitselaarf3c52612014-04-24 00:31:48 -0700266
Markus Grabner705ecec2009-02-27 19:43:04 -0800267 return sprintf(buf, "%d\n", pod->serial_number);
268}
269
270/*
271 "read" request on "firmware_version" special file.
272*/
Greg Kroah-Hartmane7c8a7e2013-08-24 10:36:49 -0700273static ssize_t firmware_version_show(struct device *dev,
274 struct device_attribute *attr, char *buf)
Markus Grabner705ecec2009-02-27 19:43:04 -0800275{
276 struct usb_interface *interface = to_usb_interface(dev);
277 struct usb_line6_pod *pod = usb_get_intfdata(interface);
Jerry Snitselaarf3c52612014-04-24 00:31:48 -0700278
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800279 return sprintf(buf, "%d.%02d\n", pod->firmware_version / 100,
280 pod->firmware_version % 100);
Markus Grabner705ecec2009-02-27 19:43:04 -0800281}
282
283/*
284 "read" request on "device_id" special file.
285*/
Greg Kroah-Hartmane7c8a7e2013-08-24 10:36:49 -0700286static ssize_t device_id_show(struct device *dev,
287 struct device_attribute *attr, char *buf)
Markus Grabner705ecec2009-02-27 19:43:04 -0800288{
289 struct usb_interface *interface = to_usb_interface(dev);
290 struct usb_line6_pod *pod = usb_get_intfdata(interface);
Jerry Snitselaarf3c52612014-04-24 00:31:48 -0700291
Markus Grabner705ecec2009-02-27 19:43:04 -0800292 return sprintf(buf, "%d\n", pod->device_id);
293}
294
295/*
Markus Grabner1027f472010-08-12 01:35:30 +0200296 POD startup procedure.
297 This is a sequence of functions with special requirements (e.g., must
298 not run immediately after initialization, must not run in interrupt
299 context). After the last one has finished, the device is ready to use.
300*/
301
302static void pod_startup1(struct usb_line6_pod *pod)
303{
Markus Grabnere1a164d2010-08-23 01:08:25 +0200304 CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_INIT);
Markus Grabner1027f472010-08-12 01:35:30 +0200305
306 /* delay startup procedure: */
Markus Grabnere1a164d2010-08-23 01:08:25 +0200307 line6_start_timer(&pod->startup_timer, POD_STARTUP_DELAY, pod_startup2,
308 (unsigned long)pod);
Markus Grabner1027f472010-08-12 01:35:30 +0200309}
310
311static void pod_startup2(unsigned long data)
312{
313 struct usb_line6_pod *pod = (struct usb_line6_pod *)data;
Markus Grabner1027f472010-08-12 01:35:30 +0200314 struct usb_line6 *line6 = &pod->line6;
Jerry Snitselaarf3c52612014-04-24 00:31:48 -0700315
Markus Grabnere1a164d2010-08-23 01:08:25 +0200316 CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_VERSIONREQ);
Markus Grabner1027f472010-08-12 01:35:30 +0200317
318 /* request firmware version: */
319 line6_version_request_async(line6);
320}
321
Stefan Hajnoczi09fda102012-11-22 20:49:24 +0100322static void pod_startup3(struct usb_line6_pod *pod)
Markus Grabner1027f472010-08-12 01:35:30 +0200323{
Markus Grabnere1a164d2010-08-23 01:08:25 +0200324 CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_WORKQUEUE);
Markus Grabner1027f472010-08-12 01:35:30 +0200325
326 /* schedule work for global work queue: */
327 schedule_work(&pod->startup_work);
328}
329
Stefan Hajnoczi09fda102012-11-22 20:49:24 +0100330static void pod_startup4(struct work_struct *work)
Markus Grabner1027f472010-08-12 01:35:30 +0200331{
Markus Grabnere1a164d2010-08-23 01:08:25 +0200332 struct usb_line6_pod *pod =
333 container_of(work, struct usb_line6_pod, startup_work);
Markus Grabner1027f472010-08-12 01:35:30 +0200334 struct usb_line6 *line6 = &pod->line6;
335
Markus Grabnere1a164d2010-08-23 01:08:25 +0200336 CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_SETUP);
Markus Grabner1027f472010-08-12 01:35:30 +0200337
338 /* serial number: */
339 line6_read_serial_number(&pod->line6, &pod->serial_number);
340
341 /* ALSA audio interface: */
Takashi Iwai85a93392015-01-19 15:54:00 +0100342 snd_card_register(line6->card);
Markus Grabner1027f472010-08-12 01:35:30 +0200343}
344
Markus Grabner705ecec2009-02-27 19:43:04 -0800345/* POD special files: */
Greg Kroah-Hartmane7c8a7e2013-08-24 10:36:49 -0700346static DEVICE_ATTR_RO(device_id);
347static DEVICE_ATTR_RO(firmware_version);
348static DEVICE_ATTR_RO(serial_number);
Markus Grabner705ecec2009-02-27 19:43:04 -0800349
Markus Grabner1027f472010-08-12 01:35:30 +0200350/* control info callback */
351static int snd_pod_control_monitor_info(struct snd_kcontrol *kcontrol,
352 struct snd_ctl_elem_info *uinfo)
353{
354 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
355 uinfo->count = 1;
356 uinfo->value.integer.min = 0;
357 uinfo->value.integer.max = 65535;
358 return 0;
359}
360
361/* control get callback */
362static int snd_pod_control_monitor_get(struct snd_kcontrol *kcontrol,
363 struct snd_ctl_elem_value *ucontrol)
364{
365 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
366 struct usb_line6_pod *pod = (struct usb_line6_pod *)line6pcm->line6;
Jerry Snitselaarf3c52612014-04-24 00:31:48 -0700367
Stefan Hajnoczi2c35dc22012-11-22 20:48:47 +0100368 ucontrol->value.integer.value[0] = pod->monitor_level;
Markus Grabner1027f472010-08-12 01:35:30 +0200369 return 0;
370}
371
372/* control put callback */
373static int snd_pod_control_monitor_put(struct snd_kcontrol *kcontrol,
374 struct snd_ctl_elem_value *ucontrol)
375{
376 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
377 struct usb_line6_pod *pod = (struct usb_line6_pod *)line6pcm->line6;
378
Stefan Hajnoczi2c35dc22012-11-22 20:48:47 +0100379 if (ucontrol->value.integer.value[0] == pod->monitor_level)
Markus Grabner1027f472010-08-12 01:35:30 +0200380 return 0;
381
Stefan Hajnoczi2c35dc22012-11-22 20:48:47 +0100382 pod->monitor_level = ucontrol->value.integer.value[0];
Markus Grabnere1a164d2010-08-23 01:08:25 +0200383 pod_set_system_param_int(pod, ucontrol->value.integer.value[0],
Stefan Hajnoczi79360952013-01-11 23:08:14 +0100384 POD_MONITOR_LEVEL);
Markus Grabner1027f472010-08-12 01:35:30 +0200385 return 1;
386}
387
388/* control definition */
389static struct snd_kcontrol_new pod_control_monitor = {
390 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
391 .name = "Monitor Playback Volume",
392 .index = 0,
393 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
394 .info = snd_pod_control_monitor_info,
395 .get = snd_pod_control_monitor_get,
396 .put = snd_pod_control_monitor_put
397};
398
Markus Grabner705ecec2009-02-27 19:43:04 -0800399/*
Chris Rorvickd29b8542015-01-12 12:43:00 -0800400 POD device disconnected.
401*/
402static void line6_pod_disconnect(struct usb_interface *interface)
403{
404 struct usb_line6_pod *pod;
405
406 if (interface == NULL)
407 return;
408 pod = usb_get_intfdata(interface);
409
410 if (pod != NULL) {
Chris Rorvickd29b8542015-01-12 12:43:00 -0800411 struct device *dev = &interface->dev;
412
Chris Rorvickd29b8542015-01-12 12:43:00 -0800413 if (dev != NULL) {
414 /* remove sysfs entries: */
415 device_remove_file(dev, &dev_attr_device_id);
416 device_remove_file(dev, &dev_attr_firmware_version);
417 device_remove_file(dev, &dev_attr_serial_number);
418 }
Chris Rorvickd29b8542015-01-12 12:43:00 -0800419
Takashi Iwai85a93392015-01-19 15:54:00 +0100420 del_timer_sync(&pod->startup_timer);
421 cancel_work_sync(&pod->startup_work);
422 }
Chris Rorvickd29b8542015-01-12 12:43:00 -0800423}
424
425/*
Markus Grabner705ecec2009-02-27 19:43:04 -0800426 Create sysfs entries.
427*/
Greg Kroah-Hartmanb702ed252009-02-27 20:45:03 -0800428static int pod_create_files2(struct device *dev)
Markus Grabner705ecec2009-02-27 19:43:04 -0800429{
430 int err;
431
Takashi Iwaib2a3b022015-01-19 16:08:02 +0100432 err = device_create_file(dev, &dev_attr_device_id);
433 if (err < 0)
434 return err;
435 err = device_create_file(dev, &dev_attr_firmware_version);
436 if (err < 0)
437 return err;
438 err = device_create_file(dev, &dev_attr_serial_number);
439 if (err < 0)
440 return err;
Markus Grabner705ecec2009-02-27 19:43:04 -0800441 return 0;
442}
443
444/*
Markus Grabner1027f472010-08-12 01:35:30 +0200445 Try to init POD device.
Markus Grabner705ecec2009-02-27 19:43:04 -0800446*/
Takashi Iwai85a93392015-01-19 15:54:00 +0100447static int pod_init(struct usb_interface *interface,
448 struct usb_line6 *line6)
Markus Grabner705ecec2009-02-27 19:43:04 -0800449{
450 int err;
Chris Rorvicka221dd42015-01-12 12:42:56 -0800451 struct usb_line6_pod *pod = (struct usb_line6_pod *) line6;
Markus Grabner705ecec2009-02-27 19:43:04 -0800452
Chris Rorvick01f6b2b2015-01-12 12:42:58 -0800453 line6->process_message = line6_pod_process_message;
Chris Rorvicka46c4672015-01-12 12:42:59 -0800454 line6->disconnect = line6_pod_disconnect;
Chris Rorvick01f6b2b2015-01-12 12:42:58 -0800455
Markus Grabnere1a164d2010-08-23 01:08:25 +0200456 init_timer(&pod->startup_timer);
Stefan Hajnoczi09fda102012-11-22 20:49:24 +0100457 INIT_WORK(&pod->startup_work, pod_startup4);
Markus Grabnere1a164d2010-08-23 01:08:25 +0200458
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800459 if ((interface == NULL) || (pod == NULL))
460 return -ENODEV;
Markus Grabner705ecec2009-02-27 19:43:04 -0800461
Markus Grabner705ecec2009-02-27 19:43:04 -0800462 /* create sysfs entries: */
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800463 err = pod_create_files2(&interface->dev);
Greg Kroah-Hartman027360c2010-09-21 16:58:00 -0700464 if (err < 0)
Markus Grabner705ecec2009-02-27 19:43:04 -0800465 return err;
Markus Grabner705ecec2009-02-27 19:43:04 -0800466
Markus Grabner705ecec2009-02-27 19:43:04 -0800467 /* initialize MIDI subsystem: */
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800468 err = line6_init_midi(line6);
Greg Kroah-Hartman027360c2010-09-21 16:58:00 -0700469 if (err < 0)
Markus Grabner705ecec2009-02-27 19:43:04 -0800470 return err;
Markus Grabner705ecec2009-02-27 19:43:04 -0800471
472 /* initialize PCM subsystem: */
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800473 err = line6_init_pcm(line6, &pod_pcm_properties);
Greg Kroah-Hartman027360c2010-09-21 16:58:00 -0700474 if (err < 0)
Markus Grabner705ecec2009-02-27 19:43:04 -0800475 return err;
Markus Grabner705ecec2009-02-27 19:43:04 -0800476
Markus Grabner1027f472010-08-12 01:35:30 +0200477 /* register monitor control: */
Greg Kroah-Hartman027360c2010-09-21 16:58:00 -0700478 err = snd_ctl_add(line6->card,
479 snd_ctl_new1(&pod_control_monitor, line6->line6pcm));
480 if (err < 0)
Markus Grabner705ecec2009-02-27 19:43:04 -0800481 return err;
Markus Grabner705ecec2009-02-27 19:43:04 -0800482
Markus Grabner1027f472010-08-12 01:35:30 +0200483 /*
Markus Grabnere1a164d2010-08-23 01:08:25 +0200484 When the sound card is registered at this point, the PODxt Live
485 displays "Invalid Code Error 07", so we do it later in the event
486 handler.
487 */
Markus Grabner1027f472010-08-12 01:35:30 +0200488
Chris Rorvick4cb1a4a2015-01-12 12:42:45 -0800489 if (pod->line6.properties->capabilities & LINE6_CAP_CONTROL) {
Stefan Hajnoczi79360952013-01-11 23:08:14 +0100490 pod->monitor_level = POD_SYSTEM_INVALID;
Markus Grabner1027f472010-08-12 01:35:30 +0200491
492 /* initiate startup procedure: */
493 pod_startup1(pod);
Markus Grabner705ecec2009-02-27 19:43:04 -0800494 }
495
496 return 0;
497}
498
Takashi Iwaiccddbe42015-01-15 08:22:31 +0100499#define LINE6_DEVICE(prod) USB_DEVICE(0x0e41, prod)
500#define LINE6_IF_NUM(prod, n) USB_DEVICE_INTERFACE_NUMBER(0x0e41, prod, n)
501
502/* table of devices that work with this driver */
503static const struct usb_device_id pod_id_table[] = {
504 { LINE6_DEVICE(0x4250), .driver_info = LINE6_BASSPODXT },
505 { LINE6_DEVICE(0x4642), .driver_info = LINE6_BASSPODXTLIVE },
506 { LINE6_DEVICE(0x4252), .driver_info = LINE6_BASSPODXTPRO },
507 { LINE6_IF_NUM(0x5051, 1), .driver_info = LINE6_POCKETPOD },
508 { LINE6_DEVICE(0x5044), .driver_info = LINE6_PODXT },
509 { LINE6_IF_NUM(0x4650, 0), .driver_info = LINE6_PODXTLIVE_POD },
510 { LINE6_DEVICE(0x5050), .driver_info = LINE6_PODXTPRO },
511 {}
512};
513
514MODULE_DEVICE_TABLE(usb, pod_id_table);
515
516static const struct line6_properties pod_properties_table[] = {
517 [LINE6_BASSPODXT] = {
518 .id = "BassPODxt",
519 .name = "BassPODxt",
520 .capabilities = LINE6_CAP_CONTROL
521 | LINE6_CAP_PCM
522 | LINE6_CAP_HWMON,
523 .altsetting = 5,
524 .ep_ctrl_r = 0x84,
525 .ep_ctrl_w = 0x03,
526 .ep_audio_r = 0x82,
527 .ep_audio_w = 0x01,
528 },
529 [LINE6_BASSPODXTLIVE] = {
530 .id = "BassPODxtLive",
531 .name = "BassPODxt Live",
532 .capabilities = LINE6_CAP_CONTROL
533 | LINE6_CAP_PCM
534 | LINE6_CAP_HWMON,
535 .altsetting = 1,
536 .ep_ctrl_r = 0x84,
537 .ep_ctrl_w = 0x03,
538 .ep_audio_r = 0x82,
539 .ep_audio_w = 0x01,
540 },
541 [LINE6_BASSPODXTPRO] = {
542 .id = "BassPODxtPro",
543 .name = "BassPODxt Pro",
544 .capabilities = LINE6_CAP_CONTROL
545 | LINE6_CAP_PCM
546 | LINE6_CAP_HWMON,
547 .altsetting = 5,
548 .ep_ctrl_r = 0x84,
549 .ep_ctrl_w = 0x03,
550 .ep_audio_r = 0x82,
551 .ep_audio_w = 0x01,
552 },
553 [LINE6_POCKETPOD] = {
554 .id = "PocketPOD",
555 .name = "Pocket POD",
556 .capabilities = LINE6_CAP_CONTROL,
557 .altsetting = 0,
558 .ep_ctrl_r = 0x82,
559 .ep_ctrl_w = 0x02,
560 /* no audio channel */
561 },
562 [LINE6_PODXT] = {
563 .id = "PODxt",
564 .name = "PODxt",
565 .capabilities = LINE6_CAP_CONTROL
566 | LINE6_CAP_PCM
567 | LINE6_CAP_HWMON,
568 .altsetting = 5,
569 .ep_ctrl_r = 0x84,
570 .ep_ctrl_w = 0x03,
571 .ep_audio_r = 0x82,
572 .ep_audio_w = 0x01,
573 },
574 [LINE6_PODXTLIVE_POD] = {
575 .id = "PODxtLive",
576 .name = "PODxt Live",
577 .capabilities = LINE6_CAP_CONTROL
578 | LINE6_CAP_PCM
579 | LINE6_CAP_HWMON,
580 .altsetting = 1,
581 .ep_ctrl_r = 0x84,
582 .ep_ctrl_w = 0x03,
583 .ep_audio_r = 0x82,
584 .ep_audio_w = 0x01,
585 },
586 [LINE6_PODXTPRO] = {
587 .id = "PODxtPro",
588 .name = "PODxt Pro",
589 .capabilities = LINE6_CAP_CONTROL
590 | LINE6_CAP_PCM
591 | LINE6_CAP_HWMON,
592 .altsetting = 5,
593 .ep_ctrl_r = 0x84,
594 .ep_ctrl_w = 0x03,
595 .ep_audio_r = 0x82,
596 .ep_audio_w = 0x01,
597 },
598};
599
600/*
601 Probe USB device.
602*/
603static int pod_probe(struct usb_interface *interface,
604 const struct usb_device_id *id)
605{
606 struct usb_line6_pod *pod;
Takashi Iwaiccddbe42015-01-15 08:22:31 +0100607
608 pod = kzalloc(sizeof(*pod), GFP_KERNEL);
609 if (!pod)
610 return -ENODEV;
Takashi Iwai85a93392015-01-19 15:54:00 +0100611 return line6_probe(interface, &pod->line6,
612 &pod_properties_table[id->driver_info],
613 pod_init);
Takashi Iwaiccddbe42015-01-15 08:22:31 +0100614}
615
616static struct usb_driver pod_driver = {
617 .name = KBUILD_MODNAME,
618 .probe = pod_probe,
619 .disconnect = line6_disconnect,
620#ifdef CONFIG_PM
621 .suspend = line6_suspend,
622 .resume = line6_resume,
623 .reset_resume = line6_resume,
624#endif
625 .id_table = pod_id_table,
626};
627
628module_usb_driver(pod_driver);
629
Chris Rorvickc6fffce2015-01-20 02:20:49 -0600630MODULE_DESCRIPTION("Line 6 POD USB driver");
Takashi Iwaiccddbe42015-01-15 08:22:31 +0100631MODULE_LICENSE("GPL");