Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v3.19 458 lines 11 kB view raw
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 201 return sprintf(buf, "%d\n", pod->serial_number); 202} 203 204/* 205 "read" request on "firmware_version" special file. 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 "read" request on "device_id" special file. 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 POD startup procedure. 231 This is a sequence of functions with special requirements (e.g., must 232 not run immediately after initialization, must not run in interrupt 233 context). After the last one has finished, the device is ready to use. 234*/ 235 236static void pod_startup1(struct usb_line6_pod *pod) 237{ 238 CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_INIT); 239 240 /* delay startup procedure: */ 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 /* request firmware version: */ 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 /* schedule work for global work queue: */ 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 /* serial number: */ 273 line6_read_serial_number(&pod->line6, &pod->serial_number); 274 275 /* ALSA audio interface: */ 276 line6_register_audio(line6); 277} 278 279/* POD special files: */ 280static DEVICE_ATTR_RO(device_id); 281static DEVICE_ATTR_RO(firmware_version); 282static DEVICE_ATTR_RO(serial_number); 283 284/* control info callback */ 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/* control get callback */ 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/* control put callback */ 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/* control definition */ 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 POD destructor. 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 Create sysfs entries. 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 Try to init POD device. 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 /* create sysfs entries: */ 377 err = pod_create_files2(&interface->dev); 378 if (err < 0) 379 return err; 380 381 /* initialize audio system: */ 382 err = line6_init_audio(line6); 383 if (err < 0) 384 return err; 385 386 /* initialize MIDI subsystem: */ 387 err = line6_init_midi(line6); 388 if (err < 0) 389 return err; 390 391 /* initialize PCM subsystem: */ 392 err = line6_init_pcm(line6, &pod_pcm_properties); 393 if (err < 0) 394 return err; 395 396 /* register monitor control: */ 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 When the sound card is registered at this point, the PODxt Live 404 displays "Invalid Code Error 07", so we do it later in the event 405 handler. 406 */ 407 408 if (pod->line6.properties->capabilities & LINE6_BIT_CONTROL) { 409 pod->monitor_level = POD_SYSTEM_INVALID; 410 411 /* initiate startup procedure: */ 412 pod_startup1(pod); 413 } 414 415 return 0; 416} 417 418/* 419 Init POD device (and clean up in case of failure). 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 POD device disconnected. 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 /* remove sysfs entries: */ 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}