blob: bc20cf1417191eaae0e89e004b528e78218d9bfd [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#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 {
Takashi Iwaicddbd4f2015-01-28 14:43:11 +010061 /* Generic Line 6 USB data */
Takashi Iwaiccddbe42015-01-15 08:22:31 +010062 struct usb_line6 line6;
63
Takashi Iwaicddbd4f2015-01-28 14:43:11 +010064 /* Instrument monitor level */
Takashi Iwaiccddbe42015-01-15 08:22:31 +010065 int monitor_level;
66
Takashi Iwaicddbd4f2015-01-28 14:43:11 +010067 /* Timer for device initialization */
Takashi Iwaiccddbe42015-01-15 08:22:31 +010068 struct timer_list startup_timer;
69
Takashi Iwaicddbd4f2015-01-28 14:43:11 +010070 /* Work handler for device initialization */
Takashi Iwaiccddbe42015-01-15 08:22:31 +010071 struct work_struct startup_work;
72
Takashi Iwaicddbd4f2015-01-28 14:43:11 +010073 /* Current progress in startup procedure */
Takashi Iwaiccddbe42015-01-15 08:22:31 +010074 int startup_progress;
75
Takashi Iwaicddbd4f2015-01-28 14:43:11 +010076 /* Serial number of device */
Takashi Iwaiccddbe42015-01-15 08:22:31 +010077 int serial_number;
78
Takashi Iwaicddbd4f2015-01-28 14:43:11 +010079 /* Firmware version (x 100) */
Takashi Iwaiccddbe42015-01-15 08:22:31 +010080 int firmware_version;
81
Takashi Iwaicddbd4f2015-01-28 14:43:11 +010082 /* Device ID */
Takashi Iwaiccddbe42015-01-15 08:22:31 +010083 int device_id;
84};
Markus Grabner705ecec2009-02-27 19:43:04 -080085
Markus Grabner705ecec2009-02-27 19:43:04 -080086#define POD_SYSEX_CODE 3
Markus Grabnere1a164d2010-08-23 01:08:25 +020087#define POD_BYTES_PER_FRAME 6 /* 24bit audio (stereo) */
Markus Grabner705ecec2009-02-27 19:43:04 -080088
Markus Grabnere1a164d2010-08-23 01:08:25 +020089/* *INDENT-OFF* */
Markus Grabner705ecec2009-02-27 19:43:04 -080090
91enum {
Markus Grabner705ecec2009-02-27 19:43:04 -080092 POD_SYSEX_SAVE = 0x24,
93 POD_SYSEX_SYSTEM = 0x56,
94 POD_SYSEX_SYSTEMREQ = 0x57,
95 /* POD_SYSEX_UPDATE = 0x6c, */ /* software update! */
96 POD_SYSEX_STORE = 0x71,
97 POD_SYSEX_FINISH = 0x72,
98 POD_SYSEX_DUMPMEM = 0x73,
99 POD_SYSEX_DUMP = 0x74,
100 POD_SYSEX_DUMPREQ = 0x75
Stefan Hajnoczi0a1eb4e2013-01-11 23:08:12 +0100101
102 /* dumps entire internal memory of PODxt Pro */
103 /* POD_SYSEX_DUMPMEM2 = 0x76 */
Markus Grabner705ecec2009-02-27 19:43:04 -0800104};
105
106enum {
Stefan Hajnoczi79360952013-01-11 23:08:14 +0100107 POD_MONITOR_LEVEL = 0x04,
108 POD_SYSTEM_INVALID = 0x10000
Markus Grabner705ecec2009-02-27 19:43:04 -0800109};
110
Markus Grabnere1a164d2010-08-23 01:08:25 +0200111/* *INDENT-ON* */
112
Markus Grabner705ecec2009-02-27 19:43:04 -0800113enum {
114 POD_DUMP_MEMORY = 2
115};
116
117enum {
118 POD_BUSY_READ,
119 POD_BUSY_WRITE,
120 POD_CHANNEL_DIRTY,
121 POD_SAVE_PRESSED,
122 POD_BUSY_MIDISEND
123};
124
Markus Grabner705ecec2009-02-27 19:43:04 -0800125static struct snd_ratden pod_ratden = {
126 .num_min = 78125,
127 .num_max = 78125,
128 .num_step = 1,
129 .den = 2
130};
131
132static struct line6_pcm_properties pod_pcm_properties = {
Markus Grabner1027f472010-08-12 01:35:30 +0200133 .snd_line6_playback_hw = {
Markus Grabnere1a164d2010-08-23 01:08:25 +0200134 .info = (SNDRV_PCM_INFO_MMAP |
135 SNDRV_PCM_INFO_INTERLEAVED |
136 SNDRV_PCM_INFO_BLOCK_TRANSFER |
137 SNDRV_PCM_INFO_MMAP_VALID |
138 SNDRV_PCM_INFO_PAUSE |
Markus Grabnere1a164d2010-08-23 01:08:25 +0200139 SNDRV_PCM_INFO_SYNC_START),
140 .formats = SNDRV_PCM_FMTBIT_S24_3LE,
141 .rates = SNDRV_PCM_RATE_KNOT,
142 .rate_min = 39062,
143 .rate_max = 39063,
144 .channels_min = 2,
145 .channels_max = 2,
146 .buffer_bytes_max = 60000,
147 .period_bytes_min = 64,
148 .period_bytes_max = 8192,
149 .periods_min = 1,
150 .periods_max = 1024},
Markus Grabner1027f472010-08-12 01:35:30 +0200151 .snd_line6_capture_hw = {
Markus Grabnere1a164d2010-08-23 01:08:25 +0200152 .info = (SNDRV_PCM_INFO_MMAP |
153 SNDRV_PCM_INFO_INTERLEAVED |
154 SNDRV_PCM_INFO_BLOCK_TRANSFER |
155 SNDRV_PCM_INFO_MMAP_VALID |
Markus Grabnere1a164d2010-08-23 01:08:25 +0200156 SNDRV_PCM_INFO_SYNC_START),
157 .formats = SNDRV_PCM_FMTBIT_S24_3LE,
158 .rates = SNDRV_PCM_RATE_KNOT,
159 .rate_min = 39062,
160 .rate_max = 39063,
161 .channels_min = 2,
162 .channels_max = 2,
163 .buffer_bytes_max = 60000,
164 .period_bytes_min = 64,
165 .period_bytes_max = 8192,
166 .periods_min = 1,
167 .periods_max = 1024},
Markus Grabner705ecec2009-02-27 19:43:04 -0800168 .snd_line6_rates = {
Markus Grabnere1a164d2010-08-23 01:08:25 +0200169 .nrats = 1,
170 .rats = &pod_ratden},
Markus Grabner705ecec2009-02-27 19:43:04 -0800171 .bytes_per_frame = POD_BYTES_PER_FRAME
172};
173
Markus Grabnere1a164d2010-08-23 01:08:25 +0200174static const char pod_version_header[] = {
Markus Grabner1027f472010-08-12 01:35:30 +0200175 0xf2, 0x7e, 0x7f, 0x06, 0x02
176};
177
Markus Grabner1027f472010-08-12 01:35:30 +0200178/* forward declarations: */
179static void pod_startup2(unsigned long data);
180static void pod_startup3(struct usb_line6_pod *pod);
Markus Grabner705ecec2009-02-27 19:43:04 -0800181
Markus Grabnere1a164d2010-08-23 01:08:25 +0200182static char *pod_alloc_sysex_buffer(struct usb_line6_pod *pod, int code,
183 int size)
Markus Grabner705ecec2009-02-27 19:43:04 -0800184{
Markus Grabnere1a164d2010-08-23 01:08:25 +0200185 return line6_alloc_sysex_buffer(&pod->line6, POD_SYSEX_CODE, code,
186 size);
Markus Grabner705ecec2009-02-27 19:43:04 -0800187}
188
189/*
Markus Grabner705ecec2009-02-27 19:43:04 -0800190 Process a completely received message.
191*/
Chris Rorvick01f6b2b2015-01-12 12:42:58 -0800192static void line6_pod_process_message(struct usb_line6 *line6)
Markus Grabner705ecec2009-02-27 19:43:04 -0800193{
Chris Rorvick1cad3e82015-01-12 12:42:57 -0800194 struct usb_line6_pod *pod = (struct usb_line6_pod *) line6;
Markus Grabner705ecec2009-02-27 19:43:04 -0800195 const unsigned char *buf = pod->line6.buffer_message;
196
Stefan Hajnoczi4e6a8ff2013-01-19 11:18:43 +0100197 if (memcmp(buf, pod_version_header, sizeof(pod_version_header)) == 0) {
198 pod->firmware_version = buf[13] * 100 + buf[14] * 10 + buf[15];
199 pod->device_id = ((int)buf[8] << 16) | ((int)buf[9] << 8) |
200 (int) buf[10];
201 pod_startup3(pod);
202 return;
Markus Grabner705ecec2009-02-27 19:43:04 -0800203 }
204
Stefan Hajnoczi4e6a8ff2013-01-19 11:18:43 +0100205 /* Only look for sysex messages from this device */
206 if (buf[0] != (LINE6_SYSEX_BEGIN | LINE6_CHANNEL_DEVICE) &&
207 buf[0] != (LINE6_SYSEX_BEGIN | LINE6_CHANNEL_UNKNOWN)) {
208 return;
209 }
Laurent Navetc19e9462013-02-25 14:08:49 +0100210 if (memcmp(buf + 1, line6_midi_id, sizeof(line6_midi_id)) != 0)
Stefan Hajnoczi4e6a8ff2013-01-19 11:18:43 +0100211 return;
Markus Grabner705ecec2009-02-27 19:43:04 -0800212
Stefan Hajnoczi4e6a8ff2013-01-19 11:18:43 +0100213 if (buf[5] == POD_SYSEX_SYSTEM && buf[6] == POD_MONITOR_LEVEL) {
214 short value = ((int)buf[7] << 12) | ((int)buf[8] << 8) |
215 ((int)buf[9] << 4) | (int)buf[10];
216 pod->monitor_level = value;
Markus Grabner705ecec2009-02-27 19:43:04 -0800217 }
218}
219
220/*
Markus Grabner1027f472010-08-12 01:35:30 +0200221 Send system parameter (from integer).
Markus Grabner705ecec2009-02-27 19:43:04 -0800222*/
Markus Grabnere1a164d2010-08-23 01:08:25 +0200223static int pod_set_system_param_int(struct usb_line6_pod *pod, int value,
224 int code)
Markus Grabner705ecec2009-02-27 19:43:04 -0800225{
226 char *sysex;
227 static const int size = 5;
Markus Grabner705ecec2009-02-27 19:43:04 -0800228
Markus Grabner705ecec2009-02-27 19:43:04 -0800229 sysex = pod_alloc_sysex_buffer(pod, POD_SYSEX_SYSTEM, size);
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800230 if (!sysex)
Markus Grabner1027f472010-08-12 01:35:30 +0200231 return -ENOMEM;
Markus Grabner705ecec2009-02-27 19:43:04 -0800232 sysex[SYSEX_DATA_OFS] = code;
233 sysex[SYSEX_DATA_OFS + 1] = (value >> 12) & 0x0f;
Markus Grabnere1a164d2010-08-23 01:08:25 +0200234 sysex[SYSEX_DATA_OFS + 2] = (value >> 8) & 0x0f;
235 sysex[SYSEX_DATA_OFS + 3] = (value >> 4) & 0x0f;
236 sysex[SYSEX_DATA_OFS + 4] = (value) & 0x0f;
Markus Grabner705ecec2009-02-27 19:43:04 -0800237 line6_send_sysex_message(&pod->line6, sysex, size);
238 kfree(sysex);
Markus Grabner1027f472010-08-12 01:35:30 +0200239 return 0;
240}
241
242/*
Markus Grabner705ecec2009-02-27 19:43:04 -0800243 "read" request on "serial_number" special file.
244*/
Greg Kroah-Hartmane7c8a7e2013-08-24 10:36:49 -0700245static ssize_t serial_number_show(struct device *dev,
246 struct device_attribute *attr, char *buf)
Markus Grabner705ecec2009-02-27 19:43:04 -0800247{
248 struct usb_interface *interface = to_usb_interface(dev);
249 struct usb_line6_pod *pod = usb_get_intfdata(interface);
Jerry Snitselaarf3c52612014-04-24 00:31:48 -0700250
Markus Grabner705ecec2009-02-27 19:43:04 -0800251 return sprintf(buf, "%d\n", pod->serial_number);
252}
253
254/*
255 "read" request on "firmware_version" special file.
256*/
Greg Kroah-Hartmane7c8a7e2013-08-24 10:36:49 -0700257static ssize_t firmware_version_show(struct device *dev,
258 struct device_attribute *attr, char *buf)
Markus Grabner705ecec2009-02-27 19:43:04 -0800259{
260 struct usb_interface *interface = to_usb_interface(dev);
261 struct usb_line6_pod *pod = usb_get_intfdata(interface);
Jerry Snitselaarf3c52612014-04-24 00:31:48 -0700262
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800263 return sprintf(buf, "%d.%02d\n", pod->firmware_version / 100,
264 pod->firmware_version % 100);
Markus Grabner705ecec2009-02-27 19:43:04 -0800265}
266
267/*
268 "read" request on "device_id" special file.
269*/
Greg Kroah-Hartmane7c8a7e2013-08-24 10:36:49 -0700270static ssize_t device_id_show(struct device *dev,
271 struct device_attribute *attr, char *buf)
Markus Grabner705ecec2009-02-27 19:43:04 -0800272{
273 struct usb_interface *interface = to_usb_interface(dev);
274 struct usb_line6_pod *pod = usb_get_intfdata(interface);
Jerry Snitselaarf3c52612014-04-24 00:31:48 -0700275
Markus Grabner705ecec2009-02-27 19:43:04 -0800276 return sprintf(buf, "%d\n", pod->device_id);
277}
278
279/*
Markus Grabner1027f472010-08-12 01:35:30 +0200280 POD startup procedure.
281 This is a sequence of functions with special requirements (e.g., must
282 not run immediately after initialization, must not run in interrupt
283 context). After the last one has finished, the device is ready to use.
284*/
285
286static void pod_startup1(struct usb_line6_pod *pod)
287{
Markus Grabnere1a164d2010-08-23 01:08:25 +0200288 CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_INIT);
Markus Grabner1027f472010-08-12 01:35:30 +0200289
290 /* delay startup procedure: */
Markus Grabnere1a164d2010-08-23 01:08:25 +0200291 line6_start_timer(&pod->startup_timer, POD_STARTUP_DELAY, pod_startup2,
292 (unsigned long)pod);
Markus Grabner1027f472010-08-12 01:35:30 +0200293}
294
295static void pod_startup2(unsigned long data)
296{
297 struct usb_line6_pod *pod = (struct usb_line6_pod *)data;
Markus Grabner1027f472010-08-12 01:35:30 +0200298 struct usb_line6 *line6 = &pod->line6;
Jerry Snitselaarf3c52612014-04-24 00:31:48 -0700299
Markus Grabnere1a164d2010-08-23 01:08:25 +0200300 CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_VERSIONREQ);
Markus Grabner1027f472010-08-12 01:35:30 +0200301
302 /* request firmware version: */
303 line6_version_request_async(line6);
304}
305
Stefan Hajnoczi09fda102012-11-22 20:49:24 +0100306static void pod_startup3(struct usb_line6_pod *pod)
Markus Grabner1027f472010-08-12 01:35:30 +0200307{
Markus Grabnere1a164d2010-08-23 01:08:25 +0200308 CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_WORKQUEUE);
Markus Grabner1027f472010-08-12 01:35:30 +0200309
310 /* schedule work for global work queue: */
311 schedule_work(&pod->startup_work);
312}
313
Stefan Hajnoczi09fda102012-11-22 20:49:24 +0100314static void pod_startup4(struct work_struct *work)
Markus Grabner1027f472010-08-12 01:35:30 +0200315{
Markus Grabnere1a164d2010-08-23 01:08:25 +0200316 struct usb_line6_pod *pod =
317 container_of(work, struct usb_line6_pod, startup_work);
Markus Grabner1027f472010-08-12 01:35:30 +0200318 struct usb_line6 *line6 = &pod->line6;
319
Markus Grabnere1a164d2010-08-23 01:08:25 +0200320 CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_SETUP);
Markus Grabner1027f472010-08-12 01:35:30 +0200321
322 /* serial number: */
323 line6_read_serial_number(&pod->line6, &pod->serial_number);
324
325 /* ALSA audio interface: */
Takashi Iwai85a93392015-01-19 15:54:00 +0100326 snd_card_register(line6->card);
Markus Grabner1027f472010-08-12 01:35:30 +0200327}
328
Markus Grabner705ecec2009-02-27 19:43:04 -0800329/* POD special files: */
Greg Kroah-Hartmane7c8a7e2013-08-24 10:36:49 -0700330static DEVICE_ATTR_RO(device_id);
331static DEVICE_ATTR_RO(firmware_version);
332static DEVICE_ATTR_RO(serial_number);
Markus Grabner705ecec2009-02-27 19:43:04 -0800333
Markus Grabner1027f472010-08-12 01:35:30 +0200334/* control info callback */
335static int snd_pod_control_monitor_info(struct snd_kcontrol *kcontrol,
336 struct snd_ctl_elem_info *uinfo)
337{
338 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
339 uinfo->count = 1;
340 uinfo->value.integer.min = 0;
341 uinfo->value.integer.max = 65535;
342 return 0;
343}
344
345/* control get callback */
346static int snd_pod_control_monitor_get(struct snd_kcontrol *kcontrol,
347 struct snd_ctl_elem_value *ucontrol)
348{
349 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
350 struct usb_line6_pod *pod = (struct usb_line6_pod *)line6pcm->line6;
Jerry Snitselaarf3c52612014-04-24 00:31:48 -0700351
Stefan Hajnoczi2c35dc22012-11-22 20:48:47 +0100352 ucontrol->value.integer.value[0] = pod->monitor_level;
Markus Grabner1027f472010-08-12 01:35:30 +0200353 return 0;
354}
355
356/* control put callback */
357static int snd_pod_control_monitor_put(struct snd_kcontrol *kcontrol,
358 struct snd_ctl_elem_value *ucontrol)
359{
360 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
361 struct usb_line6_pod *pod = (struct usb_line6_pod *)line6pcm->line6;
362
Stefan Hajnoczi2c35dc22012-11-22 20:48:47 +0100363 if (ucontrol->value.integer.value[0] == pod->monitor_level)
Markus Grabner1027f472010-08-12 01:35:30 +0200364 return 0;
365
Stefan Hajnoczi2c35dc22012-11-22 20:48:47 +0100366 pod->monitor_level = ucontrol->value.integer.value[0];
Markus Grabnere1a164d2010-08-23 01:08:25 +0200367 pod_set_system_param_int(pod, ucontrol->value.integer.value[0],
Stefan Hajnoczi79360952013-01-11 23:08:14 +0100368 POD_MONITOR_LEVEL);
Markus Grabner1027f472010-08-12 01:35:30 +0200369 return 1;
370}
371
372/* control definition */
373static struct snd_kcontrol_new pod_control_monitor = {
374 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
375 .name = "Monitor Playback Volume",
376 .index = 0,
377 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
378 .info = snd_pod_control_monitor_info,
379 .get = snd_pod_control_monitor_get,
380 .put = snd_pod_control_monitor_put
381};
382
Markus Grabner705ecec2009-02-27 19:43:04 -0800383/*
Chris Rorvickd29b8542015-01-12 12:43:00 -0800384 POD device disconnected.
385*/
Takashi Iwaif66fd992015-01-25 18:22:58 +0100386static void line6_pod_disconnect(struct usb_line6 *line6)
Chris Rorvickd29b8542015-01-12 12:43:00 -0800387{
Takashi Iwaif66fd992015-01-25 18:22:58 +0100388 struct usb_line6_pod *pod = (struct usb_line6_pod *)line6;
389 struct device *dev = line6->ifcdev;
Chris Rorvickd29b8542015-01-12 12:43:00 -0800390
Takashi Iwai8a3b7c02015-01-20 08:42:42 +0100391 /* remove sysfs entries: */
392 device_remove_file(dev, &dev_attr_device_id);
393 device_remove_file(dev, &dev_attr_firmware_version);
394 device_remove_file(dev, &dev_attr_serial_number);
Chris Rorvickd29b8542015-01-12 12:43:00 -0800395
Takashi Iwai8a3b7c02015-01-20 08:42:42 +0100396 del_timer_sync(&pod->startup_timer);
397 cancel_work_sync(&pod->startup_work);
Chris Rorvickd29b8542015-01-12 12:43:00 -0800398}
399
400/*
Markus Grabner705ecec2009-02-27 19:43:04 -0800401 Create sysfs entries.
402*/
Greg Kroah-Hartmanb702ed252009-02-27 20:45:03 -0800403static int pod_create_files2(struct device *dev)
Markus Grabner705ecec2009-02-27 19:43:04 -0800404{
405 int err;
406
Takashi Iwaib2a3b022015-01-19 16:08:02 +0100407 err = device_create_file(dev, &dev_attr_device_id);
408 if (err < 0)
409 return err;
410 err = device_create_file(dev, &dev_attr_firmware_version);
411 if (err < 0)
412 return err;
413 err = device_create_file(dev, &dev_attr_serial_number);
414 if (err < 0)
415 return err;
Markus Grabner705ecec2009-02-27 19:43:04 -0800416 return 0;
417}
418
419/*
Markus Grabner1027f472010-08-12 01:35:30 +0200420 Try to init POD device.
Markus Grabner705ecec2009-02-27 19:43:04 -0800421*/
Takashi Iwaif66fd992015-01-25 18:22:58 +0100422static int pod_init(struct usb_line6 *line6,
423 const struct usb_device_id *id)
Markus Grabner705ecec2009-02-27 19:43:04 -0800424{
425 int err;
Chris Rorvicka221dd42015-01-12 12:42:56 -0800426 struct usb_line6_pod *pod = (struct usb_line6_pod *) line6;
Markus Grabner705ecec2009-02-27 19:43:04 -0800427
Chris Rorvick01f6b2b2015-01-12 12:42:58 -0800428 line6->process_message = line6_pod_process_message;
Chris Rorvicka46c4672015-01-12 12:42:59 -0800429 line6->disconnect = line6_pod_disconnect;
Chris Rorvick01f6b2b2015-01-12 12:42:58 -0800430
Markus Grabnere1a164d2010-08-23 01:08:25 +0200431 init_timer(&pod->startup_timer);
Stefan Hajnoczi09fda102012-11-22 20:49:24 +0100432 INIT_WORK(&pod->startup_work, pod_startup4);
Markus Grabnere1a164d2010-08-23 01:08:25 +0200433
Markus Grabner705ecec2009-02-27 19:43:04 -0800434 /* create sysfs entries: */
Takashi Iwaif66fd992015-01-25 18:22:58 +0100435 err = pod_create_files2(line6->ifcdev);
Greg Kroah-Hartman027360c2010-09-21 16:58:00 -0700436 if (err < 0)
Markus Grabner705ecec2009-02-27 19:43:04 -0800437 return err;
Markus Grabner705ecec2009-02-27 19:43:04 -0800438
Markus Grabner705ecec2009-02-27 19:43:04 -0800439 /* initialize MIDI subsystem: */
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800440 err = line6_init_midi(line6);
Greg Kroah-Hartman027360c2010-09-21 16:58:00 -0700441 if (err < 0)
Markus Grabner705ecec2009-02-27 19:43:04 -0800442 return err;
Markus Grabner705ecec2009-02-27 19:43:04 -0800443
444 /* initialize PCM subsystem: */
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800445 err = line6_init_pcm(line6, &pod_pcm_properties);
Greg Kroah-Hartman027360c2010-09-21 16:58:00 -0700446 if (err < 0)
Markus Grabner705ecec2009-02-27 19:43:04 -0800447 return err;
Markus Grabner705ecec2009-02-27 19:43:04 -0800448
Markus Grabner1027f472010-08-12 01:35:30 +0200449 /* register monitor control: */
Greg Kroah-Hartman027360c2010-09-21 16:58:00 -0700450 err = snd_ctl_add(line6->card,
451 snd_ctl_new1(&pod_control_monitor, line6->line6pcm));
452 if (err < 0)
Markus Grabner705ecec2009-02-27 19:43:04 -0800453 return err;
Markus Grabner705ecec2009-02-27 19:43:04 -0800454
Markus Grabner1027f472010-08-12 01:35:30 +0200455 /*
Markus Grabnere1a164d2010-08-23 01:08:25 +0200456 When the sound card is registered at this point, the PODxt Live
457 displays "Invalid Code Error 07", so we do it later in the event
458 handler.
459 */
Markus Grabner1027f472010-08-12 01:35:30 +0200460
Chris Rorvick4cb1a4a2015-01-12 12:42:45 -0800461 if (pod->line6.properties->capabilities & LINE6_CAP_CONTROL) {
Stefan Hajnoczi79360952013-01-11 23:08:14 +0100462 pod->monitor_level = POD_SYSTEM_INVALID;
Markus Grabner1027f472010-08-12 01:35:30 +0200463
464 /* initiate startup procedure: */
465 pod_startup1(pod);
Markus Grabner705ecec2009-02-27 19:43:04 -0800466 }
467
468 return 0;
469}
470
Takashi Iwaiccddbe42015-01-15 08:22:31 +0100471#define LINE6_DEVICE(prod) USB_DEVICE(0x0e41, prod)
472#define LINE6_IF_NUM(prod, n) USB_DEVICE_INTERFACE_NUMBER(0x0e41, prod, n)
473
474/* table of devices that work with this driver */
475static const struct usb_device_id pod_id_table[] = {
476 { LINE6_DEVICE(0x4250), .driver_info = LINE6_BASSPODXT },
477 { LINE6_DEVICE(0x4642), .driver_info = LINE6_BASSPODXTLIVE },
478 { LINE6_DEVICE(0x4252), .driver_info = LINE6_BASSPODXTPRO },
479 { LINE6_IF_NUM(0x5051, 1), .driver_info = LINE6_POCKETPOD },
480 { LINE6_DEVICE(0x5044), .driver_info = LINE6_PODXT },
481 { LINE6_IF_NUM(0x4650, 0), .driver_info = LINE6_PODXTLIVE_POD },
482 { LINE6_DEVICE(0x5050), .driver_info = LINE6_PODXTPRO },
483 {}
484};
485
486MODULE_DEVICE_TABLE(usb, pod_id_table);
487
488static const struct line6_properties pod_properties_table[] = {
489 [LINE6_BASSPODXT] = {
490 .id = "BassPODxt",
491 .name = "BassPODxt",
492 .capabilities = LINE6_CAP_CONTROL
493 | LINE6_CAP_PCM
494 | LINE6_CAP_HWMON,
495 .altsetting = 5,
496 .ep_ctrl_r = 0x84,
497 .ep_ctrl_w = 0x03,
498 .ep_audio_r = 0x82,
499 .ep_audio_w = 0x01,
500 },
501 [LINE6_BASSPODXTLIVE] = {
502 .id = "BassPODxtLive",
503 .name = "BassPODxt Live",
504 .capabilities = LINE6_CAP_CONTROL
505 | LINE6_CAP_PCM
506 | LINE6_CAP_HWMON,
507 .altsetting = 1,
508 .ep_ctrl_r = 0x84,
509 .ep_ctrl_w = 0x03,
510 .ep_audio_r = 0x82,
511 .ep_audio_w = 0x01,
512 },
513 [LINE6_BASSPODXTPRO] = {
514 .id = "BassPODxtPro",
515 .name = "BassPODxt Pro",
516 .capabilities = LINE6_CAP_CONTROL
517 | LINE6_CAP_PCM
518 | LINE6_CAP_HWMON,
519 .altsetting = 5,
520 .ep_ctrl_r = 0x84,
521 .ep_ctrl_w = 0x03,
522 .ep_audio_r = 0x82,
523 .ep_audio_w = 0x01,
524 },
525 [LINE6_POCKETPOD] = {
526 .id = "PocketPOD",
527 .name = "Pocket POD",
528 .capabilities = LINE6_CAP_CONTROL,
529 .altsetting = 0,
530 .ep_ctrl_r = 0x82,
531 .ep_ctrl_w = 0x02,
532 /* no audio channel */
533 },
534 [LINE6_PODXT] = {
535 .id = "PODxt",
536 .name = "PODxt",
537 .capabilities = LINE6_CAP_CONTROL
538 | LINE6_CAP_PCM
539 | LINE6_CAP_HWMON,
540 .altsetting = 5,
541 .ep_ctrl_r = 0x84,
542 .ep_ctrl_w = 0x03,
543 .ep_audio_r = 0x82,
544 .ep_audio_w = 0x01,
545 },
546 [LINE6_PODXTLIVE_POD] = {
547 .id = "PODxtLive",
548 .name = "PODxt Live",
549 .capabilities = LINE6_CAP_CONTROL
550 | LINE6_CAP_PCM
551 | LINE6_CAP_HWMON,
552 .altsetting = 1,
553 .ep_ctrl_r = 0x84,
554 .ep_ctrl_w = 0x03,
555 .ep_audio_r = 0x82,
556 .ep_audio_w = 0x01,
557 },
558 [LINE6_PODXTPRO] = {
559 .id = "PODxtPro",
560 .name = "PODxt Pro",
561 .capabilities = LINE6_CAP_CONTROL
562 | LINE6_CAP_PCM
563 | LINE6_CAP_HWMON,
564 .altsetting = 5,
565 .ep_ctrl_r = 0x84,
566 .ep_ctrl_w = 0x03,
567 .ep_audio_r = 0x82,
568 .ep_audio_w = 0x01,
569 },
570};
571
572/*
573 Probe USB device.
574*/
575static int pod_probe(struct usb_interface *interface,
576 const struct usb_device_id *id)
577{
Takashi Iwaiaca514b2015-01-25 18:36:29 +0100578 return line6_probe(interface, id,
Takashi Iwai85a93392015-01-19 15:54:00 +0100579 &pod_properties_table[id->driver_info],
Takashi Iwaiaca514b2015-01-25 18:36:29 +0100580 pod_init, sizeof(struct usb_line6_pod));
Takashi Iwaiccddbe42015-01-15 08:22:31 +0100581}
582
583static struct usb_driver pod_driver = {
584 .name = KBUILD_MODNAME,
585 .probe = pod_probe,
586 .disconnect = line6_disconnect,
587#ifdef CONFIG_PM
588 .suspend = line6_suspend,
589 .resume = line6_resume,
590 .reset_resume = line6_resume,
591#endif
592 .id_table = pod_id_table,
593};
594
595module_usb_driver(pod_driver);
596
Chris Rorvickc6fffce2015-01-20 02:20:49 -0600597MODULE_DESCRIPTION("Line 6 POD USB driver");
Takashi Iwaiccddbe42015-01-15 08:22:31 +0100598MODULE_LICENSE("GPL");