root/sound/usb/line6/playback.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. change_volume
  2. create_impulse_test_signal
  3. add_monitor_signal
  4. submit_audio_out_urb
  5. line6_submit_audio_out_all_urbs
  6. audio_out_callback
  7. snd_line6_playback_open
  8. snd_line6_playback_close
  9. line6_create_audio_out_urbs

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

/* [<][>][^][v][top][bottom][index][help] */