blob: 61aadd7d4b7f0a15b4c65bf1fefbae2491fd81ab [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 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
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 */
Takashi Iwaiccddbe42015-01-15 08:22:31 +010076 int serial_number;
77
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 Grabnere1a164d2010-08-23 01:08:25 +020086#define POD_BYTES_PER_FRAME 6 /* 24bit audio (stereo) */
Markus Grabner705ecec2009-02-27 19:43:04 -080087
Markus Grabnere1a164d2010-08-23 01:08:25 +020088/* *INDENT-OFF* */
Markus Grabner705ecec2009-02-27 19:43:04 -080089
90enum {
Markus Grabner705ecec2009-02-27 19:43:04 -080091 POD_SYSEX_SAVE = 0x24,
92 POD_SYSEX_SYSTEM = 0x56,
93 POD_SYSEX_SYSTEMREQ = 0x57,
94 /* POD_SYSEX_UPDATE = 0x6c, */ /* software update! */
95 POD_SYSEX_STORE = 0x71,
96 POD_SYSEX_FINISH = 0x72,
97 POD_SYSEX_DUMPMEM = 0x73,
98 POD_SYSEX_DUMP = 0x74,
99 POD_SYSEX_DUMPREQ = 0x75
Stefan Hajnoczi0a1eb4e2013-01-11 23:08:12 +0100100
101 /* dumps entire internal memory of PODxt Pro */
102 /* POD_SYSEX_DUMPMEM2 = 0x76 */
Markus Grabner705ecec2009-02-27 19:43:04 -0800103};
104
105enum {
Stefan Hajnoczi79360952013-01-11 23:08:14 +0100106 POD_MONITOR_LEVEL = 0x04,
107 POD_SYSTEM_INVALID = 0x10000
Markus Grabner705ecec2009-02-27 19:43:04 -0800108};
109
Markus Grabnere1a164d2010-08-23 01:08:25 +0200110/* *INDENT-ON* */
111
Markus Grabner705ecec2009-02-27 19:43:04 -0800112enum {
113 POD_DUMP_MEMORY = 2
114};
115
116enum {
117 POD_BUSY_READ,
118 POD_BUSY_WRITE,
119 POD_CHANNEL_DIRTY,
120 POD_SAVE_PRESSED,
121 POD_BUSY_MIDISEND
122};
123
Markus Grabner705ecec2009-02-27 19:43:04 -0800124static struct snd_ratden pod_ratden = {
125 .num_min = 78125,
126 .num_max = 78125,
127 .num_step = 1,
128 .den = 2
129};
130
131static struct line6_pcm_properties pod_pcm_properties = {
Takashi Iwai1263f612015-01-28 15:08:59 +0100132 .playback_hw = {
Markus Grabnere1a164d2010-08-23 01:08:25 +0200133 .info = (SNDRV_PCM_INFO_MMAP |
134 SNDRV_PCM_INFO_INTERLEAVED |
135 SNDRV_PCM_INFO_BLOCK_TRANSFER |
136 SNDRV_PCM_INFO_MMAP_VALID |
137 SNDRV_PCM_INFO_PAUSE |
Markus Grabnere1a164d2010-08-23 01:08:25 +0200138 SNDRV_PCM_INFO_SYNC_START),
139 .formats = SNDRV_PCM_FMTBIT_S24_3LE,
140 .rates = SNDRV_PCM_RATE_KNOT,
141 .rate_min = 39062,
142 .rate_max = 39063,
143 .channels_min = 2,
144 .channels_max = 2,
145 .buffer_bytes_max = 60000,
146 .period_bytes_min = 64,
147 .period_bytes_max = 8192,
148 .periods_min = 1,
149 .periods_max = 1024},
Takashi Iwai1263f612015-01-28 15:08:59 +0100150 .capture_hw = {
Markus Grabnere1a164d2010-08-23 01:08:25 +0200151 .info = (SNDRV_PCM_INFO_MMAP |
152 SNDRV_PCM_INFO_INTERLEAVED |
153 SNDRV_PCM_INFO_BLOCK_TRANSFER |
154 SNDRV_PCM_INFO_MMAP_VALID |
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},
Takashi Iwai1263f612015-01-28 15:08:59 +0100167 .rates = {
Markus Grabnere1a164d2010-08-23 01:08:25 +0200168 .nrats = 1,
169 .rats = &pod_ratden},
Markus Grabner705ecec2009-02-27 19:43:04 -0800170 .bytes_per_frame = POD_BYTES_PER_FRAME
171};
172
Markus Grabnere1a164d2010-08-23 01:08:25 +0200173static const char pod_version_header[] = {
Markus Grabner1027f472010-08-12 01:35:30 +0200174 0xf2, 0x7e, 0x7f, 0x06, 0x02
175};
176
Markus Grabner1027f472010-08-12 01:35:30 +0200177/* forward declarations: */
178static void pod_startup2(unsigned long data);
179static void pod_startup3(struct usb_line6_pod *pod);
Markus Grabner705ecec2009-02-27 19:43:04 -0800180
Markus Grabnere1a164d2010-08-23 01:08:25 +0200181static char *pod_alloc_sysex_buffer(struct usb_line6_pod *pod, int code,
182 int size)
Markus Grabner705ecec2009-02-27 19:43:04 -0800183{
Markus Grabnere1a164d2010-08-23 01:08:25 +0200184 return line6_alloc_sysex_buffer(&pod->line6, POD_SYSEX_CODE, code,
185 size);
Markus Grabner705ecec2009-02-27 19:43:04 -0800186}
187
188/*
Markus Grabner705ecec2009-02-27 19:43:04 -0800189 Process a completely received message.
190*/
Chris Rorvick01f6b2b2015-01-12 12:42:58 -0800191static void line6_pod_process_message(struct usb_line6 *line6)
Markus Grabner705ecec2009-02-27 19:43:04 -0800192{
Chris Rorvick1cad3e82015-01-12 12:42:57 -0800193 struct usb_line6_pod *pod = (struct usb_line6_pod *) line6;
Markus Grabner705ecec2009-02-27 19:43:04 -0800194 const unsigned char *buf = pod->line6.buffer_message;
195
Stefan Hajnoczi4e6a8ff2013-01-19 11:18:43 +0100196 if (memcmp(buf, pod_version_header, sizeof(pod_version_header)) == 0) {
197 pod->firmware_version = buf[13] * 100 + buf[14] * 10 + buf[15];
198 pod->device_id = ((int)buf[8] << 16) | ((int)buf[9] << 8) |
199 (int) buf[10];
200 pod_startup3(pod);
201 return;
Markus Grabner705ecec2009-02-27 19:43:04 -0800202 }
203
Stefan Hajnoczi4e6a8ff2013-01-19 11:18:43 +0100204 /* Only look for sysex messages from this device */
205 if (buf[0] != (LINE6_SYSEX_BEGIN | LINE6_CHANNEL_DEVICE) &&
206 buf[0] != (LINE6_SYSEX_BEGIN | LINE6_CHANNEL_UNKNOWN)) {
207 return;
208 }
Laurent Navetc19e9462013-02-25 14:08:49 +0100209 if (memcmp(buf + 1, line6_midi_id, sizeof(line6_midi_id)) != 0)
Stefan Hajnoczi4e6a8ff2013-01-19 11:18:43 +0100210 return;
Markus Grabner705ecec2009-02-27 19:43:04 -0800211
Stefan Hajnoczi4e6a8ff2013-01-19 11:18:43 +0100212 if (buf[5] == POD_SYSEX_SYSTEM && buf[6] == POD_MONITOR_LEVEL) {
213 short value = ((int)buf[7] << 12) | ((int)buf[8] << 8) |
214 ((int)buf[9] << 4) | (int)buf[10];
215 pod->monitor_level = value;
Markus Grabner705ecec2009-02-27 19:43:04 -0800216 }
217}
218
219/*
Markus Grabner1027f472010-08-12 01:35:30 +0200220 Send system parameter (from integer).
Markus Grabner705ecec2009-02-27 19:43:04 -0800221*/
Markus Grabnere1a164d2010-08-23 01:08:25 +0200222static int pod_set_system_param_int(struct usb_line6_pod *pod, int value,
223 int code)
Markus Grabner705ecec2009-02-27 19:43:04 -0800224{
225 char *sysex;
226 static const int size = 5;
Markus Grabner705ecec2009-02-27 19:43:04 -0800227
Markus Grabner705ecec2009-02-27 19:43:04 -0800228 sysex = pod_alloc_sysex_buffer(pod, POD_SYSEX_SYSTEM, size);
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800229 if (!sysex)
Markus Grabner1027f472010-08-12 01:35:30 +0200230 return -ENOMEM;
Markus Grabner705ecec2009-02-27 19:43:04 -0800231 sysex[SYSEX_DATA_OFS] = code;
232 sysex[SYSEX_DATA_OFS + 1] = (value >> 12) & 0x0f;
Markus Grabnere1a164d2010-08-23 01:08:25 +0200233 sysex[SYSEX_DATA_OFS + 2] = (value >> 8) & 0x0f;
234 sysex[SYSEX_DATA_OFS + 3] = (value >> 4) & 0x0f;
235 sysex[SYSEX_DATA_OFS + 4] = (value) & 0x0f;
Markus Grabner705ecec2009-02-27 19:43:04 -0800236 line6_send_sysex_message(&pod->line6, sysex, size);
237 kfree(sysex);
Markus Grabner1027f472010-08-12 01:35:30 +0200238 return 0;
239}
240
241/*
Markus Grabner705ecec2009-02-27 19:43:04 -0800242 "read" request on "serial_number" special file.
243*/
Greg Kroah-Hartmane7c8a7e2013-08-24 10:36:49 -0700244static ssize_t serial_number_show(struct device *dev,
245 struct device_attribute *attr, char *buf)
Markus Grabner705ecec2009-02-27 19:43:04 -0800246{
247 struct usb_interface *interface = to_usb_interface(dev);
248 struct usb_line6_pod *pod = usb_get_intfdata(interface);
Jerry Snitselaarf3c52612014-04-24 00:31:48 -0700249
Markus Grabner705ecec2009-02-27 19:43:04 -0800250 return sprintf(buf, "%d\n", pod->serial_number);
251}
252
253/*
254 "read" request on "firmware_version" special file.
255*/
Greg Kroah-Hartmane7c8a7e2013-08-24 10:36:49 -0700256static ssize_t firmware_version_show(struct device *dev,
257 struct device_attribute *attr, char *buf)
Markus Grabner705ecec2009-02-27 19:43:04 -0800258{
259 struct usb_interface *interface = to_usb_interface(dev);
260 struct usb_line6_pod *pod = usb_get_intfdata(interface);
Jerry Snitselaarf3c52612014-04-24 00:31:48 -0700261
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800262 return sprintf(buf, "%d.%02d\n", pod->firmware_version / 100,
263 pod->firmware_version % 100);
Markus Grabner705ecec2009-02-27 19:43:04 -0800264}
265
266/*
267 "read" request on "device_id" special file.
268*/
Greg Kroah-Hartmane7c8a7e2013-08-24 10:36:49 -0700269static ssize_t device_id_show(struct device *dev,
270 struct device_attribute *attr, char *buf)
Markus Grabner705ecec2009-02-27 19:43:04 -0800271{
272 struct usb_interface *interface = to_usb_interface(dev);
273 struct usb_line6_pod *pod = usb_get_intfdata(interface);
Jerry Snitselaarf3c52612014-04-24 00:31:48 -0700274
Markus Grabner705ecec2009-02-27 19:43:04 -0800275 return sprintf(buf, "%d\n", pod->device_id);
276}
277
278/*
Markus Grabner1027f472010-08-12 01:35:30 +0200279 POD startup procedure.
280 This is a sequence of functions with special requirements (e.g., must
281 not run immediately after initialization, must not run in interrupt
282 context). After the last one has finished, the device is ready to use.
283*/
284
285static void pod_startup1(struct usb_line6_pod *pod)
286{
Markus Grabnere1a164d2010-08-23 01:08:25 +0200287 CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_INIT);
Markus Grabner1027f472010-08-12 01:35:30 +0200288
289 /* delay startup procedure: */
Markus Grabnere1a164d2010-08-23 01:08:25 +0200290 line6_start_timer(&pod->startup_timer, POD_STARTUP_DELAY, pod_startup2,
291 (unsigned long)pod);
Markus Grabner1027f472010-08-12 01:35:30 +0200292}
293
294static void pod_startup2(unsigned long data)
295{
296 struct usb_line6_pod *pod = (struct usb_line6_pod *)data;
Markus Grabner1027f472010-08-12 01:35:30 +0200297 struct usb_line6 *line6 = &pod->line6;
Jerry Snitselaarf3c52612014-04-24 00:31:48 -0700298
Markus Grabnere1a164d2010-08-23 01:08:25 +0200299 CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_VERSIONREQ);
Markus Grabner1027f472010-08-12 01:35:30 +0200300
301 /* request firmware version: */
302 line6_version_request_async(line6);
303}
304
Stefan Hajnoczi09fda102012-11-22 20:49:24 +0100305static void pod_startup3(struct usb_line6_pod *pod)
Markus Grabner1027f472010-08-12 01:35:30 +0200306{
Markus Grabnere1a164d2010-08-23 01:08:25 +0200307 CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_WORKQUEUE);
Markus Grabner1027f472010-08-12 01:35:30 +0200308
309 /* schedule work for global work queue: */
310 schedule_work(&pod->startup_work);
311}
312
Stefan Hajnoczi09fda102012-11-22 20:49:24 +0100313static void pod_startup4(struct work_struct *work)
Markus Grabner1027f472010-08-12 01:35:30 +0200314{
Markus Grabnere1a164d2010-08-23 01:08:25 +0200315 struct usb_line6_pod *pod =
316 container_of(work, struct usb_line6_pod, startup_work);
Markus Grabner1027f472010-08-12 01:35:30 +0200317 struct usb_line6 *line6 = &pod->line6;
318
Markus Grabnere1a164d2010-08-23 01:08:25 +0200319 CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_SETUP);
Markus Grabner1027f472010-08-12 01:35:30 +0200320
321 /* serial number: */
322 line6_read_serial_number(&pod->line6, &pod->serial_number);
323
324 /* ALSA audio interface: */
Takashi Iwai85a93392015-01-19 15:54:00 +0100325 snd_card_register(line6->card);
Markus Grabner1027f472010-08-12 01:35:30 +0200326}
327
Markus Grabner705ecec2009-02-27 19:43:04 -0800328/* POD special files: */
Greg Kroah-Hartmane7c8a7e2013-08-24 10:36:49 -0700329static DEVICE_ATTR_RO(device_id);
330static DEVICE_ATTR_RO(firmware_version);
331static DEVICE_ATTR_RO(serial_number);
Markus Grabner705ecec2009-02-27 19:43:04 -0800332
Markus Grabner1027f472010-08-12 01:35:30 +0200333/* control info callback */
334static int snd_pod_control_monitor_info(struct snd_kcontrol *kcontrol,
335 struct snd_ctl_elem_info *uinfo)
336{
337 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
338 uinfo->count = 1;
339 uinfo->value.integer.min = 0;
340 uinfo->value.integer.max = 65535;
341 return 0;
342}
343
344/* control get callback */
345static int snd_pod_control_monitor_get(struct snd_kcontrol *kcontrol,
346 struct snd_ctl_elem_value *ucontrol)
347{
348 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
349 struct usb_line6_pod *pod = (struct usb_line6_pod *)line6pcm->line6;
Jerry Snitselaarf3c52612014-04-24 00:31:48 -0700350
Stefan Hajnoczi2c35dc22012-11-22 20:48:47 +0100351 ucontrol->value.integer.value[0] = pod->monitor_level;
Markus Grabner1027f472010-08-12 01:35:30 +0200352 return 0;
353}
354
355/* control put callback */
356static int snd_pod_control_monitor_put(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;
361
Stefan Hajnoczi2c35dc22012-11-22 20:48:47 +0100362 if (ucontrol->value.integer.value[0] == pod->monitor_level)
Markus Grabner1027f472010-08-12 01:35:30 +0200363 return 0;
364
Stefan Hajnoczi2c35dc22012-11-22 20:48:47 +0100365 pod->monitor_level = ucontrol->value.integer.value[0];
Markus Grabnere1a164d2010-08-23 01:08:25 +0200366 pod_set_system_param_int(pod, ucontrol->value.integer.value[0],
Stefan Hajnoczi79360952013-01-11 23:08:14 +0100367 POD_MONITOR_LEVEL);
Markus Grabner1027f472010-08-12 01:35:30 +0200368 return 1;
369}
370
371/* control definition */
372static struct snd_kcontrol_new pod_control_monitor = {
373 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
374 .name = "Monitor Playback Volume",
375 .index = 0,
376 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
377 .info = snd_pod_control_monitor_info,
378 .get = snd_pod_control_monitor_get,
379 .put = snd_pod_control_monitor_put
380};
381
Markus Grabner705ecec2009-02-27 19:43:04 -0800382/*
Chris Rorvickd29b8542015-01-12 12:43:00 -0800383 POD device disconnected.
384*/
Takashi Iwaif66fd992015-01-25 18:22:58 +0100385static void line6_pod_disconnect(struct usb_line6 *line6)
Chris Rorvickd29b8542015-01-12 12:43:00 -0800386{
Takashi Iwaif66fd992015-01-25 18:22:58 +0100387 struct usb_line6_pod *pod = (struct usb_line6_pod *)line6;
388 struct device *dev = line6->ifcdev;
Chris Rorvickd29b8542015-01-12 12:43:00 -0800389
Takashi Iwai8a3b7c02015-01-20 08:42:42 +0100390 /* remove sysfs entries: */
391 device_remove_file(dev, &dev_attr_device_id);
392 device_remove_file(dev, &dev_attr_firmware_version);
393 device_remove_file(dev, &dev_attr_serial_number);
Chris Rorvickd29b8542015-01-12 12:43:00 -0800394
Takashi Iwai8a3b7c02015-01-20 08:42:42 +0100395 del_timer_sync(&pod->startup_timer);
396 cancel_work_sync(&pod->startup_work);
Chris Rorvickd29b8542015-01-12 12:43:00 -0800397}
398
399/*
Markus Grabner705ecec2009-02-27 19:43:04 -0800400 Create sysfs entries.
401*/
Greg Kroah-Hartmanb702ed252009-02-27 20:45:03 -0800402static int pod_create_files2(struct device *dev)
Markus Grabner705ecec2009-02-27 19:43:04 -0800403{
404 int err;
405
Takashi Iwaib2a3b022015-01-19 16:08:02 +0100406 err = device_create_file(dev, &dev_attr_device_id);
407 if (err < 0)
408 return err;
409 err = device_create_file(dev, &dev_attr_firmware_version);
410 if (err < 0)
411 return err;
412 err = device_create_file(dev, &dev_attr_serial_number);
413 if (err < 0)
414 return err;
Markus Grabner705ecec2009-02-27 19:43:04 -0800415 return 0;
416}
417
418/*
Markus Grabner1027f472010-08-12 01:35:30 +0200419 Try to init POD device.
Markus Grabner705ecec2009-02-27 19:43:04 -0800420*/
Takashi Iwaif66fd992015-01-25 18:22:58 +0100421static int pod_init(struct usb_line6 *line6,
422 const struct usb_device_id *id)
Markus Grabner705ecec2009-02-27 19:43:04 -0800423{
424 int err;
Chris Rorvicka221dd42015-01-12 12:42:56 -0800425 struct usb_line6_pod *pod = (struct usb_line6_pod *) line6;
Markus Grabner705ecec2009-02-27 19:43:04 -0800426
Chris Rorvick01f6b2b2015-01-12 12:42:58 -0800427 line6->process_message = line6_pod_process_message;
Chris Rorvicka46c4672015-01-12 12:42:59 -0800428 line6->disconnect = line6_pod_disconnect;
Chris Rorvick01f6b2b2015-01-12 12:42:58 -0800429
Markus Grabnere1a164d2010-08-23 01:08:25 +0200430 init_timer(&pod->startup_timer);
Stefan Hajnoczi09fda102012-11-22 20:49:24 +0100431 INIT_WORK(&pod->startup_work, pod_startup4);
Markus Grabnere1a164d2010-08-23 01:08:25 +0200432
Markus Grabner705ecec2009-02-27 19:43:04 -0800433 /* create sysfs entries: */
Takashi Iwaif66fd992015-01-25 18:22:58 +0100434 err = pod_create_files2(line6->ifcdev);
Greg Kroah-Hartman027360c2010-09-21 16:58:00 -0700435 if (err < 0)
Markus Grabner705ecec2009-02-27 19:43:04 -0800436 return err;
Markus Grabner705ecec2009-02-27 19:43:04 -0800437
Markus Grabner705ecec2009-02-27 19:43:04 -0800438 /* initialize MIDI subsystem: */
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800439 err = line6_init_midi(line6);
Greg Kroah-Hartman027360c2010-09-21 16:58:00 -0700440 if (err < 0)
Markus Grabner705ecec2009-02-27 19:43:04 -0800441 return err;
Markus Grabner705ecec2009-02-27 19:43:04 -0800442
443 /* initialize PCM subsystem: */
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800444 err = line6_init_pcm(line6, &pod_pcm_properties);
Greg Kroah-Hartman027360c2010-09-21 16:58:00 -0700445 if (err < 0)
Markus Grabner705ecec2009-02-27 19:43:04 -0800446 return err;
Markus Grabner705ecec2009-02-27 19:43:04 -0800447
Markus Grabner1027f472010-08-12 01:35:30 +0200448 /* register monitor control: */
Greg Kroah-Hartman027360c2010-09-21 16:58:00 -0700449 err = snd_ctl_add(line6->card,
450 snd_ctl_new1(&pod_control_monitor, line6->line6pcm));
451 if (err < 0)
Markus Grabner705ecec2009-02-27 19:43:04 -0800452 return err;
Markus Grabner705ecec2009-02-27 19:43:04 -0800453
Markus Grabner1027f472010-08-12 01:35:30 +0200454 /*
Markus Grabnere1a164d2010-08-23 01:08:25 +0200455 When the sound card is registered at this point, the PODxt Live
456 displays "Invalid Code Error 07", so we do it later in the event
457 handler.
458 */
Markus Grabner1027f472010-08-12 01:35:30 +0200459
Chris Rorvick4cb1a4a2015-01-12 12:42:45 -0800460 if (pod->line6.properties->capabilities & LINE6_CAP_CONTROL) {
Stefan Hajnoczi79360952013-01-11 23:08:14 +0100461 pod->monitor_level = POD_SYSTEM_INVALID;
Markus Grabner1027f472010-08-12 01:35:30 +0200462
463 /* initiate startup procedure: */
464 pod_startup1(pod);
Markus Grabner705ecec2009-02-27 19:43:04 -0800465 }
466
467 return 0;
468}
469
Takashi Iwaiccddbe42015-01-15 08:22:31 +0100470#define LINE6_DEVICE(prod) USB_DEVICE(0x0e41, prod)
471#define LINE6_IF_NUM(prod, n) USB_DEVICE_INTERFACE_NUMBER(0x0e41, prod, n)
472
473/* table of devices that work with this driver */
474static const struct usb_device_id pod_id_table[] = {
475 { LINE6_DEVICE(0x4250), .driver_info = LINE6_BASSPODXT },
476 { LINE6_DEVICE(0x4642), .driver_info = LINE6_BASSPODXTLIVE },
477 { LINE6_DEVICE(0x4252), .driver_info = LINE6_BASSPODXTPRO },
478 { LINE6_IF_NUM(0x5051, 1), .driver_info = LINE6_POCKETPOD },
479 { LINE6_DEVICE(0x5044), .driver_info = LINE6_PODXT },
480 { LINE6_IF_NUM(0x4650, 0), .driver_info = LINE6_PODXTLIVE_POD },
481 { LINE6_DEVICE(0x5050), .driver_info = LINE6_PODXTPRO },
482 {}
483};
484
485MODULE_DEVICE_TABLE(usb, pod_id_table);
486
487static const struct line6_properties pod_properties_table[] = {
488 [LINE6_BASSPODXT] = {
489 .id = "BassPODxt",
490 .name = "BassPODxt",
491 .capabilities = LINE6_CAP_CONTROL
492 | LINE6_CAP_PCM
493 | LINE6_CAP_HWMON,
494 .altsetting = 5,
495 .ep_ctrl_r = 0x84,
496 .ep_ctrl_w = 0x03,
497 .ep_audio_r = 0x82,
498 .ep_audio_w = 0x01,
499 },
500 [LINE6_BASSPODXTLIVE] = {
501 .id = "BassPODxtLive",
502 .name = "BassPODxt Live",
503 .capabilities = LINE6_CAP_CONTROL
504 | LINE6_CAP_PCM
505 | LINE6_CAP_HWMON,
506 .altsetting = 1,
507 .ep_ctrl_r = 0x84,
508 .ep_ctrl_w = 0x03,
509 .ep_audio_r = 0x82,
510 .ep_audio_w = 0x01,
511 },
512 [LINE6_BASSPODXTPRO] = {
513 .id = "BassPODxtPro",
514 .name = "BassPODxt Pro",
515 .capabilities = LINE6_CAP_CONTROL
516 | LINE6_CAP_PCM
517 | LINE6_CAP_HWMON,
518 .altsetting = 5,
519 .ep_ctrl_r = 0x84,
520 .ep_ctrl_w = 0x03,
521 .ep_audio_r = 0x82,
522 .ep_audio_w = 0x01,
523 },
524 [LINE6_POCKETPOD] = {
525 .id = "PocketPOD",
526 .name = "Pocket POD",
527 .capabilities = LINE6_CAP_CONTROL,
528 .altsetting = 0,
529 .ep_ctrl_r = 0x82,
530 .ep_ctrl_w = 0x02,
531 /* no audio channel */
532 },
533 [LINE6_PODXT] = {
534 .id = "PODxt",
535 .name = "PODxt",
536 .capabilities = LINE6_CAP_CONTROL
537 | LINE6_CAP_PCM
538 | LINE6_CAP_HWMON,
539 .altsetting = 5,
540 .ep_ctrl_r = 0x84,
541 .ep_ctrl_w = 0x03,
542 .ep_audio_r = 0x82,
543 .ep_audio_w = 0x01,
544 },
545 [LINE6_PODXTLIVE_POD] = {
546 .id = "PODxtLive",
547 .name = "PODxt Live",
548 .capabilities = LINE6_CAP_CONTROL
549 | LINE6_CAP_PCM
550 | LINE6_CAP_HWMON,
551 .altsetting = 1,
552 .ep_ctrl_r = 0x84,
553 .ep_ctrl_w = 0x03,
554 .ep_audio_r = 0x82,
555 .ep_audio_w = 0x01,
556 },
557 [LINE6_PODXTPRO] = {
558 .id = "PODxtPro",
559 .name = "PODxt Pro",
560 .capabilities = LINE6_CAP_CONTROL
561 | LINE6_CAP_PCM
562 | LINE6_CAP_HWMON,
563 .altsetting = 5,
564 .ep_ctrl_r = 0x84,
565 .ep_ctrl_w = 0x03,
566 .ep_audio_r = 0x82,
567 .ep_audio_w = 0x01,
568 },
569};
570
571/*
572 Probe USB device.
573*/
574static int pod_probe(struct usb_interface *interface,
575 const struct usb_device_id *id)
576{
Takashi Iwaiaca514b2015-01-25 18:36:29 +0100577 return line6_probe(interface, id,
Takashi Iwai85a93392015-01-19 15:54:00 +0100578 &pod_properties_table[id->driver_info],
Takashi Iwaiaca514b2015-01-25 18:36:29 +0100579 pod_init, sizeof(struct usb_line6_pod));
Takashi Iwaiccddbe42015-01-15 08:22:31 +0100580}
581
582static struct usb_driver pod_driver = {
583 .name = KBUILD_MODNAME,
584 .probe = pod_probe,
585 .disconnect = line6_disconnect,
586#ifdef CONFIG_PM
587 .suspend = line6_suspend,
588 .resume = line6_resume,
589 .reset_resume = line6_resume,
590#endif
591 .id_table = pod_id_table,
592};
593
594module_usb_driver(pod_driver);
595
Chris Rorvickc6fffce2015-01-20 02:20:49 -0600596MODULE_DESCRIPTION("Line 6 POD USB driver");
Takashi Iwaiccddbe42015-01-15 08:22:31 +0100597MODULE_LICENSE("GPL");