linux/sound/usb/line6/pcm.c
<<
>>
Prefs
   1/*
   2 * Line 6 Linux USB driver
   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/export.h>
  14#include <sound/core.h>
  15#include <sound/control.h>
  16#include <sound/pcm.h>
  17#include <sound/pcm_params.h>
  18
  19#include "capture.h"
  20#include "driver.h"
  21#include "playback.h"
  22
  23/* impulse response volume controls */
  24static int snd_line6_impulse_volume_info(struct snd_kcontrol *kcontrol,
  25                                         struct snd_ctl_elem_info *uinfo)
  26{
  27        uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
  28        uinfo->count = 1;
  29        uinfo->value.integer.min = 0;
  30        uinfo->value.integer.max = 255;
  31        return 0;
  32}
  33
  34static int snd_line6_impulse_volume_get(struct snd_kcontrol *kcontrol,
  35                                        struct snd_ctl_elem_value *ucontrol)
  36{
  37        struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
  38
  39        ucontrol->value.integer.value[0] = line6pcm->impulse_volume;
  40        return 0;
  41}
  42
  43static int snd_line6_impulse_volume_put(struct snd_kcontrol *kcontrol,
  44                                        struct snd_ctl_elem_value *ucontrol)
  45{
  46        struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
  47        int value = ucontrol->value.integer.value[0];
  48        int err;
  49
  50        if (line6pcm->impulse_volume == value)
  51                return 0;
  52
  53        line6pcm->impulse_volume = value;
  54        if (value > 0) {
  55                err = line6_pcm_acquire(line6pcm, LINE6_STREAM_IMPULSE, true);
  56                if (err < 0) {
  57                        line6pcm->impulse_volume = 0;
  58                        return err;
  59                }
  60        } else {
  61                line6_pcm_release(line6pcm, LINE6_STREAM_IMPULSE);
  62        }
  63        return 1;
  64}
  65
  66/* impulse response period controls */
  67static int snd_line6_impulse_period_info(struct snd_kcontrol *kcontrol,
  68                                         struct snd_ctl_elem_info *uinfo)
  69{
  70        uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
  71        uinfo->count = 1;
  72        uinfo->value.integer.min = 0;
  73        uinfo->value.integer.max = 2000;
  74        return 0;
  75}
  76
  77static int snd_line6_impulse_period_get(struct snd_kcontrol *kcontrol,
  78                                        struct snd_ctl_elem_value *ucontrol)
  79{
  80        struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
  81
  82        ucontrol->value.integer.value[0] = line6pcm->impulse_period;
  83        return 0;
  84}
  85
  86static int snd_line6_impulse_period_put(struct snd_kcontrol *kcontrol,
  87                                        struct snd_ctl_elem_value *ucontrol)
  88{
  89        struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
  90        int value = ucontrol->value.integer.value[0];
  91
  92        if (line6pcm->impulse_period == value)
  93                return 0;
  94
  95        line6pcm->impulse_period = value;
  96        return 1;
  97}
  98
  99/*
 100        Unlink all currently active URBs.
 101*/
 102static void line6_unlink_audio_urbs(struct snd_line6_pcm *line6pcm,
 103                                    struct line6_pcm_stream *pcms)
 104{
 105        int i;
 106
 107        for (i = 0; i < line6pcm->line6->iso_buffers; i++) {
 108                if (test_bit(i, &pcms->active_urbs)) {
 109                        if (!test_and_set_bit(i, &pcms->unlink_urbs))
 110                                usb_unlink_urb(pcms->urbs[i]);
 111                }
 112        }
 113}
 114
 115/*
 116        Wait until unlinking of all currently active URBs has been finished.
 117*/
 118static void line6_wait_clear_audio_urbs(struct snd_line6_pcm *line6pcm,
 119                                        struct line6_pcm_stream *pcms)
 120{
 121        int timeout = HZ;
 122        int i;
 123        int alive;
 124
 125        do {
 126                alive = 0;
 127                for (i = 0; i < line6pcm->line6->iso_buffers; i++) {
 128                        if (test_bit(i, &pcms->active_urbs))
 129                                alive++;
 130                }
 131                if (!alive)
 132                        break;
 133                set_current_state(TASK_UNINTERRUPTIBLE);
 134                schedule_timeout(1);
 135        } while (--timeout > 0);
 136        if (alive)
 137                dev_err(line6pcm->line6->ifcdev,
 138                        "timeout: still %d active urbs..\n", alive);
 139}
 140
 141static inline struct line6_pcm_stream *
 142get_stream(struct snd_line6_pcm *line6pcm, int direction)
 143{
 144        return (direction == SNDRV_PCM_STREAM_PLAYBACK) ?
 145                &line6pcm->out : &line6pcm->in;
 146}
 147
 148/* allocate a buffer if not opened yet;
 149 * call this in line6pcm.state_mutex
 150 */
 151static int line6_buffer_acquire(struct snd_line6_pcm *line6pcm,
 152                                struct line6_pcm_stream *pstr, int direction, int type)
 153{
 154        const int pkt_size =
 155                (direction == SNDRV_PCM_STREAM_PLAYBACK) ?
 156                        line6pcm->max_packet_size_out :
 157                        line6pcm->max_packet_size_in;
 158
 159        /* Invoked multiple times in a row so allocate once only */
 160        if (!test_and_set_bit(type, &pstr->opened) && !pstr->buffer) {
 161                pstr->buffer =
 162                        kmalloc(array3_size(line6pcm->line6->iso_buffers,
 163                                            LINE6_ISO_PACKETS, pkt_size),
 164                                GFP_KERNEL);
 165                if (!pstr->buffer)
 166                        return -ENOMEM;
 167        }
 168        return 0;
 169}
 170
 171/* free a buffer if all streams are closed;
 172 * call this in line6pcm.state_mutex
 173 */
 174static void line6_buffer_release(struct snd_line6_pcm *line6pcm,
 175                                 struct line6_pcm_stream *pstr, int type)
 176{
 177        clear_bit(type, &pstr->opened);
 178        if (!pstr->opened) {
 179                line6_wait_clear_audio_urbs(line6pcm, pstr);
 180                kfree(pstr->buffer);
 181                pstr->buffer = NULL;
 182        }
 183}
 184
 185/* start a PCM stream */
 186static int line6_stream_start(struct snd_line6_pcm *line6pcm, int direction,
 187                              int type)
 188{
 189        unsigned long flags;
 190        struct line6_pcm_stream *pstr = get_stream(line6pcm, direction);
 191        int ret = 0;
 192
 193        spin_lock_irqsave(&pstr->lock, flags);
 194        if (!test_and_set_bit(type, &pstr->running) &&
 195            !(pstr->active_urbs || pstr->unlink_urbs)) {
 196                pstr->count = 0;
 197                /* Submit all currently available URBs */
 198                if (direction == SNDRV_PCM_STREAM_PLAYBACK)
 199                        ret = line6_submit_audio_out_all_urbs(line6pcm);
 200                else
 201                        ret = line6_submit_audio_in_all_urbs(line6pcm);
 202        }
 203
 204        if (ret < 0)
 205                clear_bit(type, &pstr->running);
 206        spin_unlock_irqrestore(&pstr->lock, flags);
 207        return ret;
 208}
 209
 210/* stop a PCM stream; this doesn't sync with the unlinked URBs */
 211static void line6_stream_stop(struct snd_line6_pcm *line6pcm, int direction,
 212                          int type)
 213{
 214        unsigned long flags;
 215        struct line6_pcm_stream *pstr = get_stream(line6pcm, direction);
 216
 217        spin_lock_irqsave(&pstr->lock, flags);
 218        clear_bit(type, &pstr->running);
 219        if (!pstr->running) {
 220                spin_unlock_irqrestore(&pstr->lock, flags);
 221                line6_unlink_audio_urbs(line6pcm, pstr);
 222                spin_lock_irqsave(&pstr->lock, flags);
 223                if (direction == SNDRV_PCM_STREAM_CAPTURE) {
 224                        line6pcm->prev_fbuf = NULL;
 225                        line6pcm->prev_fsize = 0;
 226                }
 227        }
 228        spin_unlock_irqrestore(&pstr->lock, flags);
 229}
 230
 231/* common PCM trigger callback */
 232int snd_line6_trigger(struct snd_pcm_substream *substream, int cmd)
 233{
 234        struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
 235        struct snd_pcm_substream *s;
 236        int err;
 237
 238        clear_bit(LINE6_FLAG_PREPARED, &line6pcm->flags);
 239
 240        snd_pcm_group_for_each_entry(s, substream) {
 241                if (s->pcm->card != substream->pcm->card)
 242                        continue;
 243
 244                switch (cmd) {
 245                case SNDRV_PCM_TRIGGER_START:
 246                case SNDRV_PCM_TRIGGER_RESUME:
 247                        if (s->stream == SNDRV_PCM_STREAM_CAPTURE &&
 248                                (line6pcm->line6->properties->capabilities &
 249                                        LINE6_CAP_IN_NEEDS_OUT)) {
 250                                err = line6_stream_start(line6pcm, SNDRV_PCM_STREAM_PLAYBACK,
 251                                                 LINE6_STREAM_CAPTURE_HELPER);
 252                                if (err < 0)
 253                                        return err;
 254                        }
 255                        err = line6_stream_start(line6pcm, s->stream,
 256                                                 LINE6_STREAM_PCM);
 257                        if (err < 0)
 258                                return err;
 259                        break;
 260
 261                case SNDRV_PCM_TRIGGER_STOP:
 262                case SNDRV_PCM_TRIGGER_SUSPEND:
 263                        if (s->stream == SNDRV_PCM_STREAM_CAPTURE &&
 264                                (line6pcm->line6->properties->capabilities &
 265                                        LINE6_CAP_IN_NEEDS_OUT)) {
 266                                line6_stream_stop(line6pcm, SNDRV_PCM_STREAM_PLAYBACK,
 267                                          LINE6_STREAM_CAPTURE_HELPER);
 268                        }
 269                        line6_stream_stop(line6pcm, s->stream,
 270                                          LINE6_STREAM_PCM);
 271                        break;
 272
 273                case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
 274                        if (s->stream != SNDRV_PCM_STREAM_PLAYBACK)
 275                                return -EINVAL;
 276                        set_bit(LINE6_FLAG_PAUSE_PLAYBACK, &line6pcm->flags);
 277                        break;
 278
 279                case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
 280                        if (s->stream != SNDRV_PCM_STREAM_PLAYBACK)
 281                                return -EINVAL;
 282                        clear_bit(LINE6_FLAG_PAUSE_PLAYBACK, &line6pcm->flags);
 283                        break;
 284
 285                default:
 286                        return -EINVAL;
 287                }
 288        }
 289
 290        return 0;
 291}
 292
 293/* common PCM pointer callback */
 294snd_pcm_uframes_t snd_line6_pointer(struct snd_pcm_substream *substream)
 295{
 296        struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
 297        struct line6_pcm_stream *pstr = get_stream(line6pcm, substream->stream);
 298
 299        return pstr->pos_done;
 300}
 301
 302/* Acquire and optionally start duplex streams:
 303 * type is either LINE6_STREAM_IMPULSE or LINE6_STREAM_MONITOR
 304 */
 305int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int type, bool start)
 306{
 307        struct line6_pcm_stream *pstr;
 308        int ret = 0, dir;
 309
 310        /* TODO: We should assert SNDRV_PCM_STREAM_PLAYBACK/CAPTURE == 0/1 */
 311        mutex_lock(&line6pcm->state_mutex);
 312        for (dir = 0; dir < 2; dir++) {
 313                pstr = get_stream(line6pcm, dir);
 314                ret = line6_buffer_acquire(line6pcm, pstr, dir, type);
 315                if (ret < 0)
 316                        goto error;
 317                if (!pstr->running)
 318                        line6_wait_clear_audio_urbs(line6pcm, pstr);
 319        }
 320        if (start) {
 321                for (dir = 0; dir < 2; dir++) {
 322                        ret = line6_stream_start(line6pcm, dir, type);
 323                        if (ret < 0)
 324                                goto error;
 325                }
 326        }
 327 error:
 328        mutex_unlock(&line6pcm->state_mutex);
 329        if (ret < 0)
 330                line6_pcm_release(line6pcm, type);
 331        return ret;
 332}
 333EXPORT_SYMBOL_GPL(line6_pcm_acquire);
 334
 335/* Stop and release duplex streams */
 336void line6_pcm_release(struct snd_line6_pcm *line6pcm, int type)
 337{
 338        struct line6_pcm_stream *pstr;
 339        int dir;
 340
 341        mutex_lock(&line6pcm->state_mutex);
 342        for (dir = 0; dir < 2; dir++)
 343                line6_stream_stop(line6pcm, dir, type);
 344        for (dir = 0; dir < 2; dir++) {
 345                pstr = get_stream(line6pcm, dir);
 346                line6_buffer_release(line6pcm, pstr, type);
 347        }
 348        mutex_unlock(&line6pcm->state_mutex);
 349}
 350EXPORT_SYMBOL_GPL(line6_pcm_release);
 351
 352/* common PCM hw_params callback */
 353int snd_line6_hw_params(struct snd_pcm_substream *substream,
 354                        struct snd_pcm_hw_params *hw_params)
 355{
 356        int ret;
 357        struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
 358        struct line6_pcm_stream *pstr = get_stream(line6pcm, substream->stream);
 359
 360        mutex_lock(&line6pcm->state_mutex);
 361        ret = line6_buffer_acquire(line6pcm, pstr, substream->stream,
 362                                   LINE6_STREAM_PCM);
 363        if (ret < 0)
 364                goto error;
 365
 366        ret = snd_pcm_lib_malloc_pages(substream,
 367                                       params_buffer_bytes(hw_params));
 368        if (ret < 0) {
 369                line6_buffer_release(line6pcm, pstr, LINE6_STREAM_PCM);
 370                goto error;
 371        }
 372
 373        pstr->period = params_period_bytes(hw_params);
 374 error:
 375        mutex_unlock(&line6pcm->state_mutex);
 376        return ret;
 377}
 378
 379/* common PCM hw_free callback */
 380int snd_line6_hw_free(struct snd_pcm_substream *substream)
 381{
 382        struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
 383        struct line6_pcm_stream *pstr = get_stream(line6pcm, substream->stream);
 384
 385        mutex_lock(&line6pcm->state_mutex);
 386        line6_buffer_release(line6pcm, pstr, LINE6_STREAM_PCM);
 387        mutex_unlock(&line6pcm->state_mutex);
 388        return snd_pcm_lib_free_pages(substream);
 389}
 390
 391
 392/* control info callback */
 393static int snd_line6_control_playback_info(struct snd_kcontrol *kcontrol,
 394                                           struct snd_ctl_elem_info *uinfo)
 395{
 396        uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 397        uinfo->count = 2;
 398        uinfo->value.integer.min = 0;
 399        uinfo->value.integer.max = 256;
 400        return 0;
 401}
 402
 403/* control get callback */
 404static int snd_line6_control_playback_get(struct snd_kcontrol *kcontrol,
 405                                          struct snd_ctl_elem_value *ucontrol)
 406{
 407        int i;
 408        struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
 409
 410        for (i = 0; i < 2; i++)
 411                ucontrol->value.integer.value[i] = line6pcm->volume_playback[i];
 412
 413        return 0;
 414}
 415
 416/* control put callback */
 417static int snd_line6_control_playback_put(struct snd_kcontrol *kcontrol,
 418                                          struct snd_ctl_elem_value *ucontrol)
 419{
 420        int i, changed = 0;
 421        struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
 422
 423        for (i = 0; i < 2; i++)
 424                if (line6pcm->volume_playback[i] !=
 425                    ucontrol->value.integer.value[i]) {
 426                        line6pcm->volume_playback[i] =
 427                            ucontrol->value.integer.value[i];
 428                        changed = 1;
 429                }
 430
 431        return changed;
 432}
 433
 434/* control definition */
 435static const struct snd_kcontrol_new line6_controls[] = {
 436        {
 437                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 438                .name = "PCM Playback Volume",
 439                .info = snd_line6_control_playback_info,
 440                .get = snd_line6_control_playback_get,
 441                .put = snd_line6_control_playback_put
 442        },
 443        {
 444                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 445                .name = "Impulse Response Volume",
 446                .info = snd_line6_impulse_volume_info,
 447                .get = snd_line6_impulse_volume_get,
 448                .put = snd_line6_impulse_volume_put
 449        },
 450        {
 451                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 452                .name = "Impulse Response Period",
 453                .info = snd_line6_impulse_period_info,
 454                .get = snd_line6_impulse_period_get,
 455                .put = snd_line6_impulse_period_put
 456        },
 457};
 458
 459/*
 460        Cleanup the PCM device.
 461*/
 462static void cleanup_urbs(struct line6_pcm_stream *pcms, int iso_buffers)
 463{
 464        int i;
 465
 466        /* Most likely impossible in current code... */
 467        if (pcms->urbs == NULL)
 468                return;
 469
 470        for (i = 0; i < iso_buffers; i++) {
 471                if (pcms->urbs[i]) {
 472                        usb_kill_urb(pcms->urbs[i]);
 473                        usb_free_urb(pcms->urbs[i]);
 474                }
 475        }
 476        kfree(pcms->urbs);
 477        pcms->urbs = NULL;
 478}
 479
 480static void line6_cleanup_pcm(struct snd_pcm *pcm)
 481{
 482        struct snd_line6_pcm *line6pcm = snd_pcm_chip(pcm);
 483
 484        cleanup_urbs(&line6pcm->out, line6pcm->line6->iso_buffers);
 485        cleanup_urbs(&line6pcm->in, line6pcm->line6->iso_buffers);
 486        kfree(line6pcm);
 487}
 488
 489/* create a PCM device */
 490static int snd_line6_new_pcm(struct usb_line6 *line6, struct snd_pcm **pcm_ret)
 491{
 492        struct snd_pcm *pcm;
 493        int err;
 494
 495        err = snd_pcm_new(line6->card, (char *)line6->properties->name,
 496                          0, 1, 1, pcm_ret);
 497        if (err < 0)
 498                return err;
 499        pcm = *pcm_ret;
 500        strcpy(pcm->name, line6->properties->name);
 501
 502        /* set operators */
 503        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
 504                        &snd_line6_playback_ops);
 505        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_line6_capture_ops);
 506
 507        /* pre-allocation of buffers */
 508        snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
 509                                              snd_dma_continuous_data
 510                                              (GFP_KERNEL), 64 * 1024,
 511                                              128 * 1024);
 512        return 0;
 513}
 514
 515/*
 516        Sync with PCM stream stops.
 517*/
 518void line6_pcm_disconnect(struct snd_line6_pcm *line6pcm)
 519{
 520        line6_unlink_audio_urbs(line6pcm, &line6pcm->out);
 521        line6_unlink_audio_urbs(line6pcm, &line6pcm->in);
 522        line6_wait_clear_audio_urbs(line6pcm, &line6pcm->out);
 523        line6_wait_clear_audio_urbs(line6pcm, &line6pcm->in);
 524}
 525
 526/*
 527        Create and register the PCM device and mixer entries.
 528        Create URBs for playback and capture.
 529*/
 530int line6_init_pcm(struct usb_line6 *line6,
 531                   struct line6_pcm_properties *properties)
 532{
 533        int i, err;
 534        unsigned ep_read = line6->properties->ep_audio_r;
 535        unsigned ep_write = line6->properties->ep_audio_w;
 536        struct snd_pcm *pcm;
 537        struct snd_line6_pcm *line6pcm;
 538
 539        if (!(line6->properties->capabilities & LINE6_CAP_PCM))
 540                return 0;       /* skip PCM initialization and report success */
 541
 542        err = snd_line6_new_pcm(line6, &pcm);
 543        if (err < 0)
 544                return err;
 545
 546        line6pcm = kzalloc(sizeof(*line6pcm), GFP_KERNEL);
 547        if (!line6pcm)
 548                return -ENOMEM;
 549
 550        mutex_init(&line6pcm->state_mutex);
 551        line6pcm->pcm = pcm;
 552        line6pcm->properties = properties;
 553        line6pcm->volume_playback[0] = line6pcm->volume_playback[1] = 255;
 554        line6pcm->volume_monitor = 255;
 555        line6pcm->line6 = line6;
 556
 557        line6pcm->max_packet_size_in =
 558                usb_maxpacket(line6->usbdev,
 559                        usb_rcvisocpipe(line6->usbdev, ep_read), 0);
 560        line6pcm->max_packet_size_out =
 561                usb_maxpacket(line6->usbdev,
 562                        usb_sndisocpipe(line6->usbdev, ep_write), 1);
 563
 564        spin_lock_init(&line6pcm->out.lock);
 565        spin_lock_init(&line6pcm->in.lock);
 566        line6pcm->impulse_period = LINE6_IMPULSE_DEFAULT_PERIOD;
 567
 568        line6->line6pcm = line6pcm;
 569
 570        pcm->private_data = line6pcm;
 571        pcm->private_free = line6_cleanup_pcm;
 572
 573        err = line6_create_audio_out_urbs(line6pcm);
 574        if (err < 0)
 575                return err;
 576
 577        err = line6_create_audio_in_urbs(line6pcm);
 578        if (err < 0)
 579                return err;
 580
 581        /* mixer: */
 582        for (i = 0; i < ARRAY_SIZE(line6_controls); i++) {
 583                err = snd_ctl_add(line6->card,
 584                                  snd_ctl_new1(&line6_controls[i], line6pcm));
 585                if (err < 0)
 586                        return err;
 587        }
 588
 589        return 0;
 590}
 591EXPORT_SYMBOL_GPL(line6_init_pcm);
 592
 593/* prepare pcm callback */
 594int snd_line6_prepare(struct snd_pcm_substream *substream)
 595{
 596        struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
 597        struct line6_pcm_stream *pstr = get_stream(line6pcm, substream->stream);
 598
 599        mutex_lock(&line6pcm->state_mutex);
 600        if (!pstr->running)
 601                line6_wait_clear_audio_urbs(line6pcm, pstr);
 602
 603        if (!test_and_set_bit(LINE6_FLAG_PREPARED, &line6pcm->flags)) {
 604                line6pcm->out.count = 0;
 605                line6pcm->out.pos = 0;
 606                line6pcm->out.pos_done = 0;
 607                line6pcm->out.bytes = 0;
 608                line6pcm->in.count = 0;
 609                line6pcm->in.pos_done = 0;
 610                line6pcm->in.bytes = 0;
 611        }
 612
 613        mutex_unlock(&line6pcm->state_mutex);
 614        return 0;
 615}
 616