pod.c 11.2 KB
Newer Older
M
Markus Grabner 已提交
1
/*
2
 * Line6 Linux USB driver - 0.9.1beta
M
Markus Grabner 已提交
3
 *
4
 * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
M
Markus Grabner 已提交
5 6 7 8 9 10 11
 *
 *	This program is free software; you can redistribute it and/or
 *	modify it under the terms of the GNU General Public License as
 *	published by the Free Software Foundation, version 2.
 *
 */

12
#include <linux/slab.h>
13 14
#include <linux/wait.h>
#include <sound/control.h>
15

M
Markus Grabner 已提交
16 17
#include "audio.h"
#include "capture.h"
18
#include "driver.h"
M
Markus Grabner 已提交
19 20 21 22
#include "playback.h"
#include "pod.h"

#define POD_SYSEX_CODE 3
23
#define POD_BYTES_PER_FRAME 6	/* 24bit audio (stereo) */
M
Markus Grabner 已提交
24

25
/* *INDENT-OFF* */
M
Markus Grabner 已提交
26 27 28 29 30 31 32 33 34 35 36

enum {
	POD_SYSEX_SAVE      = 0x24,
	POD_SYSEX_SYSTEM    = 0x56,
	POD_SYSEX_SYSTEMREQ = 0x57,
	/* POD_SYSEX_UPDATE    = 0x6c, */  /* software update! */
	POD_SYSEX_STORE     = 0x71,
	POD_SYSEX_FINISH    = 0x72,
	POD_SYSEX_DUMPMEM   = 0x73,
	POD_SYSEX_DUMP      = 0x74,
	POD_SYSEX_DUMPREQ   = 0x75
37 38 39

	/* dumps entire internal memory of PODxt Pro */
	/* POD_SYSEX_DUMPMEM2  = 0x76 */
M
Markus Grabner 已提交
40 41 42
};

enum {
43 44
	POD_MONITOR_LEVEL  = 0x04,
	POD_SYSTEM_INVALID = 0x10000
M
Markus Grabner 已提交
45 46
};

47 48
/* *INDENT-ON* */

M
Markus Grabner 已提交
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
enum {
	POD_DUMP_MEMORY = 2
};

enum {
	POD_BUSY_READ,
	POD_BUSY_WRITE,
	POD_CHANNEL_DIRTY,
	POD_SAVE_PRESSED,
	POD_BUSY_MIDISEND
};

static struct snd_ratden pod_ratden = {
	.num_min = 78125,
	.num_max = 78125,
	.num_step = 1,
	.den = 2
};

static struct line6_pcm_properties pod_pcm_properties = {
69
	.snd_line6_playback_hw = {
70 71 72 73 74
				  .info = (SNDRV_PCM_INFO_MMAP |
					   SNDRV_PCM_INFO_INTERLEAVED |
					   SNDRV_PCM_INFO_BLOCK_TRANSFER |
					   SNDRV_PCM_INFO_MMAP_VALID |
					   SNDRV_PCM_INFO_PAUSE |
75
#ifdef CONFIG_PM
76
					   SNDRV_PCM_INFO_RESUME |
77
#endif
78 79 80 81 82 83 84 85 86 87 88 89
					   SNDRV_PCM_INFO_SYNC_START),
				  .formats = SNDRV_PCM_FMTBIT_S24_3LE,
				  .rates = SNDRV_PCM_RATE_KNOT,
				  .rate_min = 39062,
				  .rate_max = 39063,
				  .channels_min = 2,
				  .channels_max = 2,
				  .buffer_bytes_max = 60000,
				  .period_bytes_min = 64,
				  .period_bytes_max = 8192,
				  .periods_min = 1,
				  .periods_max = 1024},
90
	.snd_line6_capture_hw = {
91 92 93 94
				 .info = (SNDRV_PCM_INFO_MMAP |
					  SNDRV_PCM_INFO_INTERLEAVED |
					  SNDRV_PCM_INFO_BLOCK_TRANSFER |
					  SNDRV_PCM_INFO_MMAP_VALID |
95
#ifdef CONFIG_PM
96
					  SNDRV_PCM_INFO_RESUME |
97
#endif
98 99 100 101 102 103 104 105 106 107 108 109
					  SNDRV_PCM_INFO_SYNC_START),
				 .formats = SNDRV_PCM_FMTBIT_S24_3LE,
				 .rates = SNDRV_PCM_RATE_KNOT,
				 .rate_min = 39062,
				 .rate_max = 39063,
				 .channels_min = 2,
				 .channels_max = 2,
				 .buffer_bytes_max = 60000,
				 .period_bytes_min = 64,
				 .period_bytes_max = 8192,
				 .periods_min = 1,
				 .periods_max = 1024},
M
Markus Grabner 已提交
110
	.snd_line6_rates = {
111 112
			    .nrats = 1,
			    .rats = &pod_ratden},
M
Markus Grabner 已提交
113 114 115
	.bytes_per_frame = POD_BYTES_PER_FRAME
};

116
static const char pod_version_header[] = {
117 118 119 120 121 122
	0xf2, 0x7e, 0x7f, 0x06, 0x02
};

/* forward declarations: */
static void pod_startup2(unsigned long data);
static void pod_startup3(struct usb_line6_pod *pod);
M
Markus Grabner 已提交
123

124 125
static char *pod_alloc_sysex_buffer(struct usb_line6_pod *pod, int code,
				    int size)
M
Markus Grabner 已提交
126
{
127 128
	return line6_alloc_sysex_buffer(&pod->line6, POD_SYSEX_CODE, code,
					size);
M
Markus Grabner 已提交
129 130 131 132 133
}

/*
	Process a completely received message.
*/
134
static void line6_pod_process_message(struct usb_line6 *line6)
M
Markus Grabner 已提交
135
{
136
	struct usb_line6_pod *pod = (struct usb_line6_pod *) line6;
M
Markus Grabner 已提交
137 138
	const unsigned char *buf = pod->line6.buffer_message;

139 140 141 142 143 144
	if (memcmp(buf, pod_version_header, sizeof(pod_version_header)) == 0) {
		pod->firmware_version = buf[13] * 100 + buf[14] * 10 + buf[15];
		pod->device_id = ((int)buf[8] << 16) | ((int)buf[9] << 8) |
				 (int) buf[10];
		pod_startup3(pod);
		return;
M
Markus Grabner 已提交
145 146
	}

147 148 149 150 151
	/* Only look for sysex messages from this device */
	if (buf[0] != (LINE6_SYSEX_BEGIN | LINE6_CHANNEL_DEVICE) &&
	    buf[0] != (LINE6_SYSEX_BEGIN | LINE6_CHANNEL_UNKNOWN)) {
		return;
	}
152
	if (memcmp(buf + 1, line6_midi_id, sizeof(line6_midi_id)) != 0)
153 154 155 156 157 158
		return;

	if (buf[5] == POD_SYSEX_SYSTEM && buf[6] == POD_MONITOR_LEVEL) {
		short value = ((int)buf[7] << 12) | ((int)buf[8] << 8) |
			      ((int)buf[9] << 4) | (int)buf[10];
		pod->monitor_level = value;
M
Markus Grabner 已提交
159 160 161 162
	}
}

/*
163
	Send system parameter (from integer).
M
Markus Grabner 已提交
164
*/
165 166
static int pod_set_system_param_int(struct usb_line6_pod *pod, int value,
				    int code)
M
Markus Grabner 已提交
167 168 169 170 171
{
	char *sysex;
	static const int size = 5;

	sysex = pod_alloc_sysex_buffer(pod, POD_SYSEX_SYSTEM, size);
172
	if (!sysex)
173
		return -ENOMEM;
M
Markus Grabner 已提交
174 175
	sysex[SYSEX_DATA_OFS] = code;
	sysex[SYSEX_DATA_OFS + 1] = (value >> 12) & 0x0f;
176 177 178
	sysex[SYSEX_DATA_OFS + 2] = (value >> 8) & 0x0f;
	sysex[SYSEX_DATA_OFS + 3] = (value >> 4) & 0x0f;
	sysex[SYSEX_DATA_OFS + 4] = (value) & 0x0f;
M
Markus Grabner 已提交
179 180
	line6_send_sysex_message(&pod->line6, sysex, size);
	kfree(sysex);
181 182 183
	return 0;
}

M
Markus Grabner 已提交
184 185 186
/*
	"read" request on "serial_number" special file.
*/
187 188
static ssize_t serial_number_show(struct device *dev,
				  struct device_attribute *attr, char *buf)
M
Markus Grabner 已提交
189 190 191
{
	struct usb_interface *interface = to_usb_interface(dev);
	struct usb_line6_pod *pod = usb_get_intfdata(interface);
192

M
Markus Grabner 已提交
193 194 195 196 197 198
	return sprintf(buf, "%d\n", pod->serial_number);
}

/*
	"read" request on "firmware_version" special file.
*/
199 200
static ssize_t firmware_version_show(struct device *dev,
				     struct device_attribute *attr, char *buf)
M
Markus Grabner 已提交
201 202 203
{
	struct usb_interface *interface = to_usb_interface(dev);
	struct usb_line6_pod *pod = usb_get_intfdata(interface);
204

205 206
	return sprintf(buf, "%d.%02d\n", pod->firmware_version / 100,
		       pod->firmware_version % 100);
M
Markus Grabner 已提交
207 208 209 210 211
}

/*
	"read" request on "device_id" special file.
*/
212 213
static ssize_t device_id_show(struct device *dev,
			      struct device_attribute *attr, char *buf)
M
Markus Grabner 已提交
214 215 216
{
	struct usb_interface *interface = to_usb_interface(dev);
	struct usb_line6_pod *pod = usb_get_intfdata(interface);
217

M
Markus Grabner 已提交
218 219 220
	return sprintf(buf, "%d\n", pod->device_id);
}

221 222 223 224 225 226 227 228 229
/*
	POD startup procedure.
	This is a sequence of functions with special requirements (e.g., must
	not run immediately after initialization, must not run in interrupt
	context). After the last one has finished, the device is ready to use.
*/

static void pod_startup1(struct usb_line6_pod *pod)
{
230
	CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_INIT);
231 232

	/* delay startup procedure: */
233 234
	line6_start_timer(&pod->startup_timer, POD_STARTUP_DELAY, pod_startup2,
			  (unsigned long)pod);
235 236 237 238 239 240
}

static void pod_startup2(unsigned long data)
{
	struct usb_line6_pod *pod = (struct usb_line6_pod *)data;
	struct usb_line6 *line6 = &pod->line6;
241

242
	CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_VERSIONREQ);
243 244 245

	/* request firmware version: */
	line6_version_request_async(line6);
M
Markus Grabner 已提交
246 247
}

248
static void pod_startup3(struct usb_line6_pod *pod)
249
{
250
	CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_WORKQUEUE);
251 252 253 254 255

	/* schedule work for global work queue: */
	schedule_work(&pod->startup_work);
}

256
static void pod_startup4(struct work_struct *work)
257
{
258 259
	struct usb_line6_pod *pod =
	    container_of(work, struct usb_line6_pod, startup_work);
260 261
	struct usb_line6 *line6 = &pod->line6;

262
	CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_SETUP);
263 264 265 266 267 268 269 270

	/* serial number: */
	line6_read_serial_number(&pod->line6, &pod->serial_number);

	/* ALSA audio interface: */
	line6_register_audio(line6);
}

M
Markus Grabner 已提交
271
/* POD special files: */
272 273 274
static DEVICE_ATTR_RO(device_id);
static DEVICE_ATTR_RO(firmware_version);
static DEVICE_ATTR_RO(serial_number);
M
Markus Grabner 已提交
275

276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292
/* control info callback */
static int snd_pod_control_monitor_info(struct snd_kcontrol *kcontrol,
					struct snd_ctl_elem_info *uinfo)
{
	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
	uinfo->count = 1;
	uinfo->value.integer.min = 0;
	uinfo->value.integer.max = 65535;
	return 0;
}

/* control get callback */
static int snd_pod_control_monitor_get(struct snd_kcontrol *kcontrol,
				       struct snd_ctl_elem_value *ucontrol)
{
	struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
	struct usb_line6_pod *pod = (struct usb_line6_pod *)line6pcm->line6;
293

294
	ucontrol->value.integer.value[0] = pod->monitor_level;
295 296 297 298 299 300 301 302 303 304
	return 0;
}

/* control put callback */
static int snd_pod_control_monitor_put(struct snd_kcontrol *kcontrol,
				       struct snd_ctl_elem_value *ucontrol)
{
	struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
	struct usb_line6_pod *pod = (struct usb_line6_pod *)line6pcm->line6;

305
	if (ucontrol->value.integer.value[0] == pod->monitor_level)
306 307
		return 0;

308
	pod->monitor_level = ucontrol->value.integer.value[0];
309
	pod_set_system_param_int(pod, ucontrol->value.integer.value[0],
310
				 POD_MONITOR_LEVEL);
311 312 313 314 315 316 317 318 319 320 321 322 323 324
	return 1;
}

/* control definition */
static struct snd_kcontrol_new pod_control_monitor = {
	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
	.name = "Monitor Playback Volume",
	.index = 0,
	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
	.info = snd_pod_control_monitor_info,
	.get = snd_pod_control_monitor_get,
	.put = snd_pod_control_monitor_put
};

M
Markus Grabner 已提交
325 326 327 328 329 330 331
/*
	POD destructor.
*/
static void pod_destruct(struct usb_interface *interface)
{
	struct usb_line6_pod *pod = usb_get_intfdata(interface);

332 333
	if (pod == NULL)
		return;
334
	line6_cleanup_audio(&pod->line6);
M
Markus Grabner 已提交
335

336 337
	del_timer(&pod->startup_timer);
	cancel_work_sync(&pod->startup_work);
M
Markus Grabner 已提交
338 339
}

340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368
/*
	POD device disconnected.
*/
static void line6_pod_disconnect(struct usb_interface *interface)
{
	struct usb_line6_pod *pod;

	if (interface == NULL)
		return;
	pod = usb_get_intfdata(interface);

	if (pod != NULL) {
		struct snd_line6_pcm *line6pcm = pod->line6.line6pcm;
		struct device *dev = &interface->dev;

		if (line6pcm != NULL)
			line6_pcm_disconnect(line6pcm);

		if (dev != NULL) {
			/* remove sysfs entries: */
			device_remove_file(dev, &dev_attr_device_id);
			device_remove_file(dev, &dev_attr_firmware_version);
			device_remove_file(dev, &dev_attr_serial_number);
		}
	}

	pod_destruct(interface);
}

M
Markus Grabner 已提交
369 370 371
/*
	Create sysfs entries.
*/
372
static int pod_create_files2(struct device *dev)
M
Markus Grabner 已提交
373 374 375 376 377 378 379 380 381 382
{
	int err;

	CHECK_RETURN(device_create_file(dev, &dev_attr_device_id));
	CHECK_RETURN(device_create_file(dev, &dev_attr_firmware_version));
	CHECK_RETURN(device_create_file(dev, &dev_attr_serial_number));
	return 0;
}

/*
383
	 Try to init POD device.
M
Markus Grabner 已提交
384
*/
385
static int pod_try_init(struct usb_interface *interface,
386
			struct usb_line6 *line6)
M
Markus Grabner 已提交
387 388
{
	int err;
389
	struct usb_line6_pod *pod = (struct usb_line6_pod *) line6;
M
Markus Grabner 已提交
390

391
	line6->process_message = line6_pod_process_message;
392
	line6->disconnect = line6_pod_disconnect;
393

394
	init_timer(&pod->startup_timer);
395
	INIT_WORK(&pod->startup_work, pod_startup4);
396

397 398
	if ((interface == NULL) || (pod == NULL))
		return -ENODEV;
M
Markus Grabner 已提交
399 400

	/* create sysfs entries: */
401
	err = pod_create_files2(&interface->dev);
402
	if (err < 0)
M
Markus Grabner 已提交
403 404 405
		return err;

	/* initialize audio system: */
406
	err = line6_init_audio(line6);
407
	if (err < 0)
M
Markus Grabner 已提交
408 409 410
		return err;

	/* initialize MIDI subsystem: */
411
	err = line6_init_midi(line6);
412
	if (err < 0)
M
Markus Grabner 已提交
413 414 415
		return err;

	/* initialize PCM subsystem: */
416
	err = line6_init_pcm(line6, &pod_pcm_properties);
417
	if (err < 0)
M
Markus Grabner 已提交
418 419
		return err;

420
	/* register monitor control: */
421 422 423
	err = snd_ctl_add(line6->card,
			  snd_ctl_new1(&pod_control_monitor, line6->line6pcm));
	if (err < 0)
M
Markus Grabner 已提交
424 425
		return err;

426
	/*
427 428 429 430
	   When the sound card is registered at this point, the PODxt Live
	   displays "Invalid Code Error 07", so we do it later in the event
	   handler.
	 */
431

432
	if (pod->line6.properties->capabilities & LINE6_CAP_CONTROL) {
433
		pod->monitor_level = POD_SYSTEM_INVALID;
434 435 436

		/* initiate startup procedure: */
		pod_startup1(pod);
M
Markus Grabner 已提交
437 438 439 440 441
	}

	return 0;
}

442 443 444
/*
	 Init POD device (and clean up in case of failure).
*/
445
int line6_pod_init(struct usb_interface *interface, struct usb_line6 *line6)
446
{
447
	int err = pod_try_init(interface, line6);
448

449
	if (err < 0)
450 451 452 453
		pod_destruct(interface);

	return err;
}