~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/sound/core/pcm_lib.c

Version: ~ [ linux-5.1-rc1 ] ~ [ linux-5.0.3 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.30 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.107 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.164 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.176 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.136 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.63 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.39.4 ] ~ [ linux-2.6.38.8 ] ~ [ linux-2.6.37.6 ] ~ [ linux-2.6.36.4 ] ~ [ linux-2.6.35.14 ] ~ [ linux-2.6.34.15 ] ~ [ linux-2.6.33.20 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  *  Digital Audio (PCM) abstract layer
  3  *  Copyright (c) by Jaroslav Kysela <perex@suse.cz>
  4  *                   Abramo Bagnara <abramo@alsa-project.org>
  5  *
  6  *
  7  *   This program is free software; you can redistribute it and/or modify
  8  *   it under the terms of the GNU General Public License as published by
  9  *   the Free Software Foundation; either version 2 of the License, or
 10  *   (at your option) any later version.
 11  *
 12  *   This program is distributed in the hope that it will be useful,
 13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 15  *   GNU General Public License for more details.
 16  *
 17  *   You should have received a copy of the GNU General Public License
 18  *   along with this program; if not, write to the Free Software
 19  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 20  *
 21  */
 22 
 23 #include <sound/driver.h>
 24 #include <linux/slab.h>
 25 #include <linux/time.h>
 26 #include <sound/core.h>
 27 #include <sound/control.h>
 28 #include <sound/info.h>
 29 #include <sound/pcm.h>
 30 #include <sound/pcm_params.h>
 31 #include <sound/timer.h>
 32 
 33 /*
 34  * fill ring buffer with silence
 35  * runtime->silence_start: starting pointer to silence area
 36  * runtime->silence_filled: size filled with silence
 37  * runtime->silence_threshold: threshold from application
 38  * runtime->silence_size: maximal size from application
 39  *
 40  * when runtime->silence_size >= runtime->boundary - fill processed area with silence immediately
 41  */
 42 void snd_pcm_playback_silence(snd_pcm_substream_t *substream, snd_pcm_uframes_t new_hw_ptr)
 43 {
 44         snd_pcm_runtime_t *runtime = substream->runtime;
 45         snd_pcm_uframes_t frames, ofs, transfer;
 46 
 47         if (runtime->silence_size < runtime->boundary) {
 48                 snd_pcm_sframes_t noise_dist, n;
 49                 if (runtime->silence_start != runtime->control->appl_ptr) {
 50                         n = runtime->control->appl_ptr - runtime->silence_start;
 51                         if (n < 0)
 52                                 n += runtime->boundary;
 53                         if ((snd_pcm_uframes_t)n < runtime->silence_filled)
 54                                 runtime->silence_filled -= n;
 55                         else
 56                                 runtime->silence_filled = 0;
 57                         runtime->silence_start = runtime->control->appl_ptr;
 58                 }
 59                 if (runtime->silence_filled == runtime->buffer_size)
 60                         return;
 61                 snd_assert(runtime->silence_filled <= runtime->buffer_size, return);
 62                 noise_dist = snd_pcm_playback_hw_avail(runtime) + runtime->silence_filled;
 63                 if (noise_dist >= (snd_pcm_sframes_t) runtime->silence_threshold)
 64                         return;
 65                 frames = runtime->silence_threshold - noise_dist;
 66                 if (frames > runtime->silence_size)
 67                         frames = runtime->silence_size;
 68         } else {
 69                 if (new_hw_ptr == ULONG_MAX) {  /* initialization */
 70                         runtime->silence_filled = 0;
 71                         runtime->silence_start = runtime->control->appl_ptr;
 72                 } else {
 73                         ofs = runtime->status->hw_ptr;
 74                         frames = new_hw_ptr - ofs;
 75                         if ((snd_pcm_sframes_t)frames < 0)
 76                                 frames += runtime->boundary;
 77                         runtime->silence_filled -= frames;
 78                         if ((snd_pcm_sframes_t)runtime->silence_filled < 0) {
 79                                 runtime->silence_filled = 0;
 80                                 runtime->silence_start = (ofs + frames) - runtime->buffer_size;
 81                         } else {
 82                                 runtime->silence_start = ofs - runtime->silence_filled;
 83                         }
 84                         if ((snd_pcm_sframes_t)runtime->silence_start < 0)
 85                                 runtime->silence_start += runtime->boundary;
 86                 }
 87                 frames = runtime->buffer_size - runtime->silence_filled;
 88         }
 89         snd_assert(frames <= runtime->buffer_size, return);
 90         if (frames == 0)
 91                 return;
 92         ofs = (runtime->silence_start + runtime->silence_filled) % runtime->buffer_size;
 93         while (frames > 0) {
 94                 transfer = ofs + frames > runtime->buffer_size ? runtime->buffer_size - ofs : frames;
 95                 if (runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED ||
 96                     runtime->access == SNDRV_PCM_ACCESS_MMAP_INTERLEAVED) {
 97                         if (substream->ops->silence) {
 98                                 int err;
 99                                 err = substream->ops->silence(substream, -1, ofs, transfer);
100                                 snd_assert(err >= 0, );
101                         } else {
102                                 char *hwbuf = runtime->dma_area + frames_to_bytes(runtime, ofs);
103                                 snd_pcm_format_set_silence(runtime->format, hwbuf, transfer * runtime->channels);
104                         }
105                 } else {
106                         unsigned int c;
107                         unsigned int channels = runtime->channels;
108                         if (substream->ops->silence) {
109                                 for (c = 0; c < channels; ++c) {
110                                         int err;
111                                         err = substream->ops->silence(substream, c, ofs, transfer);
112                                         snd_assert(err >= 0, );
113                                 }
114                         } else {
115                                 size_t dma_csize = runtime->dma_bytes / channels;
116                                 for (c = 0; c < channels; ++c) {
117                                         char *hwbuf = runtime->dma_area + (c * dma_csize) + samples_to_bytes(runtime, ofs);
118                                         snd_pcm_format_set_silence(runtime->format, hwbuf, transfer);
119                                 }
120                         }
121                 }
122                 runtime->silence_filled += transfer;
123                 frames -= transfer;
124                 ofs = 0;
125         }
126 }
127 
128 static inline int snd_pcm_update_hw_ptr_interrupt(snd_pcm_substream_t *substream)
129 {
130         snd_pcm_runtime_t *runtime = substream->runtime;
131         snd_pcm_uframes_t pos;
132         snd_pcm_uframes_t old_hw_ptr, new_hw_ptr, hw_ptr_interrupt;
133         snd_pcm_uframes_t avail;
134         snd_pcm_sframes_t delta;
135 
136         old_hw_ptr = runtime->status->hw_ptr;
137         pos = substream->ops->pointer(substream);
138         if (runtime->tstamp_mode & SNDRV_PCM_TSTAMP_MMAP)
139                 snd_timestamp_now((snd_timestamp_t*)&runtime->status->tstamp, runtime->tstamp_timespec);
140 #ifdef CONFIG_SND_DEBUG
141         if (pos >= runtime->buffer_size) {
142                 snd_printk(KERN_ERR  "BUG: stream = %i, pos = 0x%lx, buffer size = 0x%lx, period size = 0x%lx\n", substream->stream, pos, runtime->buffer_size, runtime->period_size);
143         } else
144 #endif
145         snd_runtime_check(pos < runtime->buffer_size, return 0);
146 
147         pos -= pos % runtime->min_align;
148         new_hw_ptr = runtime->hw_ptr_base + pos;
149 
150         hw_ptr_interrupt = runtime->hw_ptr_interrupt + runtime->period_size;
151 
152         delta = hw_ptr_interrupt - new_hw_ptr;
153         if (delta > 0) {
154                 if ((snd_pcm_uframes_t)delta < runtime->buffer_size / 2) {
155                         snd_printd("Unexpected hw_pointer value (stream = %i, delta: -%ld, max jitter = %ld): wrong interrupt acknowledge?\n", substream->stream, (long) delta, runtime->buffer_size / 2);
156                         return 0;
157                 }
158                 runtime->hw_ptr_base += runtime->buffer_size;
159                 if (runtime->hw_ptr_base == runtime->boundary)
160                         runtime->hw_ptr_base = 0;
161                 new_hw_ptr = runtime->hw_ptr_base + pos;
162         }
163 
164         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
165             runtime->silence_size > 0)
166                 snd_pcm_playback_silence(substream, new_hw_ptr);
167 
168         runtime->status->hw_ptr = new_hw_ptr;
169         runtime->hw_ptr_interrupt = new_hw_ptr - new_hw_ptr % runtime->period_size;
170 
171         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
172                 avail = snd_pcm_playback_avail(runtime);
173         else
174                 avail = snd_pcm_capture_avail(runtime);
175         if (avail > runtime->avail_max)
176                 runtime->avail_max = avail;
177         if (avail >= runtime->stop_threshold) {
178                 snd_pcm_stop(substream,
179                              runtime->status->state == SNDRV_PCM_STATE_DRAINING ?
180                              SNDRV_PCM_STATE_SETUP : SNDRV_PCM_STATE_XRUN);
181                 return -EPIPE;
182         }
183         if (avail >= runtime->control->avail_min)
184                 wake_up(&runtime->sleep);
185         return 0;
186 }
187 
188 /* CAUTION: call it with irq disabled */
189 int snd_pcm_update_hw_ptr(snd_pcm_substream_t *substream)
190 {
191         snd_pcm_runtime_t *runtime = substream->runtime;
192         snd_pcm_uframes_t pos;
193         snd_pcm_uframes_t old_hw_ptr, new_hw_ptr;
194         snd_pcm_uframes_t avail;
195         snd_pcm_sframes_t delta;
196 
197         old_hw_ptr = runtime->status->hw_ptr;
198         pos = substream->ops->pointer(substream);
199         if (runtime->tstamp_mode & SNDRV_PCM_TSTAMP_MMAP)
200                 snd_timestamp_now((snd_timestamp_t*)&runtime->status->tstamp, runtime->tstamp_timespec);
201 #ifdef CONFIG_SND_DEBUG
202         if (pos >= runtime->buffer_size) {
203                 snd_printk(KERN_ERR "BUG: stream = %i, pos = 0x%lx, buffer size = 0x%lx, period size = 0x%lx\n", substream->stream, pos, runtime->buffer_size, runtime->period_size);
204         } else
205 #endif
206         snd_runtime_check(pos < runtime->buffer_size, return 0);
207 
208         pos -= pos % runtime->min_align;
209         new_hw_ptr = runtime->hw_ptr_base + pos;
210 
211         delta = old_hw_ptr - new_hw_ptr;
212         if (delta > 0) {
213                 if ((snd_pcm_uframes_t)delta < runtime->buffer_size / 2) {
214                         snd_printd("Unexpected hw_pointer value (stream = %i, delta: -%ld, max jitter = %ld): wrong interrupt acknowledge?\n", substream->stream, (long) delta, runtime->buffer_size / 2);
215                         return 0;
216                 }
217                 runtime->hw_ptr_base += runtime->buffer_size;
218                 if (runtime->hw_ptr_base == runtime->boundary)
219                         runtime->hw_ptr_base = 0;
220                 new_hw_ptr = runtime->hw_ptr_base + pos;
221         }
222         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
223             runtime->silence_size > 0)
224                 snd_pcm_playback_silence(substream, new_hw_ptr);
225         runtime->status->hw_ptr = new_hw_ptr;
226 
227         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
228                 avail = snd_pcm_playback_avail(runtime);
229         else
230                 avail = snd_pcm_capture_avail(runtime);
231         if (avail > runtime->avail_max)
232                 runtime->avail_max = avail;
233         if (avail >= runtime->stop_threshold) {
234                 snd_pcm_stop(substream,
235                              runtime->status->state == SNDRV_PCM_STATE_DRAINING ?
236                              SNDRV_PCM_STATE_SETUP : SNDRV_PCM_STATE_XRUN);
237                 return -EPIPE;
238         }
239         if (avail >= runtime->control->avail_min)
240                 wake_up(&runtime->sleep);
241         return 0;
242 }
243 
244 /**
245  * snd_pcm_set_ops - set the PCM operators
246  * @pcm: the pcm instance
247  * @direction: stream direction, SNDRV_PCM_STREAM_XXX
248  * @ops: the operator table
249  *
250  * Sets the given PCM operators to the pcm instance.
251  */
252 void snd_pcm_set_ops(snd_pcm_t *pcm, int direction, snd_pcm_ops_t *ops)
253 {
254         snd_pcm_str_t *stream = &pcm->streams[direction];
255         snd_pcm_substream_t *substream;
256         
257         for (substream = stream->substream; substream != NULL; substream = substream->next)
258                 substream->ops = ops;
259 }
260 
261 
262 /**
263  * snd_pcm_sync - set the PCM sync id
264  * @substream: the pcm substream
265  *
266  * Sets the PCM sync identifier for the card.
267  */
268 void snd_pcm_set_sync(snd_pcm_substream_t * substream)
269 {
270         snd_pcm_runtime_t *runtime = substream->runtime;
271         
272         runtime->sync.id32[0] = substream->pcm->card->number;
273         runtime->sync.id32[1] = -1;
274         runtime->sync.id32[2] = -1;
275         runtime->sync.id32[3] = -1;
276 }
277 
278 /*
279  *  Standard ioctl routine
280  */
281 
282 /* Code taken from alsa-lib */
283 #define assert(a) snd_assert((a), return -EINVAL)
284 
285 static inline unsigned int div32(unsigned int a, unsigned int b, 
286                                  unsigned int *r)
287 {
288         if (b == 0) {
289                 *r = 0;
290                 return UINT_MAX;
291         }
292         *r = a % b;
293         return a / b;
294 }
295 
296 static inline unsigned int div_down(unsigned int a, unsigned int b)
297 {
298         if (b == 0)
299                 return UINT_MAX;
300         return a / b;
301 }
302 
303 static inline unsigned int div_up(unsigned int a, unsigned int b)
304 {
305         unsigned int r;
306         unsigned int q;
307         if (b == 0)
308                 return UINT_MAX;
309         q = div32(a, b, &r);
310         if (r)
311                 ++q;
312         return q;
313 }
314 
315 static inline unsigned int mul(unsigned int a, unsigned int b)
316 {
317         if (a == 0)
318                 return 0;
319         if (div_down(UINT_MAX, a) < b)
320                 return UINT_MAX;
321         return a * b;
322 }
323 
324 static inline unsigned int muldiv32(unsigned int a, unsigned int b,
325                                     unsigned int c, unsigned int *r)
326 {
327         u_int64_t n = (u_int64_t) a * b;
328         if (c == 0) {
329                 snd_assert(n > 0, );
330                 *r = 0;
331                 return UINT_MAX;
332         }
333         div64_32(&n, c, r);
334         if (n >= UINT_MAX) {
335                 *r = 0;
336                 return UINT_MAX;
337         }
338         return n;
339 }
340 
341 int snd_interval_refine_min(snd_interval_t *i, unsigned int min, int openmin)
342 {
343         int changed = 0;
344         assert(!snd_interval_empty(i));
345         if (i->min < min) {
346                 i->min = min;
347                 i->openmin = openmin;
348                 changed = 1;
349         } else if (i->min == min && !i->openmin && openmin) {
350                 i->openmin = 1;
351                 changed = 1;
352         }
353         if (i->integer) {
354                 if (i->openmin) {
355                         i->min++;
356                         i->openmin = 0;
357                 }
358         }
359         if (snd_interval_checkempty(i)) {
360                 snd_interval_none(i);
361                 return -EINVAL;
362         }
363         return changed;
364 }
365 
366 int snd_interval_refine_max(snd_interval_t *i, unsigned int max, int openmax)
367 {
368         int changed = 0;
369         assert(!snd_interval_empty(i));
370         if (i->max > max) {
371                 i->max = max;
372                 i->openmax = openmax;
373                 changed = 1;
374         } else if (i->max == max && !i->openmax && openmax) {
375                 i->openmax = 1;
376                 changed = 1;
377         }
378         if (i->integer) {
379                 if (i->openmax) {
380                         i->max--;
381                         i->openmax = 0;
382                 }
383         }
384         if (snd_interval_checkempty(i)) {
385                 snd_interval_none(i);
386                 return -EINVAL;
387         }
388         return changed;
389 }
390 
391 /**
392  * snd_interval_refine - refine the interval value of configurator
393  * @i: the interval value to refine
394  * @v: the interval value to refer to
395  *
396  * Refines the interval value with the reference value.
397  * The interval is changed to the range satisfying both intervals.
398  * The interval status (min, max, integer, etc.) are evaluated.
399  *
400  * Returns non-zero if the value is changed, zero if not changed.
401  */
402 int snd_interval_refine(snd_interval_t *i, const snd_interval_t *v)
403 {
404         int changed = 0;
405         assert(!snd_interval_empty(i));
406         if (i->min < v->min) {
407                 i->min = v->min;
408                 i->openmin = v->openmin;
409                 changed = 1;
410         } else if (i->min == v->min && !i->openmin && v->openmin) {
411                 i->openmin = 1;
412                 changed = 1;
413         }
414         if (i->max > v->max) {
415                 i->max = v->max;
416                 i->openmax = v->openmax;
417                 changed = 1;
418         } else if (i->max == v->max && !i->openmax && v->openmax) {
419                 i->openmax = 1;
420                 changed = 1;
421         }
422         if (!i->integer && v->integer) {
423                 i->integer = 1;
424                 changed = 1;
425         }
426         if (i->integer) {
427                 if (i->openmin) {
428                         i->min++;
429                         i->openmin = 0;
430                 }
431                 if (i->openmax) {
432                         i->max--;
433                         i->openmax = 0;
434                 }
435         } else if (!i->openmin && !i->openmax && i->min == i->max)
436                 i->integer = 1;
437         if (snd_interval_checkempty(i)) {
438                 snd_interval_none(i);
439                 return -EINVAL;
440         }
441         return changed;
442 }
443 
444 int snd_interval_refine_first(snd_interval_t *i)
445 {
446         assert(!snd_interval_empty(i));
447         if (snd_interval_single(i))
448                 return 0;
449         i->max = i->min;
450         i->openmax = i->openmin;
451         if (i->openmax)
452                 i->max++;
453         return 1;
454 }
455 
456 int snd_interval_refine_last(snd_interval_t *i)
457 {
458         assert(!snd_interval_empty(i));
459         if (snd_interval_single(i))
460                 return 0;
461         i->min = i->max;
462         i->openmin = i->openmax;
463         if (i->openmin)
464                 i->min--;
465         return 1;
466 }
467 
468 int snd_interval_refine_set(snd_interval_t *i, unsigned int val)
469 {
470         snd_interval_t t;
471         t.empty = 0;
472         t.min = t.max = val;
473         t.openmin = t.openmax = 0;
474         t.integer = 1;
475         return snd_interval_refine(i, &t);
476 }
477 
478 void snd_interval_mul(const snd_interval_t *a, const snd_interval_t *b, snd_interval_t *c)
479 {
480         if (a->empty || b->empty) {
481                 snd_interval_none(c);
482                 return;
483         }
484         c->empty = 0;
485         c->min = mul(a->min, b->min);
486         c->openmin = (a->openmin || b->openmin);
487         c->max = mul(a->max,  b->max);
488         c->openmax = (a->openmax || b->openmax);
489         c->integer = (a->integer && b->integer);
490 }
491 
492 /**
493  * snd_interval_div - refine the interval value with division
494  *
495  * c = a / b
496  *
497  * Returns non-zero if the value is changed, zero if not changed.
498  */
499 void snd_interval_div(const snd_interval_t *a, const snd_interval_t *b, snd_interval_t *c)
500 {
501         unsigned int r;
502         if (a->empty || b->empty) {
503                 snd_interval_none(c);
504                 return;
505         }
506         c->empty = 0;
507         c->min = div32(a->min, b->max, &r);
508         c->openmin = (r || a->openmin || b->openmax);
509         if (b->min > 0) {
510                 c->max = div32(a->max, b->min, &r);
511                 if (r) {
512                         c->max++;
513                         c->openmax = 1;
514                 } else
515                         c->openmax = (a->openmax || b->openmin);
516         } else {
517                 c->max = UINT_MAX;
518                 c->openmax = 0;
519         }
520         c->integer = 0;
521 }
522 
523 /**
524  * snd_interval_muldivk - refine the interval value
525  *
526  * c = a * b / k
527  *
528  * Returns non-zero if the value is changed, zero if not changed.
529  */
530 void snd_interval_muldivk(const snd_interval_t *a, const snd_interval_t *b,
531                       unsigned int k, snd_interval_t *c)
532 {
533         unsigned int r;
534         if (a->empty || b->empty) {
535                 snd_interval_none(c);
536                 return;
537         }
538         c->empty = 0;
539         c->min = muldiv32(a->min, b->min, k, &r);
540         c->openmin = (r || a->openmin || b->openmin);
541         c->max = muldiv32(a->max, b->max, k, &r);
542         if (r) {
543                 c->max++;
544                 c->openmax = 1;
545         } else
546                 c->openmax = (a->openmax || b->openmax);
547         c->integer = 0;
548 }
549 
550 /**
551  * snd_interval_mulkdiv - refine the interval value
552  *
553  * c = a * k / b
554  *
555  * Returns non-zero if the value is changed, zero if not changed.
556  */
557 void snd_interval_mulkdiv(const snd_interval_t *a, unsigned int k,
558                       const snd_interval_t *b, snd_interval_t *c)
559 {
560         unsigned int r;
561         if (a->empty || b->empty) {
562                 snd_interval_none(c);
563                 return;
564         }
565         c->empty = 0;
566         c->min = muldiv32(a->min, k, b->max, &r);
567         c->openmin = (r || a->openmin || b->openmax);
568         if (b->min > 0) {
569                 c->max = muldiv32(a->max, k, b->min, &r);
570                 if (r) {
571                         c->max++;
572                         c->openmax = 1;
573                 } else
574                         c->openmax = (a->openmax || b->openmin);
575         } else {
576                 c->max = UINT_MAX;
577                 c->openmax = 0;
578         }
579         c->integer = 0;
580 }
581 
582 #undef assert
583 /* ---- */
584 
585 
586 /**
587  * snd_interval_ratnum - refine the interval value
588  *
589  * Returns non-zero if the value is changed, zero if not changed.
590  */
591 int snd_interval_ratnum(snd_interval_t *i,
592                     unsigned int rats_count, ratnum_t *rats,
593                     unsigned int *nump, unsigned int *denp)
594 {
595         unsigned int best_num, best_diff, best_den;
596         unsigned int k;
597         snd_interval_t t;
598         int err;
599 
600         best_num = best_den = best_diff = 0;
601         for (k = 0; k < rats_count; ++k) {
602                 unsigned int num = rats[k].num;
603                 unsigned int den;
604                 unsigned int q = i->min;
605                 int diff;
606                 if (q == 0)
607                         q = 1;
608                 den = div_down(num, q);
609                 if (den < rats[k].den_min)
610                         continue;
611                 if (den > rats[k].den_max)
612                         den = rats[k].den_max;
613                 else {
614                         unsigned int r;
615                         r = (den - rats[k].den_min) % rats[k].den_step;
616                         if (r != 0)
617                                 den -= r;
618                 }
619                 diff = num - q * den;
620                 if (best_num == 0 ||
621                     diff * best_den < best_diff * den) {
622                         best_diff = diff;
623                         best_den = den;
624                         best_num = num;
625                 }
626         }
627         if (best_den == 0) {
628                 i->empty = 1;
629                 return -EINVAL;
630         }
631         t.min = div_down(best_num, best_den);
632         t.openmin = !!(best_num % best_den);
633         
634         best_num = best_den = best_diff = 0;
635         for (k = 0; k < rats_count; ++k) {
636                 unsigned int num = rats[k].num;
637                 unsigned int den;
638                 unsigned int q = i->max;
639                 int diff;
640                 if (q == 0) {
641                         i->empty = 1;
642                         return -EINVAL;
643                 }
644                 den = div_up(num, q);
645                 if (den > rats[k].den_max)
646                         continue;
647                 if (den < rats[k].den_min)
648                         den = rats[k].den_min;
649                 else {
650                         unsigned int r;
651                         r = (den - rats[k].den_min) % rats[k].den_step;
652                         if (r != 0)
653                                 den += rats[k].den_step - r;
654                 }
655                 diff = q * den - num;
656                 if (best_num == 0 ||
657                     diff * best_den < best_diff * den) {
658                         best_diff = diff;
659                         best_den = den;
660                         best_num = num;
661                 }
662         }
663         if (best_den == 0) {
664                 i->empty = 1;
665                 return -EINVAL;
666         }
667         t.max = div_up(best_num, best_den);
668         t.openmax = !!(best_num % best_den);
669         t.integer = 0;
670         err = snd_interval_refine(i, &t);
671         if (err < 0)
672                 return err;
673 
674         if (snd_interval_single(i)) {
675                 if (nump)
676                         *nump = best_num;
677                 if (denp)
678                         *denp = best_den;
679         }
680         return err;
681 }
682 
683 /**
684  * snd_interval_ratden - refine the interval value
685  *
686  * Returns non-zero if the value is changed, zero if not changed.
687  */
688 int snd_interval_ratden(snd_interval_t *i,
689                     unsigned int rats_count, ratden_t *rats,
690                     unsigned int *nump, unsigned int *denp)
691 {
692         unsigned int best_num, best_diff, best_den;
693         unsigned int k;
694         snd_interval_t t;
695         int err;
696 
697         best_num = best_den = best_diff = 0;
698         for (k = 0; k < rats_count; ++k) {
699                 unsigned int num;
700                 unsigned int den = rats[k].den;
701                 unsigned int q = i->min;
702                 int diff;
703                 num = mul(q, den);
704                 if (num > rats[k].num_max)
705                         continue;
706                 if (num < rats[k].num_min)
707                         num = rats[k].num_max;
708                 else {
709                         unsigned int r;
710                         r = (num - rats[k].num_min) % rats[k].num_step;
711                         if (r != 0)
712                                 num += rats[k].num_step - r;
713                 }
714                 diff = num - q * den;
715                 if (best_num == 0 ||
716                     diff * best_den < best_diff * den) {
717                         best_diff = diff;
718                         best_den = den;
719                         best_num = num;
720                 }
721         }
722         if (best_den == 0) {
723                 i->empty = 1;
724                 return -EINVAL;
725         }
726         t.min = div_down(best_num, best_den);
727         t.openmin = !!(best_num % best_den);
728         
729         best_num = best_den = best_diff = 0;
730         for (k = 0; k < rats_count; ++k) {
731                 unsigned int num;
732                 unsigned int den = rats[k].den;
733                 unsigned int q = i->max;
734                 int diff;
735                 num = mul(q, den);
736                 if (num < rats[k].num_min)
737                         continue;
738                 if (num > rats[k].num_max)
739                         num = rats[k].num_max;
740                 else {
741                         unsigned int r;
742                         r = (num - rats[k].num_min) % rats[k].num_step;
743                         if (r != 0)
744                                 num -= r;
745                 }
746                 diff = q * den - num;
747                 if (best_num == 0 ||
748                     diff * best_den < best_diff * den) {
749                         best_diff = diff;
750                         best_den = den;
751                         best_num = num;
752                 }
753         }
754         if (best_den == 0) {
755                 i->empty = 1;
756                 return -EINVAL;
757         }
758         t.max = div_up(best_num, best_den);
759         t.openmax = !!(best_num % best_den);
760         t.integer = 0;
761         err = snd_interval_refine(i, &t);
762         if (err < 0)
763                 return err;
764 
765         if (snd_interval_single(i)) {
766                 if (nump)
767                         *nump = best_num;
768                 if (denp)
769                         *denp = best_den;
770         }
771         return err;
772 }
773 
774 /**
775  * snd_interval_list - refine the interval value from the list
776  * @i: the interval value to refine
777  * @count: the number of elements in the list
778  * @list: the value list
779  * @mask: the bit-mask to evaluate
780  *
781  * Refines the interval value from the list.
782  * When mask is non-zero, only the elements corresponding to bit 1 are
783  * evaluated.
784  *
785  * Returns non-zero if the value is changed, zero if not changed.
786  */
787 int snd_interval_list(snd_interval_t *i, unsigned int count, unsigned int *list, unsigned int mask)
788 {
789         unsigned int k;
790         int changed = 0;
791         for (k = 0; k < count; k++) {
792                 if (mask && !(mask & (1 << k)))
793                         continue;
794                 if (i->min == list[k] && !i->openmin)
795                         goto _l1;
796                 if (i->min < list[k]) {
797                         i->min = list[k];
798                         i->openmin = 0;
799                         changed = 1;
800                         goto _l1;
801                 }
802         }
803         i->empty = 1;
804         return -EINVAL;
805  _l1:
806         for (k = count; k-- > 0;) {
807                 if (mask && !(mask & (1 << k)))
808                         continue;
809                 if (i->max == list[k] && !i->openmax)
810                         goto _l2;
811                 if (i->max > list[k]) {
812                         i->max = list[k];
813                         i->openmax = 0;
814                         changed = 1;
815                         goto _l2;
816                 }
817         }
818         i->empty = 1;
819         return -EINVAL;
820  _l2:
821         if (snd_interval_checkempty(i)) {
822                 i->empty = 1;
823                 return -EINVAL;
824         }
825         return changed;
826 }
827 
828 int snd_interval_step(snd_interval_t *i, unsigned int min, unsigned int step)
829 {
830         unsigned int n;
831         int changed = 0;
832         n = (i->min - min) % step;
833         if (n != 0 || i->openmin) {
834                 i->min += step - n;
835                 changed = 1;
836         }
837         n = (i->max - min) % step;
838         if (n != 0 || i->openmax) {
839                 i->max -= n;
840                 changed = 1;
841         }
842         if (snd_interval_checkempty(i)) {
843                 i->empty = 1;
844                 return -EINVAL;
845         }
846         return changed;
847 }
848 
849 /* Info constraints helpers */
850 
851 /**
852  * snd_pcm_hw_rule_add - add the hw-constraint rule
853  * @runtime: the pcm runtime instance
854  * @cond: condition bits
855  * @var: the variable to evaluate
856  * @func: the evaluation function
857  * @private: the private data pointer passed to function
858  * @dep: the dependent variables
859  *
860  * Returns zero if successful, or a negative error code on failure.
861  */
862 int snd_pcm_hw_rule_add(snd_pcm_runtime_t *runtime, unsigned int cond,
863                         int var,
864                         snd_pcm_hw_rule_func_t func, void *private,
865                         int dep, ...)
866 {
867         snd_pcm_hw_constraints_t *constrs = &runtime->hw_constraints;
868         snd_pcm_hw_rule_t *c;
869         unsigned int k;
870         va_list args;
871         va_start(args, dep);
872         if (constrs->rules_num >= constrs->rules_all) {
873                 snd_pcm_hw_rule_t *old = constrs->rules;
874                 if (constrs->rules_all == 0)
875                         constrs->rules_all = 32;
876                 else {
877                         old = constrs->rules;
878                         constrs->rules_all += 10;
879                 }
880                 constrs->rules = snd_kcalloc(constrs->rules_all * sizeof(*c),
881                                              GFP_KERNEL);
882                 if (!constrs->rules)
883                         return -ENOMEM;
884                 if (old) {
885                         memcpy(constrs->rules, old,
886                                constrs->rules_num * sizeof(*c));
887                         kfree(old);
888                 }
889         }
890         c = &constrs->rules[constrs->rules_num];
891         c->cond = cond;
892         c->func = func;
893         c->var = var;
894         c->private = private;
895         k = 0;
896         while (1) {
897                 snd_assert(k < sizeof(c->deps) / sizeof(c->deps[0]), return -EINVAL);
898                 c->deps[k++] = dep;
899                 if (dep < 0)
900                         break;
901                 dep = va_arg(args, int);
902         }
903         constrs->rules_num++;
904         va_end(args);
905         return 0;
906 }                                   
907 
908 /**
909  * snd_pcm_hw_constraint_mask
910  */
911 int snd_pcm_hw_constraint_mask(snd_pcm_runtime_t *runtime, snd_pcm_hw_param_t var,
912                                u_int32_t mask)
913 {
914         snd_pcm_hw_constraints_t *constrs = &runtime->hw_constraints;
915         snd_mask_t *maskp = constrs_mask(constrs, var);
916         *maskp->bits &= mask;
917         memset(maskp->bits + 1, 0, (SNDRV_MASK_MAX-32) / 8); /* clear rest */
918         if (*maskp->bits == 0)
919                 return -EINVAL;
920         return 0;
921 }
922 
923 /**
924  * snd_pcm_hw_constraint_mask64
925  */
926 int snd_pcm_hw_constraint_mask64(snd_pcm_runtime_t *runtime, snd_pcm_hw_param_t var,
927                                  u_int64_t mask)
928 {
929         snd_pcm_hw_constraints_t *constrs = &runtime->hw_constraints;
930         snd_mask_t *maskp = constrs_mask(constrs, var);
931         maskp->bits[0] &= (u_int32_t)mask;
932         maskp->bits[1] &= (u_int32_t)(mask >> 32);
933         memset(maskp->bits + 2, 0, (SNDRV_MASK_MAX-64) / 8); /* clear rest */
934         if (! maskp->bits[0] && ! maskp->bits[1])
935                 return -EINVAL;
936         return 0;
937 }
938 
939 /**
940  * snd_pcm_hw_constraint_integer
941  */
942 int snd_pcm_hw_constraint_integer(snd_pcm_runtime_t *runtime, snd_pcm_hw_param_t var)
943 {
944         snd_pcm_hw_constraints_t *constrs = &runtime->hw_constraints;
945         return snd_interval_setinteger(constrs_interval(constrs, var));
946 }
947 
948 /**
949  * snd_pcm_hw_constraint_minmax
950  */
951 int snd_pcm_hw_constraint_minmax(snd_pcm_runtime_t *runtime, snd_pcm_hw_param_t var,
952                                  unsigned int min, unsigned int max)
953 {
954         snd_pcm_hw_constraints_t *constrs = &runtime->hw_constraints;
955         snd_interval_t t;
956         t.min = min;
957         t.max = max;
958         t.openmin = t.openmax = 0;
959         t.integer = 0;
960         return snd_interval_refine(constrs_interval(constrs, var), &t);
961 }
962 
963 static int snd_pcm_hw_rule_list(snd_pcm_hw_params_t *params,
964                                 snd_pcm_hw_rule_t *rule)
965 {
966         snd_pcm_hw_constraint_list_t *list = rule->private;
967         return snd_interval_list(hw_param_interval(params, rule->var), list->count, list->list, list->mask);
968 }               
969 
970 
971 /**
972  * snd_pcm_hw_constraint_list
973  */
974 int snd_pcm_hw_constraint_list(snd_pcm_runtime_t *runtime,
975                                unsigned int cond,
976                                snd_pcm_hw_param_t var,
977                                snd_pcm_hw_constraint_list_t *l)
978 {
979         return snd_pcm_hw_rule_add(runtime, cond, var,
980                                    snd_pcm_hw_rule_list, l,
981                                    var, -1);
982 }
983 
984 static int snd_pcm_hw_rule_ratnums(snd_pcm_hw_params_t *params,
985                                    snd_pcm_hw_rule_t *rule)
986 {
987         snd_pcm_hw_constraint_ratnums_t *r = rule->private;
988         unsigned int num = 0, den = 0;
989         int err;
990         err = snd_interval_ratnum(hw_param_interval(params, rule->var),
991                                   r->nrats, r->rats, &num, &den);
992         if (err >= 0 && den && rule->var == SNDRV_PCM_HW_PARAM_RATE) {
993                 params->rate_num = num;
994                 params->rate_den = den;
995         }
996         return err;
997 }
998 
999 /**
1000  * snd_pcm_hw_constraint_ratnums
1001  */
1002 int snd_pcm_hw_constraint_ratnums(snd_pcm_runtime_t *runtime, 
1003                                   unsigned int cond,
1004                                   snd_pcm_hw_param_t var,
1005                                   snd_pcm_hw_constraint_ratnums_t *r)
1006 {
1007         return snd_pcm_hw_rule_add(runtime, cond, var,
1008                                    snd_pcm_hw_rule_ratnums, r,
1009                                    var, -1);
1010 }
1011 
1012 static int snd_pcm_hw_rule_ratdens(snd_pcm_hw_params_t *params,
1013                                    snd_pcm_hw_rule_t *rule)
1014 {
1015         snd_pcm_hw_constraint_ratdens_t *r = rule->private;
1016         unsigned int num = 0, den = 0;
1017         int err = snd_interval_ratden(hw_param_interval(params, rule->var),
1018                                   r->nrats, r->rats, &num, &den);
1019         if (err >= 0 && den && rule->var == SNDRV_PCM_HW_PARAM_RATE) {
1020                 params->rate_num = num;
1021                 params->rate_den = den;
1022         }
1023         return err;
1024 }
1025 
1026 /**
1027  * snd_pcm_hw_constraint_ratdens
1028  */
1029 int snd_pcm_hw_constraint_ratdens(snd_pcm_runtime_t *runtime, 
1030                                   unsigned int cond,
1031                                   snd_pcm_hw_param_t var,
1032                                   snd_pcm_hw_constraint_ratdens_t *r)
1033 {
1034         return snd_pcm_hw_rule_add(runtime, cond, var,
1035                                    snd_pcm_hw_rule_ratdens, r,
1036                                    var, -1);
1037 }
1038 
1039 static int snd_pcm_hw_rule_msbits(snd_pcm_hw_params_t *params,
1040                                   snd_pcm_hw_rule_t *rule)
1041 {
1042         unsigned int l = (unsigned long) rule->private;
1043         int width = l & 0xffff;
1044         unsigned int msbits = l >> 16;
1045         snd_interval_t *i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS);
1046         if (snd_interval_single(i) && snd_interval_value(i) == width)
1047                 params->msbits = msbits;
1048         return 0;
1049 }
1050 
1051 /**
1052  * snd_pcm_hw_constraint_msbits
1053  */
1054 int snd_pcm_hw_constraint_msbits(snd_pcm_runtime_t *runtime, 
1055                                  unsigned int cond,
1056                                  unsigned int width,
1057                                  unsigned int msbits)
1058 {
1059         unsigned long l = (msbits << 16) | width;
1060         return snd_pcm_hw_rule_add(runtime, cond, -1,
1061                                     snd_pcm_hw_rule_msbits,
1062                                     (void*) l,
1063                                     SNDRV_PCM_HW_PARAM_SAMPLE_BITS, -1);
1064 }
1065 
1066 static int snd_pcm_hw_rule_step(snd_pcm_hw_params_t *params,
1067                                 snd_pcm_hw_rule_t *rule)
1068 {
1069         unsigned long step = (unsigned long) rule->private;
1070         return snd_interval_step(hw_param_interval(params, rule->var), 0, step);
1071 }
1072 
1073 /**
1074  * snd_pcm_hw_constraint_step
1075  */
1076 int snd_pcm_hw_constraint_step(snd_pcm_runtime_t *runtime,
1077                                unsigned int cond,
1078                                snd_pcm_hw_param_t var,
1079                                unsigned long step)
1080 {
1081         return snd_pcm_hw_rule_add(runtime, cond, var, 
1082                                    snd_pcm_hw_rule_step, (void *) step,
1083                                    var, -1);
1084 }
1085 
1086 static int snd_pcm_hw_rule_pow2(snd_pcm_hw_params_t *params, snd_pcm_hw_rule_t *rule)
1087 {
1088         static int pow2_sizes[] = {
1089                 1<<0, 1<<1, 1<<2, 1<<3, 1<<4, 1<<5, 1<<6, 1<<7,
1090                 1<<8, 1<<9, 1<<10, 1<<11, 1<<12, 1<<13, 1<<14, 1<<15,
1091                 1<<16, 1<<17, 1<<18, 1<<19, 1<<20, 1<<21, 1<<22, 1<<23,
1092                 1<<24, 1<<25, 1<<26, 1<<27, 1<<28, 1<<29, 1<<30
1093         };
1094         return snd_interval_list(hw_param_interval(params, rule->var),
1095                                  sizeof(pow2_sizes)/sizeof(int), pow2_sizes, 0);
1096 }               
1097 
1098 /**
1099  * snd_pcm_hw_constraint_pow2
1100  */
1101 int snd_pcm_hw_constraint_pow2(snd_pcm_runtime_t *runtime,
1102                                unsigned int cond,
1103                                snd_pcm_hw_param_t var)
1104 {
1105         return snd_pcm_hw_rule_add(runtime, cond, var, 
1106                                    snd_pcm_hw_rule_pow2, NULL,
1107                                    var, -1);
1108 }
1109 
1110 /* To use the same code we have in alsa-lib */
1111 #define snd_pcm_t snd_pcm_substream_t
1112 #define assert(i) snd_assert((i), return -EINVAL)
1113 #ifndef INT_MIN
1114 #define INT_MIN ((int)((unsigned int)INT_MAX+1))
1115 #endif
1116 
1117 void _snd_pcm_hw_param_any(snd_pcm_hw_params_t *params, snd_pcm_hw_param_t var)
1118 {
1119         if (hw_is_mask(var)) {
1120                 snd_mask_any(hw_param_mask(params, var));
1121                 params->cmask |= 1 << var;
1122                 params->rmask |= 1 << var;
1123                 return;
1124         }
1125         if (hw_is_interval(var)) {
1126                 snd_interval_any(hw_param_interval(params, var));
1127                 params->cmask |= 1 << var;
1128                 params->rmask |= 1 << var;
1129                 return;
1130         }
1131         snd_BUG();
1132 }
1133 
1134 /**
1135  * snd_pcm_hw_param_any
1136  */
1137 int snd_pcm_hw_param_any(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
1138                          snd_pcm_hw_param_t var)
1139 {
1140         _snd_pcm_hw_param_any(params, var);
1141         return snd_pcm_hw_refine(pcm, params);
1142 }
1143 
1144 void _snd_pcm_hw_params_any(snd_pcm_hw_params_t *params)
1145 {
1146         unsigned int k;
1147         memset(params, 0, sizeof(*params));
1148         for (k = SNDRV_PCM_HW_PARAM_FIRST_MASK; k <= SNDRV_PCM_HW_PARAM_LAST_MASK; k++)
1149                 _snd_pcm_hw_param_any(params, k);
1150         for (k = SNDRV_PCM_HW_PARAM_FIRST_INTERVAL; k <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; k++)
1151                 _snd_pcm_hw_param_any(params, k);
1152         params->info = ~0U;
1153 }
1154 
1155 /**
1156  * snd_pcm_hw_params_any
1157  *
1158  * Fill PARAMS with full configuration space boundaries
1159  */
1160 int snd_pcm_hw_params_any(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
1161 {
1162         _snd_pcm_hw_params_any(params);
1163         return snd_pcm_hw_refine(pcm, params);
1164 }
1165 
1166 /**
1167  * snd_pcm_hw_param_value
1168  *
1169  * Return the value for field PAR if it's fixed in configuration space 
1170  *  defined by PARAMS. Return -EINVAL otherwise
1171  */
1172 int snd_pcm_hw_param_value(const snd_pcm_hw_params_t *params,
1173                            snd_pcm_hw_param_t var, int *dir)
1174 {
1175         if (hw_is_mask(var)) {
1176                 const snd_mask_t *mask = hw_param_mask_c(params, var);
1177                 if (!snd_mask_single(mask))
1178                         return -EINVAL;
1179                 if (dir)
1180                         *dir = 0;
1181                 return snd_mask_value(mask);
1182         }
1183         if (hw_is_interval(var)) {
1184                 const snd_interval_t *i = hw_param_interval_c(params, var);
1185                 if (!snd_interval_single(i))
1186                         return -EINVAL;
1187                 if (dir)
1188                         *dir = i->openmin;
1189                 return snd_interval_value(i);
1190         }
1191         assert(0);
1192         return -EINVAL;
1193 }
1194 
1195 /**
1196  * snd_pcm_hw_param_value_min
1197  *
1198  * Return the minimum value for field PAR.
1199  */
1200 unsigned int snd_pcm_hw_param_value_min(const snd_pcm_hw_params_t *params,
1201                                         snd_pcm_hw_param_t var, int *dir)
1202 {
1203         if (hw_is_mask(var)) {
1204                 if (dir)
1205                         *dir = 0;
1206                 return snd_mask_min(hw_param_mask_c(params, var));
1207         }
1208         if (hw_is_interval(var)) {
1209                 const snd_interval_t *i = hw_param_interval_c(params, var);
1210                 if (dir)
1211                         *dir = i->openmin;
1212                 return snd_interval_min(i);
1213         }
1214         assert(0);
1215         return -EINVAL;
1216 }
1217 
1218 /**
1219  * snd_pcm_hw_param_value_max
1220  *
1221  * Return the maximum value for field PAR.
1222  */
1223 unsigned int snd_pcm_hw_param_value_max(const snd_pcm_hw_params_t *params,
1224                                         snd_pcm_hw_param_t var, int *dir)
1225 {
1226         if (hw_is_mask(var)) {
1227                 if (dir)
1228                         *dir = 0;
1229                 return snd_mask_max(hw_param_mask_c(params, var));
1230         }
1231         if (hw_is_interval(var)) {
1232                 const snd_interval_t *i = hw_param_interval_c(params, var);
1233                 if (dir)
1234                         *dir = - (int) i->openmax;
1235                 return snd_interval_max(i);
1236         }
1237         assert(0);
1238         return -EINVAL;
1239 }
1240 
1241 void _snd_pcm_hw_param_setempty(snd_pcm_hw_params_t *params,
1242                                 snd_pcm_hw_param_t var)
1243 {
1244         if (hw_is_mask(var)) {
1245                 snd_mask_none(hw_param_mask(params, var));
1246                 params->cmask |= 1 << var;
1247                 params->rmask |= 1 << var;
1248         } else if (hw_is_interval(var)) {
1249                 snd_interval_none(hw_param_interval(params, var));
1250                 params->cmask |= 1 << var;
1251                 params->rmask |= 1 << var;
1252         } else {
1253                 snd_BUG();
1254         }
1255 }
1256 
1257 int _snd_pcm_hw_param_setinteger(snd_pcm_hw_params_t *params,
1258                                  snd_pcm_hw_param_t var)
1259 {
1260         int changed;
1261         assert(hw_is_interval(var));
1262         changed = snd_interval_setinteger(hw_param_interval(params, var));
1263         if (changed) {
1264                 params->cmask |= 1 << var;
1265                 params->rmask |= 1 << var;
1266         }
1267         return changed;
1268 }
1269         
1270 /**
1271  * snd_pcm_hw_param_setinteger
1272  *
1273  * Inside configuration space defined by PARAMS remove from PAR all 
1274  * non integer values. Reduce configuration space accordingly.
1275  * Return -EINVAL if the configuration space is empty
1276  */
1277 int snd_pcm_hw_param_setinteger(snd_pcm_t *pcm, 
1278                                 snd_pcm_hw_params_t *params,
1279                                 snd_pcm_hw_param_t var)
1280 {
1281         int changed = _snd_pcm_hw_param_setinteger(params, var);
1282         if (changed < 0)
1283                 return changed;
1284         if (params->rmask) {
1285                 int err = snd_pcm_hw_refine(pcm, params);
1286                 if (err < 0)
1287                         return err;
1288         }
1289         return 0;
1290 }
1291 
1292 int _snd_pcm_hw_param_first(snd_pcm_hw_params_t *params,
1293                             snd_pcm_hw_param_t var)
1294 {
1295         int changed;
1296         if (hw_is_mask(var))
1297                 changed = snd_mask_refine_first(hw_param_mask(params, var));
1298         else if (hw_is_interval(var))
1299                 changed = snd_interval_refine_first(hw_param_interval(params, var));
1300         else {
1301                 assert(0);
1302                 return -EINVAL;
1303         }
1304         if (changed) {
1305                 params->cmask |= 1 << var;
1306                 params->rmask |= 1 << var;
1307         }
1308         return changed;
1309 }
1310 
1311 
1312 /**
1313  * snd_pcm_hw_param_first
1314  *
1315  * Inside configuration space defined by PARAMS remove from PAR all 
1316  * values > minimum. Reduce configuration space accordingly.
1317  * Return the minimum.
1318  */
1319 int snd_pcm_hw_param_first(snd_pcm_t *pcm, 
1320                            snd_pcm_hw_params_t *params, 
1321                            snd_pcm_hw_param_t var, int *dir)
1322 {
1323         int changed = _snd_pcm_hw_param_first(params, var);
1324         if (changed < 0)
1325                 return changed;
1326         if (params->rmask) {
1327                 int err = snd_pcm_hw_refine(pcm, params);
1328                 assert(err >= 0);
1329         }
1330         return snd_pcm_hw_param_value(params, var, dir);
1331 }
1332 
1333 int _snd_pcm_hw_param_last(snd_pcm_hw_params_t *params,
1334                            snd_pcm_hw_param_t var)
1335 {
1336         int changed;
1337         if (hw_is_mask(var))
1338                 changed = snd_mask_refine_last(hw_param_mask(params, var));
1339         else if (hw_is_interval(var))
1340                 changed = snd_interval_refine_last(hw_param_interval(params, var));
1341         else {
1342                 assert(0);
1343                 return -EINVAL;
1344         }
1345         if (changed) {
1346                 params->cmask |= 1 << var;
1347                 params->rmask |= 1 << var;
1348         }
1349         return changed;
1350 }
1351 
1352 
1353 /**
1354  * snd_pcm_hw_param_last
1355  *
1356  * Inside configuration space defined by PARAMS remove from PAR all 
1357  * values < maximum. Reduce configuration space accordingly.
1358  * Return the maximum.
1359  */
1360 int snd_pcm_hw_param_last(snd_pcm_t *pcm, 
1361                           snd_pcm_hw_params_t *params,
1362                           snd_pcm_hw_param_t var, int *dir)
1363 {
1364         int changed = _snd_pcm_hw_param_last(params, var);
1365         if (changed < 0)
1366                 return changed;
1367         if (params->rmask) {
1368                 int err = snd_pcm_hw_refine(pcm, params);
1369                 assert(err >= 0);
1370         }
1371         return snd_pcm_hw_param_value(params, var, dir);
1372 }
1373 
1374 int _snd_pcm_hw_param_min(snd_pcm_hw_params_t *params,
1375                           snd_pcm_hw_param_t var, unsigned int val, int dir)
1376 {
1377         int changed;
1378         int open = 0;
1379         if (dir) {
1380                 if (dir > 0) {
1381                         open = 1;
1382                 } else if (dir < 0) {
1383                         if (val > 0) {
1384                                 open = 1;
1385                                 val--;
1386                         }
1387                 }
1388         }
1389         if (hw_is_mask(var))
1390                 changed = snd_mask_refine_min(hw_param_mask(params, var), val + !!open);
1391         else if (hw_is_interval(var))
1392                 changed = snd_interval_refine_min(hw_param_interval(params, var), val, open);
1393         else {
1394                 assert(0);
1395                 return -EINVAL;
1396         }
1397         if (changed) {
1398                 params->cmask |= 1 << var;
1399                 params->rmask |= 1 << var;
1400         }
1401         return changed;
1402 }
1403 
1404 /**
1405  * snd_pcm_hw_param_min
1406  *
1407  * Inside configuration space defined by PARAMS remove from PAR all 
1408  * values < VAL. Reduce configuration space accordingly.
1409  * Return new minimum or -EINVAL if the configuration space is empty
1410  */
1411 int snd_pcm_hw_param_min(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
1412                          snd_pcm_hw_param_t var, unsigned int val, int *dir)
1413 {
1414         int changed = _snd_pcm_hw_param_min(params, var, val, dir ? *dir : 0);
1415         if (changed < 0)
1416                 return changed;
1417         if (params->rmask) {
1418                 int err = snd_pcm_hw_refine(pcm, params);
1419                 if (err < 0)
1420                         return err;
1421         }
1422         return snd_pcm_hw_param_value_min(params, var, dir);
1423 }
1424 
1425 int _snd_pcm_hw_param_max(snd_pcm_hw_params_t *params,
1426                            snd_pcm_hw_param_t var, unsigned int val, int dir)
1427 {
1428         int changed;
1429         int open = 0;
1430         if (dir) {
1431                 if (dir < 0) {
1432                         open = 1;
1433                 } else if (dir > 0) {
1434                         open = 1;
1435                         val++;
1436                 }
1437         }
1438         if (hw_is_mask(var)) {
1439                 if (val == 0 && open) {
1440                         snd_mask_none(hw_param_mask(params, var));
1441                         changed = -EINVAL;
1442                 } else
1443                         changed = snd_mask_refine_max(hw_param_mask(params, var), val - !!open);
1444         } else if (hw_is_interval(var))
1445                 changed = snd_interval_refine_max(hw_param_interval(params, var), val, open);
1446         else {
1447                 assert(0);
1448                 return -EINVAL;
1449         }
1450         if (changed) {
1451                 params->cmask |= 1 << var;
1452                 params->rmask |= 1 << var;
1453         }
1454         return changed;
1455 }
1456 
1457 /**
1458  * snd_pcm_hw_param_max
1459  *
1460  * Inside configuration space defined by PARAMS remove from PAR all 
1461  *  values >= VAL + 1. Reduce configuration space accordingly.
1462  *  Return new maximum or -EINVAL if the configuration space is empty
1463  */
1464 int snd_pcm_hw_param_max(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
1465                           snd_pcm_hw_param_t var, unsigned int val, int *dir)
1466 {
1467         int changed = _snd_pcm_hw_param_max(params, var, val, dir ? *dir : 0);
1468         if (changed < 0)
1469                 return changed;
1470         if (params->rmask) {
1471                 int err = snd_pcm_hw_refine(pcm, params);
1472                 if (err < 0)
1473                         return err;
1474         }
1475         return snd_pcm_hw_param_value_max(params, var, dir);
1476 }
1477 
1478 int _snd_pcm_hw_param_set(snd_pcm_hw_params_t *params,
1479                           snd_pcm_hw_param_t var, unsigned int val, int dir)
1480 {
1481         int changed;
1482         if (hw_is_mask(var)) {
1483                 snd_mask_t *m = hw_param_mask(params, var);
1484                 if (val == 0 && dir < 0) {
1485                         changed = -EINVAL;
1486                         snd_mask_none(m);
1487                 } else {
1488                         if (dir > 0)
1489                                 val++;
1490                         else if (dir < 0)
1491                                 val--;
1492                         changed = snd_mask_refine_set(hw_param_mask(params, var), val);
1493                 }
1494         } else if (hw_is_interval(var)) {
1495                 snd_interval_t *i = hw_param_interval(params, var);
1496                 if (val == 0 && dir < 0) {
1497                         changed = -EINVAL;
1498                         snd_interval_none(i);
1499                 } else if (dir == 0)
1500                         changed = snd_interval_refine_set(i, val);
1501                 else {
1502                         snd_interval_t t;
1503                         t.openmin = 1;
1504                         t.openmax = 1;
1505                         t.empty = 0;
1506                         t.integer = 0;
1507                         if (dir < 0) {
1508                                 t.min = val - 1;
1509                                 t.max = val;
1510                         } else {
1511                                 t.min = val;
1512                                 t.max = val+1;
1513                         }
1514                         changed = snd_interval_refine(i, &t);
1515                 }
1516         } else {
1517                 assert(0);
1518                 return -EINVAL;
1519         }
1520         if (changed) {
1521                 params->cmask |= 1 << var;
1522                 params->rmask |= 1 << var;
1523         }
1524         return changed;
1525 }
1526 
1527 /**
1528  * snd_pcm_hw_param_set
1529  *
1530  * Inside configuration space defined by PARAMS remove from PAR all 
1531  * values != VAL. Reduce configuration space accordingly.
1532  *  Return VAL or -EINVAL if the configuration space is empty
1533  */
1534 int snd_pcm_hw_param_set(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
1535                          snd_pcm_hw_param_t var, unsigned int val, int dir)
1536 {
1537         int changed = _snd_pcm_hw_param_set(params, var, val, dir);
1538         if (changed < 0)
1539                 return changed;
1540         if (params->rmask) {
1541                 int err = snd_pcm_hw_refine(pcm, params);
1542                 if (err < 0)
1543                         return err;
1544         }
1545         return snd_pcm_hw_param_value(params, var, 0);
1546 }
1547 
1548 int _snd_pcm_hw_param_mask(snd_pcm_hw_params_t *params,
1549                            snd_pcm_hw_param_t var, const snd_mask_t *val)
1550 {
1551         int changed;
1552         assert(hw_is_mask(var));
1553         changed = snd_mask_refine(hw_param_mask(params, var), val);
1554         if (changed) {
1555                 params->cmask |= 1 << var;
1556                 params->rmask |= 1 << var;
1557         }
1558         return changed;
1559 }
1560 
1561 /**
1562  * snd_pcm_hw_param_mask
1563  *
1564  * Inside configuration space defined by PARAMS remove from PAR all values
1565  * not contained in MASK. Reduce configuration space accordingly.
1566  * This function can be called only for SNDRV_PCM_HW_PARAM_ACCESS,
1567  * SNDRV_PCM_HW_PARAM_FORMAT, SNDRV_PCM_HW_PARAM_SUBFORMAT.
1568  * Return 0 on success or -EINVAL
1569  * if the configuration space is empty
1570  */
1571 int snd_pcm_hw_param_mask(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
1572                           snd_pcm_hw_param_t var, const snd_mask_t *val)
1573 {
1574         int changed = _snd_pcm_hw_param_mask(params, var, val);
1575         if (changed < 0)
1576                 return changed;
1577         if (params->rmask) {
1578                 int err = snd_pcm_hw_refine(pcm, params);
1579                 if (err < 0)
1580                         return err;
1581         }
1582         return 0;
1583 }
1584 
1585 static int boundary_sub(int a, int adir,
1586                         int b, int bdir,
1587                         int *c, int *cdir)
1588 {
1589         adir = adir < 0 ? -1 : (adir > 0 ? 1 : 0);
1590         bdir = bdir < 0 ? -1 : (bdir > 0 ? 1 : 0);
1591         *c = a - b;
1592         *cdir = adir - bdir;
1593         if (*cdir == -2) {
1594                 assert(*c > INT_MIN);
1595                 (*c)--;
1596         } else if (*cdir == 2) {
1597                 assert(*c < INT_MAX);
1598                 (*c)++;
1599         }
1600         return 0;
1601 }
1602 
1603 static int boundary_lt(unsigned int a, int adir,
1604                        unsigned int b, int bdir)
1605 {
1606         assert(a > 0 || adir >= 0);
1607         assert(b > 0 || bdir >= 0);
1608         if (adir < 0) {
1609                 a--;
1610                 adir = 1;
1611         } else if (adir > 0)
1612                 adir = 1;
1613         if (bdir < 0) {
1614                 b--;
1615                 bdir = 1;
1616         } else if (bdir > 0)
1617                 bdir = 1;
1618         return a < b || (a == b && adir < bdir);
1619 }
1620 
1621 /* Return 1 if min is nearer to best than max */
1622 static int boundary_nearer(int min, int mindir,
1623                            int best, int bestdir,
1624                            int max, int maxdir)
1625 {
1626         int dmin, dmindir;
1627         int dmax, dmaxdir;
1628         boundary_sub(best, bestdir, min, mindir, &dmin, &dmindir);
1629         boundary_sub(max, maxdir, best, bestdir, &dmax, &dmaxdir);
1630         return boundary_lt(dmin, dmindir, dmax, dmaxdir);
1631 }
1632 
1633 /**
1634  * snd_pcm_hw_param_near
1635  *
1636  * Inside configuration space defined by PARAMS set PAR to the available value
1637  * nearest to VAL. Reduce configuration space accordingly.
1638  * This function cannot be called for SNDRV_PCM_HW_PARAM_ACCESS,
1639  * SNDRV_PCM_HW_PARAM_FORMAT, SNDRV_PCM_HW_PARAM_SUBFORMAT.
1640  * Return the value found.
1641   */
1642 int snd_pcm_hw_param_near(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
1643                           snd_pcm_hw_param_t var, unsigned int best, int *dir)
1644 {
1645         snd_pcm_hw_params_t *save = NULL;
1646         int v;
1647         unsigned int saved_min;
1648         int last = 0;
1649         int min, max;
1650         int mindir, maxdir;
1651         int valdir = dir ? *dir : 0;
1652         /* FIXME */
1653         if (best > INT_MAX)
1654                 best = INT_MAX;
1655         min = max = best;
1656         mindir = maxdir = valdir;
1657         if (maxdir > 0)
1658                 maxdir = 0;
1659         else if (maxdir == 0)
1660                 maxdir = -1;
1661         else {
1662                 maxdir = 1;
1663                 max--;
1664         }
1665         save = kmalloc(sizeof(*save), GFP_KERNEL);
1666         if (save == NULL)
1667                 return -ENOMEM;
1668         *save = *params;
1669         saved_min = min;
1670         min = snd_pcm_hw_param_min(pcm, params, var, min, &mindir);
1671         if (min >= 0) {
1672                 snd_pcm_hw_params_t *params1;
1673                 if (max < 0)
1674                         goto _end;
1675                 if ((unsigned int)min == saved_min && mindir == valdir)
1676                         goto _end;
1677                 params1 = kmalloc(sizeof(*params1), GFP_KERNEL);
1678                 if (params1 == NULL) {
1679                         kfree(save);
1680                         return -ENOMEM;
1681                 }
1682                 *params1 = *save;
1683                 max = snd_pcm_hw_param_max(pcm, params1, var, max, &maxdir);
1684                 if (max < 0) {
1685                         kfree(params1);
1686                         goto _end;
1687                 }
1688                 if (boundary_nearer(max, maxdir, best, valdir, min, mindir)) {
1689                         *params = *params1;
1690                         last = 1;
1691                 }
1692                 kfree(params1);
1693         } else {
1694                 *params = *save;
1695                 max = snd_pcm_hw_param_max(pcm, params, var, max, &maxdir);
1696                 assert(max >= 0);
1697                 last = 1;
1698         }
1699  _end:
1700         kfree(save);
1701         if (last)
1702                 v = snd_pcm_hw_param_last(pcm, params, var, dir);
1703         else
1704                 v = snd_pcm_hw_param_first(pcm, params, var, dir);
1705         assert(v >= 0);
1706         return v;
1707 }
1708 
1709 /**
1710  * snd_pcm_hw_param_choose
1711  *
1712  * Choose one configuration from configuration space defined by PARAMS
1713  * The configuration chosen is that obtained fixing in this order:
1714  * first access, first format, first subformat, min channels,
1715  * min rate, min period time, max buffer size, min tick time
1716  */
1717 int snd_pcm_hw_params_choose(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
1718 {
1719         int err;
1720 
1721         err = snd_pcm_hw_param_first(pcm, params, SNDRV_PCM_HW_PARAM_ACCESS, 0);
1722         assert(err >= 0);
1723 
1724         err = snd_pcm_hw_param_first(pcm, params, SNDRV_PCM_HW_PARAM_FORMAT, 0);
1725         assert(err >= 0);
1726 
1727         err = snd_pcm_hw_param_first(pcm, params, SNDRV_PCM_HW_PARAM_SUBFORMAT, 0);
1728         assert(err >= 0);
1729 
1730         err = snd_pcm_hw_param_first(pcm, params, SNDRV_PCM_HW_PARAM_CHANNELS, 0);
1731         assert(err >= 0);
1732 
1733         err = snd_pcm_hw_param_first(pcm, params, SNDRV_PCM_HW_PARAM_RATE, 0);
1734         assert(err >= 0);
1735 
1736         err = snd_pcm_hw_param_first(pcm, params, SNDRV_PCM_HW_PARAM_PERIOD_TIME, 0);
1737         assert(err >= 0);
1738 
1739         err = snd_pcm_hw_param_last(pcm, params, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0);
1740         assert(err >= 0);
1741 
1742         err = snd_pcm_hw_param_first(pcm, params, SNDRV_PCM_HW_PARAM_TICK_TIME, 0);
1743         assert(err >= 0);
1744 
1745         return 0;
1746 }
1747 
1748 #undef snd_pcm_t
1749 #undef assert
1750 
1751 static int snd_pcm_lib_ioctl_reset(snd_pcm_substream_t *substream,
1752                                    void *arg)
1753 {
1754         snd_pcm_runtime_t *runtime = substream->runtime;
1755         if (snd_pcm_running(substream) &&
1756             snd_pcm_update_hw_ptr(substream) >= 0) {
1757                 runtime->status->hw_ptr %= runtime->buffer_size;
1758                 return 0;
1759         }
1760         runtime->status->hw_ptr = 0;
1761         return 0;
1762 }
1763 
1764 static int snd_pcm_lib_ioctl_channel_info(snd_pcm_substream_t *substream,
1765                                           void *arg)
1766 {
1767         snd_pcm_channel_info_t *info = arg;
1768         snd_pcm_runtime_t *runtime = substream->runtime;
1769         int width;
1770         if (!(runtime->info & SNDRV_PCM_INFO_MMAP)) {
1771                 info->offset = -1;
1772                 return 0;
1773         }
1774         width = snd_pcm_format_physical_width(runtime->format);
1775         if (width < 0)
1776                 return width;
1777         info->offset = 0;
1778         switch (runtime->access) {
1779         case SNDRV_PCM_ACCESS_MMAP_INTERLEAVED:
1780         case SNDRV_PCM_ACCESS_RW_INTERLEAVED:
1781                 info->first = info->channel * width;
1782                 info->step = runtime->channels * width;
1783                 break;
1784         case SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED:
1785         case SNDRV_PCM_ACCESS_RW_NONINTERLEAVED:
1786         {
1787                 size_t size = runtime->dma_bytes / runtime->channels;
1788                 info->first = info->channel * size * 8;
1789                 info->step = width;
1790                 break;
1791         }
1792         default:
1793                 snd_BUG();
1794                 break;
1795         }
1796         return 0;
1797 }
1798 
1799 /**
1800  * snd_pcm_lib_ioctl - a generic PCM ioctl callback
1801  * @substream: the pcm substream instance
1802  * @cmd: ioctl command
1803  * @arg: ioctl argument
1804  *
1805  * Processes the generic ioctl commands for PCM.
1806  * Can be passed as the ioctl callback for PCM ops.
1807  *
1808  * Returns zero if successful, or a negative error code on failure.
1809  */
1810 int snd_pcm_lib_ioctl(snd_pcm_substream_t *substream,
1811                       unsigned int cmd, void *arg)
1812 {
1813         switch (cmd) {
1814         case SNDRV_PCM_IOCTL1_INFO:
1815                 return 0;
1816         case SNDRV_PCM_IOCTL1_RESET:
1817                 return snd_pcm_lib_ioctl_reset(substream, arg);
1818         case SNDRV_PCM_IOCTL1_CHANNEL_INFO:
1819                 return snd_pcm_lib_ioctl_channel_info(substream, arg);
1820         }
1821         return -ENXIO;
1822 }
1823 
1824 /*
1825  *  Conditions
1826  */
1827 
1828 /**
1829  * snd_pcm_playback_ready - check whether the playback buffer is available
1830  * @substream: the pcm substream instance
1831  *
1832  * Checks whether enough free space is available on the playback buffer.
1833  *
1834  * Returns non-zero if available, or zero if not.
1835  */
1836 int snd_pcm_playback_ready(snd_pcm_substream_t *substream)
1837 {
1838         snd_pcm_runtime_t *runtime = substream->runtime;
1839         return snd_pcm_playback_avail(runtime) >= runtime->control->avail_min;
1840 }
1841 
1842 /**
1843  * snd_pcm_capture_ready - check whether the capture buffer is available
1844  * @substream: the pcm substream instance
1845  *
1846  * Checks whether enough capture data is available on the capture buffer.
1847  *
1848  * Returns non-zero if available, or zero if not.
1849  */
1850 int snd_pcm_capture_ready(snd_pcm_substream_t *substream)
1851 {
1852         snd_pcm_runtime_t *runtime = substream->runtime;
1853         return snd_pcm_capture_avail(runtime) >= runtime->control->avail_min;
1854 }
1855 
1856 /**
1857  * snd_pcm_playback_data - check whether any data exists on the playback buffer
1858  * @substream: the pcm substream instance
1859  *
1860  * Checks whether any data exists on the playback buffer. If stop_threshold
1861  * is bigger or equal to boundary, then this function returns always non-zero.
1862  *
1863  * Returns non-zero if exists, or zero if not.
1864  */
1865 int snd_pcm_playback_data(snd_pcm_substream_t *substream)
1866 {
1867         snd_pcm_runtime_t *runtime = substream->runtime;
1868         
1869         if (runtime->stop_threshold >= runtime->boundary)
1870                 return 1;
1871         return snd_pcm_playback_avail(runtime) < runtime->buffer_size;
1872 }
1873 
1874 /**
1875  * snd_pcm_playback_empty - check whether the playback buffer is empty
1876  * @substream: the pcm substream instance
1877  *
1878  * Checks whether the playback buffer is empty.
1879  *
1880  * Returns non-zero if empty, or zero if not.
1881  */
1882 int snd_pcm_playback_empty(snd_pcm_substream_t *substream)
1883 {
1884         snd_pcm_runtime_t *runtime = substream->runtime;
1885         return snd_pcm_playback_avail(runtime) >= runtime->buffer_size;
1886 }
1887 
1888 /**
1889  * snd_pcm_capture_empty - check whether the capture buffer is empty
1890  * @substream: the pcm substream instance
1891  *
1892  * Checks whether the capture buffer is empty.
1893  *
1894  * Returns non-zero if empty, or zero if not.
1895  */
1896 int snd_pcm_capture_empty(snd_pcm_substream_t *substream)
1897 {
1898         snd_pcm_runtime_t *runtime = substream->runtime;
1899         return snd_pcm_capture_avail(runtime) == 0;
1900 }
1901 
1902 static void snd_pcm_system_tick_set(snd_pcm_substream_t *substream, 
1903                                     unsigned long ticks)
1904 {
1905         snd_pcm_runtime_t *runtime = substream->runtime;
1906         if (ticks == 0)
1907                 del_timer(&runtime->tick_timer);
1908         else {
1909                 ticks /= (1000000 / HZ);
1910                 if (ticks % (1000000 / HZ))
1911                         ticks++;
1912                 mod_timer(&runtime->tick_timer, jiffies + ticks);
1913         }
1914 }
1915 
1916 /* Temporary alias */
1917 void snd_pcm_tick_set(snd_pcm_substream_t *substream, unsigned long ticks)
1918 {
1919         snd_pcm_system_tick_set(substream, ticks);
1920 }
1921 
1922 void snd_pcm_tick_prepare(snd_pcm_substream_t *substream)
1923 {
1924         snd_pcm_runtime_t *runtime = substream->runtime;
1925         snd_pcm_uframes_t frames = ULONG_MAX;
1926         snd_pcm_uframes_t avail, dist;
1927         unsigned int ticks;
1928         u_int64_t n;
1929         u_int32_t r;
1930         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
1931                 if (runtime->silence_size >= runtime->boundary) {
1932                         frames = 1;
1933                 } else if (runtime->silence_size > 0 &&
1934                            runtime->silence_filled < runtime->buffer_size) {
1935                         snd_pcm_sframes_t noise_dist;
1936                         noise_dist = snd_pcm_playback_hw_avail(runtime) + runtime->silence_filled;
1937                         snd_assert(noise_dist <= (snd_pcm_sframes_t)runtime->silence_threshold, );
1938                         frames = noise_dist - runtime->silence_threshold;
1939                 }
1940                 avail = snd_pcm_playback_avail(runtime);
1941         } else {
1942                 avail = snd_pcm_capture_avail(runtime);
1943         }
1944         if (avail < runtime->control->avail_min) {
1945                 snd_pcm_sframes_t n = runtime->control->avail_min - avail;
1946                 if (n > 0 && frames > (snd_pcm_uframes_t)n)
1947                         frames = n;
1948         }
1949         if (avail < runtime->buffer_size) {
1950                 snd_pcm_sframes_t n = runtime->buffer_size - avail;
1951                 if (n > 0 && frames > (snd_pcm_uframes_t)n)
1952                         frames = n;
1953         }
1954         if (frames == ULONG_MAX) {
1955                 snd_pcm_tick_set(substream, 0);
1956                 return;
1957         }
1958         dist = runtime->status->hw_ptr - runtime->hw_ptr_base;
1959         /* Distance to next interrupt */
1960         dist = runtime->period_size - dist % runtime->period_size;
1961         if (dist <= frames) {
1962                 snd_pcm_tick_set(substream, 0);
1963                 return;
1964         }
1965         /* the base time is us */
1966         n = frames;
1967         n *= 1000000;
1968         div64_32(&n, runtime->tick_time * runtime->rate, &r);
1969         ticks = n + (r > 0 ? 1 : 0);
1970         if (ticks < runtime->sleep_min)
1971                 ticks = runtime->sleep_min;
1972         snd_pcm_tick_set(substream, (unsigned long) ticks);
1973 }
1974 
1975 void snd_pcm_tick_elapsed(snd_pcm_substream_t *substream)
1976 {
1977         snd_pcm_runtime_t *runtime;
1978         unsigned long flags;
1979         
1980         snd_assert(substream != NULL, return);
1981         runtime = substream->runtime;
1982         snd_assert(runtime != NULL, return);
1983 
1984         snd_pcm_stream_lock_irqsave(substream, flags);
1985         if (!snd_pcm_running(substream) ||
1986             snd_pcm_update_hw_ptr(substream) < 0)
1987                 goto _end;
1988         if (runtime->sleep_min)
1989                 snd_pcm_tick_prepare(substream);
1990  _end:
1991         snd_pcm_stream_unlock_irqrestore(substream, flags);
1992 }
1993 
1994 /**
1995  * snd_pcm_period_elapsed - update the pcm status for the next period
1996  * @substream: the pcm substream instance
1997  *
1998  * This function is called from the interrupt handler when the
1999  * PCM has processed the period size.  It will update the current
2000  * pointer, set up the tick, wake up sleepers, etc.
2001  *
2002  * Even if more than one periods have elapsed since the last call, you
2003  * have to call this only once.
2004  */
2005 void snd_pcm_period_elapsed(snd_pcm_substream_t *substream)
2006 {
2007         snd_pcm_runtime_t *runtime;
2008         unsigned long flags;
2009 
2010         snd_assert(substream != NULL, return);
2011         runtime = substream->runtime;
2012         snd_assert(runtime != NULL, return);
2013 
2014         if (runtime->transfer_ack_begin)
2015                 runtime->transfer_ack_begin(substream);
2016 
2017         snd_pcm_stream_lock_irqsave(substream, flags);
2018         if (!snd_pcm_running(substream) ||
2019             snd_pcm_update_hw_ptr_interrupt(substream) < 0)
2020                 goto _end;
2021 
2022         if (substream->timer_running)
2023                 snd_timer_interrupt(substream->timer, 1);
2024         if (runtime->sleep_min)
2025                 snd_pcm_tick_prepare(substream);
2026  _end:
2027         snd_pcm_stream_unlock_irqrestore(substream, flags);
2028         if (runtime->transfer_ack_end)
2029                 runtime->transfer_ack_end(substream);
2030         kill_fasync(&runtime->fasync, SIGIO, POLL_IN);
2031 }
2032 
2033 static int snd_pcm_lib_write_transfer(snd_pcm_substream_t *substream,
2034                                       unsigned int hwoff,
2035                                       void *data, unsigned int off,
2036                                       snd_pcm_uframes_t frames)
2037 {
2038         snd_pcm_runtime_t *runtime = substream->runtime;
2039         int err;
2040         char *buf = (char *) data + frames_to_bytes(runtime, off);
2041         if (substream->ops->copy) {
2042                 if ((err = substream->ops->copy(substream, -1, hwoff, buf, frames)) < 0)
2043                         return err;
2044         } else {
2045                 char *hwbuf = runtime->dma_area + frames_to_bytes(runtime, hwoff);
2046                 snd_assert(runtime->dma_area, return -EFAULT);
2047                 if (copy_from_user(hwbuf, buf, frames_to_bytes(runtime, frames)))
2048                         return -EFAULT;
2049         }
2050         return 0;
2051 }
2052  
2053 typedef int (*transfer_f)(snd_pcm_substream_t *substream, unsigned int hwoff,
2054                           void *data, unsigned int off, snd_pcm_uframes_t size);
2055 
2056 static snd_pcm_sframes_t snd_pcm_lib_write1(snd_pcm_substream_t *substream, 
2057                                             const void *data, snd_pcm_uframes_t size,
2058                                             int nonblock,
2059                                             transfer_f transfer)
2060 {
2061         snd_pcm_runtime_t *runtime = substream->runtime;
2062         snd_pcm_uframes_t xfer = 0;
2063         snd_pcm_uframes_t offset = 0;
2064         int err = 0;
2065 
2066         if (size == 0)
2067                 return 0;
2068         if (size > runtime->xfer_align)
2069                 size -= size % runtime->xfer_align;
2070 
2071         snd_pcm_stream_lock_irq(substream);
2072         switch (runtime->status->state) {
2073         case SNDRV_PCM_STATE_PREPARED:
2074         case SNDRV_PCM_STATE_RUNNING:
2075         case SNDRV_PCM_STATE_PAUSED:
2076                 break;
2077         case SNDRV_PCM_STATE_XRUN:
2078                 err = -EPIPE;
2079                 goto _end_unlock;
2080         case SNDRV_PCM_STATE_SUSPENDED:
2081                 err = -ESTRPIPE;
2082                 goto _end_unlock;
2083         default:
2084                 err = -EBADFD;
2085                 goto _end_unlock;
2086         }
2087 
2088         while (size > 0) {
2089                 snd_pcm_uframes_t frames, appl_ptr, appl_ofs;
2090                 snd_pcm_uframes_t avail;
2091                 snd_pcm_uframes_t cont;
2092                 if (runtime->sleep_min == 0 && runtime->status->state == SNDRV_PCM_STATE_RUNNING)
2093                         snd_pcm_update_hw_ptr(substream);
2094                 avail = snd_pcm_playback_avail(runtime);
2095                 if (((avail < runtime->control->avail_min && size > avail) ||
2096                    (size >= runtime->xfer_align && avail < runtime->xfer_align))) {
2097                         wait_queue_t wait;
2098                         enum { READY, SIGNALED, ERROR, SUSPENDED, EXPIRED } state;
2099                         long tout;
2100 
2101                         if (nonblock) {
2102                                 err = -EAGAIN;
2103                                 goto _end_unlock;
2104                         }
2105 
2106                         init_waitqueue_entry(&wait, current);
2107                         add_wait_queue(&runtime->sleep, &wait);
2108                         while (1) {
2109                                 if (signal_pending(current)) {
2110                                         state = SIGNALED;
2111                                         break;
2112                                 }
2113                                 set_current_state(TASK_INTERRUPTIBLE);
2114                                 snd_pcm_stream_unlock_irq(substream);
2115                                 tout = schedule_timeout(10 * HZ);
2116                                 snd_pcm_stream_lock_irq(substream);
2117                                 if (tout == 0) {
2118                                         if (runtime->status->state != SNDRV_PCM_STATE_PREPARED &&
2119                                             runtime->status->state != SNDRV_PCM_STATE_PAUSED) {
2120                                                 state = runtime->status->state == SNDRV_PCM_STATE_SUSPENDED ? SUSPENDED : EXPIRED;
2121                                                 break;
2122                                         }
2123                                 }
2124                                 switch (runtime->status->state) {
2125                                 case SNDRV_PCM_STATE_XRUN:
2126                                 case SNDRV_PCM_STATE_DRAINING:
2127                                         state = ERROR;
2128                                         goto _end_loop;
2129                                 case SNDRV_PCM_STATE_SUSPENDED:
2130                                         state = SUSPENDED;
2131                                         goto _end_loop;
2132                                 default:
2133                                         break;
2134                                 }
2135                                 avail = snd_pcm_playback_avail(runtime);
2136                                 if (avail >= runtime->control->avail_min) {
2137                                         state = READY;
2138                                         break;
2139                                 }
2140                         }
2141                        _end_loop:
2142                         remove_wait_queue(&runtime->sleep, &wait);
2143 
2144                         switch (state) {
2145                         case ERROR:
2146                                 err = -EPIPE;
2147                                 goto _end_unlock;
2148                         case SUSPENDED:
2149                                 err = -ESTRPIPE;
2150                                 goto _end_unlock;
2151                         case SIGNALED:
2152                                 err = -ERESTARTSYS;
2153                                 goto _end_unlock;
2154                         case EXPIRED:
2155                                 snd_printd("playback write error (DMA or IRQ trouble?)\n");
2156                                 err = -EIO;
2157                                 goto _end_unlock;
2158                         default:
2159                                 break;
2160                         }
2161                 }
2162                 if (avail > runtime->xfer_align)
2163                         avail -= avail % runtime->xfer_align;
2164                 frames = size > avail ? avail : size;
2165                 cont = runtime->buffer_size - runtime->control->appl_ptr % runtime->buffer_size;
2166                 if (frames > cont)
2167                         frames = cont;
2168                 snd_assert(frames != 0, snd_pcm_stream_unlock_irq(substream); return -EINVAL);
2169                 appl_ptr = runtime->control->appl_ptr;
2170                 appl_ofs = appl_ptr % runtime->buffer_size;
2171                 snd_pcm_stream_unlock_irq(substream);
2172                 if ((err = transfer(substream, appl_ofs, (void *)data, offset, frames)) < 0)
2173                         goto _end;
2174                 snd_pcm_stream_lock_irq(substream);
2175                 switch (runtime->status->state) {
2176                 case SNDRV_PCM_STATE_XRUN:
2177                         err = -EPIPE;
2178                         goto _end_unlock;
2179                 case SNDRV_PCM_STATE_SUSPENDED:
2180                         err = -ESTRPIPE;
2181                         goto _end_unlock;
2182                 default:
2183                         break;
2184                 }
2185                 appl_ptr += frames;
2186                 if (appl_ptr >= runtime->boundary) {
2187                         runtime->control->appl_ptr = 0;
2188                 } else {
2189                         runtime->control->appl_ptr = appl_ptr;
2190                 }
2191                 if (substream->ops->ack)
2192                         substream->ops->ack(substream);
2193 
2194                 offset += frames;
2195                 size -= frames;
2196                 xfer += frames;
2197                 if (runtime->status->state == SNDRV_PCM_STATE_PREPARED &&
2198                     snd_pcm_playback_hw_avail(runtime) >= (snd_pcm_sframes_t)runtime->start_threshold) {
2199                         err = snd_pcm_start(substream);
2200                         if (err < 0)
2201                                 goto _end_unlock;
2202                 }
2203                 if (runtime->sleep_min &&
2204                     runtime->status->state == SNDRV_PCM_STATE_RUNNING)
2205                         snd_pcm_tick_prepare(substream);
2206         }
2207  _end_unlock:
2208         snd_pcm_stream_unlock_irq(substream);
2209  _end:
2210         return xfer > 0 ? (snd_pcm_sframes_t)xfer : err;
2211 }
2212 
2213 snd_pcm_sframes_t snd_pcm_lib_write(snd_pcm_substream_t *substream, const void *buf, snd_pcm_uframes_t size)
2214 {
2215         snd_pcm_runtime_t *runtime;
2216         int nonblock;
2217 
2218         snd_assert(substream != NULL, return -ENXIO);
2219         runtime = substream->runtime;
2220         snd_assert(runtime != NULL, return -ENXIO);
2221         snd_assert(substream->ops->copy != NULL || runtime->dma_area != NULL, return -EINVAL);
2222         if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
2223                 return -EBADFD;
2224 
2225         snd_assert(substream->ffile != NULL, return -ENXIO);
2226         nonblock = !!(substream->ffile->f_flags & O_NONBLOCK);
2227 #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
2228         if (substream->oss.oss) {
2229                 snd_pcm_oss_setup_t *setup = substream->oss.setup;
2230                 if (setup != NULL) {
2231                         if (setup->nonblock)
2232                                 nonblock = 1;
2233                         else if (setup->block)
2234                                 nonblock = 0;
2235                 }
2236         }
2237 #endif
2238 
2239         if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED &&
2240             runtime->channels > 1)
2241                 return -EINVAL;
2242         return snd_pcm_lib_write1(substream, buf, size, nonblock,
2243                                   snd_pcm_lib_write_transfer);
2244 }
2245 
2246 static int snd_pcm_lib_writev_transfer(snd_pcm_substream_t *substream,
2247                                        unsigned int hwoff,
2248                                        void *data, unsigned int off,
2249                                        snd_pcm_uframes_t frames)
2250 {
2251         snd_pcm_runtime_t *runtime = substream->runtime;
2252         int err;
2253         void **bufs = data;
2254         int channels = runtime->channels;
2255         int c;
2256         if (substream->ops->copy) {
2257                 snd_assert(substream->ops->silence != NULL, return -EINVAL);
2258                 for (c = 0; c < channels; ++c, ++bufs) {
2259                         if (*bufs == NULL) {
2260                                 if ((err = substream->ops->silence(substream, c, hwoff, frames)) < 0)
2261                                         return err;
2262                         } else {
2263                                 char *buf = *bufs + samples_to_bytes(runtime, off);
2264                                 if ((err = substream->ops->copy(substream, c, hwoff, buf, frames)) < 0)
2265                                         return err;
2266                         }
2267                 }
2268         } else {
2269                 /* default transfer behaviour */
2270                 size_t dma_csize = runtime->dma_bytes / channels;
2271                 snd_assert(runtime->dma_area, return -EFAULT);
2272                 for (c = 0; c < channels; ++c, ++bufs) {
2273                         char *hwbuf = runtime->dma_area + (c * dma_csize) + samples_to_bytes(runtime, hwoff);
2274                         if (*bufs == NULL) {
2275                                 snd_pcm_format_set_silence(runtime->format, hwbuf, frames);
2276                         } else {
2277                                 char *buf = *bufs + samples_to_bytes(runtime, off);
2278                                 if (copy_from_user(hwbuf, buf, samples_to_bytes(runtime, frames)))
2279                                         return -EFAULT;
2280                         }
2281                 }
2282         }
2283         return 0;
2284 }
2285  
2286 snd_pcm_sframes_t snd_pcm_lib_writev(snd_pcm_substream_t *substream, void **bufs,
2287                                      snd_pcm_uframes_t frames)
2288 {
2289         snd_pcm_runtime_t *runtime;
2290         int nonblock;
2291 
2292         snd_assert(substream != NULL, return -ENXIO);
2293         runtime = substream->runtime;
2294         snd_assert(runtime != NULL, return -ENXIO);
2295         snd_assert(substream->ops->copy != NULL || runtime->dma_area != NULL, return -EINVAL);
2296         if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
2297                 return -EBADFD;
2298 
2299         snd_assert(substream->ffile != NULL, return -ENXIO);
2300         nonblock = !!(substream->ffile->f_flags & O_NONBLOCK);
2301 #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
2302         if (substream->oss.oss) {
2303                 snd_pcm_oss_setup_t *setup = substream->oss.setup;
2304                 if (setup != NULL) {
2305                         if (setup->nonblock)
2306                                 nonblock = 1;
2307                         else if (setup->block)
2308                                 nonblock = 0;
2309                 }
2310         }
2311 #endif
2312 
2313         if (runtime->access != SNDRV_PCM_ACCESS_RW_NONINTERLEAVED)
2314                 return -EINVAL;
2315         return snd_pcm_lib_write1(substream, bufs, frames, nonblock,
2316                                   snd_pcm_lib_writev_transfer);
2317 }
2318 
2319 static int snd_pcm_lib_read_transfer(snd_pcm_substream_t *substream, 
2320                                      unsigned int hwoff,
2321                                      void *data, unsigned int off,
2322                                      snd_pcm_uframes_t frames)
2323 {
2324         snd_pcm_runtime_t *runtime = substream->runtime;
2325         int err;
2326         char *buf = (char *) data + frames_to_bytes(runtime, off);
2327         if (substream->ops->copy) {
2328                 if ((err = substream->ops->copy(substream, -1, hwoff, buf, frames)) < 0)
2329                         return err;
2330         } else {
2331                 char *hwbuf = runtime->dma_area + frames_to_bytes(runtime, hwoff);
2332                 snd_assert(runtime->dma_area, return -EFAULT);
2333                 if (copy_to_user(buf, hwbuf, frames_to_bytes(runtime, frames)))
2334                         return -EFAULT;
2335         }
2336         return 0;
2337 }
2338 
2339 static snd_pcm_sframes_t snd_pcm_lib_read1(snd_pcm_substream_t *substream, void *data, snd_pcm_uframes_t size, int nonblock,
2340                                            transfer_f transfer)
2341 {
2342         snd_pcm_runtime_t *runtime = substream->runtime;
2343         snd_pcm_uframes_t xfer = 0;
2344         snd_pcm_uframes_t offset = 0;
2345         int err = 0;
2346 
2347         if (size == 0)
2348                 return 0;
2349         if (size > runtime->xfer_align)
2350                 size -= size % runtime->xfer_align;
2351 
2352         snd_pcm_stream_lock_irq(substream);
2353         switch (runtime->status->state) {
2354         case SNDRV_PCM_STATE_PREPARED:
2355                 if (size >= runtime->start_threshold) {
2356                         err = snd_pcm_start(substream);
2357                         if (err < 0)
2358                                 goto _end_unlock;
2359                 }
2360                 break;
2361         case SNDRV_PCM_STATE_DRAINING:
2362         case SNDRV_PCM_STATE_RUNNING:
2363         case SNDRV_PCM_STATE_PAUSED:
2364                 break;
2365         case SNDRV_PCM_STATE_XRUN:
2366                 err = -EPIPE;
2367                 goto _end_unlock;
2368         case SNDRV_PCM_STATE_SUSPENDED:
2369                 err = -ESTRPIPE;
2370                 goto _end_unlock;
2371         default:
2372                 err = -EBADFD;
2373                 goto _end_unlock;
2374         }
2375 
2376         while (size > 0) {
2377                 snd_pcm_uframes_t frames, appl_ptr, appl_ofs;
2378                 snd_pcm_uframes_t avail;
2379                 snd_pcm_uframes_t cont;
2380                 if (runtime->sleep_min == 0 && runtime->status->state == SNDRV_PCM_STATE_RUNNING)
2381                         snd_pcm_update_hw_ptr(substream);
2382               __draining:
2383                 avail = snd_pcm_capture_avail(runtime);
2384                 if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) {
2385                         if (avail < runtime->xfer_align) {
2386                                 err = -EPIPE;
2387                                 goto _end_unlock;
2388                         }
2389                 } else if ((avail < runtime->control->avail_min && size > avail) ||
2390                            (size >= runtime->xfer_align && avail < runtime->xfer_align)) {
2391                         wait_queue_t wait;
2392                         enum { READY, SIGNALED, ERROR, SUSPENDED, EXPIRED } state;
2393                         long tout;
2394 
2395                         if (nonblock) {
2396                                 err = -EAGAIN;
2397                                 goto _end_unlock;
2398                         }
2399 
2400                         init_waitqueue_entry(&wait, current);
2401                         add_wait_queue(&runtime->sleep, &wait);
2402                         while (1) {
2403                                 if (signal_pending(current)) {
2404                                         state = SIGNALED;
2405                                         break;
2406                                 }
2407                                 set_current_state(TASK_INTERRUPTIBLE);
2408                                 snd_pcm_stream_unlock_irq(substream);
2409                                 tout = schedule_timeout(10 * HZ);
2410                                 snd_pcm_stream_lock_irq(substream);
2411                                 if (tout == 0) {
2412                                         if (runtime->status->state != SNDRV_PCM_STATE_PREPARED &&
2413                                             runtime->status->state != SNDRV_PCM_STATE_PAUSED) {
2414                                                 state = runtime->status->state == SNDRV_PCM_STATE_SUSPENDED ? SUSPENDED : EXPIRED;
2415                                                 break;
2416                                         }
2417                                 }
2418                                 switch (runtime->status->state) {
2419                                 case SNDRV_PCM_STATE_XRUN:
2420                                         state = ERROR;
2421                                         goto _end_loop;
2422                                 case SNDRV_PCM_STATE_SUSPENDED:
2423                                         state = SUSPENDED;
2424                                         goto _end_loop;
2425                                 case SNDRV_PCM_STATE_DRAINING:
2426                                         goto __draining;
2427                                 default:
2428                                         break;
2429                                 }
2430                                 avail = snd_pcm_capture_avail(runtime);
2431                                 if (avail >= runtime->control->avail_min) {
2432                                         state = READY;
2433                                         break;
2434                                 }
2435                         }
2436                        _end_loop:
2437                         remove_wait_queue(&runtime->sleep, &wait);
2438 
2439                         switch (state) {
2440                         case ERROR:
2441                                 err = -EPIPE;
2442                                 goto _end_unlock;
2443                         case SUSPENDED:
2444                                 err = -ESTRPIPE;
2445                                 goto _end_unlock;
2446                         case SIGNALED:
2447                                 err = -ERESTARTSYS;
2448                                 goto _end_unlock;
2449                         case EXPIRED:
2450                                 snd_printd("capture read error (DMA or IRQ trouble?)\n");
2451                                 err = -EIO;
2452                                 goto _end_unlock;
2453                         default:
2454                                 break;
2455                         }
2456                 }
2457                 if (avail > runtime->xfer_align)
2458                         avail -= avail % runtime->xfer_align;
2459                 frames = size > avail ? avail : size;
2460                 cont = runtime->buffer_size - runtime->control->appl_ptr % runtime->buffer_size;
2461                 if (frames > cont)
2462                         frames = cont;
2463                 snd_assert(frames != 0, snd_pcm_stream_unlock_irq(substream); return -EINVAL);
2464                 appl_ptr = runtime->control->appl_ptr;
2465                 appl_ofs = appl_ptr % runtime->buffer_size;
2466                 snd_pcm_stream_unlock_irq(substream);
2467                 if ((err = transfer(substream, appl_ofs, (void *)data, offset, frames)) < 0)
2468                         goto _end;
2469                 snd_pcm_stream_lock_irq(substream);
2470                 switch (runtime->status->state) {
2471                 case SNDRV_PCM_STATE_XRUN:
2472                         err = -EPIPE;
2473                         goto _end_unlock;
2474                 case SNDRV_PCM_STATE_SUSPENDED:
2475                         err = -ESTRPIPE;
2476                         goto _end_unlock;
2477                 default:
2478                         break;
2479                 }
2480                 appl_ptr += frames;
2481                 if (appl_ptr >= runtime->boundary) {
2482                         runtime->control->appl_ptr = 0;
2483                 } else {
2484                         runtime->control->appl_ptr = appl_ptr;
2485                 }
2486                 if (substream->ops->ack)
2487                         substream->ops->ack(substream);
2488 
2489                 offset += frames;
2490                 size -= frames;
2491                 xfer += frames;
2492                 if (runtime->sleep_min &&
2493                     runtime->status->state == SNDRV_PCM_STATE_RUNNING)
2494                         snd_pcm_tick_prepare(substream);
2495         }
2496  _end_unlock:
2497         snd_pcm_stream_unlock_irq(substream);
2498  _end:
2499         return xfer > 0 ? (snd_pcm_sframes_t)xfer : err;
2500 }
2501 
2502 snd_pcm_sframes_t snd_pcm_lib_read(snd_pcm_substream_t *substream, void *buf, snd_pcm_uframes_t size)
2503 {
2504         snd_pcm_runtime_t *runtime;
2505         int nonblock;
2506         
2507         snd_assert(substream != NULL, return -ENXIO);
2508         runtime = substream->runtime;
2509         snd_assert(runtime != NULL, return -ENXIO);
2510         snd_assert(substream->ops->copy != NULL || runtime->dma_area != NULL, return -EINVAL);
2511         if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
2512                 return -EBADFD;
2513 
2514         snd_assert(substream->ffile != NULL, return -ENXIO);
2515         nonblock = !!(substream->ffile->f_flags & O_NONBLOCK);
2516 #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
2517         if (substream->oss.oss) {
2518                 snd_pcm_oss_setup_t *setup = substream->oss.setup;
2519                 if (setup != NULL) {
2520                         if (setup->nonblock)
2521                                 nonblock = 1;
2522                         else if (setup->block)
2523                                 nonblock = 0;
2524                 }
2525         }
2526 #endif
2527         if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED)
2528                 return -EINVAL;
2529         return snd_pcm_lib_read1(substream, buf, size, nonblock, snd_pcm_lib_read_transfer);
2530 }
2531 
2532 static int snd_pcm_lib_readv_transfer(snd_pcm_substream_t *substream,
2533                                       unsigned int hwoff,
2534                                       void *data, unsigned int off,
2535                                       snd_pcm_uframes_t frames)
2536 {
2537         snd_pcm_runtime_t *runtime = substream->runtime;
2538         int err;
2539         void **bufs = data;
2540         int channels = runtime->channels;
2541         int c;
2542         if (substream->ops->copy) {
2543                 for (c = 0; c < channels; ++c, ++bufs) {
2544                         char *buf;
2545                         if (*bufs == NULL)
2546                                 continue;
2547                         buf = *bufs + samples_to_bytes(runtime, off);
2548                         if ((err = substream->ops->copy(substream, c, hwoff, buf, frames)) < 0)
2549                                 return err;
2550                 }
2551         } else {
2552                 snd_pcm_uframes_t dma_csize = runtime->dma_bytes / channels;
2553                 snd_assert(runtime->dma_area, return -EFAULT);
2554                 for (c = 0; c < channels; ++c, ++bufs) {
2555                         char *hwbuf, *buf;
2556                         if (*bufs == NULL)
2557                                 continue;
2558 
2559                         hwbuf = runtime->dma_area + (c * dma_csize) + samples_to_bytes(runtime, hwoff);
2560                         buf = *bufs + samples_to_bytes(runtime, off);
2561                         if (copy_to_user(buf, hwbuf, samples_to_bytes(runtime, frames)))
2562                                 return -EFAULT;
2563                 }
2564         }
2565         return 0;
2566 }
2567  
2568 snd_pcm_sframes_t snd_pcm_lib_readv(snd_pcm_substream_t *substream, void **bufs,
2569                                     snd_pcm_uframes_t frames)
2570 {
2571         snd_pcm_runtime_t *runtime;
2572         int nonblock;
2573 
2574         snd_assert(substream != NULL, return -ENXIO);
2575         runtime = substream->runtime;
2576         snd_assert(runtime != NULL, return -ENXIO);
2577         snd_assert(substream->ops->copy != NULL || runtime->dma_area != NULL, return -EINVAL);
2578         if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
2579                 return -EBADFD;
2580 
2581         snd_assert(substream->ffile != NULL, return -ENXIO);
2582         nonblock = !!(substream->ffile->f_flags & O_NONBLOCK);
2583 #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
2584         if (substream->oss.oss) {
2585                 snd_pcm_oss_setup_t *setup = substream->oss.setup;
2586                 if (setup != NULL) {
2587                         if (setup->nonblock)
2588                                 nonblock = 1;
2589                         else if (setup->block)
2590                                 nonblock = 0;
2591                 }
2592         }
2593 #endif
2594 
2595         if (runtime->access != SNDRV_PCM_ACCESS_RW_NONINTERLEAVED)
2596                 return -EINVAL;
2597         return snd_pcm_lib_read1(substream, bufs, frames, nonblock, snd_pcm_lib_readv_transfer);
2598 }
2599 
2600 /*
2601  *  Exported symbols
2602  */
2603 
2604 EXPORT_SYMBOL(snd_interval_refine);
2605 EXPORT_SYMBOL(snd_interval_list);
2606 EXPORT_SYMBOL(snd_interval_ratnum);
2607 EXPORT_SYMBOL(snd_interval_ratden);
2608 EXPORT_SYMBOL(snd_interval_muldivk);
2609 EXPORT_SYMBOL(snd_interval_mulkdiv);
2610 EXPORT_SYMBOL(snd_interval_div);
2611 EXPORT_SYMBOL(_snd_pcm_hw_params_any);
2612 EXPORT_SYMBOL(_snd_pcm_hw_param_min);
2613 EXPORT_SYMBOL(_snd_pcm_hw_param_set);
2614 EXPORT_SYMBOL(_snd_pcm_hw_param_setempty);
2615 EXPORT_SYMBOL(_snd_pcm_hw_param_setinteger);
2616 EXPORT_SYMBOL(snd_pcm_hw_param_value_min);
2617 EXPORT_SYMBOL(snd_pcm_hw_param_value_max);
2618 EXPORT_SYMBOL(snd_pcm_hw_param_mask);
2619 EXPORT_SYMBOL(snd_pcm_hw_param_first);
2620 EXPORT_SYMBOL(snd_pcm_hw_param_last);
2621 EXPORT_SYMBOL(snd_pcm_hw_param_near);
2622 EXPORT_SYMBOL(snd_pcm_hw_param_set);
2623 EXPORT_SYMBOL(snd_pcm_hw_refine);
2624 EXPORT_SYMBOL(snd_pcm_hw_constraints_init);
2625 EXPORT_SYMBOL(snd_pcm_hw_constraints_complete);
2626 EXPORT_SYMBOL(snd_pcm_hw_constraint_list);
2627 EXPORT_SYMBOL(snd_pcm_hw_constraint_step);
2628 EXPORT_SYMBOL(snd_pcm_hw_constraint_ratnums);
2629 EXPORT_SYMBOL(snd_pcm_hw_constraint_ratdens);
2630 EXPORT_SYMBOL(snd_pcm_hw_constraint_msbits);
2631 EXPORT_SYMBOL(snd_pcm_hw_constraint_minmax);
2632 EXPORT_SYMBOL(snd_pcm_hw_constraint_integer);
2633 EXPORT_SYMBOL(snd_pcm_hw_constraint_pow2);
2634 EXPORT_SYMBOL(snd_pcm_hw_rule_add);
2635 EXPORT_SYMBOL(snd_pcm_set_ops);
2636 EXPORT_SYMBOL(snd_pcm_set_sync);
2637 EXPORT_SYMBOL(snd_pcm_lib_ioctl);
2638 EXPORT_SYMBOL(snd_pcm_playback_ready);
2639 EXPORT_SYMBOL(snd_pcm_capture_ready);
2640 EXPORT_SYMBOL(snd_pcm_playback_data);
2641 EXPORT_SYMBOL(snd_pcm_capture_empty);
2642 EXPORT_SYMBOL(snd_pcm_stop);
2643 EXPORT_SYMBOL(snd_pcm_period_elapsed);
2644 EXPORT_SYMBOL(snd_pcm_lib_write);
2645 EXPORT_SYMBOL(snd_pcm_lib_read);
2646 EXPORT_SYMBOL(snd_pcm_lib_writev);
2647 EXPORT_SYMBOL(snd_pcm_lib_readv);
2648 EXPORT_SYMBOL(snd_pcm_lib_buffer_bytes);
2649 EXPORT_SYMBOL(snd_pcm_lib_period_bytes);
2650 /* pcm_memory.c */
2651 EXPORT_SYMBOL(snd_pcm_lib_preallocate_free);
2652 EXPORT_SYMBOL(snd_pcm_lib_preallocate_free_for_all);
2653 EXPORT_SYMBOL(snd_pcm_lib_preallocate_pages);
2654 EXPORT_SYMBOL(snd_pcm_lib_preallocate_pages_for_all);
2655 EXPORT_SYMBOL(snd_pcm_lib_malloc_pages);
2656 EXPORT_SYMBOL(snd_pcm_lib_free_pages);
2657 #ifdef CONFIG_ISA
2658 EXPORT_SYMBOL(snd_pcm_lib_preallocate_isa_pages);
2659 EXPORT_SYMBOL(snd_pcm_lib_preallocate_isa_pages_for_all);
2660 #endif
2661 #ifdef CONFIG_PCI
2662 EXPORT_SYMBOL(snd_pcm_lib_preallocate_pci_pages);
2663 EXPORT_SYMBOL(snd_pcm_lib_preallocate_pci_pages_for_all);
2664 EXPORT_SYMBOL(snd_pcm_lib_preallocate_sg_pages);
2665 EXPORT_SYMBOL(snd_pcm_lib_preallocate_sg_pages_for_all);
2666 EXPORT_SYMBOL(snd_pcm_sgbuf_ops_page);
2667 #endif
2668 #ifdef CONFIG_SBUS
2669 EXPORT_SYMBOL(snd_pcm_lib_preallocate_sbus_pages);
2670 EXPORT_SYMBOL(snd_pcm_lib_preallocate_sbus_pages_for_all);
2671 #endif
2672 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp