linux/drivers/staging/line6/pod.c
<<
>>
Prefs
   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 pod_get_serial_number(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 pod_get_firmware_version(struct device *dev,
 207                                        struct device_attribute *attr,
 208                                        char *buf)
 209{
 210        struct usb_interface *interface = to_usb_interface(dev);
 211        struct usb_line6_pod *pod = usb_get_intfdata(interface);
 212        return sprintf(buf, "%d.%02d\n", pod->firmware_version / 100,
 213                       pod->firmware_version % 100);
 214}
 215
 216/*
 217        "read" request on "device_id" special file.
 218*/
 219static ssize_t pod_get_device_id(struct device *dev,
 220                                 struct device_attribute *attr, char *buf)
 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
 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{
 236        CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_INIT);
 237
 238        /* delay startup procedure: */
 239        line6_start_timer(&pod->startup_timer, POD_STARTUP_DELAY, pod_startup2,
 240                          (unsigned long)pod);
 241}
 242
 243static void pod_startup2(unsigned long data)
 244{
 245        struct usb_line6_pod *pod = (struct usb_line6_pod *)data;
 246        struct usb_line6 *line6 = &pod->line6;
 247        CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_VERSIONREQ);
 248
 249        /* request firmware version: */
 250        line6_version_request_async(line6);
 251}
 252
 253static void pod_startup3(struct usb_line6_pod *pod)
 254{
 255        CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_WORKQUEUE);
 256
 257        /* schedule work for global work queue: */
 258        schedule_work(&pod->startup_work);
 259}
 260
 261static void pod_startup4(struct work_struct *work)
 262{
 263        struct usb_line6_pod *pod =
 264            container_of(work, struct usb_line6_pod, startup_work);
 265        struct usb_line6 *line6 = &pod->line6;
 266
 267        CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_SETUP);
 268
 269        /* serial number: */
 270        line6_read_serial_number(&pod->line6, &pod->serial_number);
 271
 272        /* ALSA audio interface: */
 273        line6_register_audio(line6);
 274}
 275
 276/* POD special files: */
 277static DEVICE_ATTR(device_id, S_IRUGO, pod_get_device_id, line6_nop_write);
 278static DEVICE_ATTR(firmware_version, S_IRUGO, pod_get_firmware_version,
 279                   line6_nop_write);
 280static DEVICE_ATTR(serial_number, S_IRUGO, pod_get_serial_number,
 281                   line6_nop_write);
 282
 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;
 300        ucontrol->value.integer.value[0] = pod->monitor_level;
 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
 311        if (ucontrol->value.integer.value[0] == pod->monitor_level)
 312                return 0;
 313
 314        pod->monitor_level = ucontrol->value.integer.value[0];
 315        pod_set_system_param_int(pod, ucontrol->value.integer.value[0],
 316                                 POD_MONITOR_LEVEL);
 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
 331/*
 332        POD destructor.
 333*/
 334static void pod_destruct(struct usb_interface *interface)
 335{
 336        struct usb_line6_pod *pod = usb_get_intfdata(interface);
 337
 338        if (pod == NULL)
 339                return;
 340        line6_cleanup_audio(&pod->line6);
 341
 342        del_timer(&pod->startup_timer);
 343        cancel_work_sync(&pod->startup_work);
 344}
 345
 346/*
 347        Create sysfs entries.
 348*/
 349static int pod_create_files2(struct device *dev)
 350{
 351        int err;
 352
 353        CHECK_RETURN(device_create_file(dev, &dev_attr_device_id));
 354        CHECK_RETURN(device_create_file(dev, &dev_attr_firmware_version));
 355        CHECK_RETURN(device_create_file(dev, &dev_attr_serial_number));
 356        return 0;
 357}
 358
 359/*
 360         Try to init POD device.
 361*/
 362static int pod_try_init(struct usb_interface *interface,
 363                        struct usb_line6_pod *pod)
 364{
 365        int err;
 366        struct usb_line6 *line6 = &pod->line6;
 367
 368        init_timer(&pod->startup_timer);
 369        INIT_WORK(&pod->startup_work, pod_startup4);
 370
 371        if ((interface == NULL) || (pod == NULL))
 372                return -ENODEV;
 373
 374        /* create sysfs entries: */
 375        err = pod_create_files2(&interface->dev);
 376        if (err < 0)
 377                return err;
 378
 379        /* initialize audio system: */
 380        err = line6_init_audio(line6);
 381        if (err < 0)
 382                return err;
 383
 384        /* initialize MIDI subsystem: */
 385        err = line6_init_midi(line6);
 386        if (err < 0)
 387                return err;
 388
 389        /* initialize PCM subsystem: */
 390        err = line6_init_pcm(line6, &pod_pcm_properties);
 391        if (err < 0)
 392                return err;
 393
 394        /* register monitor control: */
 395        err = snd_ctl_add(line6->card,
 396                          snd_ctl_new1(&pod_control_monitor, line6->line6pcm));
 397        if (err < 0)
 398                return err;
 399
 400        /*
 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         */
 405
 406        if (pod->line6.properties->capabilities & LINE6_BIT_CONTROL) {
 407                pod->monitor_level = POD_SYSTEM_INVALID;
 408
 409                /* initiate startup procedure: */
 410                pod_startup1(pod);
 411        }
 412
 413        return 0;
 414}
 415
 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
 423        if (err < 0)
 424                pod_destruct(interface);
 425
 426        return err;
 427}
 428
 429/*
 430        POD device disconnected.
 431*/
 432void line6_pod_disconnect(struct usb_interface *interface)
 433{
 434        struct usb_line6_pod *pod;
 435
 436        if (interface == NULL)
 437                return;
 438        pod = usb_get_intfdata(interface);
 439
 440        if (pod != NULL) {
 441                struct snd_line6_pcm *line6pcm = pod->line6.line6pcm;
 442                struct device *dev = &interface->dev;
 443
 444                if (line6pcm != NULL)
 445                        line6_pcm_disconnect(line6pcm);
 446
 447                if (dev != NULL) {
 448                        /* remove sysfs entries: */
 449                        device_remove_file(dev, &dev_attr_device_id);
 450                        device_remove_file(dev, &dev_attr_firmware_version);
 451                        device_remove_file(dev, &dev_attr_serial_number);
 452                }
 453        }
 454
 455        pod_destruct(interface);
 456}
 457