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