linux/drivers/staging/line6/pcm.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 <sound/core.h>
  14#include <sound/control.h>
  15#include <sound/pcm.h>
  16#include <sound/pcm_params.h>
  17
  18#include "audio.h"
  19#include "capture.h"
  20#include "driver.h"
  21#include "playback.h"
  22#include "pod.h"
  23
  24#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
  25
  26static struct snd_line6_pcm *dev2pcm(struct device *dev)
  27{
  28        struct usb_interface *interface = to_usb_interface(dev);
  29        struct usb_line6 *line6 = usb_get_intfdata(interface);
  30        struct snd_line6_pcm *line6pcm = line6->line6pcm;
  31        return line6pcm;
  32}
  33
  34/*
  35        "read" request on "impulse_volume" special file.
  36*/
  37static ssize_t pcm_get_impulse_volume(struct device *dev,
  38                                      struct device_attribute *attr, char *buf)
  39{
  40        return sprintf(buf, "%d\n", dev2pcm(dev)->impulse_volume);
  41}
  42
  43/*
  44        "write" request on "impulse_volume" special file.
  45*/
  46static ssize_t pcm_set_impulse_volume(struct device *dev,
  47                                      struct device_attribute *attr,
  48                                      const char *buf, size_t count)
  49{
  50        struct snd_line6_pcm *line6pcm = dev2pcm(dev);
  51        int value = simple_strtoul(buf, NULL, 10);
  52        line6pcm->impulse_volume = value;
  53
  54        if (value > 0)
  55                line6_pcm_start(line6pcm, MASK_PCM_IMPULSE);
  56        else
  57                line6_pcm_stop(line6pcm, MASK_PCM_IMPULSE);
  58
  59        return count;
  60}
  61
  62/*
  63        "read" request on "impulse_period" special file.
  64*/
  65static ssize_t pcm_get_impulse_period(struct device *dev,
  66                                      struct device_attribute *attr, char *buf)
  67{
  68        return sprintf(buf, "%d\n", dev2pcm(dev)->impulse_period);
  69}
  70
  71/*
  72        "write" request on "impulse_period" special file.
  73*/
  74static ssize_t pcm_set_impulse_period(struct device *dev,
  75                                      struct device_attribute *attr,
  76                                      const char *buf, size_t count)
  77{
  78        dev2pcm(dev)->impulse_period = simple_strtoul(buf, NULL, 10);
  79        return count;
  80}
  81
  82static DEVICE_ATTR(impulse_volume, S_IWUSR | S_IRUGO, pcm_get_impulse_volume,
  83                   pcm_set_impulse_volume);
  84static DEVICE_ATTR(impulse_period, S_IWUSR | S_IRUGO, pcm_get_impulse_period,
  85                   pcm_set_impulse_period);
  86
  87#endif
  88
  89static bool test_flags(unsigned long flags0, unsigned long flags1,
  90                       unsigned long mask)
  91{
  92        return ((flags0 & mask) == 0) && ((flags1 & mask) != 0);
  93}
  94
  95int line6_pcm_start(struct snd_line6_pcm *line6pcm, int channels)
  96{
  97        unsigned long flags_old =
  98            __sync_fetch_and_or(&line6pcm->flags, channels);
  99        unsigned long flags_new = flags_old | channels;
 100        int err = 0;
 101        
 102        line6pcm->prev_fbuf = NULL;
 103
 104        if (test_flags(flags_old, flags_new, MASK_CAPTURE)) {
 105                /*
 106                   Waiting for completion of active URBs in the stop handler is
 107                   a bug, we therefore report an error if capturing is restarted
 108                   too soon.
 109                 */
 110                if (line6pcm->active_urb_in | line6pcm->unlink_urb_in)
 111                        return -EBUSY;
 112
 113                if (!(flags_new & MASK_PCM_ALSA_CAPTURE)) {
 114                        err = line6_alloc_capture_buffer(line6pcm);
 115
 116                        if (err < 0)
 117                                goto pcm_start_error;
 118                }
 119
 120                line6pcm->count_in = 0;
 121                line6pcm->prev_fsize = 0;
 122                err = line6_submit_audio_in_all_urbs(line6pcm);
 123
 124                if (err < 0)
 125                        goto pcm_start_error;
 126        }
 127
 128        if (test_flags(flags_old, flags_new, MASK_PLAYBACK)) {
 129                /*
 130                   See comment above regarding PCM restart.
 131                 */
 132                if (line6pcm->active_urb_out | line6pcm->unlink_urb_out)
 133                        return -EBUSY;
 134
 135                if (!(flags_new & MASK_PCM_ALSA_PLAYBACK)) {
 136                        err = line6_alloc_playback_buffer(line6pcm);
 137
 138                        if (err < 0)
 139                                goto pcm_start_error;
 140                }
 141
 142                line6pcm->count_out = 0;
 143                err = line6_submit_audio_out_all_urbs(line6pcm);
 144
 145                if (err < 0)
 146                        goto pcm_start_error;
 147        }
 148
 149        return 0;
 150
 151pcm_start_error:
 152        __sync_fetch_and_and(&line6pcm->flags, ~channels);
 153        return err;
 154}
 155
 156int line6_pcm_stop(struct snd_line6_pcm *line6pcm, int channels)
 157{
 158        unsigned long flags_old =
 159            __sync_fetch_and_and(&line6pcm->flags, ~channels);
 160        unsigned long flags_new = flags_old & ~channels;
 161
 162        if (test_flags(flags_new, flags_old, MASK_CAPTURE)) {
 163                line6_unlink_audio_in_urbs(line6pcm);
 164
 165                if (!(flags_old & MASK_PCM_ALSA_CAPTURE))
 166                        line6_free_capture_buffer(line6pcm);
 167        }
 168
 169        if (test_flags(flags_new, flags_old, MASK_PLAYBACK)) {
 170                line6_unlink_audio_out_urbs(line6pcm);
 171
 172                if (!(flags_old & MASK_PCM_ALSA_PLAYBACK))
 173                        line6_free_playback_buffer(line6pcm);
 174        }
 175
 176        return 0;
 177}
 178
 179/* trigger callback */
 180int snd_line6_trigger(struct snd_pcm_substream *substream, int cmd)
 181{
 182        struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
 183        struct snd_pcm_substream *s;
 184        int err;
 185        unsigned long flags;
 186
 187        spin_lock_irqsave(&line6pcm->lock_trigger, flags);
 188        clear_bit(BIT_PREPARED, &line6pcm->flags);
 189
 190        snd_pcm_group_for_each_entry(s, substream) {
 191                switch (s->stream) {
 192                case SNDRV_PCM_STREAM_PLAYBACK:
 193                        err = snd_line6_playback_trigger(line6pcm, cmd);
 194
 195                        if (err < 0) {
 196                                spin_unlock_irqrestore(&line6pcm->lock_trigger,
 197                                                       flags);
 198                                return err;
 199                        }
 200
 201                        break;
 202
 203                case SNDRV_PCM_STREAM_CAPTURE:
 204                        err = snd_line6_capture_trigger(line6pcm, cmd);
 205
 206                        if (err < 0) {
 207                                spin_unlock_irqrestore(&line6pcm->lock_trigger,
 208                                                       flags);
 209                                return err;
 210                        }
 211
 212                        break;
 213
 214                default:
 215                        dev_err(line6pcm->line6->ifcdev,
 216                                "Unknown stream direction %d\n", s->stream);
 217                }
 218        }
 219
 220        spin_unlock_irqrestore(&line6pcm->lock_trigger, flags);
 221        return 0;
 222}
 223
 224/* control info callback */
 225static int snd_line6_control_playback_info(struct snd_kcontrol *kcontrol,
 226                                           struct snd_ctl_elem_info *uinfo)
 227{
 228        uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 229        uinfo->count = 2;
 230        uinfo->value.integer.min = 0;
 231        uinfo->value.integer.max = 256;
 232        return 0;
 233}
 234
 235/* control get callback */
 236static int snd_line6_control_playback_get(struct snd_kcontrol *kcontrol,
 237                                          struct snd_ctl_elem_value *ucontrol)
 238{
 239        int i;
 240        struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
 241
 242        for (i = 2; i--;)
 243                ucontrol->value.integer.value[i] = line6pcm->volume_playback[i];
 244
 245        return 0;
 246}
 247
 248/* control put callback */
 249static int snd_line6_control_playback_put(struct snd_kcontrol *kcontrol,
 250                                          struct snd_ctl_elem_value *ucontrol)
 251{
 252        int i, changed = 0;
 253        struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
 254
 255        for (i = 2; i--;)
 256                if (line6pcm->volume_playback[i] !=
 257                    ucontrol->value.integer.value[i]) {
 258                        line6pcm->volume_playback[i] =
 259                            ucontrol->value.integer.value[i];
 260                        changed = 1;
 261                }
 262
 263        return changed;
 264}
 265
 266/* control definition */
 267static struct snd_kcontrol_new line6_control_playback = {
 268        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 269        .name = "PCM Playback Volume",
 270        .index = 0,
 271        .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
 272        .info = snd_line6_control_playback_info,
 273        .get = snd_line6_control_playback_get,
 274        .put = snd_line6_control_playback_put
 275};
 276
 277/*
 278        Cleanup the PCM device.
 279*/
 280static void line6_cleanup_pcm(struct snd_pcm *pcm)
 281{
 282        int i;
 283        struct snd_line6_pcm *line6pcm = snd_pcm_chip(pcm);
 284
 285#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
 286        device_remove_file(line6pcm->line6->ifcdev, &dev_attr_impulse_volume);
 287        device_remove_file(line6pcm->line6->ifcdev, &dev_attr_impulse_period);
 288#endif
 289
 290        for (i = LINE6_ISO_BUFFERS; i--;) {
 291                if (line6pcm->urb_audio_out[i]) {
 292                        usb_kill_urb(line6pcm->urb_audio_out[i]);
 293                        usb_free_urb(line6pcm->urb_audio_out[i]);
 294                }
 295                if (line6pcm->urb_audio_in[i]) {
 296                        usb_kill_urb(line6pcm->urb_audio_in[i]);
 297                        usb_free_urb(line6pcm->urb_audio_in[i]);
 298                }
 299        }
 300}
 301
 302/* create a PCM device */
 303static int snd_line6_new_pcm(struct snd_line6_pcm *line6pcm)
 304{
 305        struct snd_pcm *pcm;
 306        int err;
 307
 308        err = snd_pcm_new(line6pcm->line6->card,
 309                          (char *)line6pcm->line6->properties->name,
 310                          0, 1, 1, &pcm);
 311        if (err < 0)
 312                return err;
 313
 314        pcm->private_data = line6pcm;
 315        pcm->private_free = line6_cleanup_pcm;
 316        line6pcm->pcm = pcm;
 317        strcpy(pcm->name, line6pcm->line6->properties->name);
 318
 319        /* set operators */
 320        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
 321                        &snd_line6_playback_ops);
 322        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_line6_capture_ops);
 323
 324        /* pre-allocation of buffers */
 325        snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
 326                                              snd_dma_continuous_data
 327                                              (GFP_KERNEL), 64 * 1024,
 328                                              128 * 1024);
 329
 330        return 0;
 331}
 332
 333/* PCM device destructor */
 334static int snd_line6_pcm_free(struct snd_device *device)
 335{
 336        return 0;
 337}
 338
 339/*
 340        Stop substream if still running.
 341*/
 342static void pcm_disconnect_substream(struct snd_pcm_substream *substream)
 343{
 344        if (substream->runtime && snd_pcm_running(substream))
 345                snd_pcm_stop(substream, SNDRV_PCM_STATE_DISCONNECTED);
 346}
 347
 348/*
 349        Stop PCM stream.
 350*/
 351void line6_pcm_disconnect(struct snd_line6_pcm *line6pcm)
 352{
 353        pcm_disconnect_substream(get_substream
 354                                 (line6pcm, SNDRV_PCM_STREAM_CAPTURE));
 355        pcm_disconnect_substream(get_substream
 356                                 (line6pcm, SNDRV_PCM_STREAM_PLAYBACK));
 357        line6_unlink_wait_clear_audio_out_urbs(line6pcm);
 358        line6_unlink_wait_clear_audio_in_urbs(line6pcm);
 359}
 360
 361/*
 362        Create and register the PCM device and mixer entries.
 363        Create URBs for playback and capture.
 364*/
 365int line6_init_pcm(struct usb_line6 *line6,
 366                   struct line6_pcm_properties *properties)
 367{
 368        static struct snd_device_ops pcm_ops = {
 369                .dev_free = snd_line6_pcm_free,
 370        };
 371
 372        int err;
 373        int ep_read = 0, ep_write = 0;
 374        struct snd_line6_pcm *line6pcm;
 375
 376        if (!(line6->properties->capabilities & LINE6_BIT_PCM))
 377                return 0;       /* skip PCM initialization and report success */
 378
 379        /* initialize PCM subsystem based on product id: */
 380        switch (line6->product) {
 381        case LINE6_DEVID_BASSPODXT:
 382        case LINE6_DEVID_BASSPODXTLIVE:
 383        case LINE6_DEVID_BASSPODXTPRO:
 384        case LINE6_DEVID_PODXT:
 385        case LINE6_DEVID_PODXTLIVE:
 386        case LINE6_DEVID_PODXTPRO:
 387        case LINE6_DEVID_PODHD300:
 388                ep_read = 0x82;
 389                ep_write = 0x01;
 390                break;
 391
 392        case LINE6_DEVID_PODHD500:
 393        case LINE6_DEVID_PODX3:
 394        case LINE6_DEVID_PODX3LIVE:
 395                ep_read = 0x86;
 396                ep_write = 0x02;
 397                break;
 398
 399        case LINE6_DEVID_POCKETPOD:
 400                ep_read = 0x82;
 401                ep_write = 0x02;
 402                break;
 403
 404        case LINE6_DEVID_GUITARPORT:
 405        case LINE6_DEVID_PODSTUDIO_GX:
 406        case LINE6_DEVID_PODSTUDIO_UX1:
 407        case LINE6_DEVID_PODSTUDIO_UX2:
 408        case LINE6_DEVID_TONEPORT_GX:
 409        case LINE6_DEVID_TONEPORT_UX1:
 410        case LINE6_DEVID_TONEPORT_UX2:
 411                ep_read = 0x82;
 412                ep_write = 0x01;
 413                break;
 414
 415                /* this is for interface_number == 1:
 416                   case LINE6_DEVID_TONEPORT_UX2:
 417                   case LINE6_DEVID_PODSTUDIO_UX2:
 418                   ep_read  = 0x87;
 419                   ep_write = 0x00;
 420                   break;
 421                 */
 422
 423        default:
 424                MISSING_CASE;
 425        }
 426
 427        line6pcm = kzalloc(sizeof(struct snd_line6_pcm), GFP_KERNEL);
 428
 429        if (line6pcm == NULL)
 430                return -ENOMEM;
 431
 432        line6pcm->volume_playback[0] = line6pcm->volume_playback[1] = 255;
 433        line6pcm->volume_monitor = 255;
 434        line6pcm->line6 = line6;
 435        line6pcm->ep_audio_read = ep_read;
 436        line6pcm->ep_audio_write = ep_write;
 437
 438        /* Read and write buffers are sized identically, so choose minimum */
 439        line6pcm->max_packet_size = min(
 440                        usb_maxpacket(line6->usbdev,
 441                                usb_rcvisocpipe(line6->usbdev, ep_read), 0),
 442                        usb_maxpacket(line6->usbdev,
 443                                usb_sndisocpipe(line6->usbdev, ep_write), 1));
 444
 445        line6pcm->properties = properties;
 446        line6->line6pcm = line6pcm;
 447
 448        /* PCM device: */
 449        err = snd_device_new(line6->card, SNDRV_DEV_PCM, line6, &pcm_ops);
 450        if (err < 0)
 451                return err;
 452
 453        snd_card_set_dev(line6->card, line6->ifcdev);
 454
 455        err = snd_line6_new_pcm(line6pcm);
 456        if (err < 0)
 457                return err;
 458
 459        spin_lock_init(&line6pcm->lock_audio_out);
 460        spin_lock_init(&line6pcm->lock_audio_in);
 461        spin_lock_init(&line6pcm->lock_trigger);
 462
 463        err = line6_create_audio_out_urbs(line6pcm);
 464        if (err < 0)
 465                return err;
 466
 467        err = line6_create_audio_in_urbs(line6pcm);
 468        if (err < 0)
 469                return err;
 470
 471        /* mixer: */
 472        err =
 473            snd_ctl_add(line6->card,
 474                        snd_ctl_new1(&line6_control_playback, line6pcm));
 475        if (err < 0)
 476                return err;
 477
 478#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
 479        /* impulse response test: */
 480        err = device_create_file(line6->ifcdev, &dev_attr_impulse_volume);
 481        if (err < 0)
 482                return err;
 483
 484        err = device_create_file(line6->ifcdev, &dev_attr_impulse_period);
 485        if (err < 0)
 486                return err;
 487
 488        line6pcm->impulse_period = LINE6_IMPULSE_DEFAULT_PERIOD;
 489#endif
 490
 491        return 0;
 492}
 493
 494/* prepare pcm callback */
 495int snd_line6_prepare(struct snd_pcm_substream *substream)
 496{
 497        struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
 498
 499        switch (substream->stream) {
 500        case SNDRV_PCM_STREAM_PLAYBACK:
 501                if ((line6pcm->flags & MASK_PLAYBACK) == 0)
 502                        line6_unlink_wait_clear_audio_out_urbs(line6pcm);
 503
 504                break;
 505
 506        case SNDRV_PCM_STREAM_CAPTURE:
 507                if ((line6pcm->flags & MASK_CAPTURE) == 0)
 508                        line6_unlink_wait_clear_audio_in_urbs(line6pcm);
 509
 510                break;
 511
 512        default:
 513                MISSING_CASE;
 514        }
 515
 516        if (!test_and_set_bit(BIT_PREPARED, &line6pcm->flags)) {
 517                line6pcm->count_out = 0;
 518                line6pcm->pos_out = 0;
 519                line6pcm->pos_out_done = 0;
 520                line6pcm->bytes_out = 0;
 521                line6pcm->count_in = 0;
 522                line6pcm->pos_in_done = 0;
 523                line6pcm->bytes_in = 0;
 524        }
 525
 526        return 0;
 527}
 528