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 = kmalloc(line6pcm->line6->iso_buffers *
 162                                       LINE6_ISO_PACKETS * pkt_size, GFP_KERNEL);
 163                if (!pstr->buffer)
 164                        return -ENOMEM;
 165        }
 166        return 0;
 167}
 168
 169/* free a buffer if all streams are closed;
 170 * call this in line6pcm.state_mutex
 171 */
 172static void line6_buffer_release(struct snd_line6_pcm *line6pcm,
 173                                 struct line6_pcm_stream *pstr, int type)
 174{
 175        clear_bit(type, &pstr->opened);
 176        if (!pstr->opened) {
 177                line6_wait_clear_audio_urbs(line6pcm, pstr);
 178                kfree(pstr->buffer);
 179                pstr->buffer = NULL;
 180        }
 181}
 182
 183/* start a PCM stream */
 184static int line6_stream_start(struct snd_line6_pcm *line6pcm, int direction,
 185                              int type)
 186{
 187        unsigned long flags;
 188        struct line6_pcm_stream *pstr = get_stream(line6pcm, direction);
 189        int ret = 0;
 190
 191        spin_lock_irqsave(&pstr->lock, flags);
 192        if (!test_and_set_bit(type, &pstr->running) &&
 193            !(pstr->active_urbs || pstr->unlink_urbs)) {
 194                pstr->count = 0;
 195                /* Submit all currently available URBs */
 196                if (direction == SNDRV_PCM_STREAM_PLAYBACK)
 197                        ret = line6_submit_audio_out_all_urbs(line6pcm);
 198                else
 199                        ret = line6_submit_audio_in_all_urbs(line6pcm);
 200        }
 201
 202        if (ret < 0)
 203                clear_bit(type, &pstr->running);
 204        spin_unlock_irqrestore(&pstr->lock, flags);
 205        return ret;
 206}
 207
 208/* stop a PCM stream; this doesn't sync with the unlinked URBs */
 209static void line6_stream_stop(struct snd_line6_pcm *line6pcm, int direction,
 210                          int type)
 211{
 212        unsigned long flags;
 213        struct line6_pcm_stream *pstr = get_stream(line6pcm, direction);
 214
 215        spin_lock_irqsave(&pstr->lock, flags);
 216        clear_bit(type, &pstr->running);
 217        if (!pstr->running) {
 218                spin_unlock_irqrestore(&pstr->lock, flags);
 219                line6_unlink_audio_urbs(line6pcm, pstr);
 220                spin_lock_irqsave(&pstr->lock, flags);
 221                if (direction == SNDRV_PCM_STREAM_CAPTURE) {
 222                        line6pcm->prev_fbuf = NULL;
 223                        line6pcm->prev_fsize = 0;
 224                }
 225        }
 226        spin_unlock_irqrestore(&pstr->lock, flags);
 227}
 228
 229/* common PCM trigger callback */
 230int snd_line6_trigger(struct snd_pcm_substream *substream, int cmd)
 231{
 232        struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
 233        struct snd_pcm_substream *s;
 234        int err;
 235
 236        clear_bit(LINE6_FLAG_PREPARED, &line6pcm->flags);
 237
 238        snd_pcm_group_for_each_entry(s, substream) {
 239                if (s->pcm->card != substream->pcm->card)
 240                        continue;
 241
 242                switch (cmd) {
 243                case SNDRV_PCM_TRIGGER_START:
 244                case SNDRV_PCM_TRIGGER_RESUME:
 245                        if (s->stream == SNDRV_PCM_STREAM_CAPTURE &&
 246                                (line6pcm->line6->properties->capabilities &
 247                                        LINE6_CAP_IN_NEEDS_OUT)) {
 248                                err = line6_stream_start(line6pcm, SNDRV_PCM_STREAM_PLAYBACK,
 249                                                 LINE6_STREAM_CAPTURE_HELPER);
 250                                if (err < 0)
 251                                        return err;
 252                        }
 253                        err = line6_stream_start(line6pcm, s->stream,
 254                                                 LINE6_STREAM_PCM);
 255                        if (err < 0)
 256                                return err;
 257                        break;
 258
 259                case SNDRV_PCM_TRIGGER_STOP:
 260                case SNDRV_PCM_TRIGGER_SUSPEND:
 261                        if (s->stream == SNDRV_PCM_STREAM_CAPTURE &&
 262                                (line6pcm->line6->properties->capabilities &
 263                                        LINE6_CAP_IN_NEEDS_OUT)) {
 264                                line6_stream_stop(line6pcm, SNDRV_PCM_STREAM_PLAYBACK,
 265                                          LINE6_STREAM_CAPTURE_HELPER);
 266                        }
 267                        line6_stream_stop(line6pcm, s->stream,
 268                                          LINE6_STREAM_PCM);
 269                        break;
 270
 271                case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
 272                        if (s->stream != SNDRV_PCM_STREAM_PLAYBACK)
 273                                return -EINVAL;
 274                        set_bit(LINE6_FLAG_PAUSE_PLAYBACK, &line6pcm->flags);
 275                        break;
 276
 277                case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
 278                        if (s->stream != SNDRV_PCM_STREAM_PLAYBACK)
 279                                return -EINVAL;
 280                        clear_bit(LINE6_FLAG_PAUSE_PLAYBACK, &line6pcm->flags);
 281                        break;
 282
 283                default:
 284                        return -EINVAL;
 285                }
 286        }
 287
 288        return 0;
 289}
 290
 291/* common PCM pointer callback */
 292snd_pcm_uframes_t snd_line6_pointer(struct snd_pcm_substream *substream)
 293{
 294        struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
 295        struct line6_pcm_stream *pstr = get_stream(line6pcm, substream->stream);
 296
 297        return pstr->pos_done;
 298}
 299
 300/* Acquire and optionally start duplex streams:
 301 * type is either LINE6_STREAM_IMPULSE or LINE6_STREAM_MONITOR
 302 */
 303int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int type, bool start)
 304{
 305        struct line6_pcm_stream *pstr;
 306        int ret = 0, dir;
 307
 308        /* TODO: We should assert SNDRV_PCM_STREAM_PLAYBACK/CAPTURE == 0/1 */
 309        mutex_lock(&line6pcm->state_mutex);
 310        for (dir = 0; dir < 2; dir++) {
 311                pstr = get_stream(line6pcm, dir);
 312                ret = line6_buffer_acquire(line6pcm, pstr, dir, type);
 313                if (ret < 0)
 314                        goto error;
 315                if (!pstr->running)
 316                        line6_wait_clear_audio_urbs(line6pcm, pstr);
 317        }
 318        if (start) {
 319                for (dir = 0; dir < 2; dir++) {
 320                        ret = line6_stream_start(line6pcm, dir, type);
 321                        if (ret < 0)
 322                                goto error;
 323                }
 324        }
 325 error:
 326        mutex_unlock(&line6pcm->state_mutex);
 327        if (ret < 0)
 328                line6_pcm_release(line6pcm, type);
 329        return ret;
 330}
 331EXPORT_SYMBOL_GPL(line6_pcm_acquire);
 332
 333/* Stop and release duplex streams */
 334void line6_pcm_release(struct snd_line6_pcm *line6pcm, int type)
 335{
 336        struct line6_pcm_stream *pstr;
 337        int dir;
 338
 339        mutex_lock(&line6pcm->state_mutex);
 340        for (dir = 0; dir < 2; dir++)
 341                line6_stream_stop(line6pcm, dir, type);
 342        for (dir = 0; dir < 2; dir++) {
 343                pstr = get_stream(line6pcm, dir);
 344                line6_buffer_release(line6pcm, pstr, type);
 345        }
 346        mutex_unlock(&line6pcm->state_mutex);
 347}
 348EXPORT_SYMBOL_GPL(line6_pcm_release);
 349
 350/* common PCM hw_params callback */
 351int snd_line6_hw_params(struct snd_pcm_substream *substream,
 352                        struct snd_pcm_hw_params *hw_params)
 353{
 354        int ret;
 355        struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
 356        struct line6_pcm_stream *pstr = get_stream(line6pcm, substream->stream);
 357
 358        mutex_lock(&line6pcm->state_mutex);
 359        ret = line6_buffer_acquire(line6pcm, pstr, substream->stream,
 360                                   LINE6_STREAM_PCM);
 361        if (ret < 0)
 362                goto error;
 363
 364        ret = snd_pcm_lib_malloc_pages(substream,
 365                                       params_buffer_bytes(hw_params));
 366        if (ret < 0) {
 367                line6_buffer_release(line6pcm, pstr, LINE6_STREAM_PCM);
 368                goto error;
 369        }
 370
 371        pstr->period = params_period_bytes(hw_params);
 372 error:
 373        mutex_unlock(&line6pcm->state_mutex);
 374        return ret;
 375}
 376
 377/* common PCM hw_free callback */
 378int snd_line6_hw_free(struct snd_pcm_substream *substream)
 379{
 380        struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
 381        struct line6_pcm_stream *pstr = get_stream(line6pcm, substream->stream);
 382
 383        mutex_lock(&line6pcm->state_mutex);
 384        line6_buffer_release(line6pcm, pstr, LINE6_STREAM_PCM);
 385        mutex_unlock(&line6pcm->state_mutex);
 386        return snd_pcm_lib_free_pages(substream);
 387}
 388
 389
 390/* control info callback */
 391static int snd_line6_control_playback_info(struct snd_kcontrol *kcontrol,
 392                                           struct snd_ctl_elem_info *uinfo)
 393{
 394        uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 395        uinfo->count = 2;
 396        uinfo->value.integer.min = 0;
 397        uinfo->value.integer.max = 256;
 398        return 0;
 399}
 400
 401/* control get callback */
 402static int snd_line6_control_playback_get(struct snd_kcontrol *kcontrol,
 403                                          struct snd_ctl_elem_value *ucontrol)
 404{
 405        int i;
 406        struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
 407
 408        for (i = 0; i < 2; i++)
 409                ucontrol->value.integer.value[i] = line6pcm->volume_playback[i];
 410
 411        return 0;
 412}
 413
 414/* control put callback */
 415static int snd_line6_control_playback_put(struct snd_kcontrol *kcontrol,
 416                                          struct snd_ctl_elem_value *ucontrol)
 417{
 418        int i, changed = 0;
 419        struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
 420
 421        for (i = 0; i < 2; i++)
 422                if (line6pcm->volume_playback[i] !=
 423                    ucontrol->value.integer.value[i]) {
 424                        line6pcm->volume_playback[i] =
 425                            ucontrol->value.integer.value[i];
 426                        changed = 1;
 427                }
 428
 429        return changed;
 430}
 431
 432/* control definition */
 433static const struct snd_kcontrol_new line6_controls[] = {
 434        {
 435                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 436                .name = "PCM Playback Volume",
 437                .info = snd_line6_control_playback_info,
 438                .get = snd_line6_control_playback_get,
 439                .put = snd_line6_control_playback_put
 440        },
 441        {
 442                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 443                .name = "Impulse Response Volume",
 444                .info = snd_line6_impulse_volume_info,
 445                .get = snd_line6_impulse_volume_get,
 446                .put = snd_line6_impulse_volume_put
 447        },
 448        {
 449                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 450                .name = "Impulse Response Period",
 451                .info = snd_line6_impulse_period_info,
 452                .get = snd_line6_impulse_period_get,
 453                .put = snd_line6_impulse_period_put
 454        },
 455};
 456
 457/*
 458        Cleanup the PCM device.
 459*/
 460static void cleanup_urbs(struct line6_pcm_stream *pcms, int iso_buffers)
 461{
 462        int i;
 463
 464        /* Most likely impossible in current code... */
 465        if (pcms->urbs == NULL)
 466                return;
 467
 468        for (i = 0; i < iso_buffers; i++) {
 469                if (pcms->urbs[i]) {
 470                        usb_kill_urb(pcms->urbs[i]);
 471                        usb_free_urb(pcms->urbs[i]);
 472                }
 473        }
 474        kfree(pcms->urbs);
 475        pcms->urbs = NULL;
 476}
 477
 478static void line6_cleanup_pcm(struct snd_pcm *pcm)
 479{
 480        struct snd_line6_pcm *line6pcm = snd_pcm_chip(pcm);
 481
 482        cleanup_urbs(&line6pcm->out, line6pcm->line6->iso_buffers);
 483        cleanup_urbs(&line6pcm->in, line6pcm->line6->iso_buffers);
 484        kfree(line6pcm);
 485}
 486
 487/* create a PCM device */
 488static int snd_line6_new_pcm(struct usb_line6 *line6, struct snd_pcm **pcm_ret)
 489{
 490        struct snd_pcm *pcm;
 491        int err;
 492
 493        err = snd_pcm_new(line6->card, (char *)line6->properties->name,
 494                          0, 1, 1, pcm_ret);
 495        if (err < 0)
 496                return err;
 497        pcm = *pcm_ret;
 498        strcpy(pcm->name, line6->properties->name);
 499
 500        /* set operators */
 501        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
 502                        &snd_line6_playback_ops);
 503        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_line6_capture_ops);
 504
 505        /* pre-allocation of buffers */
 506        snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
 507                                              snd_dma_continuous_data
 508                                              (GFP_KERNEL), 64 * 1024,
 509                                              128 * 1024);
 510        return 0;
 511}
 512
 513/*
 514        Sync with PCM stream stops.
 515*/
 516void line6_pcm_disconnect(struct snd_line6_pcm *line6pcm)
 517{
 518        line6_unlink_audio_urbs(line6pcm, &line6pcm->out);
 519        line6_unlink_audio_urbs(line6pcm, &line6pcm->in);
 520        line6_wait_clear_audio_urbs(line6pcm, &line6pcm->out);
 521        line6_wait_clear_audio_urbs(line6pcm, &line6pcm->in);
 522}
 523
 524/*
 525        Create and register the PCM device and mixer entries.
 526        Create URBs for playback and capture.
 527*/
 528int line6_init_pcm(struct usb_line6 *line6,
 529                   struct line6_pcm_properties *properties)
 530{
 531        int i, err;
 532        unsigned ep_read = line6->properties->ep_audio_r;
 533        unsigned ep_write = line6->properties->ep_audio_w;
 534        struct snd_pcm *pcm;
 535        struct snd_line6_pcm *line6pcm;
 536
 537        if (!(line6->properties->capabilities & LINE6_CAP_PCM))
 538                return 0;       /* skip PCM initialization and report success */
 539
 540        err = snd_line6_new_pcm(line6, &pcm);
 541        if (err < 0)
 542                return err;
 543
 544        line6pcm = kzalloc(sizeof(*line6pcm), GFP_KERNEL);
 545        if (!line6pcm)
 546                return -ENOMEM;
 547
 548        mutex_init(&line6pcm->state_mutex);
 549        line6pcm->pcm = pcm;
 550        line6pcm->properties = properties;
 551        line6pcm->volume_playback[0] = line6pcm->volume_playback[1] = 255;
 552        line6pcm->volume_monitor = 255;
 553        line6pcm->line6 = line6;
 554
 555        line6pcm->max_packet_size_in =
 556                usb_maxpacket(line6->usbdev,
 557                        usb_rcvisocpipe(line6->usbdev, ep_read), 0);
 558        line6pcm->max_packet_size_out =
 559                usb_maxpacket(line6->usbdev,
 560                        usb_sndisocpipe(line6->usbdev, ep_write), 1);
 561
 562        spin_lock_init(&line6pcm->out.lock);
 563        spin_lock_init(&line6pcm->in.lock);
 564        line6pcm->impulse_period = LINE6_IMPULSE_DEFAULT_PERIOD;
 565
 566        line6->line6pcm = line6pcm;
 567
 568        pcm->private_data = line6pcm;
 569        pcm->private_free = line6_cleanup_pcm;
 570
 571        err = line6_create_audio_out_urbs(line6pcm);
 572        if (err < 0)
 573                return err;
 574
 575        err = line6_create_audio_in_urbs(line6pcm);
 576        if (err < 0)
 577                return err;
 578
 579        /* mixer: */
 580        for (i = 0; i < ARRAY_SIZE(line6_controls); i++) {
 581                err = snd_ctl_add(line6->card,
 582                                  snd_ctl_new1(&line6_controls[i], line6pcm));
 583                if (err < 0)
 584                        return err;
 585        }
 586
 587        return 0;
 588}
 589EXPORT_SYMBOL_GPL(line6_init_pcm);
 590
 591/* prepare pcm callback */
 592int snd_line6_prepare(struct snd_pcm_substream *substream)
 593{
 594        struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
 595        struct line6_pcm_stream *pstr = get_stream(line6pcm, substream->stream);
 596
 597        mutex_lock(&line6pcm->state_mutex);
 598        if (!pstr->running)
 599                line6_wait_clear_audio_urbs(line6pcm, pstr);
 600
 601        if (!test_and_set_bit(LINE6_FLAG_PREPARED, &line6pcm->flags)) {
 602                line6pcm->out.count = 0;
 603                line6pcm->out.pos = 0;
 604                line6pcm->out.pos_done = 0;
 605                line6pcm->out.bytes = 0;
 606                line6pcm->in.count = 0;
 607                line6pcm->in.pos_done = 0;
 608                line6pcm->in.bytes = 0;
 609        }
 610
 611        mutex_unlock(&line6pcm->state_mutex);
 612        return 0;
 613}
 614