root/sound/drivers/pcm-indirect2.c

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

DEFINITIONS

This source file includes following definitions.
  1. snd_pcm_indirect2_stat
  2. snd_pcm_indirect2_increase_min_periods
  3. snd_pcm_indirect2_pointer
  4. snd_pcm_indirect2_playback_transfer
  5. snd_pcm_indirect2_playback_interrupt
  6. snd_pcm_indirect2_capture_transfer
  7. snd_pcm_indirect2_capture_interrupt

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * Helper functions for indirect PCM data transfer to a simple FIFO in
   4  * hardware (small, no possibility to read "hardware io position",
   5  * updating position done by interrupt, ...)
   6  *
   7  *  Copyright (c) by 2007  Joachim Foerster <JOFT@gmx.de>
   8  *
   9  *  Based on "pcm-indirect.h" (alsa-driver-1.0.13) by
  10  *
  11  *  Copyright (c) by Takashi Iwai <tiwai@suse.de>
  12  *                   Jaroslav Kysela <perex@suse.cz>
  13  */
  14 
  15 /* snd_printk/d() */
  16 #include <sound/core.h>
  17 /* struct snd_pcm_substream, struct snd_pcm_runtime, snd_pcm_uframes_t
  18  * snd_pcm_period_elapsed() */
  19 #include <sound/pcm.h>
  20 
  21 #include "pcm-indirect2.h"
  22 
  23 #ifdef SND_PCM_INDIRECT2_STAT
  24 /* jiffies */
  25 #include <linux/jiffies.h>
  26 
  27 void snd_pcm_indirect2_stat(struct snd_pcm_substream *substream,
  28                             struct snd_pcm_indirect2 *rec)
  29 {
  30         struct snd_pcm_runtime *runtime = substream->runtime;
  31         int i;
  32         int j;
  33         int k;
  34         int seconds = (rec->lastbytetime - rec->firstbytetime) / HZ;
  35 
  36         snd_printk(KERN_DEBUG "STAT: mul_elapsed: %u, mul_elapsed_real: %d, "
  37                    "irq_occurred: %d\n",
  38                    rec->mul_elapsed, rec->mul_elapsed_real, rec->irq_occured);
  39         snd_printk(KERN_DEBUG "STAT: min_multiple: %d (irqs/period)\n",
  40                    rec->min_multiple);
  41         snd_printk(KERN_DEBUG "STAT: firstbytetime: %lu, lastbytetime: %lu, "
  42                    "firstzerotime: %lu\n",
  43                  rec->firstbytetime, rec->lastbytetime, rec->firstzerotime);
  44         snd_printk(KERN_DEBUG "STAT: bytes2hw: %u Bytes => (by runtime->rate) "
  45                    "length: %d s\n",
  46                  rec->bytes2hw, rec->bytes2hw / 2 / 2 / runtime->rate);
  47         snd_printk(KERN_DEBUG "STAT: (by measurement) length: %d => "
  48                    "rate: %d Bytes/s = %d Frames/s|Hz\n",
  49                    seconds, rec->bytes2hw / seconds,
  50                    rec->bytes2hw / 2 / 2 / seconds);
  51         snd_printk(KERN_DEBUG
  52                    "STAT: zeros2hw: %u = %d ms ~ %d * %d zero copies\n",
  53                    rec->zeros2hw, ((rec->zeros2hw / 2 / 2) * 1000) /
  54                    runtime->rate,
  55                    rec->zeros2hw / (rec->hw_buffer_size / 2),
  56                    (rec->hw_buffer_size / 2));
  57         snd_printk(KERN_DEBUG "STAT: pointer_calls: %u, lastdifftime: %u\n",
  58                    rec->pointer_calls, rec->lastdifftime);
  59         snd_printk(KERN_DEBUG "STAT: sw_io: %d, sw_data: %d\n", rec->sw_io,
  60                    rec->sw_data);
  61         snd_printk(KERN_DEBUG "STAT: byte_sizes[]:\n");
  62         k = 0;
  63         for (j = 0; j < 8; j++) {
  64                 for (i = j * 8; i < (j + 1) * 8; i++)
  65                         if (rec->byte_sizes[i] != 0) {
  66                                 snd_printk(KERN_DEBUG "%u: %u",
  67                                            i, rec->byte_sizes[i]);
  68                                 k++;
  69                         }
  70                 if (((k % 8) == 0) && (k != 0)) {
  71                         snd_printk(KERN_DEBUG "\n");
  72                         k = 0;
  73                 }
  74         }
  75         snd_printk(KERN_DEBUG "\n");
  76         snd_printk(KERN_DEBUG "STAT: zero_sizes[]:\n");
  77         for (j = 0; j < 8; j++) {
  78                 k = 0;
  79                 for (i = j * 8; i < (j + 1) * 8; i++)
  80                         if (rec->zero_sizes[i] != 0)
  81                                 snd_printk(KERN_DEBUG "%u: %u",
  82                                            i, rec->zero_sizes[i]);
  83                         else
  84                                 k++;
  85                 if (!k)
  86                         snd_printk(KERN_DEBUG "\n");
  87         }
  88         snd_printk(KERN_DEBUG "\n");
  89         snd_printk(KERN_DEBUG "STAT: min_adds[]:\n");
  90         for (j = 0; j < 8; j++) {
  91                 if (rec->min_adds[j] != 0)
  92                         snd_printk(KERN_DEBUG "%u: %u", j, rec->min_adds[j]);
  93         }
  94         snd_printk(KERN_DEBUG "\n");
  95         snd_printk(KERN_DEBUG "STAT: mul_adds[]:\n");
  96         for (j = 0; j < 8; j++) {
  97                 if (rec->mul_adds[j] != 0)
  98                         snd_printk(KERN_DEBUG "%u: %u", j, rec->mul_adds[j]);
  99         }
 100         snd_printk(KERN_DEBUG "\n");
 101         snd_printk(KERN_DEBUG
 102                    "STAT: zero_times_saved: %d, zero_times_notsaved: %d\n",
 103                    rec->zero_times_saved, rec->zero_times_notsaved);
 104         /* snd_printk(KERN_DEBUG "STAT: zero_times[]\n");
 105         i = 0;
 106         for (j = 0; j < 3750; j++) {
 107                 if (rec->zero_times[j] != 0) {
 108                         snd_printk(KERN_DEBUG "%u: %u", j, rec->zero_times[j]);
 109                         i++;
 110                 }
 111                 if (((i % 8) == 0) && (i != 0))
 112                         snd_printk(KERN_DEBUG "\n");
 113         }
 114         snd_printk(KERN_DEBUG "\n"); */
 115         return;
 116 }
 117 #endif
 118 
 119 /*
 120  * _internal_ helper function for playback/capture transfer function
 121  */
 122 static void
 123 snd_pcm_indirect2_increase_min_periods(struct snd_pcm_substream *substream,
 124                                        struct snd_pcm_indirect2 *rec,
 125                                        int isplay, int iscopy,
 126                                        unsigned int bytes)
 127 {
 128         if (rec->min_periods >= 0) {
 129                 if (iscopy) {
 130                         rec->sw_io += bytes;
 131                         if (rec->sw_io >= rec->sw_buffer_size)
 132                                 rec->sw_io -= rec->sw_buffer_size;
 133                 } else if (isplay) {
 134                         /* If application does not write data in multiples of
 135                          * a period, move sw_data to the next correctly aligned
 136                          * position, so that sw_io can converge to it (in the
 137                          * next step).
 138                          */
 139                         if (!rec->check_alignment) {
 140                                 if (rec->bytes2hw %
 141                                     snd_pcm_lib_period_bytes(substream)) {
 142                                         unsigned bytes2hw_aligned =
 143                                             (1 +
 144                                              (rec->bytes2hw /
 145                                               snd_pcm_lib_period_bytes
 146                                               (substream))) *
 147                                             snd_pcm_lib_period_bytes
 148                                             (substream);
 149                                         rec->sw_data =
 150                                             bytes2hw_aligned %
 151                                             rec->sw_buffer_size;
 152 #ifdef SND_PCM_INDIRECT2_STAT
 153                                         snd_printk(KERN_DEBUG
 154                                                    "STAT: @re-align: aligned "
 155                                                    "bytes2hw to next period "
 156                                                    "size boundary: %d "
 157                                                    "(instead of %d)\n",
 158                                                    bytes2hw_aligned,
 159                                                    rec->bytes2hw);
 160                                         snd_printk(KERN_DEBUG
 161                                                    "STAT: @re-align: sw_data "
 162                                                    "moves to: %d\n",
 163                                                    rec->sw_data);
 164 #endif
 165                                 }
 166                                 rec->check_alignment = 1;
 167                         }
 168                         /* We are at the end and are copying zeros into the
 169                          * fifo.
 170                          * Now, we have to make sure that sw_io is increased
 171                          * until the position of sw_data: Filling the fifo with
 172                          * the first zeros means, the last bytes were played.
 173                          */
 174                         if (rec->sw_io != rec->sw_data) {
 175                                 unsigned int diff;
 176                                 if (rec->sw_data > rec->sw_io)
 177                                         diff = rec->sw_data - rec->sw_io;
 178                                 else
 179                                         diff = (rec->sw_buffer_size -
 180                                                 rec->sw_io) +
 181                                                 rec->sw_data;
 182                                 if (bytes >= diff)
 183                                         rec->sw_io = rec->sw_data;
 184                                 else {
 185                                         rec->sw_io += bytes;
 186                                         if (rec->sw_io >= rec->sw_buffer_size)
 187                                                 rec->sw_io -=
 188                                                     rec->sw_buffer_size;
 189                                 }
 190                         }
 191                 }
 192                 rec->min_period_count += bytes;
 193                 if (rec->min_period_count >= (rec->hw_buffer_size / 2)) {
 194                         rec->min_periods += (rec->min_period_count /
 195                                              (rec->hw_buffer_size / 2));
 196 #ifdef SND_PCM_INDIRECT2_STAT
 197                         if ((rec->min_period_count /
 198                              (rec->hw_buffer_size / 2)) > 7)
 199                                 snd_printk(KERN_DEBUG
 200                                            "STAT: more than 7 (%d) min_adds "
 201                                            "at once - too big to save!\n",
 202                                            (rec->min_period_count /
 203                                             (rec->hw_buffer_size / 2)));
 204                         else
 205                                 rec->min_adds[(rec->min_period_count /
 206                                                (rec->hw_buffer_size / 2))]++;
 207 #endif
 208                         rec->min_period_count = (rec->min_period_count %
 209                                                  (rec->hw_buffer_size / 2));
 210                 }
 211         } else if (isplay && iscopy)
 212                 rec->min_periods = 0;
 213 }
 214 
 215 /*
 216  * helper function for playback/capture pointer callback
 217  */
 218 snd_pcm_uframes_t
 219 snd_pcm_indirect2_pointer(struct snd_pcm_substream *substream,
 220                           struct snd_pcm_indirect2 *rec)
 221 {
 222 #ifdef SND_PCM_INDIRECT2_STAT
 223         rec->pointer_calls++;
 224 #endif
 225         return bytes_to_frames(substream->runtime, rec->sw_io);
 226 }
 227 
 228 /*
 229  * _internal_ helper function for playback interrupt callback
 230  */
 231 static void
 232 snd_pcm_indirect2_playback_transfer(struct snd_pcm_substream *substream,
 233                                     struct snd_pcm_indirect2 *rec,
 234                                     snd_pcm_indirect2_copy_t copy,
 235                                     snd_pcm_indirect2_zero_t zero)
 236 {
 237         struct snd_pcm_runtime *runtime = substream->runtime;
 238         snd_pcm_uframes_t appl_ptr = runtime->control->appl_ptr;
 239 
 240         /* runtime->control->appl_ptr: position where ALSA will write next time
 241          * rec->appl_ptr: position where ALSA was last time
 242          * diff: obviously ALSA wrote that much bytes into the intermediate
 243          * buffer since we checked last time
 244          */
 245         snd_pcm_sframes_t diff = appl_ptr - rec->appl_ptr;
 246 
 247         if (diff) {
 248 #ifdef SND_PCM_INDIRECT2_STAT
 249                 rec->lastdifftime = jiffies;
 250 #endif
 251                 if (diff < -(snd_pcm_sframes_t) (runtime->boundary / 2))
 252                         diff += runtime->boundary;
 253                 /* number of bytes "added" by ALSA increases the number of
 254                  * bytes which are ready to "be transferred to HW"/"played"
 255                  * Then, set rec->appl_ptr to not count bytes twice next time.
 256                  */
 257                 rec->sw_ready += (int)frames_to_bytes(runtime, diff);
 258                 rec->appl_ptr = appl_ptr;
 259         }
 260         if (rec->hw_ready && (rec->sw_ready <= 0)) {
 261                 unsigned int bytes;
 262 
 263 #ifdef SND_PCM_INDIRECT2_STAT
 264                 if (rec->firstzerotime == 0) {
 265                         rec->firstzerotime = jiffies;
 266                         snd_printk(KERN_DEBUG
 267                                    "STAT: @firstzerotime: mul_elapsed: %d, "
 268                                    "min_period_count: %d\n",
 269                                    rec->mul_elapsed, rec->min_period_count);
 270                         snd_printk(KERN_DEBUG
 271                                    "STAT: @firstzerotime: sw_io: %d, "
 272                                    "sw_data: %d, appl_ptr: %u\n",
 273                                    rec->sw_io, rec->sw_data,
 274                                    (unsigned int)appl_ptr);
 275                 }
 276                 if ((jiffies - rec->firstzerotime) < 3750) {
 277                         rec->zero_times[(jiffies - rec->firstzerotime)]++;
 278                         rec->zero_times_saved++;
 279                 } else
 280                         rec->zero_times_notsaved++;
 281 #endif
 282                 bytes = zero(substream, rec);
 283 
 284 #ifdef SND_PCM_INDIRECT2_STAT
 285                 rec->zeros2hw += bytes;
 286                 if (bytes < 64)
 287                         rec->zero_sizes[bytes]++;
 288                 else
 289                         snd_printk(KERN_DEBUG
 290                                    "STAT: %d zero Bytes copied to hardware at "
 291                                    "once - too big to save!\n",
 292                                    bytes);
 293 #endif
 294                 snd_pcm_indirect2_increase_min_periods(substream, rec, 1, 0,
 295                                                        bytes);
 296                 return;
 297         }
 298         while (rec->hw_ready && (rec->sw_ready > 0)) {
 299                 /* sw_to_end: max. number of bytes that can be read/take from
 300                  * the current position (sw_data) in _one_ step
 301                  */
 302                 unsigned int sw_to_end = rec->sw_buffer_size - rec->sw_data;
 303 
 304                 /* bytes: number of bytes we have available (for reading) */
 305                 unsigned int bytes = rec->sw_ready;
 306 
 307                 if (sw_to_end < bytes)
 308                         bytes = sw_to_end;
 309                 if (!bytes)
 310                         break;
 311 
 312 #ifdef SND_PCM_INDIRECT2_STAT
 313                 if (rec->firstbytetime == 0)
 314                         rec->firstbytetime = jiffies;
 315                 rec->lastbytetime = jiffies;
 316 #endif
 317                 /* copy bytes from intermediate buffer position sw_data to the
 318                  * HW and return number of bytes actually written
 319                  * Furthermore, set hw_ready to 0, if the fifo isn't empty
 320                  * now => more could be transferred to fifo
 321                  */
 322                 bytes = copy(substream, rec, bytes);
 323                 rec->bytes2hw += bytes;
 324 
 325 #ifdef SND_PCM_INDIRECT2_STAT
 326                 if (bytes < 64)
 327                         rec->byte_sizes[bytes]++;
 328                 else
 329                         snd_printk(KERN_DEBUG
 330                                    "STAT: %d Bytes copied to hardware at once "
 331                                    "- too big to save!\n",
 332                                    bytes);
 333 #endif
 334                 /* increase sw_data by the number of actually written bytes
 335                  * (= number of taken bytes from intermediate buffer)
 336                  */
 337                 rec->sw_data += bytes;
 338                 if (rec->sw_data == rec->sw_buffer_size)
 339                         rec->sw_data = 0;
 340                 /* now sw_data is the position where ALSA is going to write
 341                  * in the intermediate buffer next time = position we are going
 342                  * to read from next time
 343                  */
 344 
 345                 snd_pcm_indirect2_increase_min_periods(substream, rec, 1, 1,
 346                                                        bytes);
 347 
 348                 /* we read bytes from intermediate buffer, so we need to say
 349                  * that the number of bytes ready for transfer are decreased
 350                  * now
 351                  */
 352                 rec->sw_ready -= bytes;
 353         }
 354         return;
 355 }
 356 
 357 /*
 358  * helper function for playback interrupt routine
 359  */
 360 void
 361 snd_pcm_indirect2_playback_interrupt(struct snd_pcm_substream *substream,
 362                                      struct snd_pcm_indirect2 *rec,
 363                                      snd_pcm_indirect2_copy_t copy,
 364                                      snd_pcm_indirect2_zero_t zero)
 365 {
 366 #ifdef SND_PCM_INDIRECT2_STAT
 367         rec->irq_occured++;
 368 #endif
 369         /* hardware played some bytes, so there is room again (in fifo) */
 370         rec->hw_ready = 1;
 371 
 372         /* don't call ack() now, instead call transfer() function directly
 373          * (normally called by ack() )
 374          */
 375         snd_pcm_indirect2_playback_transfer(substream, rec, copy, zero);
 376 
 377         if (rec->min_periods >= rec->min_multiple) {
 378 #ifdef SND_PCM_INDIRECT2_STAT
 379                 if ((rec->min_periods / rec->min_multiple) > 7)
 380                         snd_printk(KERN_DEBUG
 381                                    "STAT: more than 7 (%d) mul_adds - too big "
 382                                    "to save!\n",
 383                                    (rec->min_periods / rec->min_multiple));
 384                 else
 385                         rec->mul_adds[(rec->min_periods /
 386                                        rec->min_multiple)]++;
 387                 rec->mul_elapsed_real += (rec->min_periods /
 388                                           rec->min_multiple);
 389                 rec->mul_elapsed++;
 390 #endif
 391                 rec->min_periods = (rec->min_periods % rec->min_multiple);
 392                 snd_pcm_period_elapsed(substream);
 393         }
 394 }
 395 
 396 /*
 397  * _internal_ helper function for capture interrupt callback
 398  */
 399 static void
 400 snd_pcm_indirect2_capture_transfer(struct snd_pcm_substream *substream,
 401                                    struct snd_pcm_indirect2 *rec,
 402                                    snd_pcm_indirect2_copy_t copy,
 403                                    snd_pcm_indirect2_zero_t null)
 404 {
 405         struct snd_pcm_runtime *runtime = substream->runtime;
 406         snd_pcm_uframes_t appl_ptr = runtime->control->appl_ptr;
 407         snd_pcm_sframes_t diff = appl_ptr - rec->appl_ptr;
 408 
 409         if (diff) {
 410 #ifdef SND_PCM_INDIRECT2_STAT
 411                 rec->lastdifftime = jiffies;
 412 #endif
 413                 if (diff < -(snd_pcm_sframes_t) (runtime->boundary / 2))
 414                         diff += runtime->boundary;
 415                 rec->sw_ready -= frames_to_bytes(runtime, diff);
 416                 rec->appl_ptr = appl_ptr;
 417         }
 418         /* if hardware has something, but the intermediate buffer is full
 419          * => skip contents of buffer
 420          */
 421         if (rec->hw_ready && (rec->sw_ready >= (int)rec->sw_buffer_size)) {
 422                 unsigned int bytes;
 423 
 424 #ifdef SND_PCM_INDIRECT2_STAT
 425                 if (rec->firstzerotime == 0) {
 426                         rec->firstzerotime = jiffies;
 427                         snd_printk(KERN_DEBUG "STAT: (capture) "
 428                                    "@firstzerotime: mul_elapsed: %d, "
 429                                    "min_period_count: %d\n",
 430                                    rec->mul_elapsed, rec->min_period_count);
 431                         snd_printk(KERN_DEBUG "STAT: (capture) "
 432                                    "@firstzerotime: sw_io: %d, sw_data: %d, "
 433                                    "appl_ptr: %u\n",
 434                                    rec->sw_io, rec->sw_data,
 435                                    (unsigned int)appl_ptr);
 436                 }
 437                 if ((jiffies - rec->firstzerotime) < 3750) {
 438                         rec->zero_times[(jiffies - rec->firstzerotime)]++;
 439                         rec->zero_times_saved++;
 440                 } else
 441                         rec->zero_times_notsaved++;
 442 #endif
 443                 bytes = null(substream, rec);
 444 
 445 #ifdef SND_PCM_INDIRECT2_STAT
 446                 rec->zeros2hw += bytes;
 447                 if (bytes < 64)
 448                         rec->zero_sizes[bytes]++;
 449                 else
 450                         snd_printk(KERN_DEBUG
 451                                    "STAT: (capture) %d zero Bytes copied to "
 452                                    "hardware at once - too big to save!\n",
 453                                    bytes);
 454 #endif
 455                 snd_pcm_indirect2_increase_min_periods(substream, rec, 0, 0,
 456                                                        bytes);
 457                 /* report an overrun */
 458                 rec->sw_io = SNDRV_PCM_POS_XRUN;
 459                 return;
 460         }
 461         while (rec->hw_ready && (rec->sw_ready < (int)rec->sw_buffer_size)) {
 462                 /* sw_to_end: max. number of bytes that we can write to the
 463                  *  intermediate buffer (until it's end)
 464                  */
 465                 size_t sw_to_end = rec->sw_buffer_size - rec->sw_data;
 466 
 467                 /* bytes: max. number of bytes, which may be copied to the
 468                  *  intermediate buffer without overflow (in _one_ step)
 469                  */
 470                 size_t bytes = rec->sw_buffer_size - rec->sw_ready;
 471 
 472                 /* limit number of bytes (for transfer) by available room in
 473                  * the intermediate buffer
 474                  */
 475                 if (sw_to_end < bytes)
 476                         bytes = sw_to_end;
 477                 if (!bytes)
 478                         break;
 479 
 480 #ifdef SND_PCM_INDIRECT2_STAT
 481                 if (rec->firstbytetime == 0)
 482                         rec->firstbytetime = jiffies;
 483                 rec->lastbytetime = jiffies;
 484 #endif
 485                 /* copy bytes from the intermediate buffer (position sw_data)
 486                  * to the HW at most and return number of bytes actually copied
 487                  * from HW
 488                  * Furthermore, set hw_ready to 0, if the fifo is empty now.
 489                  */
 490                 bytes = copy(substream, rec, bytes);
 491                 rec->bytes2hw += bytes;
 492 
 493 #ifdef SND_PCM_INDIRECT2_STAT
 494                 if (bytes < 64)
 495                         rec->byte_sizes[bytes]++;
 496                 else
 497                         snd_printk(KERN_DEBUG
 498                                    "STAT: (capture) %d Bytes copied to "
 499                                    "hardware at once - too big to save!\n",
 500                                    bytes);
 501 #endif
 502                 /* increase sw_data by the number of actually copied bytes from
 503                  * HW
 504                  */
 505                 rec->sw_data += bytes;
 506                 if (rec->sw_data == rec->sw_buffer_size)
 507                         rec->sw_data = 0;
 508 
 509                 snd_pcm_indirect2_increase_min_periods(substream, rec, 0, 1,
 510                                                        bytes);
 511 
 512                 /* number of bytes in the intermediate buffer, which haven't
 513                  * been fetched by ALSA yet.
 514                  */
 515                 rec->sw_ready += bytes;
 516         }
 517         return;
 518 }
 519 
 520 /*
 521  * helper function for capture interrupt routine
 522  */
 523 void
 524 snd_pcm_indirect2_capture_interrupt(struct snd_pcm_substream *substream,
 525                                     struct snd_pcm_indirect2 *rec,
 526                                     snd_pcm_indirect2_copy_t copy,
 527                                     snd_pcm_indirect2_zero_t null)
 528 {
 529 #ifdef SND_PCM_INDIRECT2_STAT
 530         rec->irq_occured++;
 531 #endif
 532         /* hardware recorded some bytes, so there is something to read from the
 533          * record fifo:
 534          */
 535         rec->hw_ready = 1;
 536 
 537         /* don't call ack() now, instead call transfer() function directly
 538          * (normally called by ack() )
 539          */
 540         snd_pcm_indirect2_capture_transfer(substream, rec, copy, null);
 541 
 542         if (rec->min_periods >= rec->min_multiple) {
 543 
 544 #ifdef SND_PCM_INDIRECT2_STAT
 545                 if ((rec->min_periods / rec->min_multiple) > 7)
 546                         snd_printk(KERN_DEBUG
 547                                    "STAT: more than 7 (%d) mul_adds - "
 548                                    "too big to save!\n",
 549                                    (rec->min_periods / rec->min_multiple));
 550                 else
 551                         rec->mul_adds[(rec->min_periods /
 552                                        rec->min_multiple)]++;
 553                 rec->mul_elapsed_real += (rec->min_periods /
 554                                           rec->min_multiple);
 555                 rec->mul_elapsed++;
 556 #endif
 557                 rec->min_periods = (rec->min_periods % rec->min_multiple);
 558                 snd_pcm_period_elapsed(substream);
 559         }
 560 }

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