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