1a10e763bSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
261864d84STakashi Iwai /*
3c078a4aaSChris Rorvick * Line 6 Linux USB driver
461864d84STakashi Iwai *
561864d84STakashi Iwai * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
661864d84STakashi Iwai */
761864d84STakashi Iwai
861864d84STakashi Iwai #include <linux/slab.h>
961864d84STakashi Iwai #include <linux/wait.h>
10ccddbe4aSTakashi Iwai #include <linux/interrupt.h>
11ccddbe4aSTakashi Iwai #include <linux/module.h>
12ccddbe4aSTakashi Iwai #include <linux/usb.h>
13ccddbe4aSTakashi Iwai
14ccddbe4aSTakashi Iwai #include <sound/core.h>
1561864d84STakashi Iwai #include <sound/control.h>
1661864d84STakashi Iwai
1761864d84STakashi Iwai #include "capture.h"
1861864d84STakashi Iwai #include "driver.h"
1961864d84STakashi Iwai #include "playback.h"
20ccddbe4aSTakashi Iwai
21ccddbe4aSTakashi Iwai /*
22ccddbe4aSTakashi Iwai Locate name in binary program dump
23ccddbe4aSTakashi Iwai */
24ccddbe4aSTakashi Iwai #define POD_NAME_OFFSET 0
25ccddbe4aSTakashi Iwai #define POD_NAME_LENGTH 16
26ccddbe4aSTakashi Iwai
27ccddbe4aSTakashi Iwai /*
28ccddbe4aSTakashi Iwai Other constants
29ccddbe4aSTakashi Iwai */
30ccddbe4aSTakashi Iwai #define POD_CONTROL_SIZE 0x80
31ccddbe4aSTakashi Iwai #define POD_BUFSIZE_DUMPREQ 7
32ccddbe4aSTakashi Iwai #define POD_STARTUP_DELAY 1000
33ccddbe4aSTakashi Iwai
34ccddbe4aSTakashi Iwai /*
35ccddbe4aSTakashi Iwai Stages of POD startup procedure
36ccddbe4aSTakashi Iwai */
37ccddbe4aSTakashi Iwai enum {
38ccddbe4aSTakashi Iwai POD_STARTUP_VERSIONREQ,
39ccddbe4aSTakashi Iwai POD_STARTUP_SETUP,
40516d3d1bSTakashi Iwai POD_STARTUP_DONE,
41ccddbe4aSTakashi Iwai };
42ccddbe4aSTakashi Iwai
43ccddbe4aSTakashi Iwai enum {
44ccddbe4aSTakashi Iwai LINE6_BASSPODXT,
45ccddbe4aSTakashi Iwai LINE6_BASSPODXTLIVE,
46ccddbe4aSTakashi Iwai LINE6_BASSPODXTPRO,
47ccddbe4aSTakashi Iwai LINE6_POCKETPOD,
48ccddbe4aSTakashi Iwai LINE6_PODXT,
49ccddbe4aSTakashi Iwai LINE6_PODXTLIVE_POD,
50ccddbe4aSTakashi Iwai LINE6_PODXTPRO,
51ccddbe4aSTakashi Iwai };
52ccddbe4aSTakashi Iwai
53ccddbe4aSTakashi Iwai struct usb_line6_pod {
54cddbd4f1STakashi Iwai /* Generic Line 6 USB data */
55ccddbe4aSTakashi Iwai struct usb_line6 line6;
56ccddbe4aSTakashi Iwai
57cddbd4f1STakashi Iwai /* Instrument monitor level */
58ccddbe4aSTakashi Iwai int monitor_level;
59ccddbe4aSTakashi Iwai
60cddbd4f1STakashi Iwai /* Current progress in startup procedure */
61ccddbe4aSTakashi Iwai int startup_progress;
62ccddbe4aSTakashi Iwai
63cddbd4f1STakashi Iwai /* Serial number of device */
6412b00157SChris Rorvick u32 serial_number;
65ccddbe4aSTakashi Iwai
66cddbd4f1STakashi Iwai /* Firmware version (x 100) */
67ccddbe4aSTakashi Iwai int firmware_version;
68ccddbe4aSTakashi Iwai
69cddbd4f1STakashi Iwai /* Device ID */
70ccddbe4aSTakashi Iwai int device_id;
71ccddbe4aSTakashi Iwai };
7261864d84STakashi Iwai
73f23a09eeSTakashi Iwai #define line6_to_pod(x) container_of(x, struct usb_line6_pod, line6)
74f23a09eeSTakashi Iwai
7561864d84STakashi Iwai #define POD_SYSEX_CODE 3
7661864d84STakashi Iwai
7761864d84STakashi Iwai /* *INDENT-OFF* */
7861864d84STakashi Iwai
7961864d84STakashi Iwai enum {
8061864d84STakashi Iwai POD_SYSEX_SAVE = 0x24,
8161864d84STakashi Iwai POD_SYSEX_SYSTEM = 0x56,
8261864d84STakashi Iwai POD_SYSEX_SYSTEMREQ = 0x57,
8361864d84STakashi Iwai /* POD_SYSEX_UPDATE = 0x6c, */ /* software update! */
8461864d84STakashi Iwai POD_SYSEX_STORE = 0x71,
8561864d84STakashi Iwai POD_SYSEX_FINISH = 0x72,
8661864d84STakashi Iwai POD_SYSEX_DUMPMEM = 0x73,
8761864d84STakashi Iwai POD_SYSEX_DUMP = 0x74,
8861864d84STakashi Iwai POD_SYSEX_DUMPREQ = 0x75
8961864d84STakashi Iwai
9061864d84STakashi Iwai /* dumps entire internal memory of PODxt Pro */
9161864d84STakashi Iwai /* POD_SYSEX_DUMPMEM2 = 0x76 */
9261864d84STakashi Iwai };
9361864d84STakashi Iwai
9461864d84STakashi Iwai enum {
9561864d84STakashi Iwai POD_MONITOR_LEVEL = 0x04,
9661864d84STakashi Iwai POD_SYSTEM_INVALID = 0x10000
9761864d84STakashi Iwai };
9861864d84STakashi Iwai
9961864d84STakashi Iwai /* *INDENT-ON* */
10061864d84STakashi Iwai
10161864d84STakashi Iwai enum {
10261864d84STakashi Iwai POD_DUMP_MEMORY = 2
10361864d84STakashi Iwai };
10461864d84STakashi Iwai
10561864d84STakashi Iwai enum {
10661864d84STakashi Iwai POD_BUSY_READ,
10761864d84STakashi Iwai POD_BUSY_WRITE,
10861864d84STakashi Iwai POD_CHANNEL_DIRTY,
10961864d84STakashi Iwai POD_SAVE_PRESSED,
11061864d84STakashi Iwai POD_BUSY_MIDISEND
11161864d84STakashi Iwai };
11261864d84STakashi Iwai
11337cc306bSTakashi Iwai static const struct snd_ratden pod_ratden = {
11461864d84STakashi Iwai .num_min = 78125,
11561864d84STakashi Iwai .num_max = 78125,
11661864d84STakashi Iwai .num_step = 1,
11761864d84STakashi Iwai .den = 2
11861864d84STakashi Iwai };
11961864d84STakashi Iwai
12061864d84STakashi Iwai static struct line6_pcm_properties pod_pcm_properties = {
1211263f611STakashi Iwai .playback_hw = {
12261864d84STakashi Iwai .info = (SNDRV_PCM_INFO_MMAP |
12361864d84STakashi Iwai SNDRV_PCM_INFO_INTERLEAVED |
12461864d84STakashi Iwai SNDRV_PCM_INFO_BLOCK_TRANSFER |
12561864d84STakashi Iwai SNDRV_PCM_INFO_MMAP_VALID |
12661864d84STakashi Iwai SNDRV_PCM_INFO_PAUSE |
12761864d84STakashi Iwai SNDRV_PCM_INFO_SYNC_START),
12861864d84STakashi Iwai .formats = SNDRV_PCM_FMTBIT_S24_3LE,
12961864d84STakashi Iwai .rates = SNDRV_PCM_RATE_KNOT,
13061864d84STakashi Iwai .rate_min = 39062,
13161864d84STakashi Iwai .rate_max = 39063,
13261864d84STakashi Iwai .channels_min = 2,
13361864d84STakashi Iwai .channels_max = 2,
13461864d84STakashi Iwai .buffer_bytes_max = 60000,
13561864d84STakashi Iwai .period_bytes_min = 64,
13661864d84STakashi Iwai .period_bytes_max = 8192,
13761864d84STakashi Iwai .periods_min = 1,
13861864d84STakashi Iwai .periods_max = 1024},
1391263f611STakashi Iwai .capture_hw = {
14061864d84STakashi Iwai .info = (SNDRV_PCM_INFO_MMAP |
14161864d84STakashi Iwai SNDRV_PCM_INFO_INTERLEAVED |
14261864d84STakashi Iwai SNDRV_PCM_INFO_BLOCK_TRANSFER |
14361864d84STakashi Iwai SNDRV_PCM_INFO_MMAP_VALID |
14461864d84STakashi Iwai SNDRV_PCM_INFO_SYNC_START),
14561864d84STakashi Iwai .formats = SNDRV_PCM_FMTBIT_S24_3LE,
14661864d84STakashi Iwai .rates = SNDRV_PCM_RATE_KNOT,
14761864d84STakashi Iwai .rate_min = 39062,
14861864d84STakashi Iwai .rate_max = 39063,
14961864d84STakashi Iwai .channels_min = 2,
15061864d84STakashi Iwai .channels_max = 2,
15161864d84STakashi Iwai .buffer_bytes_max = 60000,
15261864d84STakashi Iwai .period_bytes_min = 64,
15361864d84STakashi Iwai .period_bytes_max = 8192,
15461864d84STakashi Iwai .periods_min = 1,
15561864d84STakashi Iwai .periods_max = 1024},
1561263f611STakashi Iwai .rates = {
15761864d84STakashi Iwai .nrats = 1,
15861864d84STakashi Iwai .rats = &pod_ratden},
15997d78acfSAndrej Krutak .bytes_per_channel = 3 /* SNDRV_PCM_FMTBIT_S24_3LE */
16061864d84STakashi Iwai };
16161864d84STakashi Iwai
162*8508fa2eSArtem Egorkine
16361864d84STakashi Iwai static const char pod_version_header[] = {
164*8508fa2eSArtem Egorkine 0xf0, 0x7e, 0x7f, 0x06, 0x02
16561864d84STakashi Iwai };
16661864d84STakashi Iwai
pod_alloc_sysex_buffer(struct usb_line6_pod * pod,int code,int size)16761864d84STakashi Iwai static char *pod_alloc_sysex_buffer(struct usb_line6_pod *pod, int code,
16861864d84STakashi Iwai int size)
16961864d84STakashi Iwai {
17061864d84STakashi Iwai return line6_alloc_sysex_buffer(&pod->line6, POD_SYSEX_CODE, code,
17161864d84STakashi Iwai size);
17261864d84STakashi Iwai }
17361864d84STakashi Iwai
17461864d84STakashi Iwai /*
17561864d84STakashi Iwai Process a completely received message.
17661864d84STakashi Iwai */
line6_pod_process_message(struct usb_line6 * line6)17761864d84STakashi Iwai static void line6_pod_process_message(struct usb_line6 *line6)
17861864d84STakashi Iwai {
179f23a09eeSTakashi Iwai struct usb_line6_pod *pod = line6_to_pod(line6);
18061864d84STakashi Iwai const unsigned char *buf = pod->line6.buffer_message;
18161864d84STakashi Iwai
18261864d84STakashi Iwai if (memcmp(buf, pod_version_header, sizeof(pod_version_header)) == 0) {
18361864d84STakashi Iwai pod->firmware_version = buf[13] * 100 + buf[14] * 10 + buf[15];
18461864d84STakashi Iwai pod->device_id = ((int)buf[8] << 16) | ((int)buf[9] << 8) |
18561864d84STakashi Iwai (int) buf[10];
186516d3d1bSTakashi Iwai if (pod->startup_progress == POD_STARTUP_VERSIONREQ) {
187516d3d1bSTakashi Iwai pod->startup_progress = POD_STARTUP_SETUP;
188516d3d1bSTakashi Iwai schedule_delayed_work(&line6->startup_work, 0);
189516d3d1bSTakashi Iwai }
19061864d84STakashi Iwai return;
19161864d84STakashi Iwai }
19261864d84STakashi Iwai
19361864d84STakashi Iwai /* Only look for sysex messages from this device */
19461864d84STakashi Iwai if (buf[0] != (LINE6_SYSEX_BEGIN | LINE6_CHANNEL_DEVICE) &&
19561864d84STakashi Iwai buf[0] != (LINE6_SYSEX_BEGIN | LINE6_CHANNEL_UNKNOWN)) {
19661864d84STakashi Iwai return;
19761864d84STakashi Iwai }
19861864d84STakashi Iwai if (memcmp(buf + 1, line6_midi_id, sizeof(line6_midi_id)) != 0)
19961864d84STakashi Iwai return;
20061864d84STakashi Iwai
20161864d84STakashi Iwai if (buf[5] == POD_SYSEX_SYSTEM && buf[6] == POD_MONITOR_LEVEL) {
20261864d84STakashi Iwai short value = ((int)buf[7] << 12) | ((int)buf[8] << 8) |
20361864d84STakashi Iwai ((int)buf[9] << 4) | (int)buf[10];
20461864d84STakashi Iwai pod->monitor_level = value;
20561864d84STakashi Iwai }
20661864d84STakashi Iwai }
20761864d84STakashi Iwai
20861864d84STakashi Iwai /*
20961864d84STakashi Iwai Send system parameter (from integer).
21061864d84STakashi Iwai */
pod_set_system_param_int(struct usb_line6_pod * pod,int value,int code)21161864d84STakashi Iwai static int pod_set_system_param_int(struct usb_line6_pod *pod, int value,
21261864d84STakashi Iwai int code)
21361864d84STakashi Iwai {
21461864d84STakashi Iwai char *sysex;
21561864d84STakashi Iwai static const int size = 5;
21661864d84STakashi Iwai
21761864d84STakashi Iwai sysex = pod_alloc_sysex_buffer(pod, POD_SYSEX_SYSTEM, size);
21861864d84STakashi Iwai if (!sysex)
21961864d84STakashi Iwai return -ENOMEM;
22061864d84STakashi Iwai sysex[SYSEX_DATA_OFS] = code;
22161864d84STakashi Iwai sysex[SYSEX_DATA_OFS + 1] = (value >> 12) & 0x0f;
22261864d84STakashi Iwai sysex[SYSEX_DATA_OFS + 2] = (value >> 8) & 0x0f;
22361864d84STakashi Iwai sysex[SYSEX_DATA_OFS + 3] = (value >> 4) & 0x0f;
22461864d84STakashi Iwai sysex[SYSEX_DATA_OFS + 4] = (value) & 0x0f;
22561864d84STakashi Iwai line6_send_sysex_message(&pod->line6, sysex, size);
22661864d84STakashi Iwai kfree(sysex);
22761864d84STakashi Iwai return 0;
22861864d84STakashi Iwai }
22961864d84STakashi Iwai
23061864d84STakashi Iwai /*
23161864d84STakashi Iwai "read" request on "serial_number" special file.
23261864d84STakashi Iwai */
serial_number_show(struct device * dev,struct device_attribute * attr,char * buf)23361864d84STakashi Iwai static ssize_t serial_number_show(struct device *dev,
23461864d84STakashi Iwai struct device_attribute *attr, char *buf)
23561864d84STakashi Iwai {
236b027d112SAndrej Krutak struct snd_card *card = dev_to_snd_card(dev);
237b027d112SAndrej Krutak struct usb_line6_pod *pod = card->private_data;
23861864d84STakashi Iwai
2396c955a9dSTakashi Iwai return sysfs_emit(buf, "%u\n", pod->serial_number);
24061864d84STakashi Iwai }
24161864d84STakashi Iwai
24261864d84STakashi Iwai /*
24361864d84STakashi Iwai "read" request on "firmware_version" special file.
24461864d84STakashi Iwai */
firmware_version_show(struct device * dev,struct device_attribute * attr,char * buf)24561864d84STakashi Iwai static ssize_t firmware_version_show(struct device *dev,
24661864d84STakashi Iwai struct device_attribute *attr, char *buf)
24761864d84STakashi Iwai {
248b027d112SAndrej Krutak struct snd_card *card = dev_to_snd_card(dev);
249b027d112SAndrej Krutak struct usb_line6_pod *pod = card->private_data;
25061864d84STakashi Iwai
2516c955a9dSTakashi Iwai return sysfs_emit(buf, "%d.%02d\n", pod->firmware_version / 100,
25261864d84STakashi Iwai pod->firmware_version % 100);
25361864d84STakashi Iwai }
25461864d84STakashi Iwai
25561864d84STakashi Iwai /*
25661864d84STakashi Iwai "read" request on "device_id" special file.
25761864d84STakashi Iwai */
device_id_show(struct device * dev,struct device_attribute * attr,char * buf)25861864d84STakashi Iwai static ssize_t device_id_show(struct device *dev,
25961864d84STakashi Iwai struct device_attribute *attr, char *buf)
26061864d84STakashi Iwai {
261b027d112SAndrej Krutak struct snd_card *card = dev_to_snd_card(dev);
262b027d112SAndrej Krutak struct usb_line6_pod *pod = card->private_data;
26361864d84STakashi Iwai
2646c955a9dSTakashi Iwai return sysfs_emit(buf, "%d\n", pod->device_id);
26561864d84STakashi Iwai }
26661864d84STakashi Iwai
26761864d84STakashi Iwai /*
26861864d84STakashi Iwai POD startup procedure.
26961864d84STakashi Iwai This is a sequence of functions with special requirements (e.g., must
27061864d84STakashi Iwai not run immediately after initialization, must not run in interrupt
27161864d84STakashi Iwai context). After the last one has finished, the device is ready to use.
27261864d84STakashi Iwai */
27361864d84STakashi Iwai
pod_startup(struct usb_line6 * line6)274516d3d1bSTakashi Iwai static void pod_startup(struct usb_line6 *line6)
27561864d84STakashi Iwai {
276f23a09eeSTakashi Iwai struct usb_line6_pod *pod = line6_to_pod(line6);
27761864d84STakashi Iwai
278516d3d1bSTakashi Iwai switch (pod->startup_progress) {
279516d3d1bSTakashi Iwai case POD_STARTUP_VERSIONREQ:
28061864d84STakashi Iwai /* request firmware version: */
28161864d84STakashi Iwai line6_version_request_async(line6);
282516d3d1bSTakashi Iwai break;
283516d3d1bSTakashi Iwai case POD_STARTUP_SETUP:
28461864d84STakashi Iwai /* serial number: */
28561864d84STakashi Iwai line6_read_serial_number(&pod->line6, &pod->serial_number);
28661864d84STakashi Iwai
28761864d84STakashi Iwai /* ALSA audio interface: */
28802cc53e2SAditya Pakki if (snd_card_register(line6->card))
28902cc53e2SAditya Pakki dev_err(line6->ifcdev, "Failed to register POD card.\n");
290516d3d1bSTakashi Iwai pod->startup_progress = POD_STARTUP_DONE;
291516d3d1bSTakashi Iwai break;
292516d3d1bSTakashi Iwai default:
293516d3d1bSTakashi Iwai break;
294516d3d1bSTakashi Iwai }
29561864d84STakashi Iwai }
29661864d84STakashi Iwai
29761864d84STakashi Iwai /* POD special files: */
29861864d84STakashi Iwai static DEVICE_ATTR_RO(device_id);
29961864d84STakashi Iwai static DEVICE_ATTR_RO(firmware_version);
30061864d84STakashi Iwai static DEVICE_ATTR_RO(serial_number);
30161864d84STakashi Iwai
30202fc76f6STakashi Iwai static struct attribute *pod_dev_attrs[] = {
30302fc76f6STakashi Iwai &dev_attr_device_id.attr,
30402fc76f6STakashi Iwai &dev_attr_firmware_version.attr,
30502fc76f6STakashi Iwai &dev_attr_serial_number.attr,
30602fc76f6STakashi Iwai NULL
30702fc76f6STakashi Iwai };
30802fc76f6STakashi Iwai
30902fc76f6STakashi Iwai static const struct attribute_group pod_dev_attr_group = {
31002fc76f6STakashi Iwai .name = "pod",
31102fc76f6STakashi Iwai .attrs = pod_dev_attrs,
31202fc76f6STakashi Iwai };
31302fc76f6STakashi Iwai
31461864d84STakashi Iwai /* control info callback */
snd_pod_control_monitor_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)31561864d84STakashi Iwai static int snd_pod_control_monitor_info(struct snd_kcontrol *kcontrol,
31661864d84STakashi Iwai struct snd_ctl_elem_info *uinfo)
31761864d84STakashi Iwai {
31861864d84STakashi Iwai uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
31961864d84STakashi Iwai uinfo->count = 1;
32061864d84STakashi Iwai uinfo->value.integer.min = 0;
32161864d84STakashi Iwai uinfo->value.integer.max = 65535;
32261864d84STakashi Iwai return 0;
32361864d84STakashi Iwai }
32461864d84STakashi Iwai
32561864d84STakashi Iwai /* control get callback */
snd_pod_control_monitor_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)32661864d84STakashi Iwai static int snd_pod_control_monitor_get(struct snd_kcontrol *kcontrol,
32761864d84STakashi Iwai struct snd_ctl_elem_value *ucontrol)
32861864d84STakashi Iwai {
32961864d84STakashi Iwai struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
330f23a09eeSTakashi Iwai struct usb_line6_pod *pod = line6_to_pod(line6pcm->line6);
33161864d84STakashi Iwai
33261864d84STakashi Iwai ucontrol->value.integer.value[0] = pod->monitor_level;
33361864d84STakashi Iwai return 0;
33461864d84STakashi Iwai }
33561864d84STakashi Iwai
33661864d84STakashi Iwai /* control put callback */
snd_pod_control_monitor_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)33761864d84STakashi Iwai static int snd_pod_control_monitor_put(struct snd_kcontrol *kcontrol,
33861864d84STakashi Iwai struct snd_ctl_elem_value *ucontrol)
33961864d84STakashi Iwai {
34061864d84STakashi Iwai struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
341f23a09eeSTakashi Iwai struct usb_line6_pod *pod = line6_to_pod(line6pcm->line6);
34261864d84STakashi Iwai
34361864d84STakashi Iwai if (ucontrol->value.integer.value[0] == pod->monitor_level)
34461864d84STakashi Iwai return 0;
34561864d84STakashi Iwai
34661864d84STakashi Iwai pod->monitor_level = ucontrol->value.integer.value[0];
34761864d84STakashi Iwai pod_set_system_param_int(pod, ucontrol->value.integer.value[0],
34861864d84STakashi Iwai POD_MONITOR_LEVEL);
34961864d84STakashi Iwai return 1;
35061864d84STakashi Iwai }
35161864d84STakashi Iwai
35261864d84STakashi Iwai /* control definition */
35349c41e1fSBhumika Goyal static const struct snd_kcontrol_new pod_control_monitor = {
35461864d84STakashi Iwai .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
35561864d84STakashi Iwai .name = "Monitor Playback Volume",
35661864d84STakashi Iwai .index = 0,
35761864d84STakashi Iwai .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
35861864d84STakashi Iwai .info = snd_pod_control_monitor_info,
35961864d84STakashi Iwai .get = snd_pod_control_monitor_get,
36061864d84STakashi Iwai .put = snd_pod_control_monitor_put
36161864d84STakashi Iwai };
36261864d84STakashi Iwai
36361864d84STakashi Iwai /*
36461864d84STakashi Iwai Try to init POD device.
36561864d84STakashi Iwai */
pod_init(struct usb_line6 * line6,const struct usb_device_id * id)366f66fd990STakashi Iwai static int pod_init(struct usb_line6 *line6,
367f66fd990STakashi Iwai const struct usb_device_id *id)
36861864d84STakashi Iwai {
36961864d84STakashi Iwai int err;
370f23a09eeSTakashi Iwai struct usb_line6_pod *pod = line6_to_pod(line6);
37161864d84STakashi Iwai
37261864d84STakashi Iwai line6->process_message = line6_pod_process_message;
373516d3d1bSTakashi Iwai line6->startup = pod_startup;
37461864d84STakashi Iwai
37561864d84STakashi Iwai /* create sysfs entries: */
37602fc76f6STakashi Iwai err = snd_card_add_dev_attr(line6->card, &pod_dev_attr_group);
37761864d84STakashi Iwai if (err < 0)
37861864d84STakashi Iwai return err;
37961864d84STakashi Iwai
38061864d84STakashi Iwai /* initialize PCM subsystem: */
38161864d84STakashi Iwai err = line6_init_pcm(line6, &pod_pcm_properties);
38261864d84STakashi Iwai if (err < 0)
38361864d84STakashi Iwai return err;
38461864d84STakashi Iwai
38561864d84STakashi Iwai /* register monitor control: */
38661864d84STakashi Iwai err = snd_ctl_add(line6->card,
38761864d84STakashi Iwai snd_ctl_new1(&pod_control_monitor, line6->line6pcm));
38861864d84STakashi Iwai if (err < 0)
38961864d84STakashi Iwai return err;
39061864d84STakashi Iwai
39161864d84STakashi Iwai /*
39261864d84STakashi Iwai When the sound card is registered at this point, the PODxt Live
39361864d84STakashi Iwai displays "Invalid Code Error 07", so we do it later in the event
39461864d84STakashi Iwai handler.
39561864d84STakashi Iwai */
39661864d84STakashi Iwai
39761864d84STakashi Iwai if (pod->line6.properties->capabilities & LINE6_CAP_CONTROL) {
39861864d84STakashi Iwai pod->monitor_level = POD_SYSTEM_INVALID;
39961864d84STakashi Iwai
40061864d84STakashi Iwai /* initiate startup procedure: */
401516d3d1bSTakashi Iwai schedule_delayed_work(&line6->startup_work,
402516d3d1bSTakashi Iwai msecs_to_jiffies(POD_STARTUP_DELAY));
40361864d84STakashi Iwai }
40461864d84STakashi Iwai
40561864d84STakashi Iwai return 0;
40661864d84STakashi Iwai }
40761864d84STakashi Iwai
408ccddbe4aSTakashi Iwai #define LINE6_DEVICE(prod) USB_DEVICE(0x0e41, prod)
409ccddbe4aSTakashi Iwai #define LINE6_IF_NUM(prod, n) USB_DEVICE_INTERFACE_NUMBER(0x0e41, prod, n)
410ccddbe4aSTakashi Iwai
411ccddbe4aSTakashi Iwai /* table of devices that work with this driver */
412ccddbe4aSTakashi Iwai static const struct usb_device_id pod_id_table[] = {
413ccddbe4aSTakashi Iwai { LINE6_DEVICE(0x4250), .driver_info = LINE6_BASSPODXT },
414ccddbe4aSTakashi Iwai { LINE6_DEVICE(0x4642), .driver_info = LINE6_BASSPODXTLIVE },
415ccddbe4aSTakashi Iwai { LINE6_DEVICE(0x4252), .driver_info = LINE6_BASSPODXTPRO },
416ccddbe4aSTakashi Iwai { LINE6_IF_NUM(0x5051, 1), .driver_info = LINE6_POCKETPOD },
417ccddbe4aSTakashi Iwai { LINE6_DEVICE(0x5044), .driver_info = LINE6_PODXT },
418ccddbe4aSTakashi Iwai { LINE6_IF_NUM(0x4650, 0), .driver_info = LINE6_PODXTLIVE_POD },
419ccddbe4aSTakashi Iwai { LINE6_DEVICE(0x5050), .driver_info = LINE6_PODXTPRO },
420ccddbe4aSTakashi Iwai {}
421ccddbe4aSTakashi Iwai };
422ccddbe4aSTakashi Iwai
423ccddbe4aSTakashi Iwai MODULE_DEVICE_TABLE(usb, pod_id_table);
424ccddbe4aSTakashi Iwai
425ccddbe4aSTakashi Iwai static const struct line6_properties pod_properties_table[] = {
426ccddbe4aSTakashi Iwai [LINE6_BASSPODXT] = {
427ccddbe4aSTakashi Iwai .id = "BassPODxt",
428ccddbe4aSTakashi Iwai .name = "BassPODxt",
429ccddbe4aSTakashi Iwai .capabilities = LINE6_CAP_CONTROL
430174e1fc0SAndrej Krutak | LINE6_CAP_CONTROL_MIDI
431ccddbe4aSTakashi Iwai | LINE6_CAP_PCM
432ccddbe4aSTakashi Iwai | LINE6_CAP_HWMON,
433ccddbe4aSTakashi Iwai .altsetting = 5,
434ccddbe4aSTakashi Iwai .ep_ctrl_r = 0x84,
435ccddbe4aSTakashi Iwai .ep_ctrl_w = 0x03,
436ccddbe4aSTakashi Iwai .ep_audio_r = 0x82,
437ccddbe4aSTakashi Iwai .ep_audio_w = 0x01,
438ccddbe4aSTakashi Iwai },
439ccddbe4aSTakashi Iwai [LINE6_BASSPODXTLIVE] = {
440ccddbe4aSTakashi Iwai .id = "BassPODxtLive",
441ccddbe4aSTakashi Iwai .name = "BassPODxt Live",
442ccddbe4aSTakashi Iwai .capabilities = LINE6_CAP_CONTROL
443174e1fc0SAndrej Krutak | LINE6_CAP_CONTROL_MIDI
444ccddbe4aSTakashi Iwai | LINE6_CAP_PCM
445ccddbe4aSTakashi Iwai | LINE6_CAP_HWMON,
446ccddbe4aSTakashi Iwai .altsetting = 1,
447ccddbe4aSTakashi Iwai .ep_ctrl_r = 0x84,
448ccddbe4aSTakashi Iwai .ep_ctrl_w = 0x03,
449ccddbe4aSTakashi Iwai .ep_audio_r = 0x82,
450ccddbe4aSTakashi Iwai .ep_audio_w = 0x01,
451ccddbe4aSTakashi Iwai },
452ccddbe4aSTakashi Iwai [LINE6_BASSPODXTPRO] = {
453ccddbe4aSTakashi Iwai .id = "BassPODxtPro",
454ccddbe4aSTakashi Iwai .name = "BassPODxt Pro",
455ccddbe4aSTakashi Iwai .capabilities = LINE6_CAP_CONTROL
456174e1fc0SAndrej Krutak | LINE6_CAP_CONTROL_MIDI
457ccddbe4aSTakashi Iwai | LINE6_CAP_PCM
458ccddbe4aSTakashi Iwai | LINE6_CAP_HWMON,
459ccddbe4aSTakashi Iwai .altsetting = 5,
460ccddbe4aSTakashi Iwai .ep_ctrl_r = 0x84,
461ccddbe4aSTakashi Iwai .ep_ctrl_w = 0x03,
462ccddbe4aSTakashi Iwai .ep_audio_r = 0x82,
463ccddbe4aSTakashi Iwai .ep_audio_w = 0x01,
464ccddbe4aSTakashi Iwai },
465ccddbe4aSTakashi Iwai [LINE6_POCKETPOD] = {
466ccddbe4aSTakashi Iwai .id = "PocketPOD",
467ccddbe4aSTakashi Iwai .name = "Pocket POD",
468174e1fc0SAndrej Krutak .capabilities = LINE6_CAP_CONTROL
469174e1fc0SAndrej Krutak | LINE6_CAP_CONTROL_MIDI,
470ccddbe4aSTakashi Iwai .altsetting = 0,
471ccddbe4aSTakashi Iwai .ep_ctrl_r = 0x82,
472ccddbe4aSTakashi Iwai .ep_ctrl_w = 0x02,
473ccddbe4aSTakashi Iwai /* no audio channel */
474ccddbe4aSTakashi Iwai },
475ccddbe4aSTakashi Iwai [LINE6_PODXT] = {
476ccddbe4aSTakashi Iwai .id = "PODxt",
477ccddbe4aSTakashi Iwai .name = "PODxt",
478ccddbe4aSTakashi Iwai .capabilities = LINE6_CAP_CONTROL
479174e1fc0SAndrej Krutak | LINE6_CAP_CONTROL_MIDI
480ccddbe4aSTakashi Iwai | LINE6_CAP_PCM
481ccddbe4aSTakashi Iwai | LINE6_CAP_HWMON,
482ccddbe4aSTakashi Iwai .altsetting = 5,
483ccddbe4aSTakashi Iwai .ep_ctrl_r = 0x84,
484ccddbe4aSTakashi Iwai .ep_ctrl_w = 0x03,
485ccddbe4aSTakashi Iwai .ep_audio_r = 0x82,
486ccddbe4aSTakashi Iwai .ep_audio_w = 0x01,
487ccddbe4aSTakashi Iwai },
488ccddbe4aSTakashi Iwai [LINE6_PODXTLIVE_POD] = {
489ccddbe4aSTakashi Iwai .id = "PODxtLive",
490ccddbe4aSTakashi Iwai .name = "PODxt Live",
491ccddbe4aSTakashi Iwai .capabilities = LINE6_CAP_CONTROL
492174e1fc0SAndrej Krutak | LINE6_CAP_CONTROL_MIDI
493ccddbe4aSTakashi Iwai | LINE6_CAP_PCM
494ccddbe4aSTakashi Iwai | LINE6_CAP_HWMON,
495ccddbe4aSTakashi Iwai .altsetting = 1,
496ccddbe4aSTakashi Iwai .ep_ctrl_r = 0x84,
497ccddbe4aSTakashi Iwai .ep_ctrl_w = 0x03,
498ccddbe4aSTakashi Iwai .ep_audio_r = 0x82,
499ccddbe4aSTakashi Iwai .ep_audio_w = 0x01,
500ccddbe4aSTakashi Iwai },
501ccddbe4aSTakashi Iwai [LINE6_PODXTPRO] = {
502ccddbe4aSTakashi Iwai .id = "PODxtPro",
503ccddbe4aSTakashi Iwai .name = "PODxt Pro",
504ccddbe4aSTakashi Iwai .capabilities = LINE6_CAP_CONTROL
505174e1fc0SAndrej Krutak | LINE6_CAP_CONTROL_MIDI
506ccddbe4aSTakashi Iwai | LINE6_CAP_PCM
507ccddbe4aSTakashi Iwai | LINE6_CAP_HWMON,
508ccddbe4aSTakashi Iwai .altsetting = 5,
509ccddbe4aSTakashi Iwai .ep_ctrl_r = 0x84,
510ccddbe4aSTakashi Iwai .ep_ctrl_w = 0x03,
511ccddbe4aSTakashi Iwai .ep_audio_r = 0x82,
512ccddbe4aSTakashi Iwai .ep_audio_w = 0x01,
513ccddbe4aSTakashi Iwai },
514ccddbe4aSTakashi Iwai };
515ccddbe4aSTakashi Iwai
516ccddbe4aSTakashi Iwai /*
517ccddbe4aSTakashi Iwai Probe USB device.
518ccddbe4aSTakashi Iwai */
pod_probe(struct usb_interface * interface,const struct usb_device_id * id)519ccddbe4aSTakashi Iwai static int pod_probe(struct usb_interface *interface,
520ccddbe4aSTakashi Iwai const struct usb_device_id *id)
521ccddbe4aSTakashi Iwai {
52212865cacSChris Rorvick return line6_probe(interface, id, "Line6-POD",
523ccddbe4aSTakashi Iwai &pod_properties_table[id->driver_info],
524aca514b8STakashi Iwai pod_init, sizeof(struct usb_line6_pod));
525ccddbe4aSTakashi Iwai }
526ccddbe4aSTakashi Iwai
527ccddbe4aSTakashi Iwai static struct usb_driver pod_driver = {
528ccddbe4aSTakashi Iwai .name = KBUILD_MODNAME,
529ccddbe4aSTakashi Iwai .probe = pod_probe,
530ccddbe4aSTakashi Iwai .disconnect = line6_disconnect,
531ccddbe4aSTakashi Iwai #ifdef CONFIG_PM
532ccddbe4aSTakashi Iwai .suspend = line6_suspend,
533ccddbe4aSTakashi Iwai .resume = line6_resume,
534ccddbe4aSTakashi Iwai .reset_resume = line6_resume,
535ccddbe4aSTakashi Iwai #endif
536ccddbe4aSTakashi Iwai .id_table = pod_id_table,
537ccddbe4aSTakashi Iwai };
538ccddbe4aSTakashi Iwai
539ccddbe4aSTakashi Iwai module_usb_driver(pod_driver);
540ccddbe4aSTakashi Iwai
541ccddbe4aSTakashi Iwai MODULE_DESCRIPTION("Line 6 POD USB driver");
542ccddbe4aSTakashi Iwai MODULE_LICENSE("GPL");
543