Linux Audio

Check our new training course

Yocto distribution development and maintenance

Need a Yocto distribution for your embedded project?
Loading...
Note: File does not exist in v6.9.4.
  1/*
  2 * Line6 Linux USB driver - 0.9.1beta
  3 *
  4 * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
  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
 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	/* 24bit audio (stereo) */
 24
 25/* *INDENT-OFF* */
 26
 27enum {
 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
 37
 38	/* dumps entire internal memory of PODxt Pro */
 39	/* POD_SYSEX_DUMPMEM2  = 0x76 */
 40};
 41
 42enum {
 43	POD_MONITOR_LEVEL  = 0x04,
 44	POD_SYSTEM_INVALID = 0x10000
 45};
 46
 47/* *INDENT-ON* */
 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/* forward declarations: */
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	Process a completely received message.
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	/* 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	}
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	Transmit PODxt Pro control parameter.
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	Send system parameter (from integer).
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	"read" request on "serial_number" special file.
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	return sprintf(buf, "%d\n", pod->serial_number);
201}
202
203/*
204	"read" request on "firmware_version" special file.
205*/
206static ssize_t firmware_version_show(struct device *dev,
207				     struct device_attribute *attr, char *buf)
208{
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);
213}
214
215/*
216	"read" request on "device_id" special file.
217*/
218static ssize_t device_id_show(struct device *dev,
219			      struct device_attribute *attr, char *buf)
220{
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);
224}
225
226/*
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.
231*/
232
233static void pod_startup1(struct usb_line6_pod *pod)
234{
235	CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_INIT);
236
237	/* delay startup procedure: */
238	line6_start_timer(&pod->startup_timer, POD_STARTUP_DELAY, pod_startup2,
239			  (unsigned long)pod);
240}
241
242static void pod_startup2(unsigned long data)
243{
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);
247
248	/* request firmware version: */
249	line6_version_request_async(line6);
250}
251
252static void pod_startup3(struct usb_line6_pod *pod)
253{
254	CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_WORKQUEUE);
255
256	/* schedule work for global work queue: */
257	schedule_work(&pod->startup_work);
258}
259
260static void pod_startup4(struct work_struct *work)
261{
262	struct usb_line6_pod *pod =
263	    container_of(work, struct usb_line6_pod, startup_work);
264	struct usb_line6 *line6 = &pod->line6;
265
266	CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_SETUP);
267
268	/* serial number: */
269	line6_read_serial_number(&pod->line6, &pod->serial_number);
270
271	/* ALSA audio interface: */
272	line6_register_audio(line6);
273}
274
275/* POD special files: */
276static DEVICE_ATTR_RO(device_id);
277static DEVICE_ATTR_RO(firmware_version);
278static DEVICE_ATTR_RO(serial_number);
279
280/* control info callback */
281static int snd_pod_control_monitor_info(struct snd_kcontrol *kcontrol,
282					struct snd_ctl_elem_info *uinfo)
283{
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;
289}
290
291/* control get callback */
292static int snd_pod_control_monitor_get(struct snd_kcontrol *kcontrol,
293				       struct snd_ctl_elem_value *ucontrol)
294{
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;
299}
300
301/* control put callback */
302static int snd_pod_control_monitor_put(struct snd_kcontrol *kcontrol,
303				       struct snd_ctl_elem_value *ucontrol)
304{
305	struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
306	struct usb_line6_pod *pod = (struct usb_line6_pod *)line6pcm->line6;
307
308	if (ucontrol->value.integer.value[0] == pod->monitor_level)
309		return 0;
310
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;
315}
316
317/* control definition */
318static 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
326};
327
328/*
329	POD destructor.
330*/
331static void pod_destruct(struct usb_interface *interface)
332{
333	struct usb_line6_pod *pod = usb_get_intfdata(interface);
334
335	if (pod == NULL)
336		return;
337	line6_cleanup_audio(&pod->line6);
338
339	del_timer(&pod->startup_timer);
340	cancel_work_sync(&pod->startup_work);
341}
342
343/*
344	Create sysfs entries.
345*/
346static int pod_create_files2(struct device *dev)
347{
348	int err;
349
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;
354}
355
356/*
357	 Try to init POD device.
358*/
359static int pod_try_init(struct usb_interface *interface,
360			struct usb_line6_pod *pod)
361{
362	int err;
363	struct usb_line6 *line6 = &pod->line6;
364
365	init_timer(&pod->startup_timer);
366	INIT_WORK(&pod->startup_work, pod_startup4);
367
368	if ((interface == NULL) || (pod == NULL))
369		return -ENODEV;
370
371	/* create sysfs entries: */
372	err = pod_create_files2(&interface->dev);
373	if (err < 0)
374		return err;
375
376	/* initialize audio system: */
377	err = line6_init_audio(line6);
378	if (err < 0)
379		return err;
380
381	/* initialize MIDI subsystem: */
382	err = line6_init_midi(line6);
383	if (err < 0)
384		return err;
385
386	/* initialize PCM subsystem: */
387	err = line6_init_pcm(line6, &pod_pcm_properties);
388	if (err < 0)
389		return err;
390
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;
396
397	/*
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.
401	 */
402
403	if (pod->line6.properties->capabilities & LINE6_BIT_CONTROL) {
404		pod->monitor_level = POD_SYSTEM_INVALID;
405
406		/* initiate startup procedure: */
407		pod_startup1(pod);
408	}
409
410	return 0;
411}
412
413/*
414	 Init POD device (and clean up in case of failure).
415*/
416int line6_pod_init(struct usb_interface *interface, struct usb_line6_pod *pod)
417{
418	int err = pod_try_init(interface, pod);
419
420	if (err < 0)
421		pod_destruct(interface);
422
423	return err;
424}
425
426/*
427	POD device disconnected.
428*/
429void line6_pod_disconnect(struct usb_interface *interface)
430{
431	struct usb_line6_pod *pod;
432
433	if (interface == NULL)
434		return;
435	pod = usb_get_intfdata(interface);
436
437	if (pod != NULL) {
438		struct snd_line6_pcm *line6pcm = pod->line6.line6pcm;
439		struct device *dev = &interface->dev;
440
441		if (line6pcm != NULL)
442			line6_pcm_disconnect(line6pcm);
443
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);
449		}
450	}
451
452	pod_destruct(interface);
453}