Staging: unisys: Remove RETINT macro
[linux/fpc-iii.git] / drivers / staging / line6 / pod.c
blobf4e95a614e3fd807e38512cde9e881a7b6ae92fd
1 /*
2 * Line6 Linux USB driver - 0.9.1beta
4 * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
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.
12 #include <linux/slab.h>
13 #include <linux/wait.h>
14 #include <sound/control.h>
16 #include "audio.h"
17 #include "capture.h"
18 #include "driver.h"
19 #include "playback.h"
20 #include "pod.h"
22 #define POD_SYSEX_CODE 3
23 #define POD_BYTES_PER_FRAME 6 /* 24bit audio (stereo) */
25 /* *INDENT-OFF* */
27 enum {
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
38 /* dumps entire internal memory of PODxt Pro */
39 /* POD_SYSEX_DUMPMEM2 = 0x76 */
42 enum {
43 POD_MONITOR_LEVEL = 0x04,
44 POD_SYSTEM_INVALID = 0x10000
47 /* *INDENT-ON* */
49 enum {
50 POD_DUMP_MEMORY = 2
53 enum {
54 POD_BUSY_READ,
55 POD_BUSY_WRITE,
56 POD_CHANNEL_DIRTY,
57 POD_SAVE_PRESSED,
58 POD_BUSY_MIDISEND
61 static struct snd_ratden pod_ratden = {
62 .num_min = 78125,
63 .num_max = 78125,
64 .num_step = 1,
65 .den = 2
68 static 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
116 static const char pod_version_header[] = {
117 0xf2, 0x7e, 0x7f, 0x06, 0x02
120 /* forward declarations: */
121 static void pod_startup2(unsigned long data);
122 static void pod_startup3(struct usb_line6_pod *pod);
124 static char *pod_alloc_sysex_buffer(struct usb_line6_pod *pod, int code,
125 int size)
127 return line6_alloc_sysex_buffer(&pod->line6, POD_SYSEX_CODE, code,
128 size);
132 Process a completely received message.
134 void line6_pod_process_message(struct usb_line6_pod *pod)
136 const unsigned char *buf = pod->line6.buffer_message;
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;
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;
151 if (memcmp(buf + 1, line6_midi_id, sizeof(line6_midi_id)) != 0)
152 return;
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;
162 Transmit PODxt Pro control parameter.
164 void line6_pod_transmit_parameter(struct usb_line6_pod *pod, int param,
165 u8 value)
167 line6_transmit_parameter(&pod->line6, param, value);
171 Send system parameter (from integer).
173 static int pod_set_system_param_int(struct usb_line6_pod *pod, int value,
174 int code)
176 char *sysex;
177 static const int size = 5;
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;
193 "read" request on "serial_number" special file.
195 static ssize_t serial_number_show(struct device *dev,
196 struct device_attribute *attr, char *buf)
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);
204 "read" request on "firmware_version" special file.
206 static ssize_t firmware_version_show(struct device *dev,
207 struct device_attribute *attr, char *buf)
209 struct usb_interface *interface = to_usb_interface(dev);
210 struct usb_line6_pod *pod = usb_get_intfdata(interface);
211 return sprintf(buf, "%d.%02d\n", pod->firmware_version / 100,
212 pod->firmware_version % 100);
216 "read" request on "device_id" special file.
218 static ssize_t device_id_show(struct device *dev,
219 struct device_attribute *attr, char *buf)
221 struct usb_interface *interface = to_usb_interface(dev);
222 struct usb_line6_pod *pod = usb_get_intfdata(interface);
223 return sprintf(buf, "%d\n", pod->device_id);
227 POD startup procedure.
228 This is a sequence of functions with special requirements (e.g., must
229 not run immediately after initialization, must not run in interrupt
230 context). After the last one has finished, the device is ready to use.
233 static void pod_startup1(struct usb_line6_pod *pod)
235 CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_INIT);
237 /* delay startup procedure: */
238 line6_start_timer(&pod->startup_timer, POD_STARTUP_DELAY, pod_startup2,
239 (unsigned long)pod);
242 static void pod_startup2(unsigned long data)
244 struct usb_line6_pod *pod = (struct usb_line6_pod *)data;
245 struct usb_line6 *line6 = &pod->line6;
246 CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_VERSIONREQ);
248 /* request firmware version: */
249 line6_version_request_async(line6);
252 static void pod_startup3(struct usb_line6_pod *pod)
254 CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_WORKQUEUE);
256 /* schedule work for global work queue: */
257 schedule_work(&pod->startup_work);
260 static void pod_startup4(struct work_struct *work)
262 struct usb_line6_pod *pod =
263 container_of(work, struct usb_line6_pod, startup_work);
264 struct usb_line6 *line6 = &pod->line6;
266 CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_SETUP);
268 /* serial number: */
269 line6_read_serial_number(&pod->line6, &pod->serial_number);
271 /* ALSA audio interface: */
272 line6_register_audio(line6);
275 /* POD special files: */
276 static DEVICE_ATTR_RO(device_id);
277 static DEVICE_ATTR_RO(firmware_version);
278 static DEVICE_ATTR_RO(serial_number);
280 /* control info callback */
281 static int snd_pod_control_monitor_info(struct snd_kcontrol *kcontrol,
282 struct snd_ctl_elem_info *uinfo)
284 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
285 uinfo->count = 1;
286 uinfo->value.integer.min = 0;
287 uinfo->value.integer.max = 65535;
288 return 0;
291 /* control get callback */
292 static int snd_pod_control_monitor_get(struct snd_kcontrol *kcontrol,
293 struct snd_ctl_elem_value *ucontrol)
295 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
296 struct usb_line6_pod *pod = (struct usb_line6_pod *)line6pcm->line6;
297 ucontrol->value.integer.value[0] = pod->monitor_level;
298 return 0;
301 /* control put callback */
302 static int snd_pod_control_monitor_put(struct snd_kcontrol *kcontrol,
303 struct snd_ctl_elem_value *ucontrol)
305 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
306 struct usb_line6_pod *pod = (struct usb_line6_pod *)line6pcm->line6;
308 if (ucontrol->value.integer.value[0] == pod->monitor_level)
309 return 0;
311 pod->monitor_level = ucontrol->value.integer.value[0];
312 pod_set_system_param_int(pod, ucontrol->value.integer.value[0],
313 POD_MONITOR_LEVEL);
314 return 1;
317 /* control definition */
318 static struct snd_kcontrol_new pod_control_monitor = {
319 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
320 .name = "Monitor Playback Volume",
321 .index = 0,
322 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
323 .info = snd_pod_control_monitor_info,
324 .get = snd_pod_control_monitor_get,
325 .put = snd_pod_control_monitor_put
329 POD destructor.
331 static void pod_destruct(struct usb_interface *interface)
333 struct usb_line6_pod *pod = usb_get_intfdata(interface);
335 if (pod == NULL)
336 return;
337 line6_cleanup_audio(&pod->line6);
339 del_timer(&pod->startup_timer);
340 cancel_work_sync(&pod->startup_work);
344 Create sysfs entries.
346 static int pod_create_files2(struct device *dev)
348 int err;
350 CHECK_RETURN(device_create_file(dev, &dev_attr_device_id));
351 CHECK_RETURN(device_create_file(dev, &dev_attr_firmware_version));
352 CHECK_RETURN(device_create_file(dev, &dev_attr_serial_number));
353 return 0;
357 Try to init POD device.
359 static int pod_try_init(struct usb_interface *interface,
360 struct usb_line6_pod *pod)
362 int err;
363 struct usb_line6 *line6 = &pod->line6;
365 init_timer(&pod->startup_timer);
366 INIT_WORK(&pod->startup_work, pod_startup4);
368 if ((interface == NULL) || (pod == NULL))
369 return -ENODEV;
371 /* create sysfs entries: */
372 err = pod_create_files2(&interface->dev);
373 if (err < 0)
374 return err;
376 /* initialize audio system: */
377 err = line6_init_audio(line6);
378 if (err < 0)
379 return err;
381 /* initialize MIDI subsystem: */
382 err = line6_init_midi(line6);
383 if (err < 0)
384 return err;
386 /* initialize PCM subsystem: */
387 err = line6_init_pcm(line6, &pod_pcm_properties);
388 if (err < 0)
389 return err;
391 /* register monitor control: */
392 err = snd_ctl_add(line6->card,
393 snd_ctl_new1(&pod_control_monitor, line6->line6pcm));
394 if (err < 0)
395 return err;
398 When the sound card is registered at this point, the PODxt Live
399 displays "Invalid Code Error 07", so we do it later in the event
400 handler.
403 if (pod->line6.properties->capabilities & LINE6_BIT_CONTROL) {
404 pod->monitor_level = POD_SYSTEM_INVALID;
406 /* initiate startup procedure: */
407 pod_startup1(pod);
410 return 0;
414 Init POD device (and clean up in case of failure).
416 int line6_pod_init(struct usb_interface *interface, struct usb_line6_pod *pod)
418 int err = pod_try_init(interface, pod);
420 if (err < 0)
421 pod_destruct(interface);
423 return err;
427 POD device disconnected.
429 void line6_pod_disconnect(struct usb_interface *interface)
431 struct usb_line6_pod *pod;
433 if (interface == NULL)
434 return;
435 pod = usb_get_intfdata(interface);
437 if (pod != NULL) {
438 struct snd_line6_pcm *line6pcm = pod->line6.line6pcm;
439 struct device *dev = &interface->dev;
441 if (line6pcm != NULL)
442 line6_pcm_disconnect(line6pcm);
444 if (dev != NULL) {
445 /* remove sysfs entries: */
446 device_remove_file(dev, &dev_attr_device_id);
447 device_remove_file(dev, &dev_attr_firmware_version);
448 device_remove_file(dev, &dev_attr_serial_number);
452 pod_destruct(interface);