linux/sound/usb/line6/playback.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 <sound/core.h>
  14#include <sound/pcm.h>
  15#include <sound/pcm_params.h>
  16
  17#include "capture.h"
  18#include "driver.h"
  19#include "pcm.h"
  20#include "playback.h"
  21
  22/*
  23        Software stereo volume control.
  24*/
  25static void change_volume(struct urb *urb_out, int volume[],
  26                          int bytes_per_frame)
  27{
  28        int chn = 0;
  29
  30        if (volume[0] == 256 && volume[1] == 256)
  31                return;         /* maximum volume - no change */
  32
  33        if (bytes_per_frame == 4) {
  34                __le16 *p, *buf_end;
  35
  36                p = (__le16 *)urb_out->transfer_buffer;
  37                buf_end = p + urb_out->transfer_buffer_length / sizeof(*p);
  38
  39                for (; p < buf_end; ++p) {
  40                        short pv = le16_to_cpu(*p);
  41                        int val = (pv * volume[chn & 1]) >> 8;
  42                        pv = clamp(val, -0x8000, 0x7fff);
  43                        *p = cpu_to_le16(pv);
  44                        ++chn;
  45                }
  46        } else if (bytes_per_frame == 6) {
  47                unsigned char *p, *buf_end;
  48
  49                p = (unsigned char *)urb_out->transfer_buffer;
  50                buf_end = p + urb_out->transfer_buffer_length;
  51
  52                for (; p < buf_end; p += 3) {
  53                        int val;
  54
  55                        val = p[0] + (p[1] << 8) + ((signed char)p[2] << 16);
  56                        val = (val * volume[chn & 1]) >> 8;
  57                        val = clamp(val, -0x800000, 0x7fffff);
  58                        p[0] = val;
  59                        p[1] = val >> 8;
  60                        p[2] = val >> 16;
  61                        ++chn;
  62                }
  63        }
  64}
  65
  66/*
  67        Create signal for impulse response test.
  68*/
  69static void create_impulse_test_signal(struct snd_line6_pcm *line6pcm,
  70                                       struct urb *urb_out, int bytes_per_frame)
  71{
  72        int frames = urb_out->transfer_buffer_length / bytes_per_frame;
  73
  74        if (bytes_per_frame == 4) {
  75                int i;
  76                short *pi = (short *)line6pcm->prev_fbuf;
  77                short *po = (short *)urb_out->transfer_buffer;
  78
  79                for (i = 0; i < frames; ++i) {
  80                        po[0] = pi[0];
  81                        po[1] = 0;
  82                        pi += 2;
  83                        po += 2;
  84                }
  85        } else if (bytes_per_frame == 6) {
  86                int i, j;
  87                unsigned char *pi = line6pcm->prev_fbuf;
  88                unsigned char *po = urb_out->transfer_buffer;
  89
  90                for (i = 0; i < frames; ++i) {
  91                        for (j = 0; j < bytes_per_frame / 2; ++j)
  92                                po[j] = pi[j];
  93
  94                        for (; j < bytes_per_frame; ++j)
  95                                po[j] = 0;
  96
  97                        pi += bytes_per_frame;
  98                        po += bytes_per_frame;
  99                }
 100        }
 101        if (--line6pcm->impulse_count <= 0) {
 102                ((unsigned char *)(urb_out->transfer_buffer))[bytes_per_frame -
 103                                                              1] =
 104                    line6pcm->impulse_volume;
 105                line6pcm->impulse_count = line6pcm->impulse_period;
 106        }
 107}
 108
 109/*
 110        Add signal to buffer for software monitoring.
 111*/
 112static void add_monitor_signal(struct urb *urb_out, unsigned char *signal,
 113                               int volume, int bytes_per_frame)
 114{
 115        if (volume == 0)
 116                return;         /* zero volume - no change */
 117
 118        if (bytes_per_frame == 4) {
 119                __le16 *pi, *po, *buf_end;
 120
 121                pi = (__le16 *)signal;
 122                po = (__le16 *)urb_out->transfer_buffer;
 123                buf_end = po + urb_out->transfer_buffer_length / sizeof(*po);
 124
 125                for (; po < buf_end; ++pi, ++po) {
 126                        short pov = le16_to_cpu(*po);
 127                        short piv = le16_to_cpu(*pi);
 128                        int val = pov + ((piv * volume) >> 8);
 129                        pov = clamp(val, -0x8000, 0x7fff);
 130                        *po = cpu_to_le16(pov);
 131                }
 132        }
 133
 134        /*
 135           We don't need to handle devices with 6 bytes per frame here
 136           since they all support hardware monitoring.
 137         */
 138}
 139
 140/*
 141        Find a free URB, prepare audio data, and submit URB.
 142        must be called in line6pcm->out.lock context
 143*/
 144static int submit_audio_out_urb(struct snd_line6_pcm *line6pcm)
 145{
 146        int index;
 147        int i, urb_size, urb_frames;
 148        int ret;
 149        const int bytes_per_frame = line6pcm->properties->bytes_per_frame;
 150        const int frame_increment =
 151                line6pcm->properties->rates.rats[0].num_min;
 152        const int frame_factor =
 153                line6pcm->properties->rates.rats[0].den *
 154                (USB_INTERVALS_PER_SECOND / LINE6_ISO_INTERVAL);
 155        struct urb *urb_out;
 156
 157        index =
 158            find_first_zero_bit(&line6pcm->out.active_urbs, LINE6_ISO_BUFFERS);
 159
 160        if (index < 0 || index >= LINE6_ISO_BUFFERS) {
 161                dev_err(line6pcm->line6->ifcdev, "no free URB found\n");
 162                return -EINVAL;
 163        }
 164
 165        urb_out = line6pcm->out.urbs[index];
 166        urb_size = 0;
 167
 168        for (i = 0; i < LINE6_ISO_PACKETS; ++i) {
 169                /* compute frame size for given sampling rate */
 170                int fsize = 0;
 171                struct usb_iso_packet_descriptor *fout =
 172                    &urb_out->iso_frame_desc[i];
 173
 174                fsize = line6pcm->prev_fsize;
 175                if (fsize == 0) {
 176                        int n;
 177
 178                        line6pcm->out.count += frame_increment;
 179                        n = line6pcm->out.count / frame_factor;
 180                        line6pcm->out.count -= n * frame_factor;
 181                        fsize = n * bytes_per_frame;
 182                }
 183
 184                fout->offset = urb_size;
 185                fout->length = fsize;
 186                urb_size += fsize;
 187        }
 188
 189        if (urb_size == 0) {
 190                /* can't determine URB size */
 191                dev_err(line6pcm->line6->ifcdev, "driver bug: urb_size = 0\n");
 192                return -EINVAL;
 193        }
 194
 195        urb_frames = urb_size / bytes_per_frame;
 196        urb_out->transfer_buffer =
 197            line6pcm->out.buffer +
 198            index * LINE6_ISO_PACKETS * line6pcm->max_packet_size;
 199        urb_out->transfer_buffer_length = urb_size;
 200        urb_out->context = line6pcm;
 201
 202        if (test_bit(LINE6_STREAM_PCM, &line6pcm->out.running) &&
 203            !test_bit(LINE6_FLAG_PAUSE_PLAYBACK, &line6pcm->flags)) {
 204                struct snd_pcm_runtime *runtime =
 205                    get_substream(line6pcm, SNDRV_PCM_STREAM_PLAYBACK)->runtime;
 206
 207                if (line6pcm->out.pos + urb_frames > runtime->buffer_size) {
 208                        /*
 209                           The transferred area goes over buffer boundary,
 210                           copy the data to the temp buffer.
 211                         */
 212                        int len;
 213
 214                        len = runtime->buffer_size - line6pcm->out.pos;
 215
 216                        if (len > 0) {
 217                                memcpy(urb_out->transfer_buffer,
 218                                       runtime->dma_area +
 219                                       line6pcm->out.pos * bytes_per_frame,
 220                                       len * bytes_per_frame);
 221                                memcpy(urb_out->transfer_buffer +
 222                                       len * bytes_per_frame, runtime->dma_area,
 223                                       (urb_frames - len) * bytes_per_frame);
 224                        } else
 225                                dev_err(line6pcm->line6->ifcdev, "driver bug: len = %d\n",
 226                                        len);
 227                } else {
 228                        memcpy(urb_out->transfer_buffer,
 229                               runtime->dma_area +
 230                               line6pcm->out.pos * bytes_per_frame,
 231                               urb_out->transfer_buffer_length);
 232                }
 233
 234                line6pcm->out.pos += urb_frames;
 235                if (line6pcm->out.pos >= runtime->buffer_size)
 236                        line6pcm->out.pos -= runtime->buffer_size;
 237
 238                change_volume(urb_out, line6pcm->volume_playback,
 239                              bytes_per_frame);
 240        } else {
 241                memset(urb_out->transfer_buffer, 0,
 242                       urb_out->transfer_buffer_length);
 243        }
 244
 245        spin_lock_nested(&line6pcm->in.lock, SINGLE_DEPTH_NESTING);
 246        if (line6pcm->prev_fbuf) {
 247                if (test_bit(LINE6_STREAM_IMPULSE, &line6pcm->out.running)) {
 248                        create_impulse_test_signal(line6pcm, urb_out,
 249                                                   bytes_per_frame);
 250                        if (test_bit(LINE6_STREAM_PCM, &line6pcm->in.running)) {
 251                                line6_capture_copy(line6pcm,
 252                                                   urb_out->transfer_buffer,
 253                                                   urb_out->
 254                                                   transfer_buffer_length);
 255                                line6_capture_check_period(line6pcm,
 256                                        urb_out->transfer_buffer_length);
 257                        }
 258                } else {
 259                        if (!(line6pcm->line6->properties->capabilities & LINE6_CAP_HWMON)
 260                            && line6pcm->out.running && line6pcm->in.running)
 261                                add_monitor_signal(urb_out, line6pcm->prev_fbuf,
 262                                                   line6pcm->volume_monitor,
 263                                                   bytes_per_frame);
 264                }
 265                line6pcm->prev_fbuf = NULL;
 266                line6pcm->prev_fsize = 0;
 267        }
 268        spin_unlock(&line6pcm->in.lock);
 269
 270        ret = usb_submit_urb(urb_out, GFP_ATOMIC);
 271
 272        if (ret == 0)
 273                set_bit(index, &line6pcm->out.active_urbs);
 274        else
 275                dev_err(line6pcm->line6->ifcdev,
 276                        "URB out #%d submission failed (%d)\n", index, ret);
 277
 278        return 0;
 279}
 280
 281/*
 282        Submit all currently available playback URBs.
 283        must be called in line6pcm->out.lock context
 284 */
 285int line6_submit_audio_out_all_urbs(struct snd_line6_pcm *line6pcm)
 286{
 287        int ret = 0, i;
 288
 289        for (i = 0; i < LINE6_ISO_BUFFERS; ++i) {
 290                ret = submit_audio_out_urb(line6pcm);
 291                if (ret < 0)
 292                        break;
 293        }
 294
 295        return ret;
 296}
 297
 298/*
 299        Callback for completed playback URB.
 300*/
 301static void audio_out_callback(struct urb *urb)
 302{
 303        int i, index, length = 0, shutdown = 0;
 304        unsigned long flags;
 305        struct snd_line6_pcm *line6pcm = (struct snd_line6_pcm *)urb->context;
 306        struct snd_pcm_substream *substream =
 307            get_substream(line6pcm, SNDRV_PCM_STREAM_PLAYBACK);
 308
 309#if USE_CLEAR_BUFFER_WORKAROUND
 310        memset(urb->transfer_buffer, 0, urb->transfer_buffer_length);
 311#endif
 312
 313        line6pcm->out.last_frame = urb->start_frame;
 314
 315        /* find index of URB */
 316        for (index = 0; index < LINE6_ISO_BUFFERS; index++)
 317                if (urb == line6pcm->out.urbs[index])
 318                        break;
 319
 320        if (index >= LINE6_ISO_BUFFERS)
 321                return;         /* URB has been unlinked asynchronously */
 322
 323        for (i = 0; i < LINE6_ISO_PACKETS; i++)
 324                length += urb->iso_frame_desc[i].length;
 325
 326        spin_lock_irqsave(&line6pcm->out.lock, flags);
 327
 328        if (test_bit(LINE6_STREAM_PCM, &line6pcm->out.running)) {
 329                struct snd_pcm_runtime *runtime = substream->runtime;
 330
 331                line6pcm->out.pos_done +=
 332                    length / line6pcm->properties->bytes_per_frame;
 333
 334                if (line6pcm->out.pos_done >= runtime->buffer_size)
 335                        line6pcm->out.pos_done -= runtime->buffer_size;
 336        }
 337
 338        clear_bit(index, &line6pcm->out.active_urbs);
 339
 340        for (i = 0; i < LINE6_ISO_PACKETS; i++)
 341                if (urb->iso_frame_desc[i].status == -EXDEV) {
 342                        shutdown = 1;
 343                        break;
 344                }
 345
 346        if (test_and_clear_bit(index, &line6pcm->out.unlink_urbs))
 347                shutdown = 1;
 348
 349        if (!shutdown) {
 350                submit_audio_out_urb(line6pcm);
 351
 352                if (test_bit(LINE6_STREAM_PCM, &line6pcm->out.running)) {
 353                        line6pcm->out.bytes += length;
 354                        if (line6pcm->out.bytes >= line6pcm->out.period) {
 355                                line6pcm->out.bytes %= line6pcm->out.period;
 356                                spin_unlock(&line6pcm->out.lock);
 357                                snd_pcm_period_elapsed(substream);
 358                                spin_lock(&line6pcm->out.lock);
 359                        }
 360                }
 361        }
 362        spin_unlock_irqrestore(&line6pcm->out.lock, flags);
 363}
 364
 365/* open playback callback */
 366static int snd_line6_playback_open(struct snd_pcm_substream *substream)
 367{
 368        int err;
 369        struct snd_pcm_runtime *runtime = substream->runtime;
 370        struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
 371
 372        err = snd_pcm_hw_constraint_ratdens(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
 373                                            &line6pcm->properties->rates);
 374        if (err < 0)
 375                return err;
 376
 377        runtime->hw = line6pcm->properties->playback_hw;
 378        return 0;
 379}
 380
 381/* close playback callback */
 382static int snd_line6_playback_close(struct snd_pcm_substream *substream)
 383{
 384        return 0;
 385}
 386
 387/* playback operators */
 388struct snd_pcm_ops snd_line6_playback_ops = {
 389        .open = snd_line6_playback_open,
 390        .close = snd_line6_playback_close,
 391        .ioctl = snd_pcm_lib_ioctl,
 392        .hw_params = snd_line6_hw_params,
 393        .hw_free = snd_line6_hw_free,
 394        .prepare = snd_line6_prepare,
 395        .trigger = snd_line6_trigger,
 396        .pointer = snd_line6_pointer,
 397};
 398
 399int line6_create_audio_out_urbs(struct snd_line6_pcm *line6pcm)
 400{
 401        struct usb_line6 *line6 = line6pcm->line6;
 402        int i;
 403
 404        /* create audio URBs and fill in constant values: */
 405        for (i = 0; i < LINE6_ISO_BUFFERS; ++i) {
 406                struct urb *urb;
 407
 408                /* URB for audio out: */
 409                urb = line6pcm->out.urbs[i] =
 410                    usb_alloc_urb(LINE6_ISO_PACKETS, GFP_KERNEL);
 411
 412                if (urb == NULL)
 413                        return -ENOMEM;
 414
 415                urb->dev = line6->usbdev;
 416                urb->pipe =
 417                    usb_sndisocpipe(line6->usbdev,
 418                                    line6->properties->ep_audio_w &
 419                                    USB_ENDPOINT_NUMBER_MASK);
 420                urb->transfer_flags = URB_ISO_ASAP;
 421                urb->start_frame = -1;
 422                urb->number_of_packets = LINE6_ISO_PACKETS;
 423                urb->interval = LINE6_ISO_INTERVAL;
 424                urb->error_count = 0;
 425                urb->complete = audio_out_callback;
 426        }
 427
 428        return 0;
 429}
 430