1
2
3
4
5
6
7
8
9
10
11
12#include <linux/slab.h>
13#include <linux/wait.h>
14#include <sound/control.h>
15
16#include "audio.h"
17#include "capture.h"
18#include "driver.h"
19#include "playback.h"
20#include "pod.h"
21
22#define POD_SYSEX_CODE 3
23#define POD_BYTES_PER_FRAME 6
24
25
26
27enum {
28 POD_SYSEX_SAVE = 0x24,
29 POD_SYSEX_SYSTEM = 0x56,
30 POD_SYSEX_SYSTEMREQ = 0x57,
31
32 POD_SYSEX_STORE = 0x71,
33 POD_SYSEX_FINISH = 0x72,
34 POD_SYSEX_DUMPMEM = 0x73,
35 POD_SYSEX_DUMP = 0x74,
36 POD_SYSEX_DUMPREQ = 0x75
37
38
39
40};
41
42enum {
43 POD_MONITOR_LEVEL = 0x04,
44 POD_SYSTEM_INVALID = 0x10000
45};
46
47
48
49enum {
50 POD_DUMP_MEMORY = 2
51};
52
53enum {
54 POD_BUSY_READ,
55 POD_BUSY_WRITE,
56 POD_CHANNEL_DIRTY,
57 POD_SAVE_PRESSED,
58 POD_BUSY_MIDISEND
59};
60
61static struct snd_ratden pod_ratden = {
62 .num_min = 78125,
63 .num_max = 78125,
64 .num_step = 1,
65 .den = 2
66};
67
68static struct line6_pcm_properties pod_pcm_properties = {
69 .snd_line6_playback_hw = {
70 .info = (SNDRV_PCM_INFO_MMAP |
71 SNDRV_PCM_INFO_INTERLEAVED |
72 SNDRV_PCM_INFO_BLOCK_TRANSFER |
73 SNDRV_PCM_INFO_MMAP_VALID |
74 SNDRV_PCM_INFO_PAUSE |
75#ifdef CONFIG_PM
76 SNDRV_PCM_INFO_RESUME |
77#endif
78 SNDRV_PCM_INFO_SYNC_START),
79 .formats = SNDRV_PCM_FMTBIT_S24_3LE,
80 .rates = SNDRV_PCM_RATE_KNOT,
81 .rate_min = 39062,
82 .rate_max = 39063,
83 .channels_min = 2,
84 .channels_max = 2,
85 .buffer_bytes_max = 60000,
86 .period_bytes_min = 64,
87 .period_bytes_max = 8192,
88 .periods_min = 1,
89 .periods_max = 1024},
90 .snd_line6_capture_hw = {
91 .info = (SNDRV_PCM_INFO_MMAP |
92 SNDRV_PCM_INFO_INTERLEAVED |
93 SNDRV_PCM_INFO_BLOCK_TRANSFER |
94 SNDRV_PCM_INFO_MMAP_VALID |
95#ifdef CONFIG_PM
96 SNDRV_PCM_INFO_RESUME |
97#endif
98 SNDRV_PCM_INFO_SYNC_START),
99 .formats = SNDRV_PCM_FMTBIT_S24_3LE,
100 .rates = SNDRV_PCM_RATE_KNOT,
101 .rate_min = 39062,
102 .rate_max = 39063,
103 .channels_min = 2,
104 .channels_max = 2,
105 .buffer_bytes_max = 60000,
106 .period_bytes_min = 64,
107 .period_bytes_max = 8192,
108 .periods_min = 1,
109 .periods_max = 1024},
110 .snd_line6_rates = {
111 .nrats = 1,
112 .rats = &pod_ratden},
113 .bytes_per_frame = POD_BYTES_PER_FRAME
114};
115
116static const char pod_version_header[] = {
117 0xf2, 0x7e, 0x7f, 0x06, 0x02
118};
119
120
121static void pod_startup2(unsigned long data);
122static void pod_startup3(struct usb_line6_pod *pod);
123
124static char *pod_alloc_sysex_buffer(struct usb_line6_pod *pod, int code,
125 int size)
126{
127 return line6_alloc_sysex_buffer(&pod->line6, POD_SYSEX_CODE, code,
128 size);
129}
130
131
132
133
134void line6_pod_process_message(struct usb_line6_pod *pod)
135{
136 const unsigned char *buf = pod->line6.buffer_message;
137
138 if (memcmp(buf, pod_version_header, sizeof(pod_version_header)) == 0) {
139 pod->firmware_version = buf[13] * 100 + buf[14] * 10 + buf[15];
140 pod->device_id = ((int)buf[8] << 16) | ((int)buf[9] << 8) |
141 (int) buf[10];
142 pod_startup3(pod);
143 return;
144 }
145
146
147 if (buf[0] != (LINE6_SYSEX_BEGIN | LINE6_CHANNEL_DEVICE) &&
148 buf[0] != (LINE6_SYSEX_BEGIN | LINE6_CHANNEL_UNKNOWN)) {
149 return;
150 }
151 if (memcmp(buf + 1, line6_midi_id, sizeof(line6_midi_id)) != 0)
152 return;
153
154 if (buf[5] == POD_SYSEX_SYSTEM && buf[6] == POD_MONITOR_LEVEL) {
155 short value = ((int)buf[7] << 12) | ((int)buf[8] << 8) |
156 ((int)buf[9] << 4) | (int)buf[10];
157 pod->monitor_level = value;
158 }
159}
160
161
162
163
164void line6_pod_transmit_parameter(struct usb_line6_pod *pod, int param,
165 u8 value)
166{
167 line6_transmit_parameter(&pod->line6, param, value);
168}
169
170
171
172
173static int pod_set_system_param_int(struct usb_line6_pod *pod, int value,
174 int code)
175{
176 char *sysex;
177 static const int size = 5;
178
179 sysex = pod_alloc_sysex_buffer(pod, POD_SYSEX_SYSTEM, size);
180 if (!sysex)
181 return -ENOMEM;
182 sysex[SYSEX_DATA_OFS] = code;
183 sysex[SYSEX_DATA_OFS + 1] = (value >> 12) & 0x0f;
184 sysex[SYSEX_DATA_OFS + 2] = (value >> 8) & 0x0f;
185 sysex[SYSEX_DATA_OFS + 3] = (value >> 4) & 0x0f;
186 sysex[SYSEX_DATA_OFS + 4] = (value) & 0x0f;
187 line6_send_sysex_message(&pod->line6, sysex, size);
188 kfree(sysex);
189 return 0;
190}
191
192
193
194
195static ssize_t serial_number_show(struct device *dev,
196 struct device_attribute *attr, char *buf)
197{
198 struct usb_interface *interface = to_usb_interface(dev);
199 struct usb_line6_pod *pod = usb_get_intfdata(interface);
200
201 return sprintf(buf, "%d\n", pod->serial_number);
202}
203
204
205
206
207static ssize_t firmware_version_show(struct device *dev,
208 struct device_attribute *attr, char *buf)
209{
210 struct usb_interface *interface = to_usb_interface(dev);
211 struct usb_line6_pod *pod = usb_get_intfdata(interface);
212
213 return sprintf(buf, "%d.%02d\n", pod->firmware_version / 100,
214 pod->firmware_version % 100);
215}
216
217
218
219
220static ssize_t device_id_show(struct device *dev,
221 struct device_attribute *attr, char *buf)
222{
223 struct usb_interface *interface = to_usb_interface(dev);
224 struct usb_line6_pod *pod = usb_get_intfdata(interface);
225
226 return sprintf(buf, "%d\n", pod->device_id);
227}
228
229
230
231
232
233
234
235
236static void pod_startup1(struct usb_line6_pod *pod)
237{
238 CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_INIT);
239
240
241 line6_start_timer(&pod->startup_timer, POD_STARTUP_DELAY, pod_startup2,
242 (unsigned long)pod);
243}
244
245static void pod_startup2(unsigned long data)
246{
247 struct usb_line6_pod *pod = (struct usb_line6_pod *)data;
248 struct usb_line6 *line6 = &pod->line6;
249
250 CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_VERSIONREQ);
251
252
253 line6_version_request_async(line6);
254}
255
256static void pod_startup3(struct usb_line6_pod *pod)
257{
258 CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_WORKQUEUE);
259
260
261 schedule_work(&pod->startup_work);
262}
263
264static void pod_startup4(struct work_struct *work)
265{
266 struct usb_line6_pod *pod =
267 container_of(work, struct usb_line6_pod, startup_work);
268 struct usb_line6 *line6 = &pod->line6;
269
270 CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_SETUP);
271
272
273 line6_read_serial_number(&pod->line6, &pod->serial_number);
274
275
276 line6_register_audio(line6);
277}
278
279
280static DEVICE_ATTR_RO(device_id);
281static DEVICE_ATTR_RO(firmware_version);
282static DEVICE_ATTR_RO(serial_number);
283
284
285static int snd_pod_control_monitor_info(struct snd_kcontrol *kcontrol,
286 struct snd_ctl_elem_info *uinfo)
287{
288 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
289 uinfo->count = 1;
290 uinfo->value.integer.min = 0;
291 uinfo->value.integer.max = 65535;
292 return 0;
293}
294
295
296static int snd_pod_control_monitor_get(struct snd_kcontrol *kcontrol,
297 struct snd_ctl_elem_value *ucontrol)
298{
299 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
300 struct usb_line6_pod *pod = (struct usb_line6_pod *)line6pcm->line6;
301
302 ucontrol->value.integer.value[0] = pod->monitor_level;
303 return 0;
304}
305
306
307static int snd_pod_control_monitor_put(struct snd_kcontrol *kcontrol,
308 struct snd_ctl_elem_value *ucontrol)
309{
310 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
311 struct usb_line6_pod *pod = (struct usb_line6_pod *)line6pcm->line6;
312
313 if (ucontrol->value.integer.value[0] == pod->monitor_level)
314 return 0;
315
316 pod->monitor_level = ucontrol->value.integer.value[0];
317 pod_set_system_param_int(pod, ucontrol->value.integer.value[0],
318 POD_MONITOR_LEVEL);
319 return 1;
320}
321
322
323static struct snd_kcontrol_new pod_control_monitor = {
324 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
325 .name = "Monitor Playback Volume",
326 .index = 0,
327 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
328 .info = snd_pod_control_monitor_info,
329 .get = snd_pod_control_monitor_get,
330 .put = snd_pod_control_monitor_put
331};
332
333
334
335
336static void pod_destruct(struct usb_interface *interface)
337{
338 struct usb_line6_pod *pod = usb_get_intfdata(interface);
339
340 if (pod == NULL)
341 return;
342 line6_cleanup_audio(&pod->line6);
343
344 del_timer(&pod->startup_timer);
345 cancel_work_sync(&pod->startup_work);
346}
347
348
349
350
351static int pod_create_files2(struct device *dev)
352{
353 int err;
354
355 CHECK_RETURN(device_create_file(dev, &dev_attr_device_id));
356 CHECK_RETURN(device_create_file(dev, &dev_attr_firmware_version));
357 CHECK_RETURN(device_create_file(dev, &dev_attr_serial_number));
358 return 0;
359}
360
361
362
363
364static int pod_try_init(struct usb_interface *interface,
365 struct usb_line6_pod *pod)
366{
367 int err;
368 struct usb_line6 *line6 = &pod->line6;
369
370 init_timer(&pod->startup_timer);
371 INIT_WORK(&pod->startup_work, pod_startup4);
372
373 if ((interface == NULL) || (pod == NULL))
374 return -ENODEV;
375
376
377 err = pod_create_files2(&interface->dev);
378 if (err < 0)
379 return err;
380
381
382 err = line6_init_audio(line6);
383 if (err < 0)
384 return err;
385
386
387 err = line6_init_midi(line6);
388 if (err < 0)
389 return err;
390
391
392 err = line6_init_pcm(line6, &pod_pcm_properties);
393 if (err < 0)
394 return err;
395
396
397 err = snd_ctl_add(line6->card,
398 snd_ctl_new1(&pod_control_monitor, line6->line6pcm));
399 if (err < 0)
400 return err;
401
402
403
404
405
406
407
408 if (pod->line6.properties->capabilities & LINE6_BIT_CONTROL) {
409 pod->monitor_level = POD_SYSTEM_INVALID;
410
411
412 pod_startup1(pod);
413 }
414
415 return 0;
416}
417
418
419
420
421int line6_pod_init(struct usb_interface *interface, struct usb_line6_pod *pod)
422{
423 int err = pod_try_init(interface, pod);
424
425 if (err < 0)
426 pod_destruct(interface);
427
428 return err;
429}
430
431
432
433
434void line6_pod_disconnect(struct usb_interface *interface)
435{
436 struct usb_line6_pod *pod;
437
438 if (interface == NULL)
439 return;
440 pod = usb_get_intfdata(interface);
441
442 if (pod != NULL) {
443 struct snd_line6_pcm *line6pcm = pod->line6.line6pcm;
444 struct device *dev = &interface->dev;
445
446 if (line6pcm != NULL)
447 line6_pcm_disconnect(line6pcm);
448
449 if (dev != NULL) {
450
451 device_remove_file(dev, &dev_attr_device_id);
452 device_remove_file(dev, &dev_attr_firmware_version);
453 device_remove_file(dev, &dev_attr_serial_number);
454 }
455 }
456
457 pod_destruct(interface);
458}
459