blob: 17aa616e61f53bd7b196422900308fefc16a7136 [file] [log] [blame]
Markus Grabner705ecec2009-02-27 19:43:04 -08001/*
Chris Rorvickc078a4a2015-01-20 02:20:50 -06002 * Line 6 Linux USB driver
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 Grabner1027f4762010-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 Grabner1027f4762010-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 Grabner1027f4762010-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
25/*
26 Locate name in binary program dump
27*/
28#define POD_NAME_OFFSET 0
29#define POD_NAME_LENGTH 16
30
31/*
32 Other constants
33*/
34#define POD_CONTROL_SIZE 0x80
35#define POD_BUFSIZE_DUMPREQ 7
36#define POD_STARTUP_DELAY 1000
37
38/*
39 Stages of POD startup procedure
40*/
41enum {
42 POD_STARTUP_INIT = 1,
43 POD_STARTUP_VERSIONREQ,
44 POD_STARTUP_WORKQUEUE,
45 POD_STARTUP_SETUP,
46 POD_STARTUP_LAST = POD_STARTUP_SETUP - 1
47};
48
49enum {
50 LINE6_BASSPODXT,
51 LINE6_BASSPODXTLIVE,
52 LINE6_BASSPODXTPRO,
53 LINE6_POCKETPOD,
54 LINE6_PODXT,
55 LINE6_PODXTLIVE_POD,
56 LINE6_PODXTPRO,
57};
58
59struct usb_line6_pod {
Takashi Iwaicddbd4f2015-01-28 14:43:11 +010060 /* Generic Line 6 USB data */
Takashi Iwaiccddbe42015-01-15 08:22:31 +010061 struct usb_line6 line6;
62
Takashi Iwaicddbd4f2015-01-28 14:43:11 +010063 /* Instrument monitor level */
Takashi Iwaiccddbe42015-01-15 08:22:31 +010064 int monitor_level;
65
Takashi Iwaicddbd4f2015-01-28 14:43:11 +010066 /* Timer for device initialization */
Takashi Iwaiccddbe42015-01-15 08:22:31 +010067 struct timer_list startup_timer;
68
Takashi Iwaicddbd4f2015-01-28 14:43:11 +010069 /* Work handler for device initialization */
Takashi Iwaiccddbe42015-01-15 08:22:31 +010070 struct work_struct startup_work;
71
Takashi Iwaicddbd4f2015-01-28 14:43:11 +010072 /* Current progress in startup procedure */
Takashi Iwaiccddbe42015-01-15 08:22:31 +010073 int startup_progress;
74
Takashi Iwaicddbd4f2015-01-28 14:43:11 +010075 /* Serial number of device */
Chris Rorvick12b00152015-02-10 23:03:16 -060076 u32 serial_number;
Takashi Iwaiccddbe42015-01-15 08:22:31 +010077
Takashi Iwaicddbd4f2015-01-28 14:43:11 +010078 /* Firmware version (x 100) */
Takashi Iwaiccddbe42015-01-15 08:22:31 +010079 int firmware_version;
80
Takashi Iwaicddbd4f2015-01-28 14:43:11 +010081 /* Device ID */
Takashi Iwaiccddbe42015-01-15 08:22:31 +010082 int device_id;
83};
Markus Grabner705ecec2009-02-27 19:43:04 -080084
Markus Grabner705ecec2009-02-27 19:43:04 -080085#define POD_SYSEX_CODE 3
Markus Grabner705ecec2009-02-27 19:43:04 -080086
Markus Grabnere1a164d2010-08-23 01:08:25 +020087/* *INDENT-OFF* */
Markus Grabner705ecec2009-02-27 19:43:04 -080088
89enum {
Markus Grabner705ecec2009-02-27 19:43:04 -080090 POD_SYSEX_SAVE = 0x24,
91 POD_SYSEX_SYSTEM = 0x56,
92 POD_SYSEX_SYSTEMREQ = 0x57,
93 /* POD_SYSEX_UPDATE = 0x6c, */ /* software update! */
94 POD_SYSEX_STORE = 0x71,
95 POD_SYSEX_FINISH = 0x72,
96 POD_SYSEX_DUMPMEM = 0x73,
97 POD_SYSEX_DUMP = 0x74,
98 POD_SYSEX_DUMPREQ = 0x75
Stefan Hajnoczi0a1eb4e2013-01-11 23:08:12 +010099
100 /* dumps entire internal memory of PODxt Pro */
101 /* POD_SYSEX_DUMPMEM2 = 0x76 */
Markus Grabner705ecec2009-02-27 19:43:04 -0800102};
103
104enum {
Stefan Hajnoczi79360952013-01-11 23:08:14 +0100105 POD_MONITOR_LEVEL = 0x04,
106 POD_SYSTEM_INVALID = 0x10000
Markus Grabner705ecec2009-02-27 19:43:04 -0800107};
108
Markus Grabnere1a164d2010-08-23 01:08:25 +0200109/* *INDENT-ON* */
110
Markus Grabner705ecec2009-02-27 19:43:04 -0800111enum {
112 POD_DUMP_MEMORY = 2
113};
114
115enum {
116 POD_BUSY_READ,
117 POD_BUSY_WRITE,
118 POD_CHANNEL_DIRTY,
119 POD_SAVE_PRESSED,
120 POD_BUSY_MIDISEND
121};
122
Markus Grabner705ecec2009-02-27 19:43:04 -0800123static struct snd_ratden pod_ratden = {
124 .num_min = 78125,
125 .num_max = 78125,
126 .num_step = 1,
127 .den = 2
128};
129
130static struct line6_pcm_properties pod_pcm_properties = {
Takashi Iwai1263f612015-01-28 15:08:59 +0100131 .playback_hw = {
Markus Grabnere1a164d2010-08-23 01:08:25 +0200132 .info = (SNDRV_PCM_INFO_MMAP |
133 SNDRV_PCM_INFO_INTERLEAVED |
134 SNDRV_PCM_INFO_BLOCK_TRANSFER |
135 SNDRV_PCM_INFO_MMAP_VALID |
136 SNDRV_PCM_INFO_PAUSE |
Markus Grabnere1a164d2010-08-23 01:08:25 +0200137 SNDRV_PCM_INFO_SYNC_START),
138 .formats = SNDRV_PCM_FMTBIT_S24_3LE,
139 .rates = SNDRV_PCM_RATE_KNOT,
140 .rate_min = 39062,
141 .rate_max = 39063,
142 .channels_min = 2,
143 .channels_max = 2,
144 .buffer_bytes_max = 60000,
145 .period_bytes_min = 64,
146 .period_bytes_max = 8192,
147 .periods_min = 1,
148 .periods_max = 1024},
Takashi Iwai1263f612015-01-28 15:08:59 +0100149 .capture_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 |
Markus Grabnere1a164d2010-08-23 01:08:25 +0200154 SNDRV_PCM_INFO_SYNC_START),
155 .formats = SNDRV_PCM_FMTBIT_S24_3LE,
156 .rates = SNDRV_PCM_RATE_KNOT,
157 .rate_min = 39062,
158 .rate_max = 39063,
159 .channels_min = 2,
160 .channels_max = 2,
161 .buffer_bytes_max = 60000,
162 .period_bytes_min = 64,
163 .period_bytes_max = 8192,
164 .periods_min = 1,
165 .periods_max = 1024},
Takashi Iwai1263f612015-01-28 15:08:59 +0100166 .rates = {
Markus Grabnere1a164d2010-08-23 01:08:25 +0200167 .nrats = 1,
168 .rats = &pod_ratden},
Andrej Krutak97d78ac2016-09-18 20:59:24 +0200169 .bytes_per_channel = 3 /* SNDRV_PCM_FMTBIT_S24_3LE */
Markus Grabner705ecec2009-02-27 19:43:04 -0800170};
171
Markus Grabnere1a164d2010-08-23 01:08:25 +0200172static const char pod_version_header[] = {
Markus Grabner1027f4762010-08-12 01:35:30 +0200173 0xf2, 0x7e, 0x7f, 0x06, 0x02
174};
175
Markus Grabner1027f4762010-08-12 01:35:30 +0200176/* forward declarations: */
177static void pod_startup2(unsigned long data);
178static void pod_startup3(struct usb_line6_pod *pod);
Markus Grabner705ecec2009-02-27 19:43:04 -0800179
Markus Grabnere1a164d2010-08-23 01:08:25 +0200180static char *pod_alloc_sysex_buffer(struct usb_line6_pod *pod, int code,
181 int size)
Markus Grabner705ecec2009-02-27 19:43:04 -0800182{
Markus Grabnere1a164d2010-08-23 01:08:25 +0200183 return line6_alloc_sysex_buffer(&pod->line6, POD_SYSEX_CODE, code,
184 size);
Markus Grabner705ecec2009-02-27 19:43:04 -0800185}
186
187/*
Markus Grabner705ecec2009-02-27 19:43:04 -0800188 Process a completely received message.
189*/
Chris Rorvick01f6b2b2015-01-12 12:42:58 -0800190static void line6_pod_process_message(struct usb_line6 *line6)
Markus Grabner705ecec2009-02-27 19:43:04 -0800191{
Chris Rorvick1cad3e82015-01-12 12:42:57 -0800192 struct usb_line6_pod *pod = (struct usb_line6_pod *) line6;
Markus Grabner705ecec2009-02-27 19:43:04 -0800193 const unsigned char *buf = pod->line6.buffer_message;
194
Stefan Hajnoczi4e6a8ff2013-01-19 11:18:43 +0100195 if (memcmp(buf, pod_version_header, sizeof(pod_version_header)) == 0) {
196 pod->firmware_version = buf[13] * 100 + buf[14] * 10 + buf[15];
197 pod->device_id = ((int)buf[8] << 16) | ((int)buf[9] << 8) |
198 (int) buf[10];
199 pod_startup3(pod);
200 return;
Markus Grabner705ecec2009-02-27 19:43:04 -0800201 }
202
Stefan Hajnoczi4e6a8ff2013-01-19 11:18:43 +0100203 /* Only look for sysex messages from this device */
204 if (buf[0] != (LINE6_SYSEX_BEGIN | LINE6_CHANNEL_DEVICE) &&
205 buf[0] != (LINE6_SYSEX_BEGIN | LINE6_CHANNEL_UNKNOWN)) {
206 return;
207 }
Laurent Navetc19e9462013-02-25 14:08:49 +0100208 if (memcmp(buf + 1, line6_midi_id, sizeof(line6_midi_id)) != 0)
Stefan Hajnoczi4e6a8ff2013-01-19 11:18:43 +0100209 return;
Markus Grabner705ecec2009-02-27 19:43:04 -0800210
Stefan Hajnoczi4e6a8ff2013-01-19 11:18:43 +0100211 if (buf[5] == POD_SYSEX_SYSTEM && buf[6] == POD_MONITOR_LEVEL) {
212 short value = ((int)buf[7] << 12) | ((int)buf[8] << 8) |
213 ((int)buf[9] << 4) | (int)buf[10];
214 pod->monitor_level = value;
Markus Grabner705ecec2009-02-27 19:43:04 -0800215 }
216}
217
218/*
Markus Grabner1027f4762010-08-12 01:35:30 +0200219 Send system parameter (from integer).
Markus Grabner705ecec2009-02-27 19:43:04 -0800220*/
Markus Grabnere1a164d2010-08-23 01:08:25 +0200221static int pod_set_system_param_int(struct usb_line6_pod *pod, int value,
222 int code)
Markus Grabner705ecec2009-02-27 19:43:04 -0800223{
224 char *sysex;
225 static const int size = 5;
Markus Grabner705ecec2009-02-27 19:43:04 -0800226
Markus Grabner705ecec2009-02-27 19:43:04 -0800227 sysex = pod_alloc_sysex_buffer(pod, POD_SYSEX_SYSTEM, size);
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800228 if (!sysex)
Markus Grabner1027f4762010-08-12 01:35:30 +0200229 return -ENOMEM;
Markus Grabner705ecec2009-02-27 19:43:04 -0800230 sysex[SYSEX_DATA_OFS] = code;
231 sysex[SYSEX_DATA_OFS + 1] = (value >> 12) & 0x0f;
Markus Grabnere1a164d2010-08-23 01:08:25 +0200232 sysex[SYSEX_DATA_OFS + 2] = (value >> 8) & 0x0f;
233 sysex[SYSEX_DATA_OFS + 3] = (value >> 4) & 0x0f;
234 sysex[SYSEX_DATA_OFS + 4] = (value) & 0x0f;
Markus Grabner705ecec2009-02-27 19:43:04 -0800235 line6_send_sysex_message(&pod->line6, sysex, size);
236 kfree(sysex);
Markus Grabner1027f4762010-08-12 01:35:30 +0200237 return 0;
238}
239
240/*
Markus Grabner705ecec2009-02-27 19:43:04 -0800241 "read" request on "serial_number" special file.
242*/
Greg Kroah-Hartmane7c8a7e2013-08-24 10:36:49 -0700243static ssize_t serial_number_show(struct device *dev,
244 struct device_attribute *attr, char *buf)
Markus Grabner705ecec2009-02-27 19:43:04 -0800245{
Andrej Krutakb027d112016-08-18 23:52:12 +0200246 struct snd_card *card = dev_to_snd_card(dev);
247 struct usb_line6_pod *pod = card->private_data;
Jerry Snitselaarf3c52612014-04-24 00:31:48 -0700248
Chris Rorvick12b00152015-02-10 23:03:16 -0600249 return sprintf(buf, "%u\n", pod->serial_number);
Markus Grabner705ecec2009-02-27 19:43:04 -0800250}
251
252/*
253 "read" request on "firmware_version" special file.
254*/
Greg Kroah-Hartmane7c8a7e2013-08-24 10:36:49 -0700255static ssize_t firmware_version_show(struct device *dev,
256 struct device_attribute *attr, char *buf)
Markus Grabner705ecec2009-02-27 19:43:04 -0800257{
Andrej Krutakb027d112016-08-18 23:52:12 +0200258 struct snd_card *card = dev_to_snd_card(dev);
259 struct usb_line6_pod *pod = card->private_data;
Jerry Snitselaarf3c52612014-04-24 00:31:48 -0700260
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800261 return sprintf(buf, "%d.%02d\n", pod->firmware_version / 100,
262 pod->firmware_version % 100);
Markus Grabner705ecec2009-02-27 19:43:04 -0800263}
264
265/*
266 "read" request on "device_id" special file.
267*/
Greg Kroah-Hartmane7c8a7e2013-08-24 10:36:49 -0700268static ssize_t device_id_show(struct device *dev,
269 struct device_attribute *attr, char *buf)
Markus Grabner705ecec2009-02-27 19:43:04 -0800270{
Andrej Krutakb027d112016-08-18 23:52:12 +0200271 struct snd_card *card = dev_to_snd_card(dev);
272 struct usb_line6_pod *pod = card->private_data;
Jerry Snitselaarf3c52612014-04-24 00:31:48 -0700273
Markus Grabner705ecec2009-02-27 19:43:04 -0800274 return sprintf(buf, "%d\n", pod->device_id);
275}
276
277/*
Markus Grabner1027f4762010-08-12 01:35:30 +0200278 POD startup procedure.
279 This is a sequence of functions with special requirements (e.g., must
280 not run immediately after initialization, must not run in interrupt
281 context). After the last one has finished, the device is ready to use.
282*/
283
284static void pod_startup1(struct usb_line6_pod *pod)
285{
Markus Grabnere1a164d2010-08-23 01:08:25 +0200286 CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_INIT);
Markus Grabner1027f4762010-08-12 01:35:30 +0200287
288 /* delay startup procedure: */
Markus Grabnere1a164d2010-08-23 01:08:25 +0200289 line6_start_timer(&pod->startup_timer, POD_STARTUP_DELAY, pod_startup2,
290 (unsigned long)pod);
Markus Grabner1027f4762010-08-12 01:35:30 +0200291}
292
293static void pod_startup2(unsigned long data)
294{
295 struct usb_line6_pod *pod = (struct usb_line6_pod *)data;
Markus Grabner1027f4762010-08-12 01:35:30 +0200296 struct usb_line6 *line6 = &pod->line6;
Jerry Snitselaarf3c52612014-04-24 00:31:48 -0700297
Markus Grabnere1a164d2010-08-23 01:08:25 +0200298 CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_VERSIONREQ);
Markus Grabner1027f4762010-08-12 01:35:30 +0200299
300 /* request firmware version: */
301 line6_version_request_async(line6);
302}
303
Stefan Hajnoczi09fda102012-11-22 20:49:24 +0100304static void pod_startup3(struct usb_line6_pod *pod)
Markus Grabner1027f4762010-08-12 01:35:30 +0200305{
Markus Grabnere1a164d2010-08-23 01:08:25 +0200306 CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_WORKQUEUE);
Markus Grabner1027f4762010-08-12 01:35:30 +0200307
308 /* schedule work for global work queue: */
309 schedule_work(&pod->startup_work);
310}
311
Stefan Hajnoczi09fda102012-11-22 20:49:24 +0100312static void pod_startup4(struct work_struct *work)
Markus Grabner1027f4762010-08-12 01:35:30 +0200313{
Markus Grabnere1a164d2010-08-23 01:08:25 +0200314 struct usb_line6_pod *pod =
315 container_of(work, struct usb_line6_pod, startup_work);
Markus Grabner1027f4762010-08-12 01:35:30 +0200316 struct usb_line6 *line6 = &pod->line6;
317
Markus Grabnere1a164d2010-08-23 01:08:25 +0200318 CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_SETUP);
Markus Grabner1027f4762010-08-12 01:35:30 +0200319
320 /* serial number: */
321 line6_read_serial_number(&pod->line6, &pod->serial_number);
322
323 /* ALSA audio interface: */
Takashi Iwai85a93392015-01-19 15:54:00 +0100324 snd_card_register(line6->card);
Markus Grabner1027f4762010-08-12 01:35:30 +0200325}
326
Markus Grabner705ecec2009-02-27 19:43:04 -0800327/* POD special files: */
Greg Kroah-Hartmane7c8a7e2013-08-24 10:36:49 -0700328static DEVICE_ATTR_RO(device_id);
329static DEVICE_ATTR_RO(firmware_version);
330static DEVICE_ATTR_RO(serial_number);
Markus Grabner705ecec2009-02-27 19:43:04 -0800331
Takashi Iwai02fc76f2015-01-30 12:36:17 +0100332static struct attribute *pod_dev_attrs[] = {
333 &dev_attr_device_id.attr,
334 &dev_attr_firmware_version.attr,
335 &dev_attr_serial_number.attr,
336 NULL
337};
338
339static const struct attribute_group pod_dev_attr_group = {
340 .name = "pod",
341 .attrs = pod_dev_attrs,
342};
343
Markus Grabner1027f4762010-08-12 01:35:30 +0200344/* control info callback */
345static int snd_pod_control_monitor_info(struct snd_kcontrol *kcontrol,
346 struct snd_ctl_elem_info *uinfo)
347{
348 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
349 uinfo->count = 1;
350 uinfo->value.integer.min = 0;
351 uinfo->value.integer.max = 65535;
352 return 0;
353}
354
355/* control get callback */
356static int snd_pod_control_monitor_get(struct snd_kcontrol *kcontrol,
357 struct snd_ctl_elem_value *ucontrol)
358{
359 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
360 struct usb_line6_pod *pod = (struct usb_line6_pod *)line6pcm->line6;
Jerry Snitselaarf3c52612014-04-24 00:31:48 -0700361
Stefan Hajnoczi2c35dc22012-11-22 20:48:47 +0100362 ucontrol->value.integer.value[0] = pod->monitor_level;
Markus Grabner1027f4762010-08-12 01:35:30 +0200363 return 0;
364}
365
366/* control put callback */
367static int snd_pod_control_monitor_put(struct snd_kcontrol *kcontrol,
368 struct snd_ctl_elem_value *ucontrol)
369{
370 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
371 struct usb_line6_pod *pod = (struct usb_line6_pod *)line6pcm->line6;
372
Stefan Hajnoczi2c35dc22012-11-22 20:48:47 +0100373 if (ucontrol->value.integer.value[0] == pod->monitor_level)
Markus Grabner1027f4762010-08-12 01:35:30 +0200374 return 0;
375
Stefan Hajnoczi2c35dc22012-11-22 20:48:47 +0100376 pod->monitor_level = ucontrol->value.integer.value[0];
Markus Grabnere1a164d2010-08-23 01:08:25 +0200377 pod_set_system_param_int(pod, ucontrol->value.integer.value[0],
Stefan Hajnoczi79360952013-01-11 23:08:14 +0100378 POD_MONITOR_LEVEL);
Markus Grabner1027f4762010-08-12 01:35:30 +0200379 return 1;
380}
381
382/* control definition */
383static struct snd_kcontrol_new pod_control_monitor = {
384 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
385 .name = "Monitor Playback Volume",
386 .index = 0,
387 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
388 .info = snd_pod_control_monitor_info,
389 .get = snd_pod_control_monitor_get,
390 .put = snd_pod_control_monitor_put
391};
392
Markus Grabner705ecec2009-02-27 19:43:04 -0800393/*
Chris Rorvickd29b8542015-01-12 12:43:00 -0800394 POD device disconnected.
395*/
Takashi Iwaif66fd992015-01-25 18:22:58 +0100396static void line6_pod_disconnect(struct usb_line6 *line6)
Chris Rorvickd29b8542015-01-12 12:43:00 -0800397{
Takashi Iwaif66fd992015-01-25 18:22:58 +0100398 struct usb_line6_pod *pod = (struct usb_line6_pod *)line6;
Chris Rorvickd29b8542015-01-12 12:43:00 -0800399
Takashi Iwai8a3b7c02015-01-20 08:42:42 +0100400 del_timer_sync(&pod->startup_timer);
401 cancel_work_sync(&pod->startup_work);
Chris Rorvickd29b8542015-01-12 12:43:00 -0800402}
403
404/*
Markus Grabner1027f4762010-08-12 01:35:30 +0200405 Try to init POD device.
Markus Grabner705ecec2009-02-27 19:43:04 -0800406*/
Takashi Iwaif66fd992015-01-25 18:22:58 +0100407static int pod_init(struct usb_line6 *line6,
408 const struct usb_device_id *id)
Markus Grabner705ecec2009-02-27 19:43:04 -0800409{
410 int err;
Chris Rorvicka221dd42015-01-12 12:42:56 -0800411 struct usb_line6_pod *pod = (struct usb_line6_pod *) line6;
Markus Grabner705ecec2009-02-27 19:43:04 -0800412
Chris Rorvick01f6b2b2015-01-12 12:42:58 -0800413 line6->process_message = line6_pod_process_message;
Chris Rorvicka46c4672015-01-12 12:42:59 -0800414 line6->disconnect = line6_pod_disconnect;
Chris Rorvick01f6b2b2015-01-12 12:42:58 -0800415
Markus Grabnere1a164d2010-08-23 01:08:25 +0200416 init_timer(&pod->startup_timer);
Stefan Hajnoczi09fda102012-11-22 20:49:24 +0100417 INIT_WORK(&pod->startup_work, pod_startup4);
Markus Grabnere1a164d2010-08-23 01:08:25 +0200418
Markus Grabner705ecec2009-02-27 19:43:04 -0800419 /* create sysfs entries: */
Takashi Iwai02fc76f2015-01-30 12:36:17 +0100420 err = snd_card_add_dev_attr(line6->card, &pod_dev_attr_group);
Greg Kroah-Hartman027360c2010-09-21 16:58:00 -0700421 if (err < 0)
Markus Grabner705ecec2009-02-27 19:43:04 -0800422 return err;
Markus Grabner705ecec2009-02-27 19:43:04 -0800423
Markus Grabner705ecec2009-02-27 19:43:04 -0800424 /* initialize MIDI subsystem: */
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800425 err = line6_init_midi(line6);
Greg Kroah-Hartman027360c2010-09-21 16:58:00 -0700426 if (err < 0)
Markus Grabner705ecec2009-02-27 19:43:04 -0800427 return err;
Markus Grabner705ecec2009-02-27 19:43:04 -0800428
429 /* initialize PCM subsystem: */
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800430 err = line6_init_pcm(line6, &pod_pcm_properties);
Greg Kroah-Hartman027360c2010-09-21 16:58:00 -0700431 if (err < 0)
Markus Grabner705ecec2009-02-27 19:43:04 -0800432 return err;
Markus Grabner705ecec2009-02-27 19:43:04 -0800433
Markus Grabner1027f4762010-08-12 01:35:30 +0200434 /* register monitor control: */
Greg Kroah-Hartman027360c2010-09-21 16:58:00 -0700435 err = snd_ctl_add(line6->card,
436 snd_ctl_new1(&pod_control_monitor, line6->line6pcm));
437 if (err < 0)
Markus Grabner705ecec2009-02-27 19:43:04 -0800438 return err;
Markus Grabner705ecec2009-02-27 19:43:04 -0800439
Markus Grabner1027f4762010-08-12 01:35:30 +0200440 /*
Markus Grabnere1a164d2010-08-23 01:08:25 +0200441 When the sound card is registered at this point, the PODxt Live
442 displays "Invalid Code Error 07", so we do it later in the event
443 handler.
444 */
Markus Grabner1027f4762010-08-12 01:35:30 +0200445
Chris Rorvick4cb1a4a2015-01-12 12:42:45 -0800446 if (pod->line6.properties->capabilities & LINE6_CAP_CONTROL) {
Stefan Hajnoczi79360952013-01-11 23:08:14 +0100447 pod->monitor_level = POD_SYSTEM_INVALID;
Markus Grabner1027f4762010-08-12 01:35:30 +0200448
449 /* initiate startup procedure: */
450 pod_startup1(pod);
Markus Grabner705ecec2009-02-27 19:43:04 -0800451 }
452
453 return 0;
454}
455
Takashi Iwaiccddbe42015-01-15 08:22:31 +0100456#define LINE6_DEVICE(prod) USB_DEVICE(0x0e41, prod)
457#define LINE6_IF_NUM(prod, n) USB_DEVICE_INTERFACE_NUMBER(0x0e41, prod, n)
458
459/* table of devices that work with this driver */
460static const struct usb_device_id pod_id_table[] = {
461 { LINE6_DEVICE(0x4250), .driver_info = LINE6_BASSPODXT },
462 { LINE6_DEVICE(0x4642), .driver_info = LINE6_BASSPODXTLIVE },
463 { LINE6_DEVICE(0x4252), .driver_info = LINE6_BASSPODXTPRO },
464 { LINE6_IF_NUM(0x5051, 1), .driver_info = LINE6_POCKETPOD },
465 { LINE6_DEVICE(0x5044), .driver_info = LINE6_PODXT },
466 { LINE6_IF_NUM(0x4650, 0), .driver_info = LINE6_PODXTLIVE_POD },
467 { LINE6_DEVICE(0x5050), .driver_info = LINE6_PODXTPRO },
468 {}
469};
470
471MODULE_DEVICE_TABLE(usb, pod_id_table);
472
473static const struct line6_properties pod_properties_table[] = {
474 [LINE6_BASSPODXT] = {
475 .id = "BassPODxt",
476 .name = "BassPODxt",
477 .capabilities = LINE6_CAP_CONTROL
Andrej Krutak174e1fc2016-09-18 20:59:26 +0200478 | LINE6_CAP_CONTROL_MIDI
Takashi Iwaiccddbe42015-01-15 08:22:31 +0100479 | LINE6_CAP_PCM
480 | LINE6_CAP_HWMON,
481 .altsetting = 5,
482 .ep_ctrl_r = 0x84,
483 .ep_ctrl_w = 0x03,
484 .ep_audio_r = 0x82,
485 .ep_audio_w = 0x01,
486 },
487 [LINE6_BASSPODXTLIVE] = {
488 .id = "BassPODxtLive",
489 .name = "BassPODxt Live",
490 .capabilities = LINE6_CAP_CONTROL
Andrej Krutak174e1fc2016-09-18 20:59:26 +0200491 | LINE6_CAP_CONTROL_MIDI
Takashi Iwaiccddbe42015-01-15 08:22:31 +0100492 | LINE6_CAP_PCM
493 | LINE6_CAP_HWMON,
494 .altsetting = 1,
495 .ep_ctrl_r = 0x84,
496 .ep_ctrl_w = 0x03,
497 .ep_audio_r = 0x82,
498 .ep_audio_w = 0x01,
499 },
500 [LINE6_BASSPODXTPRO] = {
501 .id = "BassPODxtPro",
502 .name = "BassPODxt Pro",
503 .capabilities = LINE6_CAP_CONTROL
Andrej Krutak174e1fc2016-09-18 20:59:26 +0200504 | LINE6_CAP_CONTROL_MIDI
Takashi Iwaiccddbe42015-01-15 08:22:31 +0100505 | LINE6_CAP_PCM
506 | LINE6_CAP_HWMON,
507 .altsetting = 5,
508 .ep_ctrl_r = 0x84,
509 .ep_ctrl_w = 0x03,
510 .ep_audio_r = 0x82,
511 .ep_audio_w = 0x01,
512 },
513 [LINE6_POCKETPOD] = {
514 .id = "PocketPOD",
515 .name = "Pocket POD",
Andrej Krutak174e1fc2016-09-18 20:59:26 +0200516 .capabilities = LINE6_CAP_CONTROL
517 | LINE6_CAP_CONTROL_MIDI,
Takashi Iwaiccddbe42015-01-15 08:22:31 +0100518 .altsetting = 0,
519 .ep_ctrl_r = 0x82,
520 .ep_ctrl_w = 0x02,
521 /* no audio channel */
522 },
523 [LINE6_PODXT] = {
524 .id = "PODxt",
525 .name = "PODxt",
526 .capabilities = LINE6_CAP_CONTROL
Andrej Krutak174e1fc2016-09-18 20:59:26 +0200527 | LINE6_CAP_CONTROL_MIDI
Takashi Iwaiccddbe42015-01-15 08:22:31 +0100528 | LINE6_CAP_PCM
529 | LINE6_CAP_HWMON,
530 .altsetting = 5,
531 .ep_ctrl_r = 0x84,
532 .ep_ctrl_w = 0x03,
533 .ep_audio_r = 0x82,
534 .ep_audio_w = 0x01,
535 },
536 [LINE6_PODXTLIVE_POD] = {
537 .id = "PODxtLive",
538 .name = "PODxt Live",
539 .capabilities = LINE6_CAP_CONTROL
Andrej Krutak174e1fc2016-09-18 20:59:26 +0200540 | LINE6_CAP_CONTROL_MIDI
Takashi Iwaiccddbe42015-01-15 08:22:31 +0100541 | LINE6_CAP_PCM
542 | LINE6_CAP_HWMON,
543 .altsetting = 1,
544 .ep_ctrl_r = 0x84,
545 .ep_ctrl_w = 0x03,
546 .ep_audio_r = 0x82,
547 .ep_audio_w = 0x01,
548 },
549 [LINE6_PODXTPRO] = {
550 .id = "PODxtPro",
551 .name = "PODxt Pro",
552 .capabilities = LINE6_CAP_CONTROL
Andrej Krutak174e1fc2016-09-18 20:59:26 +0200553 | LINE6_CAP_CONTROL_MIDI
Takashi Iwaiccddbe42015-01-15 08:22:31 +0100554 | LINE6_CAP_PCM
555 | LINE6_CAP_HWMON,
556 .altsetting = 5,
557 .ep_ctrl_r = 0x84,
558 .ep_ctrl_w = 0x03,
559 .ep_audio_r = 0x82,
560 .ep_audio_w = 0x01,
561 },
562};
563
564/*
565 Probe USB device.
566*/
567static int pod_probe(struct usb_interface *interface,
568 const struct usb_device_id *id)
569{
Chris Rorvick12865ca2015-02-07 10:43:19 -0600570 return line6_probe(interface, id, "Line6-POD",
Takashi Iwai85a93392015-01-19 15:54:00 +0100571 &pod_properties_table[id->driver_info],
Takashi Iwaiaca514b2015-01-25 18:36:29 +0100572 pod_init, sizeof(struct usb_line6_pod));
Takashi Iwaiccddbe42015-01-15 08:22:31 +0100573}
574
575static struct usb_driver pod_driver = {
576 .name = KBUILD_MODNAME,
577 .probe = pod_probe,
578 .disconnect = line6_disconnect,
579#ifdef CONFIG_PM
580 .suspend = line6_suspend,
581 .resume = line6_resume,
582 .reset_resume = line6_resume,
583#endif
584 .id_table = pod_id_table,
585};
586
587module_usb_driver(pod_driver);
588
Chris Rorvickc6fffce2015-01-20 02:20:49 -0600589MODULE_DESCRIPTION("Line 6 POD USB driver");
Takashi Iwaiccddbe42015-01-15 08:22:31 +0100590MODULE_LICENSE("GPL");