blob: 1d11185780e3407dc5ea4f399619e85c2d97f6e6 [file] [log] [blame]
Stefan Hajnoczi16dc1042011-11-23 08:20:42 +00001/*
2 * Line6 Pod HD
3 *
4 * Copyright (C) 2011 Stefan Hajnoczi <stefanha@gmail.com>
5 *
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
Takashi Iwaiccddbe42015-01-15 08:22:31 +010012#include <linux/usb.h>
13#include <linux/slab.h>
14#include <linux/module.h>
Stefan Hajnoczi16dc1042011-11-23 08:20:42 +000015#include <sound/core.h>
16#include <sound/pcm.h>
17
Stefan Hajnoczi16dc1042011-11-23 08:20:42 +000018#include "driver.h"
19#include "pcm.h"
Takashi Iwaiccddbe42015-01-15 08:22:31 +010020#include "usbdefs.h"
21
22enum {
23 LINE6_PODHD300,
24 LINE6_PODHD400,
25 LINE6_PODHD500_0,
26 LINE6_PODHD500_1,
27};
28
29struct usb_line6_podhd {
30 /**
31 Generic Line6 USB data.
32 */
33 struct usb_line6 line6;
34};
Stefan Hajnoczi16dc1042011-11-23 08:20:42 +000035
36#define PODHD_BYTES_PER_FRAME 6 /* 24bit audio (stereo) */
37
38static struct snd_ratden podhd_ratden = {
39 .num_min = 48000,
40 .num_max = 48000,
41 .num_step = 1,
42 .den = 1,
43};
44
45static struct line6_pcm_properties podhd_pcm_properties = {
46 .snd_line6_playback_hw = {
47 .info = (SNDRV_PCM_INFO_MMAP |
48 SNDRV_PCM_INFO_INTERLEAVED |
49 SNDRV_PCM_INFO_BLOCK_TRANSFER |
50 SNDRV_PCM_INFO_MMAP_VALID |
51 SNDRV_PCM_INFO_PAUSE |
Stefan Hajnoczi16dc1042011-11-23 08:20:42 +000052 SNDRV_PCM_INFO_SYNC_START),
53 .formats = SNDRV_PCM_FMTBIT_S24_3LE,
54 .rates = SNDRV_PCM_RATE_48000,
55 .rate_min = 48000,
56 .rate_max = 48000,
57 .channels_min = 2,
58 .channels_max = 2,
59 .buffer_bytes_max = 60000,
60 .period_bytes_min = 64,
61 .period_bytes_max = 8192,
62 .periods_min = 1,
63 .periods_max = 1024},
64 .snd_line6_capture_hw = {
65 .info = (SNDRV_PCM_INFO_MMAP |
66 SNDRV_PCM_INFO_INTERLEAVED |
67 SNDRV_PCM_INFO_BLOCK_TRANSFER |
68 SNDRV_PCM_INFO_MMAP_VALID |
Stefan Hajnoczi16dc1042011-11-23 08:20:42 +000069 SNDRV_PCM_INFO_SYNC_START),
70 .formats = SNDRV_PCM_FMTBIT_S24_3LE,
71 .rates = SNDRV_PCM_RATE_48000,
72 .rate_min = 48000,
73 .rate_max = 48000,
74 .channels_min = 2,
75 .channels_max = 2,
76 .buffer_bytes_max = 60000,
77 .period_bytes_min = 64,
78 .period_bytes_max = 8192,
79 .periods_min = 1,
80 .periods_max = 1024},
81 .snd_line6_rates = {
82 .nrats = 1,
83 .rats = &podhd_ratden},
84 .bytes_per_frame = PODHD_BYTES_PER_FRAME
85};
86
87/*
Stefan Hajnoczi16dc1042011-11-23 08:20:42 +000088 Try to init POD HD device.
89*/
Takashi Iwai85a93392015-01-19 15:54:00 +010090static int podhd_init(struct usb_interface *interface,
91 struct usb_line6 *line6)
Stefan Hajnoczi16dc1042011-11-23 08:20:42 +000092{
Takashi Iwai85a93392015-01-19 15:54:00 +010093 struct usb_line6_podhd *podhd = (struct usb_line6_podhd *) line6;
Stefan Hajnoczi16dc1042011-11-23 08:20:42 +000094 int err;
Stefan Hajnoczi16dc1042011-11-23 08:20:42 +000095
96 if ((interface == NULL) || (podhd == NULL))
97 return -ENODEV;
98
Stefan Hajnoczi16dc1042011-11-23 08:20:42 +000099 /* initialize MIDI subsystem: */
100 err = line6_init_midi(line6);
101 if (err < 0)
102 return err;
103
104 /* initialize PCM subsystem: */
105 err = line6_init_pcm(line6, &podhd_pcm_properties);
106 if (err < 0)
107 return err;
108
109 /* register USB audio system: */
Takashi Iwai85a93392015-01-19 15:54:00 +0100110 return snd_card_register(line6->card);
Stefan Hajnoczi16dc1042011-11-23 08:20:42 +0000111}
112
Takashi Iwaiccddbe42015-01-15 08:22:31 +0100113#define LINE6_DEVICE(prod) USB_DEVICE(0x0e41, prod)
114#define LINE6_IF_NUM(prod, n) USB_DEVICE_INTERFACE_NUMBER(0x0e41, prod, n)
115
116/* table of devices that work with this driver */
117static const struct usb_device_id podhd_id_table[] = {
118 { LINE6_DEVICE(0x5057), .driver_info = LINE6_PODHD300 },
119 { LINE6_DEVICE(0x5058), .driver_info = LINE6_PODHD400 },
120 { LINE6_IF_NUM(0x414D, 0), .driver_info = LINE6_PODHD500_0 },
121 { LINE6_IF_NUM(0x414D, 1), .driver_info = LINE6_PODHD500_1 },
122 {}
123};
124
125MODULE_DEVICE_TABLE(usb, podhd_id_table);
126
127static const struct line6_properties podhd_properties_table[] = {
128 [LINE6_PODHD300] = {
129 .id = "PODHD300",
130 .name = "POD HD300",
131 .capabilities = LINE6_CAP_CONTROL
132 | LINE6_CAP_PCM
133 | LINE6_CAP_HWMON,
134 .altsetting = 5,
135 .ep_ctrl_r = 0x84,
136 .ep_ctrl_w = 0x03,
137 .ep_audio_r = 0x82,
138 .ep_audio_w = 0x01,
139 },
140 [LINE6_PODHD400] = {
141 .id = "PODHD400",
142 .name = "POD HD400",
143 .capabilities = LINE6_CAP_CONTROL
144 | LINE6_CAP_PCM
145 | LINE6_CAP_HWMON,
146 .altsetting = 5,
147 .ep_ctrl_r = 0x84,
148 .ep_ctrl_w = 0x03,
149 .ep_audio_r = 0x82,
150 .ep_audio_w = 0x01,
151 },
152 [LINE6_PODHD500_0] = {
153 .id = "PODHD500",
154 .name = "POD HD500",
155 .capabilities = LINE6_CAP_CONTROL
156 | LINE6_CAP_PCM
157 | LINE6_CAP_HWMON,
158 .altsetting = 1,
159 .ep_ctrl_r = 0x81,
160 .ep_ctrl_w = 0x01,
161 .ep_audio_r = 0x86,
162 .ep_audio_w = 0x02,
163 },
164 [LINE6_PODHD500_1] = {
165 .id = "PODHD500",
166 .name = "POD HD500",
167 .capabilities = LINE6_CAP_CONTROL
168 | LINE6_CAP_PCM
169 | LINE6_CAP_HWMON,
170 .altsetting = 1,
171 .ep_ctrl_r = 0x81,
172 .ep_ctrl_w = 0x01,
173 .ep_audio_r = 0x86,
174 .ep_audio_w = 0x02,
175 },
176};
177
Stefan Hajnoczi16dc1042011-11-23 08:20:42 +0000178/*
Takashi Iwaiccddbe42015-01-15 08:22:31 +0100179 Probe USB device.
180*/
181static int podhd_probe(struct usb_interface *interface,
182 const struct usb_device_id *id)
183{
184 struct usb_line6_podhd *podhd;
Takashi Iwaiccddbe42015-01-15 08:22:31 +0100185
186 podhd = kzalloc(sizeof(*podhd), GFP_KERNEL);
187 if (!podhd)
188 return -ENODEV;
Takashi Iwai85a93392015-01-19 15:54:00 +0100189 return line6_probe(interface, &podhd->line6,
190 &podhd_properties_table[id->driver_info],
191 podhd_init);
Takashi Iwaiccddbe42015-01-15 08:22:31 +0100192}
193
194static struct usb_driver podhd_driver = {
195 .name = KBUILD_MODNAME,
196 .probe = podhd_probe,
197 .disconnect = line6_disconnect,
198#ifdef CONFIG_PM
199 .suspend = line6_suspend,
200 .resume = line6_resume,
201 .reset_resume = line6_resume,
202#endif
203 .id_table = podhd_id_table,
204};
205
206module_usb_driver(podhd_driver);
207
208MODULE_DESCRIPTION("Line6 PODHD USB driver");
209MODULE_LICENSE("GPL");