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        pstr->period = params_period_bytes(hw_params);
 363 error:
 364        mutex_unlock(&line6pcm->state_mutex);
 365        return ret;
 366}
 367
 368/* common PCM hw_free callback */
 369int snd_line6_hw_free(struct snd_pcm_substream *substream)
 370{
 371        struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
 372        struct line6_pcm_stream *pstr = get_stream(line6pcm, substream->stream);
 373
 374        mutex_lock(&line6pcm->state_mutex);
 375        line6_buffer_release(line6pcm, pstr, LINE6_STREAM_PCM);
 376        mutex_unlock(&line6pcm->state_mutex);
 377        return 0;
 378}
 379
 380
 381/* control info callback */
 382static int snd_line6_control_playback_info(struct snd_kcontrol *kcontrol,
 383                                           struct snd_ctl_elem_info *uinfo)
 384{
 385        uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 386        uinfo->count = 2;
 387        uinfo->value.integer.min = 0;
 388        uinfo->value.integer.max = 256;
 389        return 0;
 390}
 391
 392/* control get callback */
 393static int snd_line6_control_playback_get(struct snd_kcontrol *kcontrol,
 394                                          struct snd_ctl_elem_value *ucontrol)
 395{
 396        int i;
 397        struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
 398
 399        for (i = 0; i < 2; i++)
 400                ucontrol->value.integer.value[i] = line6pcm->volume_playback[i];
 401
 402        return 0;
 403}
 404
 405/* control put callback */
 406static int snd_line6_control_playback_put(struct snd_kcontrol *kcontrol,
 407                                          struct snd_ctl_elem_value *ucontrol)
 408{
 409        int i, changed = 0;
 410        struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
 411
 412        for (i = 0; i < 2; i++)
 413                if (line6pcm->volume_playback[i] !=
 414                    ucontrol->value.integer.value[i]) {
 415                        line6pcm->volume_playback[i] =
 416                            ucontrol->value.integer.value[i];
 417                        changed = 1;
 418                }
 419
 420        return changed;
 421}
 422
 423/* control definition */
 424static const struct snd_kcontrol_new line6_controls[] = {
 425        {
 426                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 427                .name = "PCM Playback Volume",
 428                .info = snd_line6_control_playback_info,
 429                .get = snd_line6_control_playback_get,
 430                .put = snd_line6_control_playback_put
 431        },
 432        {
 433                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 434                .name = "Impulse Response Volume",
 435                .info = snd_line6_impulse_volume_info,
 436                .get = snd_line6_impulse_volume_get,
 437                .put = snd_line6_impulse_volume_put
 438        },
 439        {
 440                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 441                .name = "Impulse Response Period",
 442                .info = snd_line6_impulse_period_info,
 443                .get = snd_line6_impulse_period_get,
 444                .put = snd_line6_impulse_period_put
 445        },
 446};
 447
 448/*
 449        Cleanup the PCM device.
 450*/
 451static void cleanup_urbs(struct line6_pcm_stream *pcms, int iso_buffers)
 452{
 453        int i;
 454
 455        /* Most likely impossible in current code... */
 456        if (pcms->urbs == NULL)
 457                return;
 458
 459        for (i = 0; i < iso_buffers; i++) {
 460                if (pcms->urbs[i]) {
 461                        usb_kill_urb(pcms->urbs[i]);
 462                        usb_free_urb(pcms->urbs[i]);
 463                }
 464        }
 465        kfree(pcms->urbs);
 466        pcms->urbs = NULL;
 467}
 468
 469static void line6_cleanup_pcm(struct snd_pcm *pcm)
 470{
 471        struct snd_line6_pcm *line6pcm = snd_pcm_chip(pcm);
 472
 473        cleanup_urbs(&line6pcm->out, line6pcm->line6->iso_buffers);
 474        cleanup_urbs(&line6pcm->in, line6pcm->line6->iso_buffers);
 475        kfree(line6pcm);
 476}
 477
 478/* create a PCM device */
 479static int snd_line6_new_pcm(struct usb_line6 *line6, struct snd_pcm **pcm_ret)
 480{
 481        struct snd_pcm *pcm;
 482        int err;
 483
 484        err = snd_pcm_new(line6->card, (char *)line6->properties->name,
 485                          0, 1, 1, pcm_ret);
 486        if (err < 0)
 487                return err;
 488        pcm = *pcm_ret;
 489        strcpy(pcm->name, line6->properties->name);
 490
 491        /* set operators */
 492        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
 493                        &snd_line6_playback_ops);
 494        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_line6_capture_ops);
 495
 496        /* pre-allocation of buffers */
 497        snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
 498                                       NULL, 64 * 1024, 128 * 1024);
 499        return 0;
 500}
 501
 502/*
 503        Sync with PCM stream stops.
 504*/
 505void line6_pcm_disconnect(struct snd_line6_pcm *line6pcm)
 506{
 507        line6_unlink_audio_urbs(line6pcm, &line6pcm->out);
 508        line6_unlink_audio_urbs(line6pcm, &line6pcm->in);
 509        line6_wait_clear_audio_urbs(line6pcm, &line6pcm->out);
 510        line6_wait_clear_audio_urbs(line6pcm, &line6pcm->in);
 511}
 512
 513/*
 514        Create and register the PCM device and mixer entries.
 515        Create URBs for playback and capture.
 516*/
 517int line6_init_pcm(struct usb_line6 *line6,
 518                   struct line6_pcm_properties *properties)
 519{
 520        int i, err;
 521        unsigned ep_read = line6->properties->ep_audio_r;
 522        unsigned ep_write = line6->properties->ep_audio_w;
 523        struct snd_pcm *pcm;
 524        struct snd_line6_pcm *line6pcm;
 525
 526        if (!(line6->properties->capabilities & LINE6_CAP_PCM))
 527                return 0;       /* skip PCM initialization and report success */
 528
 529        err = snd_line6_new_pcm(line6, &pcm);
 530        if (err < 0)
 531                return err;
 532
 533        line6pcm = kzalloc(sizeof(*line6pcm), GFP_KERNEL);
 534        if (!line6pcm)
 535                return -ENOMEM;
 536
 537        mutex_init(&line6pcm->state_mutex);
 538        line6pcm->pcm = pcm;
 539        line6pcm->properties = properties;
 540        line6pcm->volume_playback[0] = line6pcm->volume_playback[1] = 255;
 541        line6pcm->volume_monitor = 255;
 542        line6pcm->line6 = line6;
 543
 544        spin_lock_init(&line6pcm->out.lock);
 545        spin_lock_init(&line6pcm->in.lock);
 546        line6pcm->impulse_period = LINE6_IMPULSE_DEFAULT_PERIOD;
 547
 548        line6->line6pcm = line6pcm;
 549
 550        pcm->private_data = line6pcm;
 551        pcm->private_free = line6_cleanup_pcm;
 552
 553        line6pcm->max_packet_size_in =
 554                usb_maxpacket(line6->usbdev,
 555                        usb_rcvisocpipe(line6->usbdev, ep_read), 0);
 556        line6pcm->max_packet_size_out =
 557                usb_maxpacket(line6->usbdev,
 558                        usb_sndisocpipe(line6->usbdev, ep_write), 1);
 559        if (!line6pcm->max_packet_size_in || !line6pcm->max_packet_size_out) {
 560                dev_err(line6pcm->line6->ifcdev,
 561                        "cannot get proper max packet size\n");
 562                return -EINVAL;
 563        }
 564
 565        err = line6_create_audio_out_urbs(line6pcm);
 566        if (err < 0)
 567                return err;
 568
 569        err = line6_create_audio_in_urbs(line6pcm);
 570        if (err < 0)
 571                return err;
 572
 573        /* mixer: */
 574        for (i = 0; i < ARRAY_SIZE(line6_controls); i++) {
 575                err = snd_ctl_add(line6->card,
 576                                  snd_ctl_new1(&line6_controls[i], line6pcm));
 577                if (err < 0)
 578                        return err;
 579        }
 580
 581        return 0;
 582}
 583EXPORT_SYMBOL_GPL(line6_init_pcm);
 584
 585/* prepare pcm callback */
 586int snd_line6_prepare(struct snd_pcm_substream *substream)
 587{
 588        struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
 589        struct line6_pcm_stream *pstr = get_stream(line6pcm, substream->stream);
 590
 591        mutex_lock(&line6pcm->state_mutex);
 592        if (!pstr->running)
 593                line6_wait_clear_audio_urbs(line6pcm, pstr);
 594
 595        if (!test_and_set_bit(LINE6_FLAG_PREPARED, &line6pcm->flags)) {
 596                line6pcm->out.count = 0;
 597                line6pcm->out.pos = 0;
 598                line6pcm->out.pos_done = 0;
 599                line6pcm->out.bytes = 0;
 600                line6pcm->in.count = 0;
 601                line6pcm->in.pos_done = 0;
 602                line6pcm->in.bytes = 0;
 603        }
 604
 605        mutex_unlock(&line6pcm->state_mutex);
 606        return 0;
 607}
 608