blob: 21d7edcfa272c269640bc7ade37768dc99bf9c8f [file] [log] [blame]
Stefan Hajnoczi16dc1042011-11-23 08:20:42 +00001/*
Chris Rorvickc6fffce2015-01-20 02:20:49 -06002 * Line 6 Pod HD
Stefan Hajnoczi16dc1042011-11-23 08:20:42 +00003 *
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 /**
Chris Rorvickc6fffce2015-01-20 02:20:49 -060031 Generic Line 6 USB data.
Takashi Iwaiccddbe42015-01-15 08:22:31 +010032 */
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 Iwaif66fd992015-01-25 18:22:58 +010090static int podhd_init(struct usb_line6 *line6,
91 const struct usb_device_id *id)
Stefan Hajnoczi16dc1042011-11-23 08:20:42 +000092{
93 int err;
Stefan Hajnoczi16dc1042011-11-23 08:20:42 +000094
Stefan Hajnoczi16dc1042011-11-23 08:20:42 +000095 /* initialize MIDI subsystem: */
96 err = line6_init_midi(line6);
97 if (err < 0)
98 return err;
99
100 /* initialize PCM subsystem: */
101 err = line6_init_pcm(line6, &podhd_pcm_properties);
102 if (err < 0)
103 return err;
104
105 /* register USB audio system: */
Takashi Iwai85a93392015-01-19 15:54:00 +0100106 return snd_card_register(line6->card);
Stefan Hajnoczi16dc1042011-11-23 08:20:42 +0000107}
108
Takashi Iwaiccddbe42015-01-15 08:22:31 +0100109#define LINE6_DEVICE(prod) USB_DEVICE(0x0e41, prod)
110#define LINE6_IF_NUM(prod, n) USB_DEVICE_INTERFACE_NUMBER(0x0e41, prod, n)
111
112/* table of devices that work with this driver */
113static const struct usb_device_id podhd_id_table[] = {
114 { LINE6_DEVICE(0x5057), .driver_info = LINE6_PODHD300 },
115 { LINE6_DEVICE(0x5058), .driver_info = LINE6_PODHD400 },
116 { LINE6_IF_NUM(0x414D, 0), .driver_info = LINE6_PODHD500_0 },
117 { LINE6_IF_NUM(0x414D, 1), .driver_info = LINE6_PODHD500_1 },
118 {}
119};
120
121MODULE_DEVICE_TABLE(usb, podhd_id_table);
122
123static const struct line6_properties podhd_properties_table[] = {
124 [LINE6_PODHD300] = {
125 .id = "PODHD300",
126 .name = "POD HD300",
127 .capabilities = LINE6_CAP_CONTROL
128 | LINE6_CAP_PCM
129 | LINE6_CAP_HWMON,
130 .altsetting = 5,
131 .ep_ctrl_r = 0x84,
132 .ep_ctrl_w = 0x03,
133 .ep_audio_r = 0x82,
134 .ep_audio_w = 0x01,
135 },
136 [LINE6_PODHD400] = {
137 .id = "PODHD400",
138 .name = "POD HD400",
139 .capabilities = LINE6_CAP_CONTROL
140 | LINE6_CAP_PCM
141 | LINE6_CAP_HWMON,
142 .altsetting = 5,
143 .ep_ctrl_r = 0x84,
144 .ep_ctrl_w = 0x03,
145 .ep_audio_r = 0x82,
146 .ep_audio_w = 0x01,
147 },
148 [LINE6_PODHD500_0] = {
149 .id = "PODHD500",
150 .name = "POD HD500",
151 .capabilities = LINE6_CAP_CONTROL
152 | LINE6_CAP_PCM
153 | LINE6_CAP_HWMON,
154 .altsetting = 1,
155 .ep_ctrl_r = 0x81,
156 .ep_ctrl_w = 0x01,
157 .ep_audio_r = 0x86,
158 .ep_audio_w = 0x02,
159 },
160 [LINE6_PODHD500_1] = {
161 .id = "PODHD500",
162 .name = "POD HD500",
163 .capabilities = LINE6_CAP_CONTROL
164 | LINE6_CAP_PCM
165 | LINE6_CAP_HWMON,
166 .altsetting = 1,
167 .ep_ctrl_r = 0x81,
168 .ep_ctrl_w = 0x01,
169 .ep_audio_r = 0x86,
170 .ep_audio_w = 0x02,
171 },
172};
173
Stefan Hajnoczi16dc1042011-11-23 08:20:42 +0000174/*
Takashi Iwaiccddbe42015-01-15 08:22:31 +0100175 Probe USB device.
176*/
177static int podhd_probe(struct usb_interface *interface,
178 const struct usb_device_id *id)
179{
180 struct usb_line6_podhd *podhd;
Takashi Iwaiccddbe42015-01-15 08:22:31 +0100181
182 podhd = kzalloc(sizeof(*podhd), GFP_KERNEL);
183 if (!podhd)
184 return -ENODEV;
Takashi Iwaif66fd992015-01-25 18:22:58 +0100185 return line6_probe(interface, id, &podhd->line6,
Takashi Iwai85a93392015-01-19 15:54:00 +0100186 &podhd_properties_table[id->driver_info],
187 podhd_init);
Takashi Iwaiccddbe42015-01-15 08:22:31 +0100188}
189
190static struct usb_driver podhd_driver = {
191 .name = KBUILD_MODNAME,
192 .probe = podhd_probe,
193 .disconnect = line6_disconnect,
194#ifdef CONFIG_PM
195 .suspend = line6_suspend,
196 .resume = line6_resume,
197 .reset_resume = line6_resume,
198#endif
199 .id_table = podhd_id_table,
200};
201
202module_usb_driver(podhd_driver);
203
Chris Rorvickc6fffce2015-01-20 02:20:49 -0600204MODULE_DESCRIPTION("Line 6 PODHD USB driver");
Takashi Iwaiccddbe42015-01-15 08:22:31 +0100205MODULE_LICENSE("GPL");