Merge 3.9-rc5 into staging-next
[deliverable/linux.git] / drivers / staging / line6 / pod.c
CommitLineData
705ececd 1/*
e1a164d7 2 * Line6 Linux USB driver - 0.9.1beta
705ececd 3 *
1027f476 4 * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
705ececd
MG
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
5a0e3ad6 12#include <linux/slab.h>
1027f476
MG
13#include <linux/wait.h>
14#include <sound/control.h>
5a0e3ad6 15
705ececd
MG
16#include "audio.h"
17#include "capture.h"
1027f476 18#include "driver.h"
705ececd
MG
19#include "playback.h"
20#include "pod.h"
21
705ececd 22#define POD_SYSEX_CODE 3
e1a164d7 23#define POD_BYTES_PER_FRAME 6 /* 24bit audio (stereo) */
705ececd 24
e1a164d7 25/* *INDENT-OFF* */
705ececd
MG
26
27enum {
705ececd
MG
28 POD_SYSEX_SAVE = 0x24,
29 POD_SYSEX_SYSTEM = 0x56,
30 POD_SYSEX_SYSTEMREQ = 0x57,
31 /* POD_SYSEX_UPDATE = 0x6c, */ /* software update! */
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
0a1eb4e8
SH
37
38 /* dumps entire internal memory of PODxt Pro */
39 /* POD_SYSEX_DUMPMEM2 = 0x76 */
705ececd
MG
40};
41
42enum {
7936095f
SH
43 POD_MONITOR_LEVEL = 0x04,
44 POD_SYSTEM_INVALID = 0x10000
705ececd
MG
45};
46
e1a164d7
MG
47/* *INDENT-ON* */
48
705ececd
MG
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
705ececd
MG
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 = {
1027f476 69 .snd_line6_playback_hw = {
e1a164d7
MG
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 |
1027f476 75#ifdef CONFIG_PM
e1a164d7 76 SNDRV_PCM_INFO_RESUME |
1027f476 77#endif
e1a164d7
MG
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},
1027f476 90 .snd_line6_capture_hw = {
e1a164d7
MG
91 .info = (SNDRV_PCM_INFO_MMAP |
92 SNDRV_PCM_INFO_INTERLEAVED |
93 SNDRV_PCM_INFO_BLOCK_TRANSFER |
94 SNDRV_PCM_INFO_MMAP_VALID |
1027f476 95#ifdef CONFIG_PM
e1a164d7 96 SNDRV_PCM_INFO_RESUME |
1027f476 97#endif
e1a164d7
MG
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},
705ececd 110 .snd_line6_rates = {
e1a164d7
MG
111 .nrats = 1,
112 .rats = &pod_ratden},
705ececd
MG
113 .bytes_per_frame = POD_BYTES_PER_FRAME
114};
115
e1a164d7 116static const char pod_version_header[] = {
1027f476
MG
117 0xf2, 0x7e, 0x7f, 0x06, 0x02
118};
119
1027f476
MG
120/* forward declarations: */
121static void pod_startup2(unsigned long data);
122static void pod_startup3(struct usb_line6_pod *pod);
705ececd 123
e1a164d7
MG
124static char *pod_alloc_sysex_buffer(struct usb_line6_pod *pod, int code,
125 int size)
705ececd 126{
e1a164d7
MG
127 return line6_alloc_sysex_buffer(&pod->line6, POD_SYSEX_CODE, code,
128 size);
705ececd
MG
129}
130
705ececd
MG
131/*
132 Process a completely received message.
133*/
1027f476 134void line6_pod_process_message(struct usb_line6_pod *pod)
705ececd
MG
135{
136 const unsigned char *buf = pod->line6.buffer_message;
137
4e6a8ffb
SH
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;
705ececd
MG
144 }
145
4e6a8ffb
SH
146 /* Only look for sysex messages from this device */
147 if (buf[0] != (LINE6_SYSEX_BEGIN | LINE6_CHANNEL_DEVICE) &&
148 buf[0] != (LINE6_SYSEX_BEGIN | LINE6_CHANNEL_UNKNOWN)) {
149 return;
150 }
c19e9461 151 if (memcmp(buf + 1, line6_midi_id, sizeof(line6_midi_id)) != 0)
4e6a8ffb 152 return;
4e6a8ffb
SH
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;
705ececd
MG
158 }
159}
160
705ececd
MG
161/*
162 Transmit PODxt Pro control parameter.
163*/
e1a164d7 164void line6_pod_transmit_parameter(struct usb_line6_pod *pod, int param,
5b9bd2ad 165 u8 value)
705ececd 166{
79038f61 167 line6_transmit_parameter(&pod->line6, param, value);
705ececd
MG
168}
169
705ececd 170/*
1027f476 171 Send system parameter (from integer).
705ececd 172*/
e1a164d7
MG
173static int pod_set_system_param_int(struct usb_line6_pod *pod, int value,
174 int code)
705ececd
MG
175{
176 char *sysex;
177 static const int size = 5;
705ececd 178
705ececd 179 sysex = pod_alloc_sysex_buffer(pod, POD_SYSEX_SYSTEM, size);
0fdef36a 180 if (!sysex)
1027f476 181 return -ENOMEM;
705ececd
MG
182 sysex[SYSEX_DATA_OFS] = code;
183 sysex[SYSEX_DATA_OFS + 1] = (value >> 12) & 0x0f;
e1a164d7
MG
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;
705ececd
MG
187 line6_send_sysex_message(&pod->line6, sysex, size);
188 kfree(sysex);
1027f476
MG
189 return 0;
190}
191
705ececd
MG
192/*
193 "read" request on "serial_number" special file.
194*/
77491e52
GKH
195static ssize_t pod_get_serial_number(struct device *dev,
196 struct device_attribute *attr, char *buf)
705ececd
MG
197{
198 struct usb_interface *interface = to_usb_interface(dev);
199 struct usb_line6_pod *pod = usb_get_intfdata(interface);
200 return sprintf(buf, "%d\n", pod->serial_number);
201}
202
203/*
204 "read" request on "firmware_version" special file.
205*/
77491e52
GKH
206static ssize_t pod_get_firmware_version(struct device *dev,
207 struct device_attribute *attr,
208 char *buf)
705ececd
MG
209{
210 struct usb_interface *interface = to_usb_interface(dev);
211 struct usb_line6_pod *pod = usb_get_intfdata(interface);
0fdef36a
GKH
212 return sprintf(buf, "%d.%02d\n", pod->firmware_version / 100,
213 pod->firmware_version % 100);
705ececd
MG
214}
215
216/*
217 "read" request on "device_id" special file.
218*/
77491e52
GKH
219static ssize_t pod_get_device_id(struct device *dev,
220 struct device_attribute *attr, char *buf)
705ececd
MG
221{
222 struct usb_interface *interface = to_usb_interface(dev);
223 struct usb_line6_pod *pod = usb_get_intfdata(interface);
224 return sprintf(buf, "%d\n", pod->device_id);
225}
226
1027f476
MG
227/*
228 POD startup procedure.
229 This is a sequence of functions with special requirements (e.g., must
230 not run immediately after initialization, must not run in interrupt
231 context). After the last one has finished, the device is ready to use.
232*/
233
234static void pod_startup1(struct usb_line6_pod *pod)
235{
e1a164d7 236 CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_INIT);
1027f476
MG
237
238 /* delay startup procedure: */
e1a164d7
MG
239 line6_start_timer(&pod->startup_timer, POD_STARTUP_DELAY, pod_startup2,
240 (unsigned long)pod);
1027f476
MG
241}
242
243static void pod_startup2(unsigned long data)
244{
245 struct usb_line6_pod *pod = (struct usb_line6_pod *)data;
1027f476 246 struct usb_line6 *line6 = &pod->line6;
e1a164d7 247 CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_VERSIONREQ);
1027f476
MG
248
249 /* request firmware version: */
250 line6_version_request_async(line6);
705ececd
MG
251}
252
09fda10a 253static void pod_startup3(struct usb_line6_pod *pod)
1027f476 254{
e1a164d7 255 CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_WORKQUEUE);
1027f476
MG
256
257 /* schedule work for global work queue: */
258 schedule_work(&pod->startup_work);
259}
260
09fda10a 261static void pod_startup4(struct work_struct *work)
1027f476 262{
e1a164d7
MG
263 struct usb_line6_pod *pod =
264 container_of(work, struct usb_line6_pod, startup_work);
1027f476
MG
265 struct usb_line6 *line6 = &pod->line6;
266
e1a164d7 267 CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_SETUP);
1027f476
MG
268
269 /* serial number: */
270 line6_read_serial_number(&pod->line6, &pod->serial_number);
271
272 /* ALSA audio interface: */
273 line6_register_audio(line6);
1027f476
MG
274}
275
705ececd 276/* POD special files: */
705ececd 277static DEVICE_ATTR(device_id, S_IRUGO, pod_get_device_id, line6_nop_write);
e1a164d7
MG
278static DEVICE_ATTR(firmware_version, S_IRUGO, pod_get_firmware_version,
279 line6_nop_write);
e1a164d7
MG
280static DEVICE_ATTR(serial_number, S_IRUGO, pod_get_serial_number,
281 line6_nop_write);
705ececd 282
1027f476
MG
283/* control info callback */
284static int snd_pod_control_monitor_info(struct snd_kcontrol *kcontrol,
285 struct snd_ctl_elem_info *uinfo)
286{
287 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
288 uinfo->count = 1;
289 uinfo->value.integer.min = 0;
290 uinfo->value.integer.max = 65535;
291 return 0;
292}
293
294/* control get callback */
295static int snd_pod_control_monitor_get(struct snd_kcontrol *kcontrol,
296 struct snd_ctl_elem_value *ucontrol)
297{
298 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
299 struct usb_line6_pod *pod = (struct usb_line6_pod *)line6pcm->line6;
2c35dc21 300 ucontrol->value.integer.value[0] = pod->monitor_level;
1027f476
MG
301 return 0;
302}
303
304/* control put callback */
305static int snd_pod_control_monitor_put(struct snd_kcontrol *kcontrol,
306 struct snd_ctl_elem_value *ucontrol)
307{
308 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
309 struct usb_line6_pod *pod = (struct usb_line6_pod *)line6pcm->line6;
310
2c35dc21 311 if (ucontrol->value.integer.value[0] == pod->monitor_level)
1027f476
MG
312 return 0;
313
2c35dc21 314 pod->monitor_level = ucontrol->value.integer.value[0];
e1a164d7 315 pod_set_system_param_int(pod, ucontrol->value.integer.value[0],
7936095f 316 POD_MONITOR_LEVEL);
1027f476
MG
317 return 1;
318}
319
320/* control definition */
321static struct snd_kcontrol_new pod_control_monitor = {
322 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
323 .name = "Monitor Playback Volume",
324 .index = 0,
325 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
326 .info = snd_pod_control_monitor_info,
327 .get = snd_pod_control_monitor_get,
328 .put = snd_pod_control_monitor_put
329};
330
705ececd
MG
331/*
332 POD destructor.
333*/
334static void pod_destruct(struct usb_interface *interface)
335{
336 struct usb_line6_pod *pod = usb_get_intfdata(interface);
705ececd 337
0fdef36a
GKH
338 if (pod == NULL)
339 return;
188e6645 340 line6_cleanup_audio(&pod->line6);
705ececd 341
e1a164d7
MG
342 del_timer(&pod->startup_timer);
343 cancel_work_sync(&pod->startup_work);
705ececd
MG
344}
345
346/*
347 Create sysfs entries.
348*/
b702ed25 349static int pod_create_files2(struct device *dev)
705ececd
MG
350{
351 int err;
352
705ececd 353 CHECK_RETURN(device_create_file(dev, &dev_attr_device_id));
705ececd 354 CHECK_RETURN(device_create_file(dev, &dev_attr_firmware_version));
705ececd 355 CHECK_RETURN(device_create_file(dev, &dev_attr_serial_number));
705ececd
MG
356 return 0;
357}
358
359/*
1027f476 360 Try to init POD device.
705ececd 361*/
e1a164d7
MG
362static int pod_try_init(struct usb_interface *interface,
363 struct usb_line6_pod *pod)
705ececd
MG
364{
365 int err;
366 struct usb_line6 *line6 = &pod->line6;
367
e1a164d7 368 init_timer(&pod->startup_timer);
09fda10a 369 INIT_WORK(&pod->startup_work, pod_startup4);
e1a164d7 370
0fdef36a
GKH
371 if ((interface == NULL) || (pod == NULL))
372 return -ENODEV;
705ececd 373
705ececd 374 /* create sysfs entries: */
0fdef36a 375 err = pod_create_files2(&interface->dev);
027360c5 376 if (err < 0)
705ececd 377 return err;
705ececd
MG
378
379 /* initialize audio system: */
0fdef36a 380 err = line6_init_audio(line6);
027360c5 381 if (err < 0)
705ececd 382 return err;
705ececd
MG
383
384 /* initialize MIDI subsystem: */
0fdef36a 385 err = line6_init_midi(line6);
027360c5 386 if (err < 0)
705ececd 387 return err;
705ececd
MG
388
389 /* initialize PCM subsystem: */
0fdef36a 390 err = line6_init_pcm(line6, &pod_pcm_properties);
027360c5 391 if (err < 0)
705ececd 392 return err;
705ececd 393
1027f476 394 /* register monitor control: */
027360c5
GKH
395 err = snd_ctl_add(line6->card,
396 snd_ctl_new1(&pod_control_monitor, line6->line6pcm));
397 if (err < 0)
705ececd 398 return err;
705ececd 399
1027f476 400 /*
e1a164d7
MG
401 When the sound card is registered at this point, the PODxt Live
402 displays "Invalid Code Error 07", so we do it later in the event
403 handler.
404 */
1027f476 405
0fdef36a 406 if (pod->line6.properties->capabilities & LINE6_BIT_CONTROL) {
7936095f 407 pod->monitor_level = POD_SYSTEM_INVALID;
1027f476
MG
408
409 /* initiate startup procedure: */
410 pod_startup1(pod);
705ececd
MG
411 }
412
413 return 0;
414}
415
1027f476
MG
416/*
417 Init POD device (and clean up in case of failure).
418*/
419int line6_pod_init(struct usb_interface *interface, struct usb_line6_pod *pod)
420{
421 int err = pod_try_init(interface, pod);
422
027360c5 423 if (err < 0)
1027f476 424 pod_destruct(interface);
1027f476
MG
425
426 return err;
427}
428
705ececd
MG
429/*
430 POD device disconnected.
431*/
1027f476 432void line6_pod_disconnect(struct usb_interface *interface)
705ececd
MG
433{
434 struct usb_line6_pod *pod;
435
0fdef36a
GKH
436 if (interface == NULL)
437 return;
705ececd
MG
438 pod = usb_get_intfdata(interface);
439
0fdef36a 440 if (pod != NULL) {
705ececd
MG
441 struct snd_line6_pcm *line6pcm = pod->line6.line6pcm;
442 struct device *dev = &interface->dev;
443
027360c5 444 if (line6pcm != NULL)
1027f476 445 line6_pcm_disconnect(line6pcm);
705ececd 446
0fdef36a 447 if (dev != NULL) {
705ececd 448 /* remove sysfs entries: */
705ececd 449 device_remove_file(dev, &dev_attr_device_id);
705ececd 450 device_remove_file(dev, &dev_attr_firmware_version);
705ececd 451 device_remove_file(dev, &dev_attr_serial_number);
705ececd
MG
452 }
453 }
454
455 pod_destruct(interface);
456}
This page took 0.45936 seconds and 5 git commands to generate.