Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0-or-later
2 : : /*
3 : : * Digital Audio (PCM) abstract layer
4 : : * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
5 : : */
6 : :
7 : : #include <linux/mm.h>
8 : : #include <linux/module.h>
9 : : #include <linux/file.h>
10 : : #include <linux/slab.h>
11 : : #include <linux/sched/signal.h>
12 : : #include <linux/time.h>
13 : : #include <linux/pm_qos.h>
14 : : #include <linux/io.h>
15 : : #include <linux/dma-mapping.h>
16 : : #include <sound/core.h>
17 : : #include <sound/control.h>
18 : : #include <sound/info.h>
19 : : #include <sound/pcm.h>
20 : : #include <sound/pcm_params.h>
21 : : #include <sound/timer.h>
22 : : #include <sound/minors.h>
23 : : #include <linux/uio.h>
24 : : #include <linux/delay.h>
25 : :
26 : : #include "pcm_local.h"
27 : :
28 : : #ifdef CONFIG_SND_DEBUG
29 : : #define CREATE_TRACE_POINTS
30 : : #include "pcm_param_trace.h"
31 : : #else
32 : : #define trace_hw_mask_param_enabled() 0
33 : : #define trace_hw_interval_param_enabled() 0
34 : : #define trace_hw_mask_param(substream, type, index, prev, curr)
35 : : #define trace_hw_interval_param(substream, type, index, prev, curr)
36 : : #endif
37 : :
38 : : /*
39 : : * Compatibility
40 : : */
41 : :
42 : : struct snd_pcm_hw_params_old {
43 : : unsigned int flags;
44 : : unsigned int masks[SNDRV_PCM_HW_PARAM_SUBFORMAT -
45 : : SNDRV_PCM_HW_PARAM_ACCESS + 1];
46 : : struct snd_interval intervals[SNDRV_PCM_HW_PARAM_TICK_TIME -
47 : : SNDRV_PCM_HW_PARAM_SAMPLE_BITS + 1];
48 : : unsigned int rmask;
49 : : unsigned int cmask;
50 : : unsigned int info;
51 : : unsigned int msbits;
52 : : unsigned int rate_num;
53 : : unsigned int rate_den;
54 : : snd_pcm_uframes_t fifo_size;
55 : : unsigned char reserved[64];
56 : : };
57 : :
58 : : #ifdef CONFIG_SND_SUPPORT_OLD_API
59 : : #define SNDRV_PCM_IOCTL_HW_REFINE_OLD _IOWR('A', 0x10, struct snd_pcm_hw_params_old)
60 : : #define SNDRV_PCM_IOCTL_HW_PARAMS_OLD _IOWR('A', 0x11, struct snd_pcm_hw_params_old)
61 : :
62 : : static int snd_pcm_hw_refine_old_user(struct snd_pcm_substream *substream,
63 : : struct snd_pcm_hw_params_old __user * _oparams);
64 : : static int snd_pcm_hw_params_old_user(struct snd_pcm_substream *substream,
65 : : struct snd_pcm_hw_params_old __user * _oparams);
66 : : #endif
67 : : static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream);
68 : :
69 : : /*
70 : : *
71 : : */
72 : :
73 : : static DECLARE_RWSEM(snd_pcm_link_rwsem);
74 : :
75 : 1656 : void snd_pcm_group_init(struct snd_pcm_group *group)
76 : : {
77 : 1656 : spin_lock_init(&group->lock);
78 : 1656 : mutex_init(&group->mutex);
79 : 1656 : INIT_LIST_HEAD(&group->substreams);
80 : : refcount_set(&group->refs, 1);
81 : 1656 : }
82 : :
83 : : /* define group lock helpers */
84 : : #define DEFINE_PCM_GROUP_LOCK(action, mutex_action) \
85 : : static void snd_pcm_group_ ## action(struct snd_pcm_group *group, bool nonatomic) \
86 : : { \
87 : : if (nonatomic) \
88 : : mutex_ ## mutex_action(&group->mutex); \
89 : : else \
90 : : spin_ ## action(&group->lock); \
91 : : }
92 : :
93 [ # # # # ]: 0 : DEFINE_PCM_GROUP_LOCK(lock, lock);
94 [ # # # # ]: 0 : DEFINE_PCM_GROUP_LOCK(unlock, unlock);
95 [ # # # # : 0 : DEFINE_PCM_GROUP_LOCK(lock_irq, lock);
# # ]
96 [ # # # # : 0 : DEFINE_PCM_GROUP_LOCK(unlock_irq, unlock);
# # ]
97 : :
98 : : /**
99 : : * snd_pcm_stream_lock - Lock the PCM stream
100 : : * @substream: PCM substream
101 : : *
102 : : * This locks the PCM stream's spinlock or mutex depending on the nonatomic
103 : : * flag of the given substream. This also takes the global link rw lock
104 : : * (or rw sem), too, for avoiding the race with linked streams.
105 : : */
106 : 0 : void snd_pcm_stream_lock(struct snd_pcm_substream *substream)
107 : : {
108 : 0 : snd_pcm_group_lock(&substream->self_group, substream->pcm->nonatomic);
109 : 0 : }
110 : : EXPORT_SYMBOL_GPL(snd_pcm_stream_lock);
111 : :
112 : : /**
113 : : * snd_pcm_stream_lock - Unlock the PCM stream
114 : : * @substream: PCM substream
115 : : *
116 : : * This unlocks the PCM stream that has been locked via snd_pcm_stream_lock().
117 : : */
118 : 0 : void snd_pcm_stream_unlock(struct snd_pcm_substream *substream)
119 : : {
120 : 0 : snd_pcm_group_unlock(&substream->self_group, substream->pcm->nonatomic);
121 : 0 : }
122 : : EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock);
123 : :
124 : : /**
125 : : * snd_pcm_stream_lock_irq - Lock the PCM stream
126 : : * @substream: PCM substream
127 : : *
128 : : * This locks the PCM stream like snd_pcm_stream_lock() and disables the local
129 : : * IRQ (only when nonatomic is false). In nonatomic case, this is identical
130 : : * as snd_pcm_stream_lock().
131 : : */
132 : 0 : void snd_pcm_stream_lock_irq(struct snd_pcm_substream *substream)
133 : : {
134 : 0 : snd_pcm_group_lock_irq(&substream->self_group,
135 : 0 : substream->pcm->nonatomic);
136 : 0 : }
137 : : EXPORT_SYMBOL_GPL(snd_pcm_stream_lock_irq);
138 : :
139 : 0 : static void snd_pcm_stream_lock_nested(struct snd_pcm_substream *substream)
140 : : {
141 : : struct snd_pcm_group *group = &substream->self_group;
142 : :
143 [ # # ]: 0 : if (substream->pcm->nonatomic)
144 : 0 : mutex_lock_nested(&group->mutex, SINGLE_DEPTH_NESTING);
145 : : else
146 : 0 : spin_lock_nested(&group->lock, SINGLE_DEPTH_NESTING);
147 : 0 : }
148 : :
149 : : /**
150 : : * snd_pcm_stream_unlock_irq - Unlock the PCM stream
151 : : * @substream: PCM substream
152 : : *
153 : : * This is a counter-part of snd_pcm_stream_lock_irq().
154 : : */
155 : 0 : void snd_pcm_stream_unlock_irq(struct snd_pcm_substream *substream)
156 : : {
157 : 0 : snd_pcm_group_unlock_irq(&substream->self_group,
158 : 0 : substream->pcm->nonatomic);
159 : 0 : }
160 : : EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock_irq);
161 : :
162 : 0 : unsigned long _snd_pcm_stream_lock_irqsave(struct snd_pcm_substream *substream)
163 : : {
164 : : unsigned long flags = 0;
165 [ # # ]: 0 : if (substream->pcm->nonatomic)
166 : 0 : mutex_lock(&substream->self_group.mutex);
167 : : else
168 : 0 : spin_lock_irqsave(&substream->self_group.lock, flags);
169 : 0 : return flags;
170 : : }
171 : : EXPORT_SYMBOL_GPL(_snd_pcm_stream_lock_irqsave);
172 : :
173 : : /**
174 : : * snd_pcm_stream_unlock_irqrestore - Unlock the PCM stream
175 : : * @substream: PCM substream
176 : : * @flags: irq flags
177 : : *
178 : : * This is a counter-part of snd_pcm_stream_lock_irqsave().
179 : : */
180 : 0 : void snd_pcm_stream_unlock_irqrestore(struct snd_pcm_substream *substream,
181 : : unsigned long flags)
182 : : {
183 [ # # ]: 0 : if (substream->pcm->nonatomic)
184 : 0 : mutex_unlock(&substream->self_group.mutex);
185 : : else
186 : : spin_unlock_irqrestore(&substream->self_group.lock, flags);
187 : 0 : }
188 : : EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock_irqrestore);
189 : :
190 : 0 : int snd_pcm_info(struct snd_pcm_substream *substream, struct snd_pcm_info *info)
191 : : {
192 : 0 : struct snd_pcm *pcm = substream->pcm;
193 : 0 : struct snd_pcm_str *pstr = substream->pstr;
194 : :
195 : 0 : memset(info, 0, sizeof(*info));
196 : 0 : info->card = pcm->card->number;
197 : 0 : info->device = pcm->device;
198 : 0 : info->stream = substream->stream;
199 : 0 : info->subdevice = substream->number;
200 : 0 : strlcpy(info->id, pcm->id, sizeof(info->id));
201 : 0 : strlcpy(info->name, pcm->name, sizeof(info->name));
202 : 0 : info->dev_class = pcm->dev_class;
203 : 0 : info->dev_subclass = pcm->dev_subclass;
204 : 0 : info->subdevices_count = pstr->substream_count;
205 : 0 : info->subdevices_avail = pstr->substream_count - pstr->substream_opened;
206 : 0 : strlcpy(info->subname, substream->name, sizeof(info->subname));
207 : :
208 : 0 : return 0;
209 : : }
210 : :
211 : 0 : int snd_pcm_info_user(struct snd_pcm_substream *substream,
212 : : struct snd_pcm_info __user * _info)
213 : : {
214 : : struct snd_pcm_info *info;
215 : : int err;
216 : :
217 : : info = kmalloc(sizeof(*info), GFP_KERNEL);
218 [ # # ]: 0 : if (! info)
219 : : return -ENOMEM;
220 : 0 : err = snd_pcm_info(substream, info);
221 [ # # ]: 0 : if (err >= 0) {
222 [ # # ]: 0 : if (copy_to_user(_info, info, sizeof(*info)))
223 : : err = -EFAULT;
224 : : }
225 : 0 : kfree(info);
226 : 0 : return err;
227 : : }
228 : :
229 : 0 : static bool hw_support_mmap(struct snd_pcm_substream *substream)
230 : : {
231 [ # # ]: 0 : if (!(substream->runtime->hw.info & SNDRV_PCM_INFO_MMAP))
232 : : return false;
233 : :
234 [ # # # # ]: 0 : if (substream->ops->mmap ||
235 : 0 : (substream->dma_buffer.dev.type != SNDRV_DMA_TYPE_DEV &&
236 : : substream->dma_buffer.dev.type != SNDRV_DMA_TYPE_DEV_UC))
237 : : return true;
238 : :
239 : 0 : return dma_can_mmap(substream->dma_buffer.dev.dev);
240 : : }
241 : :
242 : 0 : static int constrain_mask_params(struct snd_pcm_substream *substream,
243 : : struct snd_pcm_hw_params *params)
244 : : {
245 : : struct snd_pcm_hw_constraints *constrs =
246 : 0 : &substream->runtime->hw_constraints;
247 : : struct snd_mask *m;
248 : : unsigned int k;
249 : : struct snd_mask old_mask;
250 : : int changed;
251 : :
252 [ # # ]: 0 : for (k = SNDRV_PCM_HW_PARAM_FIRST_MASK; k <= SNDRV_PCM_HW_PARAM_LAST_MASK; k++) {
253 : 0 : m = hw_param_mask(params, k);
254 [ # # ]: 0 : if (snd_mask_empty(m))
255 : : return -EINVAL;
256 : :
257 : : /* This parameter is not requested to change by a caller. */
258 [ # # ]: 0 : if (!(params->rmask & (1 << k)))
259 : 0 : continue;
260 : :
261 : : if (trace_hw_mask_param_enabled())
262 : : old_mask = *m;
263 : :
264 : 0 : changed = snd_mask_refine(m, constrs_mask(constrs, k));
265 [ # # ]: 0 : if (changed < 0)
266 : 0 : return changed;
267 [ # # ]: 0 : if (changed == 0)
268 : 0 : continue;
269 : :
270 : : /* Set corresponding flag so that the caller gets it. */
271 : : trace_hw_mask_param(substream, k, 0, &old_mask, m);
272 : 0 : params->cmask |= 1 << k;
273 : : }
274 : :
275 : : return 0;
276 : : }
277 : :
278 : 0 : static int constrain_interval_params(struct snd_pcm_substream *substream,
279 : : struct snd_pcm_hw_params *params)
280 : : {
281 : : struct snd_pcm_hw_constraints *constrs =
282 : 0 : &substream->runtime->hw_constraints;
283 : : struct snd_interval *i;
284 : : unsigned int k;
285 : : struct snd_interval old_interval;
286 : : int changed;
287 : :
288 [ # # ]: 0 : for (k = SNDRV_PCM_HW_PARAM_FIRST_INTERVAL; k <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; k++) {
289 : 0 : i = hw_param_interval(params, k);
290 [ # # ]: 0 : if (snd_interval_empty(i))
291 : : return -EINVAL;
292 : :
293 : : /* This parameter is not requested to change by a caller. */
294 [ # # ]: 0 : if (!(params->rmask & (1 << k)))
295 : 0 : continue;
296 : :
297 : : if (trace_hw_interval_param_enabled())
298 : : old_interval = *i;
299 : :
300 : 0 : changed = snd_interval_refine(i, constrs_interval(constrs, k));
301 [ # # ]: 0 : if (changed < 0)
302 : 0 : return changed;
303 [ # # ]: 0 : if (changed == 0)
304 : 0 : continue;
305 : :
306 : : /* Set corresponding flag so that the caller gets it. */
307 : : trace_hw_interval_param(substream, k, 0, &old_interval, i);
308 : 0 : params->cmask |= 1 << k;
309 : : }
310 : :
311 : : return 0;
312 : : }
313 : :
314 : 0 : static int constrain_params_by_rules(struct snd_pcm_substream *substream,
315 : : struct snd_pcm_hw_params *params)
316 : : {
317 : : struct snd_pcm_hw_constraints *constrs =
318 : 0 : &substream->runtime->hw_constraints;
319 : : unsigned int k;
320 : : unsigned int *rstamps;
321 : : unsigned int vstamps[SNDRV_PCM_HW_PARAM_LAST_INTERVAL + 1];
322 : : unsigned int stamp;
323 : : struct snd_pcm_hw_rule *r;
324 : : unsigned int d;
325 : : struct snd_mask old_mask;
326 : : struct snd_interval old_interval;
327 : : bool again;
328 : : int changed, err = 0;
329 : :
330 : : /*
331 : : * Each application of rule has own sequence number.
332 : : *
333 : : * Each member of 'rstamps' array represents the sequence number of
334 : : * recent application of corresponding rule.
335 : : */
336 : 0 : rstamps = kcalloc(constrs->rules_num, sizeof(unsigned int), GFP_KERNEL);
337 [ # # ]: 0 : if (!rstamps)
338 : : return -ENOMEM;
339 : :
340 : : /*
341 : : * Each member of 'vstamps' array represents the sequence number of
342 : : * recent application of rule in which corresponding parameters were
343 : : * changed.
344 : : *
345 : : * In initial state, elements corresponding to parameters requested by
346 : : * a caller is 1. For unrequested parameters, corresponding members
347 : : * have 0 so that the parameters are never changed anymore.
348 : : */
349 [ # # ]: 0 : for (k = 0; k <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; k++)
350 : 0 : vstamps[k] = (params->rmask & (1 << k)) ? 1 : 0;
351 : :
352 : : /* Due to the above design, actual sequence number starts at 2. */
353 : : stamp = 2;
354 : : retry:
355 : : /* Apply all rules in order. */
356 : : again = false;
357 [ # # ]: 0 : for (k = 0; k < constrs->rules_num; k++) {
358 : 0 : r = &constrs->rules[k];
359 : :
360 : : /*
361 : : * Check condition bits of this rule. When the rule has
362 : : * some condition bits, parameter without the bits is
363 : : * never processed. SNDRV_PCM_HW_PARAMS_NO_PERIOD_WAKEUP
364 : : * is an example of the condition bits.
365 : : */
366 [ # # # # ]: 0 : if (r->cond && !(r->cond & params->flags))
367 : 0 : continue;
368 : :
369 : : /*
370 : : * The 'deps' array includes maximum three dependencies
371 : : * to SNDRV_PCM_HW_PARAM_XXXs for this rule. The fourth
372 : : * member of this array is a sentinel and should be
373 : : * negative value.
374 : : *
375 : : * This rule should be processed in this time when dependent
376 : : * parameters were changed at former applications of the other
377 : : * rules.
378 : : */
379 [ # # ]: 0 : for (d = 0; r->deps[d] >= 0; d++) {
380 [ # # ]: 0 : if (vstamps[r->deps[d]] > rstamps[k])
381 : : break;
382 : : }
383 [ # # ]: 0 : if (r->deps[d] < 0)
384 : 0 : continue;
385 : :
386 : : if (trace_hw_mask_param_enabled()) {
387 : : if (hw_is_mask(r->var))
388 : : old_mask = *hw_param_mask(params, r->var);
389 : : }
390 : : if (trace_hw_interval_param_enabled()) {
391 : : if (hw_is_interval(r->var))
392 : : old_interval = *hw_param_interval(params, r->var);
393 : : }
394 : :
395 : 0 : changed = r->func(params, r);
396 [ # # ]: 0 : if (changed < 0) {
397 : 0 : err = changed;
398 : 0 : goto out;
399 : : }
400 : :
401 : : /*
402 : : * When the parameter is changed, notify it to the caller
403 : : * by corresponding returned bit, then preparing for next
404 : : * iteration.
405 : : */
406 [ # # # # ]: 0 : if (changed && r->var >= 0) {
407 : : if (hw_is_mask(r->var)) {
408 : : trace_hw_mask_param(substream, r->var,
409 : : k + 1, &old_mask,
410 : : hw_param_mask(params, r->var));
411 : : }
412 : : if (hw_is_interval(r->var)) {
413 : : trace_hw_interval_param(substream, r->var,
414 : : k + 1, &old_interval,
415 : : hw_param_interval(params, r->var));
416 : : }
417 : :
418 : 0 : params->cmask |= (1 << r->var);
419 : 0 : vstamps[r->var] = stamp;
420 : : again = true;
421 : : }
422 : :
423 : 0 : rstamps[k] = stamp++;
424 : : }
425 : :
426 : : /* Iterate to evaluate all rules till no parameters are changed. */
427 [ # # ]: 0 : if (again)
428 : : goto retry;
429 : :
430 : : out:
431 : 0 : kfree(rstamps);
432 : 0 : return err;
433 : : }
434 : :
435 : 0 : static int fixup_unreferenced_params(struct snd_pcm_substream *substream,
436 : : struct snd_pcm_hw_params *params)
437 : : {
438 : : const struct snd_interval *i;
439 : : const struct snd_mask *m;
440 : : int err;
441 : :
442 [ # # ]: 0 : if (!params->msbits) {
443 : : i = hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS);
444 [ # # ]: 0 : if (snd_interval_single(i))
445 : 0 : params->msbits = snd_interval_value(i);
446 : : }
447 : :
448 [ # # ]: 0 : if (!params->rate_den) {
449 : : i = hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_RATE);
450 [ # # ]: 0 : if (snd_interval_single(i)) {
451 : 0 : params->rate_num = snd_interval_value(i);
452 : 0 : params->rate_den = 1;
453 : : }
454 : : }
455 : :
456 [ # # ]: 0 : if (!params->fifo_size) {
457 : : m = hw_param_mask_c(params, SNDRV_PCM_HW_PARAM_FORMAT);
458 : : i = hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_CHANNELS);
459 [ # # # # ]: 0 : if (snd_mask_single(m) && snd_interval_single(i)) {
460 : 0 : err = substream->ops->ioctl(substream,
461 : : SNDRV_PCM_IOCTL1_FIFO_SIZE, params);
462 [ # # ]: 0 : if (err < 0)
463 : : return err;
464 : : }
465 : : }
466 : :
467 [ # # ]: 0 : if (!params->info) {
468 : 0 : params->info = substream->runtime->hw.info;
469 : 0 : params->info &= ~(SNDRV_PCM_INFO_FIFO_IN_FRAMES |
470 : : SNDRV_PCM_INFO_DRAIN_TRIGGER);
471 [ # # ]: 0 : if (!hw_support_mmap(substream))
472 : 0 : params->info &= ~(SNDRV_PCM_INFO_MMAP |
473 : : SNDRV_PCM_INFO_MMAP_VALID);
474 : : }
475 : :
476 : : return 0;
477 : : }
478 : :
479 : 0 : int snd_pcm_hw_refine(struct snd_pcm_substream *substream,
480 : : struct snd_pcm_hw_params *params)
481 : : {
482 : : int err;
483 : :
484 : 0 : params->info = 0;
485 : 0 : params->fifo_size = 0;
486 [ # # ]: 0 : if (params->rmask & (1 << SNDRV_PCM_HW_PARAM_SAMPLE_BITS))
487 : 0 : params->msbits = 0;
488 [ # # ]: 0 : if (params->rmask & (1 << SNDRV_PCM_HW_PARAM_RATE)) {
489 : 0 : params->rate_num = 0;
490 : 0 : params->rate_den = 0;
491 : : }
492 : :
493 : 0 : err = constrain_mask_params(substream, params);
494 [ # # ]: 0 : if (err < 0)
495 : : return err;
496 : :
497 : 0 : err = constrain_interval_params(substream, params);
498 [ # # ]: 0 : if (err < 0)
499 : : return err;
500 : :
501 : 0 : err = constrain_params_by_rules(substream, params);
502 [ # # ]: 0 : if (err < 0)
503 : : return err;
504 : :
505 : 0 : params->rmask = 0;
506 : :
507 : 0 : return 0;
508 : : }
509 : : EXPORT_SYMBOL(snd_pcm_hw_refine);
510 : :
511 : 0 : static int snd_pcm_hw_refine_user(struct snd_pcm_substream *substream,
512 : : struct snd_pcm_hw_params __user * _params)
513 : : {
514 : : struct snd_pcm_hw_params *params;
515 : : int err;
516 : :
517 : 0 : params = memdup_user(_params, sizeof(*params));
518 [ # # ]: 0 : if (IS_ERR(params))
519 : 0 : return PTR_ERR(params);
520 : :
521 : 0 : err = snd_pcm_hw_refine(substream, params);
522 [ # # ]: 0 : if (err < 0)
523 : : goto end;
524 : :
525 : 0 : err = fixup_unreferenced_params(substream, params);
526 [ # # ]: 0 : if (err < 0)
527 : : goto end;
528 : :
529 [ # # ]: 0 : if (copy_to_user(_params, params, sizeof(*params)))
530 : : err = -EFAULT;
531 : : end:
532 : 0 : kfree(params);
533 : 0 : return err;
534 : : }
535 : :
536 : : static int period_to_usecs(struct snd_pcm_runtime *runtime)
537 : : {
538 : : int usecs;
539 : :
540 [ # # ]: 0 : if (! runtime->rate)
541 : : return -1; /* invalid */
542 : :
543 : : /* take 75% of period time as the deadline */
544 : 0 : usecs = (750000 / runtime->rate) * runtime->period_size;
545 : 0 : usecs += ((750000 % runtime->rate) * runtime->period_size) /
546 : : runtime->rate;
547 : :
548 : : return usecs;
549 : : }
550 : :
551 : 0 : static void snd_pcm_set_state(struct snd_pcm_substream *substream, int state)
552 : : {
553 : 0 : snd_pcm_stream_lock_irq(substream);
554 [ # # ]: 0 : if (substream->runtime->status->state != SNDRV_PCM_STATE_DISCONNECTED)
555 : 0 : substream->runtime->status->state = state;
556 : 0 : snd_pcm_stream_unlock_irq(substream);
557 : 0 : }
558 : :
559 : : static inline void snd_pcm_timer_notify(struct snd_pcm_substream *substream,
560 : : int event)
561 : : {
562 : : #ifdef CONFIG_SND_PCM_TIMER
563 [ # # # # : 0 : if (substream->timer)
# # # # #
# # # ]
564 : 0 : snd_timer_notify(substream->timer, event,
565 : 0 : &substream->runtime->trigger_tstamp);
566 : : #endif
567 : : }
568 : :
569 : : /**
570 : : * snd_pcm_hw_param_choose - choose a configuration defined by @params
571 : : * @pcm: PCM instance
572 : : * @params: the hw_params instance
573 : : *
574 : : * Choose one configuration from configuration space defined by @params.
575 : : * The configuration chosen is that obtained fixing in this order:
576 : : * first access, first format, first subformat, min channels,
577 : : * min rate, min period time, max buffer size, min tick time
578 : : *
579 : : * Return: Zero if successful, or a negative error code on failure.
580 : : */
581 : 0 : static int snd_pcm_hw_params_choose(struct snd_pcm_substream *pcm,
582 : : struct snd_pcm_hw_params *params)
583 : : {
584 : : static const int vars[] = {
585 : : SNDRV_PCM_HW_PARAM_ACCESS,
586 : : SNDRV_PCM_HW_PARAM_FORMAT,
587 : : SNDRV_PCM_HW_PARAM_SUBFORMAT,
588 : : SNDRV_PCM_HW_PARAM_CHANNELS,
589 : : SNDRV_PCM_HW_PARAM_RATE,
590 : : SNDRV_PCM_HW_PARAM_PERIOD_TIME,
591 : : SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
592 : : SNDRV_PCM_HW_PARAM_TICK_TIME,
593 : : -1
594 : : };
595 : : const int *v;
596 : : struct snd_mask old_mask;
597 : : struct snd_interval old_interval;
598 : : int changed;
599 : :
600 [ # # ]: 0 : for (v = vars; *v != -1; v++) {
601 : : /* Keep old parameter to trace. */
602 : : if (trace_hw_mask_param_enabled()) {
603 : : if (hw_is_mask(*v))
604 : : old_mask = *hw_param_mask(params, *v);
605 : : }
606 : : if (trace_hw_interval_param_enabled()) {
607 : : if (hw_is_interval(*v))
608 : : old_interval = *hw_param_interval(params, *v);
609 : : }
610 [ # # ]: 0 : if (*v != SNDRV_PCM_HW_PARAM_BUFFER_SIZE)
611 : 0 : changed = snd_pcm_hw_param_first(pcm, params, *v, NULL);
612 : : else
613 : 0 : changed = snd_pcm_hw_param_last(pcm, params, *v, NULL);
614 [ # # ]: 0 : if (changed < 0)
615 : 0 : return changed;
616 : : if (changed == 0)
617 : : continue;
618 : :
619 : : /* Trace the changed parameter. */
620 : : if (hw_is_mask(*v)) {
621 : : trace_hw_mask_param(pcm, *v, 0, &old_mask,
622 : : hw_param_mask(params, *v));
623 : : }
624 : : if (hw_is_interval(*v)) {
625 : : trace_hw_interval_param(pcm, *v, 0, &old_interval,
626 : : hw_param_interval(params, *v));
627 : : }
628 : : }
629 : :
630 : : return 0;
631 : : }
632 : :
633 : 0 : static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
634 : : struct snd_pcm_hw_params *params)
635 : : {
636 : : struct snd_pcm_runtime *runtime;
637 : : int err, usecs;
638 : : unsigned int bits;
639 : : snd_pcm_uframes_t frames;
640 : :
641 [ # # # # : 0 : if (PCM_RUNTIME_CHECK(substream))
# # ]
642 : : return -ENXIO;
643 : 0 : runtime = substream->runtime;
644 : 0 : snd_pcm_stream_lock_irq(substream);
645 [ # # ]: 0 : switch (runtime->status->state) {
646 : : case SNDRV_PCM_STATE_OPEN:
647 : : case SNDRV_PCM_STATE_SETUP:
648 : : case SNDRV_PCM_STATE_PREPARED:
649 : : break;
650 : : default:
651 : 0 : snd_pcm_stream_unlock_irq(substream);
652 : 0 : return -EBADFD;
653 : : }
654 : 0 : snd_pcm_stream_unlock_irq(substream);
655 : : #if IS_ENABLED(CONFIG_SND_PCM_OSS)
656 : : if (!substream->oss.oss)
657 : : #endif
658 [ # # ]: 0 : if (atomic_read(&substream->mmap_count))
659 : : return -EBADFD;
660 : :
661 : 0 : params->rmask = ~0U;
662 : 0 : err = snd_pcm_hw_refine(substream, params);
663 [ # # ]: 0 : if (err < 0)
664 : : goto _error;
665 : :
666 : 0 : err = snd_pcm_hw_params_choose(substream, params);
667 [ # # ]: 0 : if (err < 0)
668 : : goto _error;
669 : :
670 : 0 : err = fixup_unreferenced_params(substream, params);
671 [ # # ]: 0 : if (err < 0)
672 : : goto _error;
673 : :
674 [ # # ]: 0 : if (substream->ops->hw_params != NULL) {
675 : 0 : err = substream->ops->hw_params(substream, params);
676 [ # # ]: 0 : if (err < 0)
677 : : goto _error;
678 : : }
679 : :
680 : 0 : runtime->access = params_access(params);
681 : 0 : runtime->format = params_format(params);
682 : 0 : runtime->subformat = params_subformat(params);
683 : 0 : runtime->channels = params_channels(params);
684 : 0 : runtime->rate = params_rate(params);
685 : 0 : runtime->period_size = params_period_size(params);
686 : 0 : runtime->periods = params_periods(params);
687 : 0 : runtime->buffer_size = params_buffer_size(params);
688 : 0 : runtime->info = params->info;
689 : 0 : runtime->rate_num = params->rate_num;
690 : 0 : runtime->rate_den = params->rate_den;
691 : 0 : runtime->no_period_wakeup =
692 [ # # # # ]: 0 : (params->info & SNDRV_PCM_INFO_NO_PERIOD_WAKEUP) &&
693 : 0 : (params->flags & SNDRV_PCM_HW_PARAMS_NO_PERIOD_WAKEUP);
694 : :
695 : 0 : bits = snd_pcm_format_physical_width(runtime->format);
696 : 0 : runtime->sample_bits = bits;
697 : 0 : bits *= runtime->channels;
698 : 0 : runtime->frame_bits = bits;
699 : : frames = 1;
700 [ # # ]: 0 : while (bits % 8 != 0) {
701 : 0 : bits *= 2;
702 : 0 : frames *= 2;
703 : : }
704 : 0 : runtime->byte_align = bits / 8;
705 : 0 : runtime->min_align = frames;
706 : :
707 : : /* Default sw params */
708 : 0 : runtime->tstamp_mode = SNDRV_PCM_TSTAMP_NONE;
709 : 0 : runtime->period_step = 1;
710 : 0 : runtime->control->avail_min = runtime->period_size;
711 : 0 : runtime->start_threshold = 1;
712 : 0 : runtime->stop_threshold = runtime->buffer_size;
713 : 0 : runtime->silence_threshold = 0;
714 : 0 : runtime->silence_size = 0;
715 : 0 : runtime->boundary = runtime->buffer_size;
716 [ # # ]: 0 : while (runtime->boundary * 2 <= LONG_MAX - runtime->buffer_size)
717 : 0 : runtime->boundary *= 2;
718 : :
719 : : /* clear the buffer for avoiding possible kernel info leaks */
720 [ # # # # ]: 0 : if (runtime->dma_area && !substream->ops->copy_user)
721 : 0 : memset(runtime->dma_area, 0, runtime->dma_bytes);
722 : :
723 : 0 : snd_pcm_timer_resolution_change(substream);
724 : 0 : snd_pcm_set_state(substream, SNDRV_PCM_STATE_SETUP);
725 : :
726 [ # # ]: 0 : if (pm_qos_request_active(&substream->latency_pm_qos_req))
727 : 0 : pm_qos_remove_request(&substream->latency_pm_qos_req);
728 [ # # ]: 0 : if ((usecs = period_to_usecs(runtime)) >= 0)
729 : 0 : pm_qos_add_request(&substream->latency_pm_qos_req,
730 : : PM_QOS_CPU_DMA_LATENCY, usecs);
731 : : return 0;
732 : : _error:
733 : : /* hardware might be unusable from this time,
734 : : so we force application to retry to set
735 : : the correct hardware parameter settings */
736 : 0 : snd_pcm_set_state(substream, SNDRV_PCM_STATE_OPEN);
737 [ # # ]: 0 : if (substream->ops->hw_free != NULL)
738 : 0 : substream->ops->hw_free(substream);
739 : 0 : return err;
740 : : }
741 : :
742 : 0 : static int snd_pcm_hw_params_user(struct snd_pcm_substream *substream,
743 : : struct snd_pcm_hw_params __user * _params)
744 : : {
745 : : struct snd_pcm_hw_params *params;
746 : : int err;
747 : :
748 : 0 : params = memdup_user(_params, sizeof(*params));
749 [ # # ]: 0 : if (IS_ERR(params))
750 : 0 : return PTR_ERR(params);
751 : :
752 : 0 : err = snd_pcm_hw_params(substream, params);
753 [ # # ]: 0 : if (err < 0)
754 : : goto end;
755 : :
756 [ # # ]: 0 : if (copy_to_user(_params, params, sizeof(*params)))
757 : : err = -EFAULT;
758 : : end:
759 : 0 : kfree(params);
760 : 0 : return err;
761 : : }
762 : :
763 : 0 : static int snd_pcm_hw_free(struct snd_pcm_substream *substream)
764 : : {
765 : : struct snd_pcm_runtime *runtime;
766 : : int result = 0;
767 : :
768 [ # # # # : 0 : if (PCM_RUNTIME_CHECK(substream))
# # ]
769 : : return -ENXIO;
770 : 0 : runtime = substream->runtime;
771 : 0 : snd_pcm_stream_lock_irq(substream);
772 [ # # ]: 0 : switch (runtime->status->state) {
773 : : case SNDRV_PCM_STATE_SETUP:
774 : : case SNDRV_PCM_STATE_PREPARED:
775 : : break;
776 : : default:
777 : 0 : snd_pcm_stream_unlock_irq(substream);
778 : 0 : return -EBADFD;
779 : : }
780 : 0 : snd_pcm_stream_unlock_irq(substream);
781 [ # # ]: 0 : if (atomic_read(&substream->mmap_count))
782 : : return -EBADFD;
783 [ # # ]: 0 : if (substream->ops->hw_free)
784 : 0 : result = substream->ops->hw_free(substream);
785 : 0 : snd_pcm_set_state(substream, SNDRV_PCM_STATE_OPEN);
786 : 0 : pm_qos_remove_request(&substream->latency_pm_qos_req);
787 : 0 : return result;
788 : : }
789 : :
790 : 0 : static int snd_pcm_sw_params(struct snd_pcm_substream *substream,
791 : : struct snd_pcm_sw_params *params)
792 : : {
793 : : struct snd_pcm_runtime *runtime;
794 : : int err;
795 : :
796 [ # # # # : 0 : if (PCM_RUNTIME_CHECK(substream))
# # ]
797 : : return -ENXIO;
798 : 0 : runtime = substream->runtime;
799 : 0 : snd_pcm_stream_lock_irq(substream);
800 [ # # ]: 0 : if (runtime->status->state == SNDRV_PCM_STATE_OPEN) {
801 : 0 : snd_pcm_stream_unlock_irq(substream);
802 : 0 : return -EBADFD;
803 : : }
804 : 0 : snd_pcm_stream_unlock_irq(substream);
805 : :
806 [ # # ]: 0 : if (params->tstamp_mode < 0 ||
807 : : params->tstamp_mode > SNDRV_PCM_TSTAMP_LAST)
808 : : return -EINVAL;
809 [ # # # # ]: 0 : if (params->proto >= SNDRV_PROTOCOL_VERSION(2, 0, 12) &&
810 : 0 : params->tstamp_type > SNDRV_PCM_TSTAMP_TYPE_LAST)
811 : : return -EINVAL;
812 [ # # ]: 0 : if (params->avail_min == 0)
813 : : return -EINVAL;
814 [ # # ]: 0 : if (params->silence_size >= runtime->boundary) {
815 [ # # ]: 0 : if (params->silence_threshold != 0)
816 : : return -EINVAL;
817 : : } else {
818 [ # # ]: 0 : if (params->silence_size > params->silence_threshold)
819 : : return -EINVAL;
820 [ # # ]: 0 : if (params->silence_threshold > runtime->buffer_size)
821 : : return -EINVAL;
822 : : }
823 : : err = 0;
824 : 0 : snd_pcm_stream_lock_irq(substream);
825 : 0 : runtime->tstamp_mode = params->tstamp_mode;
826 [ # # ]: 0 : if (params->proto >= SNDRV_PROTOCOL_VERSION(2, 0, 12))
827 : 0 : runtime->tstamp_type = params->tstamp_type;
828 : 0 : runtime->period_step = params->period_step;
829 : 0 : runtime->control->avail_min = params->avail_min;
830 : 0 : runtime->start_threshold = params->start_threshold;
831 : 0 : runtime->stop_threshold = params->stop_threshold;
832 : 0 : runtime->silence_threshold = params->silence_threshold;
833 : 0 : runtime->silence_size = params->silence_size;
834 : 0 : params->boundary = runtime->boundary;
835 [ # # ]: 0 : if (snd_pcm_running(substream)) {
836 [ # # # # ]: 0 : if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
837 : 0 : runtime->silence_size > 0)
838 : 0 : snd_pcm_playback_silence(substream, ULONG_MAX);
839 : 0 : err = snd_pcm_update_state(substream, runtime);
840 : : }
841 : 0 : snd_pcm_stream_unlock_irq(substream);
842 : 0 : return err;
843 : : }
844 : :
845 : 0 : static int snd_pcm_sw_params_user(struct snd_pcm_substream *substream,
846 : : struct snd_pcm_sw_params __user * _params)
847 : : {
848 : : struct snd_pcm_sw_params params;
849 : : int err;
850 [ # # ]: 0 : if (copy_from_user(¶ms, _params, sizeof(params)))
851 : : return -EFAULT;
852 : 0 : err = snd_pcm_sw_params(substream, ¶ms);
853 [ # # ]: 0 : if (copy_to_user(_params, ¶ms, sizeof(params)))
854 : : return -EFAULT;
855 : 0 : return err;
856 : : }
857 : :
858 : : static inline snd_pcm_uframes_t
859 : 0 : snd_pcm_calc_delay(struct snd_pcm_substream *substream)
860 : : {
861 : : snd_pcm_uframes_t delay;
862 : :
863 [ # # ]: 0 : if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
864 : 0 : delay = snd_pcm_playback_hw_avail(substream->runtime);
865 : : else
866 : 0 : delay = snd_pcm_capture_avail(substream->runtime);
867 : 0 : return delay + substream->runtime->delay;
868 : : }
869 : :
870 : 0 : int snd_pcm_status(struct snd_pcm_substream *substream,
871 : : struct snd_pcm_status *status)
872 : : {
873 : 0 : struct snd_pcm_runtime *runtime = substream->runtime;
874 : :
875 : 0 : snd_pcm_stream_lock_irq(substream);
876 : :
877 : 0 : snd_pcm_unpack_audio_tstamp_config(status->audio_tstamp_data,
878 : : &runtime->audio_tstamp_config);
879 : :
880 : : /* backwards compatible behavior */
881 [ # # ]: 0 : if (runtime->audio_tstamp_config.type_requested ==
882 : : SNDRV_PCM_AUDIO_TSTAMP_TYPE_COMPAT) {
883 [ # # ]: 0 : if (runtime->hw.info & SNDRV_PCM_INFO_HAS_WALL_CLOCK)
884 : 0 : runtime->audio_tstamp_config.type_requested =
885 : : SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK;
886 : : else
887 : 0 : runtime->audio_tstamp_config.type_requested =
888 : : SNDRV_PCM_AUDIO_TSTAMP_TYPE_DEFAULT;
889 : 0 : runtime->audio_tstamp_report.valid = 0;
890 : : } else
891 : 0 : runtime->audio_tstamp_report.valid = 1;
892 : :
893 : 0 : status->state = runtime->status->state;
894 : 0 : status->suspended_state = runtime->status->suspended_state;
895 [ # # ]: 0 : if (status->state == SNDRV_PCM_STATE_OPEN)
896 : : goto _end;
897 : 0 : status->trigger_tstamp = runtime->trigger_tstamp;
898 [ # # ]: 0 : if (snd_pcm_running(substream)) {
899 : 0 : snd_pcm_update_hw_ptr(substream);
900 [ # # ]: 0 : if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE) {
901 : 0 : status->tstamp = runtime->status->tstamp;
902 : 0 : status->driver_tstamp = runtime->driver_tstamp;
903 : 0 : status->audio_tstamp =
904 : 0 : runtime->status->audio_tstamp;
905 [ # # ]: 0 : if (runtime->audio_tstamp_report.valid == 1)
906 : : /* backwards compatibility, no report provided in COMPAT mode */
907 : : snd_pcm_pack_audio_tstamp_report(&status->audio_tstamp_data,
908 : : &status->audio_tstamp_accuracy,
909 : : &runtime->audio_tstamp_report);
910 : :
911 : : goto _tstamp_end;
912 : : }
913 : : } else {
914 : : /* get tstamp only in fallback mode and only if enabled */
915 [ # # ]: 0 : if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE)
916 : 0 : snd_pcm_gettime(runtime, &status->tstamp);
917 : : }
918 : : _tstamp_end:
919 : 0 : status->appl_ptr = runtime->control->appl_ptr;
920 : 0 : status->hw_ptr = runtime->status->hw_ptr;
921 : 0 : status->avail = snd_pcm_avail(substream);
922 [ # # ]: 0 : status->delay = snd_pcm_running(substream) ?
923 : 0 : snd_pcm_calc_delay(substream) : 0;
924 : 0 : status->avail_max = runtime->avail_max;
925 : 0 : status->overrange = runtime->overrange;
926 : 0 : runtime->avail_max = 0;
927 : 0 : runtime->overrange = 0;
928 : : _end:
929 : 0 : snd_pcm_stream_unlock_irq(substream);
930 : 0 : return 0;
931 : : }
932 : :
933 : 0 : static int snd_pcm_status_user(struct snd_pcm_substream *substream,
934 : : struct snd_pcm_status __user * _status,
935 : : bool ext)
936 : : {
937 : : struct snd_pcm_status status;
938 : : int res;
939 : :
940 : 0 : memset(&status, 0, sizeof(status));
941 : : /*
942 : : * with extension, parameters are read/write,
943 : : * get audio_tstamp_data from user,
944 : : * ignore rest of status structure
945 : : */
946 [ # # # # ]: 0 : if (ext && get_user(status.audio_tstamp_data,
947 : : (u32 __user *)(&_status->audio_tstamp_data)))
948 : : return -EFAULT;
949 : 0 : res = snd_pcm_status(substream, &status);
950 [ # # ]: 0 : if (res < 0)
951 : : return res;
952 [ # # ]: 0 : if (copy_to_user(_status, &status, sizeof(status)))
953 : : return -EFAULT;
954 : 0 : return 0;
955 : : }
956 : :
957 : 0 : static int snd_pcm_channel_info(struct snd_pcm_substream *substream,
958 : : struct snd_pcm_channel_info * info)
959 : : {
960 : : struct snd_pcm_runtime *runtime;
961 : : unsigned int channel;
962 : :
963 : 0 : channel = info->channel;
964 : 0 : runtime = substream->runtime;
965 : 0 : snd_pcm_stream_lock_irq(substream);
966 [ # # ]: 0 : if (runtime->status->state == SNDRV_PCM_STATE_OPEN) {
967 : 0 : snd_pcm_stream_unlock_irq(substream);
968 : 0 : return -EBADFD;
969 : : }
970 : 0 : snd_pcm_stream_unlock_irq(substream);
971 [ # # ]: 0 : if (channel >= runtime->channels)
972 : : return -EINVAL;
973 : 0 : memset(info, 0, sizeof(*info));
974 : 0 : info->channel = channel;
975 : 0 : return substream->ops->ioctl(substream, SNDRV_PCM_IOCTL1_CHANNEL_INFO, info);
976 : : }
977 : :
978 : 0 : static int snd_pcm_channel_info_user(struct snd_pcm_substream *substream,
979 : : struct snd_pcm_channel_info __user * _info)
980 : : {
981 : : struct snd_pcm_channel_info info;
982 : : int res;
983 : :
984 [ # # ]: 0 : if (copy_from_user(&info, _info, sizeof(info)))
985 : : return -EFAULT;
986 : 0 : res = snd_pcm_channel_info(substream, &info);
987 [ # # ]: 0 : if (res < 0)
988 : : return res;
989 [ # # ]: 0 : if (copy_to_user(_info, &info, sizeof(info)))
990 : : return -EFAULT;
991 : 0 : return 0;
992 : : }
993 : :
994 : 0 : static void snd_pcm_trigger_tstamp(struct snd_pcm_substream *substream)
995 : : {
996 : 0 : struct snd_pcm_runtime *runtime = substream->runtime;
997 [ # # ]: 0 : if (runtime->trigger_master == NULL)
998 : 0 : return;
999 [ # # ]: 0 : if (runtime->trigger_master == substream) {
1000 [ # # ]: 0 : if (!runtime->trigger_tstamp_latched)
1001 : 0 : snd_pcm_gettime(runtime, &runtime->trigger_tstamp);
1002 : : } else {
1003 : 0 : snd_pcm_trigger_tstamp(runtime->trigger_master);
1004 : 0 : runtime->trigger_tstamp = runtime->trigger_master->runtime->trigger_tstamp;
1005 : : }
1006 : 0 : runtime->trigger_master = NULL;
1007 : : }
1008 : :
1009 : : struct action_ops {
1010 : : int (*pre_action)(struct snd_pcm_substream *substream, int state);
1011 : : int (*do_action)(struct snd_pcm_substream *substream, int state);
1012 : : void (*undo_action)(struct snd_pcm_substream *substream, int state);
1013 : : void (*post_action)(struct snd_pcm_substream *substream, int state);
1014 : : };
1015 : :
1016 : : /*
1017 : : * this functions is core for handling of linked stream
1018 : : * Note: the stream state might be changed also on failure
1019 : : * Note2: call with calling stream lock + link lock
1020 : : */
1021 : 0 : static int snd_pcm_action_group(const struct action_ops *ops,
1022 : : struct snd_pcm_substream *substream,
1023 : : int state, int do_lock)
1024 : : {
1025 : : struct snd_pcm_substream *s = NULL;
1026 : : struct snd_pcm_substream *s1;
1027 : : int res = 0, depth = 1;
1028 : :
1029 [ # # ]: 0 : snd_pcm_group_for_each_entry(s, substream) {
1030 [ # # ]: 0 : if (do_lock && s != substream) {
1031 [ # # ]: 0 : if (s->pcm->nonatomic)
1032 : 0 : mutex_lock_nested(&s->self_group.mutex, depth);
1033 : : else
1034 : 0 : spin_lock_nested(&s->self_group.lock, depth);
1035 : : depth++;
1036 : : }
1037 : 0 : res = ops->pre_action(s, state);
1038 [ # # ]: 0 : if (res < 0)
1039 : : goto _unlock;
1040 : : }
1041 [ # # ]: 0 : snd_pcm_group_for_each_entry(s, substream) {
1042 : 0 : res = ops->do_action(s, state);
1043 [ # # ]: 0 : if (res < 0) {
1044 [ # # ]: 0 : if (ops->undo_action) {
1045 [ # # ]: 0 : snd_pcm_group_for_each_entry(s1, substream) {
1046 [ # # ]: 0 : if (s1 == s) /* failed stream */
1047 : : break;
1048 : 0 : ops->undo_action(s1, state);
1049 : : }
1050 : : }
1051 : : s = NULL; /* unlock all */
1052 : : goto _unlock;
1053 : : }
1054 : : }
1055 [ # # ]: 0 : snd_pcm_group_for_each_entry(s, substream) {
1056 : 0 : ops->post_action(s, state);
1057 : : }
1058 : : _unlock:
1059 [ # # ]: 0 : if (do_lock) {
1060 : : /* unlock streams */
1061 [ # # ]: 0 : snd_pcm_group_for_each_entry(s1, substream) {
1062 [ # # ]: 0 : if (s1 != substream) {
1063 [ # # ]: 0 : if (s1->pcm->nonatomic)
1064 : 0 : mutex_unlock(&s1->self_group.mutex);
1065 : : else
1066 : : spin_unlock(&s1->self_group.lock);
1067 : : }
1068 [ # # ]: 0 : if (s1 == s) /* end */
1069 : : break;
1070 : : }
1071 : : }
1072 : 0 : return res;
1073 : : }
1074 : :
1075 : : /*
1076 : : * Note: call with stream lock
1077 : : */
1078 : 0 : static int snd_pcm_action_single(const struct action_ops *ops,
1079 : : struct snd_pcm_substream *substream,
1080 : : int state)
1081 : : {
1082 : : int res;
1083 : :
1084 : 0 : res = ops->pre_action(substream, state);
1085 [ # # ]: 0 : if (res < 0)
1086 : : return res;
1087 : 0 : res = ops->do_action(substream, state);
1088 [ # # ]: 0 : if (res == 0)
1089 : 0 : ops->post_action(substream, state);
1090 [ # # ]: 0 : else if (ops->undo_action)
1091 : 0 : ops->undo_action(substream, state);
1092 : 0 : return res;
1093 : : }
1094 : :
1095 : : static void snd_pcm_group_assign(struct snd_pcm_substream *substream,
1096 : : struct snd_pcm_group *new_group)
1097 : : {
1098 : 0 : substream->group = new_group;
1099 : 0 : list_move(&substream->link_list, &new_group->substreams);
1100 : : }
1101 : :
1102 : : /*
1103 : : * Unref and unlock the group, but keep the stream lock;
1104 : : * when the group becomes empty and no longer referred, destroy itself
1105 : : */
1106 : 0 : static void snd_pcm_group_unref(struct snd_pcm_group *group,
1107 : : struct snd_pcm_substream *substream)
1108 : : {
1109 : : bool do_free;
1110 : :
1111 [ # # ]: 0 : if (!group)
1112 : 0 : return;
1113 : 0 : do_free = refcount_dec_and_test(&group->refs);
1114 : 0 : snd_pcm_group_unlock(group, substream->pcm->nonatomic);
1115 [ # # ]: 0 : if (do_free)
1116 : 0 : kfree(group);
1117 : : }
1118 : :
1119 : : /*
1120 : : * Lock the group inside a stream lock and reference it;
1121 : : * return the locked group object, or NULL if not linked
1122 : : */
1123 : : static struct snd_pcm_group *
1124 : 0 : snd_pcm_stream_group_ref(struct snd_pcm_substream *substream)
1125 : : {
1126 : 0 : bool nonatomic = substream->pcm->nonatomic;
1127 : : struct snd_pcm_group *group;
1128 : : bool trylock;
1129 : :
1130 : : for (;;) {
1131 [ # # ]: 0 : if (!snd_pcm_stream_linked(substream))
1132 : : return NULL;
1133 : : group = substream->group;
1134 : : /* block freeing the group object */
1135 : 0 : refcount_inc(&group->refs);
1136 : :
1137 [ # # ]: 0 : trylock = nonatomic ? mutex_trylock(&group->mutex) :
1138 : : spin_trylock(&group->lock);
1139 [ # # ]: 0 : if (trylock)
1140 : : break; /* OK */
1141 : :
1142 : : /* re-lock for avoiding ABBA deadlock */
1143 : 0 : snd_pcm_stream_unlock(substream);
1144 : : snd_pcm_group_lock(group, nonatomic);
1145 : 0 : snd_pcm_stream_lock(substream);
1146 : :
1147 : : /* check the group again; the above opens a small race window */
1148 [ # # ]: 0 : if (substream->group == group)
1149 : : break; /* OK */
1150 : : /* group changed, try again */
1151 : 0 : snd_pcm_group_unref(group, substream);
1152 : 0 : }
1153 : 0 : return group;
1154 : : }
1155 : :
1156 : : /*
1157 : : * Note: call with stream lock
1158 : : */
1159 : 0 : static int snd_pcm_action(const struct action_ops *ops,
1160 : : struct snd_pcm_substream *substream,
1161 : : int state)
1162 : : {
1163 : : struct snd_pcm_group *group;
1164 : : int res;
1165 : :
1166 : 0 : group = snd_pcm_stream_group_ref(substream);
1167 [ # # ]: 0 : if (group)
1168 : 0 : res = snd_pcm_action_group(ops, substream, state, 1);
1169 : : else
1170 : 0 : res = snd_pcm_action_single(ops, substream, state);
1171 : 0 : snd_pcm_group_unref(group, substream);
1172 : 0 : return res;
1173 : : }
1174 : :
1175 : : /*
1176 : : * Note: don't use any locks before
1177 : : */
1178 : 0 : static int snd_pcm_action_lock_irq(const struct action_ops *ops,
1179 : : struct snd_pcm_substream *substream,
1180 : : int state)
1181 : : {
1182 : : int res;
1183 : :
1184 : 0 : snd_pcm_stream_lock_irq(substream);
1185 : 0 : res = snd_pcm_action(ops, substream, state);
1186 : 0 : snd_pcm_stream_unlock_irq(substream);
1187 : 0 : return res;
1188 : : }
1189 : :
1190 : : /*
1191 : : */
1192 : 0 : static int snd_pcm_action_nonatomic(const struct action_ops *ops,
1193 : : struct snd_pcm_substream *substream,
1194 : : int state)
1195 : : {
1196 : : int res;
1197 : :
1198 : : /* Guarantee the group members won't change during non-atomic action */
1199 : 0 : down_read(&snd_pcm_link_rwsem);
1200 [ # # ]: 0 : if (snd_pcm_stream_linked(substream))
1201 : 0 : res = snd_pcm_action_group(ops, substream, state, 0);
1202 : : else
1203 : 0 : res = snd_pcm_action_single(ops, substream, state);
1204 : 0 : up_read(&snd_pcm_link_rwsem);
1205 : 0 : return res;
1206 : : }
1207 : :
1208 : : /*
1209 : : * start callbacks
1210 : : */
1211 : 0 : static int snd_pcm_pre_start(struct snd_pcm_substream *substream, int state)
1212 : : {
1213 : 0 : struct snd_pcm_runtime *runtime = substream->runtime;
1214 [ # # ]: 0 : if (runtime->status->state != SNDRV_PCM_STATE_PREPARED)
1215 : : return -EBADFD;
1216 [ # # # # ]: 0 : if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
1217 : 0 : !snd_pcm_playback_data(substream))
1218 : : return -EPIPE;
1219 : 0 : runtime->trigger_tstamp_latched = false;
1220 : 0 : runtime->trigger_master = substream;
1221 : 0 : return 0;
1222 : : }
1223 : :
1224 : 0 : static int snd_pcm_do_start(struct snd_pcm_substream *substream, int state)
1225 : : {
1226 [ # # # # ]: 0 : if (substream->runtime->trigger_master != substream)
1227 : : return 0;
1228 : 0 : return substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_START);
1229 : : }
1230 : :
1231 : 0 : static void snd_pcm_undo_start(struct snd_pcm_substream *substream, int state)
1232 : : {
1233 [ # # ]: 0 : if (substream->runtime->trigger_master == substream)
1234 : 0 : substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_STOP);
1235 : 0 : }
1236 : :
1237 : 0 : static void snd_pcm_post_start(struct snd_pcm_substream *substream, int state)
1238 : : {
1239 : 0 : struct snd_pcm_runtime *runtime = substream->runtime;
1240 : 0 : snd_pcm_trigger_tstamp(substream);
1241 : 0 : runtime->hw_ptr_jiffies = jiffies;
1242 : 0 : runtime->hw_ptr_buffer_jiffies = (runtime->buffer_size * HZ) /
1243 : 0 : runtime->rate;
1244 : 0 : runtime->status->state = state;
1245 [ # # # # ]: 0 : if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
1246 : 0 : runtime->silence_size > 0)
1247 : 0 : snd_pcm_playback_silence(substream, ULONG_MAX);
1248 : : snd_pcm_timer_notify(substream, SNDRV_TIMER_EVENT_MSTART);
1249 : 0 : }
1250 : :
1251 : : static const struct action_ops snd_pcm_action_start = {
1252 : : .pre_action = snd_pcm_pre_start,
1253 : : .do_action = snd_pcm_do_start,
1254 : : .undo_action = snd_pcm_undo_start,
1255 : : .post_action = snd_pcm_post_start
1256 : : };
1257 : :
1258 : : /**
1259 : : * snd_pcm_start - start all linked streams
1260 : : * @substream: the PCM substream instance
1261 : : *
1262 : : * Return: Zero if successful, or a negative error code.
1263 : : * The stream lock must be acquired before calling this function.
1264 : : */
1265 : 0 : int snd_pcm_start(struct snd_pcm_substream *substream)
1266 : : {
1267 : 0 : return snd_pcm_action(&snd_pcm_action_start, substream,
1268 : : SNDRV_PCM_STATE_RUNNING);
1269 : : }
1270 : :
1271 : : /* take the stream lock and start the streams */
1272 : : static int snd_pcm_start_lock_irq(struct snd_pcm_substream *substream)
1273 : : {
1274 : 0 : return snd_pcm_action_lock_irq(&snd_pcm_action_start, substream,
1275 : : SNDRV_PCM_STATE_RUNNING);
1276 : : }
1277 : :
1278 : : /*
1279 : : * stop callbacks
1280 : : */
1281 : 0 : static int snd_pcm_pre_stop(struct snd_pcm_substream *substream, int state)
1282 : : {
1283 : 0 : struct snd_pcm_runtime *runtime = substream->runtime;
1284 [ # # ]: 0 : if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
1285 : : return -EBADFD;
1286 : 0 : runtime->trigger_master = substream;
1287 : 0 : return 0;
1288 : : }
1289 : :
1290 : 0 : static int snd_pcm_do_stop(struct snd_pcm_substream *substream, int state)
1291 : : {
1292 [ # # # # ]: 0 : if (substream->runtime->trigger_master == substream &&
1293 : : snd_pcm_running(substream))
1294 : 0 : substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_STOP);
1295 : 0 : return 0; /* unconditonally stop all substreams */
1296 : : }
1297 : :
1298 : 0 : static void snd_pcm_post_stop(struct snd_pcm_substream *substream, int state)
1299 : : {
1300 : 0 : struct snd_pcm_runtime *runtime = substream->runtime;
1301 [ # # ]: 0 : if (runtime->status->state != state) {
1302 : 0 : snd_pcm_trigger_tstamp(substream);
1303 : 0 : runtime->status->state = state;
1304 : : snd_pcm_timer_notify(substream, SNDRV_TIMER_EVENT_MSTOP);
1305 : : }
1306 : 0 : wake_up(&runtime->sleep);
1307 : 0 : wake_up(&runtime->tsleep);
1308 : 0 : }
1309 : :
1310 : : static const struct action_ops snd_pcm_action_stop = {
1311 : : .pre_action = snd_pcm_pre_stop,
1312 : : .do_action = snd_pcm_do_stop,
1313 : : .post_action = snd_pcm_post_stop
1314 : : };
1315 : :
1316 : : /**
1317 : : * snd_pcm_stop - try to stop all running streams in the substream group
1318 : : * @substream: the PCM substream instance
1319 : : * @state: PCM state after stopping the stream
1320 : : *
1321 : : * The state of each stream is then changed to the given state unconditionally.
1322 : : *
1323 : : * Return: Zero if successful, or a negative error code.
1324 : : */
1325 : 0 : int snd_pcm_stop(struct snd_pcm_substream *substream, snd_pcm_state_t state)
1326 : : {
1327 : 0 : return snd_pcm_action(&snd_pcm_action_stop, substream, state);
1328 : : }
1329 : : EXPORT_SYMBOL(snd_pcm_stop);
1330 : :
1331 : : /**
1332 : : * snd_pcm_drain_done - stop the DMA only when the given stream is playback
1333 : : * @substream: the PCM substream
1334 : : *
1335 : : * After stopping, the state is changed to SETUP.
1336 : : * Unlike snd_pcm_stop(), this affects only the given stream.
1337 : : *
1338 : : * Return: Zero if succesful, or a negative error code.
1339 : : */
1340 : 0 : int snd_pcm_drain_done(struct snd_pcm_substream *substream)
1341 : : {
1342 : 0 : return snd_pcm_action_single(&snd_pcm_action_stop, substream,
1343 : : SNDRV_PCM_STATE_SETUP);
1344 : : }
1345 : :
1346 : : /**
1347 : : * snd_pcm_stop_xrun - stop the running streams as XRUN
1348 : : * @substream: the PCM substream instance
1349 : : *
1350 : : * This stops the given running substream (and all linked substreams) as XRUN.
1351 : : * Unlike snd_pcm_stop(), this function takes the substream lock by itself.
1352 : : *
1353 : : * Return: Zero if successful, or a negative error code.
1354 : : */
1355 : 0 : int snd_pcm_stop_xrun(struct snd_pcm_substream *substream)
1356 : : {
1357 : : unsigned long flags;
1358 : :
1359 : 0 : snd_pcm_stream_lock_irqsave(substream, flags);
1360 [ # # # # ]: 0 : if (substream->runtime && snd_pcm_running(substream))
1361 : 0 : __snd_pcm_xrun(substream);
1362 : 0 : snd_pcm_stream_unlock_irqrestore(substream, flags);
1363 : 0 : return 0;
1364 : : }
1365 : : EXPORT_SYMBOL_GPL(snd_pcm_stop_xrun);
1366 : :
1367 : : /*
1368 : : * pause callbacks
1369 : : */
1370 : 0 : static int snd_pcm_pre_pause(struct snd_pcm_substream *substream, int push)
1371 : : {
1372 : 0 : struct snd_pcm_runtime *runtime = substream->runtime;
1373 [ # # ]: 0 : if (!(runtime->info & SNDRV_PCM_INFO_PAUSE))
1374 : : return -ENOSYS;
1375 [ # # ]: 0 : if (push) {
1376 [ # # ]: 0 : if (runtime->status->state != SNDRV_PCM_STATE_RUNNING)
1377 : : return -EBADFD;
1378 [ # # ]: 0 : } else if (runtime->status->state != SNDRV_PCM_STATE_PAUSED)
1379 : : return -EBADFD;
1380 : 0 : runtime->trigger_master = substream;
1381 : 0 : return 0;
1382 : : }
1383 : :
1384 : 0 : static int snd_pcm_do_pause(struct snd_pcm_substream *substream, int push)
1385 : : {
1386 [ # # ]: 0 : if (substream->runtime->trigger_master != substream)
1387 : : return 0;
1388 : : /* some drivers might use hw_ptr to recover from the pause -
1389 : : update the hw_ptr now */
1390 [ # # ]: 0 : if (push)
1391 : 0 : snd_pcm_update_hw_ptr(substream);
1392 : : /* The jiffies check in snd_pcm_update_hw_ptr*() is done by
1393 : : * a delta between the current jiffies, this gives a large enough
1394 : : * delta, effectively to skip the check once.
1395 : : */
1396 : 0 : substream->runtime->hw_ptr_jiffies = jiffies - HZ * 1000;
1397 [ # # ]: 0 : return substream->ops->trigger(substream,
1398 : : push ? SNDRV_PCM_TRIGGER_PAUSE_PUSH :
1399 : : SNDRV_PCM_TRIGGER_PAUSE_RELEASE);
1400 : : }
1401 : :
1402 : 0 : static void snd_pcm_undo_pause(struct snd_pcm_substream *substream, int push)
1403 : : {
1404 [ # # ]: 0 : if (substream->runtime->trigger_master == substream)
1405 [ # # ]: 0 : substream->ops->trigger(substream,
1406 : : push ? SNDRV_PCM_TRIGGER_PAUSE_RELEASE :
1407 : : SNDRV_PCM_TRIGGER_PAUSE_PUSH);
1408 : 0 : }
1409 : :
1410 : 0 : static void snd_pcm_post_pause(struct snd_pcm_substream *substream, int push)
1411 : : {
1412 : 0 : struct snd_pcm_runtime *runtime = substream->runtime;
1413 : 0 : snd_pcm_trigger_tstamp(substream);
1414 [ # # ]: 0 : if (push) {
1415 : 0 : runtime->status->state = SNDRV_PCM_STATE_PAUSED;
1416 : : snd_pcm_timer_notify(substream, SNDRV_TIMER_EVENT_MPAUSE);
1417 : 0 : wake_up(&runtime->sleep);
1418 : 0 : wake_up(&runtime->tsleep);
1419 : : } else {
1420 : 0 : runtime->status->state = SNDRV_PCM_STATE_RUNNING;
1421 : : snd_pcm_timer_notify(substream, SNDRV_TIMER_EVENT_MCONTINUE);
1422 : : }
1423 : 0 : }
1424 : :
1425 : : static const struct action_ops snd_pcm_action_pause = {
1426 : : .pre_action = snd_pcm_pre_pause,
1427 : : .do_action = snd_pcm_do_pause,
1428 : : .undo_action = snd_pcm_undo_pause,
1429 : : .post_action = snd_pcm_post_pause
1430 : : };
1431 : :
1432 : : /*
1433 : : * Push/release the pause for all linked streams.
1434 : : */
1435 : : static int snd_pcm_pause(struct snd_pcm_substream *substream, int push)
1436 : : {
1437 : 0 : return snd_pcm_action(&snd_pcm_action_pause, substream, push);
1438 : : }
1439 : :
1440 : : #ifdef CONFIG_PM
1441 : : /* suspend */
1442 : :
1443 : 0 : static int snd_pcm_pre_suspend(struct snd_pcm_substream *substream, int state)
1444 : : {
1445 : 0 : struct snd_pcm_runtime *runtime = substream->runtime;
1446 [ # # ]: 0 : switch (runtime->status->state) {
1447 : : case SNDRV_PCM_STATE_SUSPENDED:
1448 : : return -EBUSY;
1449 : : /* unresumable PCM state; return -EBUSY for skipping suspend */
1450 : : case SNDRV_PCM_STATE_OPEN:
1451 : : case SNDRV_PCM_STATE_SETUP:
1452 : : case SNDRV_PCM_STATE_DISCONNECTED:
1453 : : return -EBUSY;
1454 : : }
1455 : 0 : runtime->trigger_master = substream;
1456 : 0 : return 0;
1457 : : }
1458 : :
1459 : 0 : static int snd_pcm_do_suspend(struct snd_pcm_substream *substream, int state)
1460 : : {
1461 : 0 : struct snd_pcm_runtime *runtime = substream->runtime;
1462 [ # # ]: 0 : if (runtime->trigger_master != substream)
1463 : : return 0;
1464 [ # # ]: 0 : if (! snd_pcm_running(substream))
1465 : : return 0;
1466 : 0 : substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_SUSPEND);
1467 : 0 : return 0; /* suspend unconditionally */
1468 : : }
1469 : :
1470 : 0 : static void snd_pcm_post_suspend(struct snd_pcm_substream *substream, int state)
1471 : : {
1472 : 0 : struct snd_pcm_runtime *runtime = substream->runtime;
1473 : 0 : snd_pcm_trigger_tstamp(substream);
1474 : 0 : runtime->status->suspended_state = runtime->status->state;
1475 : 0 : runtime->status->state = SNDRV_PCM_STATE_SUSPENDED;
1476 : : snd_pcm_timer_notify(substream, SNDRV_TIMER_EVENT_MSUSPEND);
1477 : 0 : wake_up(&runtime->sleep);
1478 : 0 : wake_up(&runtime->tsleep);
1479 : 0 : }
1480 : :
1481 : : static const struct action_ops snd_pcm_action_suspend = {
1482 : : .pre_action = snd_pcm_pre_suspend,
1483 : : .do_action = snd_pcm_do_suspend,
1484 : : .post_action = snd_pcm_post_suspend
1485 : : };
1486 : :
1487 : : /*
1488 : : * snd_pcm_suspend - trigger SUSPEND to all linked streams
1489 : : * @substream: the PCM substream
1490 : : *
1491 : : * After this call, all streams are changed to SUSPENDED state.
1492 : : *
1493 : : * Return: Zero if successful, or a negative error code.
1494 : : */
1495 : 0 : static int snd_pcm_suspend(struct snd_pcm_substream *substream)
1496 : : {
1497 : : int err;
1498 : : unsigned long flags;
1499 : :
1500 : 0 : snd_pcm_stream_lock_irqsave(substream, flags);
1501 : 0 : err = snd_pcm_action(&snd_pcm_action_suspend, substream, 0);
1502 : 0 : snd_pcm_stream_unlock_irqrestore(substream, flags);
1503 : 0 : return err;
1504 : : }
1505 : :
1506 : : /**
1507 : : * snd_pcm_suspend_all - trigger SUSPEND to all substreams in the given pcm
1508 : : * @pcm: the PCM instance
1509 : : *
1510 : : * After this call, all streams are changed to SUSPENDED state.
1511 : : *
1512 : : * Return: Zero if successful (or @pcm is %NULL), or a negative error code.
1513 : : */
1514 : 0 : int snd_pcm_suspend_all(struct snd_pcm *pcm)
1515 : : {
1516 : : struct snd_pcm_substream *substream;
1517 : : int stream, err = 0;
1518 : :
1519 [ # # ]: 0 : if (! pcm)
1520 : : return 0;
1521 : :
1522 [ # # ]: 0 : for (stream = 0; stream < 2; stream++) {
1523 [ # # ]: 0 : for (substream = pcm->streams[stream].substream;
1524 : 0 : substream; substream = substream->next) {
1525 : : /* FIXME: the open/close code should lock this as well */
1526 [ # # ]: 0 : if (substream->runtime == NULL)
1527 : 0 : continue;
1528 : :
1529 : : /*
1530 : : * Skip BE dai link PCM's that are internal and may
1531 : : * not have their substream ops set.
1532 : : */
1533 [ # # ]: 0 : if (!substream->ops)
1534 : 0 : continue;
1535 : :
1536 : 0 : err = snd_pcm_suspend(substream);
1537 [ # # ]: 0 : if (err < 0 && err != -EBUSY)
1538 : 0 : return err;
1539 : : }
1540 : : }
1541 : : return 0;
1542 : : }
1543 : : EXPORT_SYMBOL(snd_pcm_suspend_all);
1544 : :
1545 : : /* resume */
1546 : :
1547 : 0 : static int snd_pcm_pre_resume(struct snd_pcm_substream *substream, int state)
1548 : : {
1549 : 0 : struct snd_pcm_runtime *runtime = substream->runtime;
1550 [ # # ]: 0 : if (!(runtime->info & SNDRV_PCM_INFO_RESUME))
1551 : : return -ENOSYS;
1552 : 0 : runtime->trigger_master = substream;
1553 : 0 : return 0;
1554 : : }
1555 : :
1556 : 0 : static int snd_pcm_do_resume(struct snd_pcm_substream *substream, int state)
1557 : : {
1558 : 0 : struct snd_pcm_runtime *runtime = substream->runtime;
1559 [ # # ]: 0 : if (runtime->trigger_master != substream)
1560 : : return 0;
1561 : : /* DMA not running previously? */
1562 [ # # # # ]: 0 : if (runtime->status->suspended_state != SNDRV_PCM_STATE_RUNNING &&
1563 [ # # ]: 0 : (runtime->status->suspended_state != SNDRV_PCM_STATE_DRAINING ||
1564 : 0 : substream->stream != SNDRV_PCM_STREAM_PLAYBACK))
1565 : : return 0;
1566 : 0 : return substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_RESUME);
1567 : : }
1568 : :
1569 : 0 : static void snd_pcm_undo_resume(struct snd_pcm_substream *substream, int state)
1570 : : {
1571 [ # # # # ]: 0 : if (substream->runtime->trigger_master == substream &&
1572 : : snd_pcm_running(substream))
1573 : 0 : substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_SUSPEND);
1574 : 0 : }
1575 : :
1576 : 0 : static void snd_pcm_post_resume(struct snd_pcm_substream *substream, int state)
1577 : : {
1578 : 0 : struct snd_pcm_runtime *runtime = substream->runtime;
1579 : 0 : snd_pcm_trigger_tstamp(substream);
1580 : 0 : runtime->status->state = runtime->status->suspended_state;
1581 : : snd_pcm_timer_notify(substream, SNDRV_TIMER_EVENT_MRESUME);
1582 : 0 : }
1583 : :
1584 : : static const struct action_ops snd_pcm_action_resume = {
1585 : : .pre_action = snd_pcm_pre_resume,
1586 : : .do_action = snd_pcm_do_resume,
1587 : : .undo_action = snd_pcm_undo_resume,
1588 : : .post_action = snd_pcm_post_resume
1589 : : };
1590 : :
1591 : : static int snd_pcm_resume(struct snd_pcm_substream *substream)
1592 : : {
1593 : 0 : return snd_pcm_action_lock_irq(&snd_pcm_action_resume, substream, 0);
1594 : : }
1595 : :
1596 : : #else
1597 : :
1598 : : static int snd_pcm_resume(struct snd_pcm_substream *substream)
1599 : : {
1600 : : return -ENOSYS;
1601 : : }
1602 : :
1603 : : #endif /* CONFIG_PM */
1604 : :
1605 : : /*
1606 : : * xrun ioctl
1607 : : *
1608 : : * Change the RUNNING stream(s) to XRUN state.
1609 : : */
1610 : 0 : static int snd_pcm_xrun(struct snd_pcm_substream *substream)
1611 : : {
1612 : 0 : struct snd_pcm_runtime *runtime = substream->runtime;
1613 : : int result;
1614 : :
1615 : 0 : snd_pcm_stream_lock_irq(substream);
1616 [ # # # ]: 0 : switch (runtime->status->state) {
1617 : : case SNDRV_PCM_STATE_XRUN:
1618 : : result = 0; /* already there */
1619 : : break;
1620 : : case SNDRV_PCM_STATE_RUNNING:
1621 : 0 : __snd_pcm_xrun(substream);
1622 : : result = 0;
1623 : 0 : break;
1624 : : default:
1625 : : result = -EBADFD;
1626 : : }
1627 : 0 : snd_pcm_stream_unlock_irq(substream);
1628 : 0 : return result;
1629 : : }
1630 : :
1631 : : /*
1632 : : * reset ioctl
1633 : : */
1634 : 0 : static int snd_pcm_pre_reset(struct snd_pcm_substream *substream, int state)
1635 : : {
1636 : 0 : struct snd_pcm_runtime *runtime = substream->runtime;
1637 [ # # ]: 0 : switch (runtime->status->state) {
1638 : : case SNDRV_PCM_STATE_RUNNING:
1639 : : case SNDRV_PCM_STATE_PREPARED:
1640 : : case SNDRV_PCM_STATE_PAUSED:
1641 : : case SNDRV_PCM_STATE_SUSPENDED:
1642 : : return 0;
1643 : : default:
1644 : 0 : return -EBADFD;
1645 : : }
1646 : : }
1647 : :
1648 : 0 : static int snd_pcm_do_reset(struct snd_pcm_substream *substream, int state)
1649 : : {
1650 : 0 : struct snd_pcm_runtime *runtime = substream->runtime;
1651 : 0 : int err = substream->ops->ioctl(substream, SNDRV_PCM_IOCTL1_RESET, NULL);
1652 [ # # ]: 0 : if (err < 0)
1653 : : return err;
1654 : 0 : runtime->hw_ptr_base = 0;
1655 : 0 : runtime->hw_ptr_interrupt = runtime->status->hw_ptr -
1656 : 0 : runtime->status->hw_ptr % runtime->period_size;
1657 : 0 : runtime->silence_start = runtime->status->hw_ptr;
1658 : 0 : runtime->silence_filled = 0;
1659 : 0 : return 0;
1660 : : }
1661 : :
1662 : 0 : static void snd_pcm_post_reset(struct snd_pcm_substream *substream, int state)
1663 : : {
1664 : 0 : struct snd_pcm_runtime *runtime = substream->runtime;
1665 : 0 : runtime->control->appl_ptr = runtime->status->hw_ptr;
1666 [ # # # # ]: 0 : if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
1667 : 0 : runtime->silence_size > 0)
1668 : 0 : snd_pcm_playback_silence(substream, ULONG_MAX);
1669 : 0 : }
1670 : :
1671 : : static const struct action_ops snd_pcm_action_reset = {
1672 : : .pre_action = snd_pcm_pre_reset,
1673 : : .do_action = snd_pcm_do_reset,
1674 : : .post_action = snd_pcm_post_reset
1675 : : };
1676 : :
1677 : : static int snd_pcm_reset(struct snd_pcm_substream *substream)
1678 : : {
1679 : 0 : return snd_pcm_action_nonatomic(&snd_pcm_action_reset, substream, 0);
1680 : : }
1681 : :
1682 : : /*
1683 : : * prepare ioctl
1684 : : */
1685 : : /* we use the second argument for updating f_flags */
1686 : 0 : static int snd_pcm_pre_prepare(struct snd_pcm_substream *substream,
1687 : : int f_flags)
1688 : : {
1689 : 0 : struct snd_pcm_runtime *runtime = substream->runtime;
1690 [ # # ]: 0 : if (runtime->status->state == SNDRV_PCM_STATE_OPEN ||
1691 : : runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED)
1692 : : return -EBADFD;
1693 [ # # ]: 0 : if (snd_pcm_running(substream))
1694 : : return -EBUSY;
1695 : 0 : substream->f_flags = f_flags;
1696 : 0 : return 0;
1697 : : }
1698 : :
1699 : 0 : static int snd_pcm_do_prepare(struct snd_pcm_substream *substream, int state)
1700 : : {
1701 : : int err;
1702 : 0 : err = substream->ops->prepare(substream);
1703 [ # # ]: 0 : if (err < 0)
1704 : : return err;
1705 : 0 : return snd_pcm_do_reset(substream, 0);
1706 : : }
1707 : :
1708 : 0 : static void snd_pcm_post_prepare(struct snd_pcm_substream *substream, int state)
1709 : : {
1710 : 0 : struct snd_pcm_runtime *runtime = substream->runtime;
1711 : 0 : runtime->control->appl_ptr = runtime->status->hw_ptr;
1712 : 0 : snd_pcm_set_state(substream, SNDRV_PCM_STATE_PREPARED);
1713 : 0 : }
1714 : :
1715 : : static const struct action_ops snd_pcm_action_prepare = {
1716 : : .pre_action = snd_pcm_pre_prepare,
1717 : : .do_action = snd_pcm_do_prepare,
1718 : : .post_action = snd_pcm_post_prepare
1719 : : };
1720 : :
1721 : : /**
1722 : : * snd_pcm_prepare - prepare the PCM substream to be triggerable
1723 : : * @substream: the PCM substream instance
1724 : : * @file: file to refer f_flags
1725 : : *
1726 : : * Return: Zero if successful, or a negative error code.
1727 : : */
1728 : 0 : static int snd_pcm_prepare(struct snd_pcm_substream *substream,
1729 : : struct file *file)
1730 : : {
1731 : : int f_flags;
1732 : :
1733 [ # # ]: 0 : if (file)
1734 : 0 : f_flags = file->f_flags;
1735 : : else
1736 : 0 : f_flags = substream->f_flags;
1737 : :
1738 : 0 : snd_pcm_stream_lock_irq(substream);
1739 [ # # # ]: 0 : switch (substream->runtime->status->state) {
1740 : : case SNDRV_PCM_STATE_PAUSED:
1741 : : snd_pcm_pause(substream, 0);
1742 : : /* fallthru */
1743 : : case SNDRV_PCM_STATE_SUSPENDED:
1744 : : snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP);
1745 : : break;
1746 : : }
1747 : 0 : snd_pcm_stream_unlock_irq(substream);
1748 : :
1749 : 0 : return snd_pcm_action_nonatomic(&snd_pcm_action_prepare,
1750 : : substream, f_flags);
1751 : : }
1752 : :
1753 : : /*
1754 : : * drain ioctl
1755 : : */
1756 : :
1757 : 0 : static int snd_pcm_pre_drain_init(struct snd_pcm_substream *substream, int state)
1758 : : {
1759 : 0 : struct snd_pcm_runtime *runtime = substream->runtime;
1760 [ # # ]: 0 : switch (runtime->status->state) {
1761 : : case SNDRV_PCM_STATE_OPEN:
1762 : : case SNDRV_PCM_STATE_DISCONNECTED:
1763 : : case SNDRV_PCM_STATE_SUSPENDED:
1764 : : return -EBADFD;
1765 : : }
1766 : 0 : runtime->trigger_master = substream;
1767 : 0 : return 0;
1768 : : }
1769 : :
1770 : 0 : static int snd_pcm_do_drain_init(struct snd_pcm_substream *substream, int state)
1771 : : {
1772 : 0 : struct snd_pcm_runtime *runtime = substream->runtime;
1773 [ # # ]: 0 : if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
1774 [ # # # # ]: 0 : switch (runtime->status->state) {
1775 : : case SNDRV_PCM_STATE_PREPARED:
1776 : : /* start playback stream if possible */
1777 [ # # ]: 0 : if (! snd_pcm_playback_empty(substream)) {
1778 : : snd_pcm_do_start(substream, SNDRV_PCM_STATE_DRAINING);
1779 : 0 : snd_pcm_post_start(substream, SNDRV_PCM_STATE_DRAINING);
1780 : : } else {
1781 : 0 : runtime->status->state = SNDRV_PCM_STATE_SETUP;
1782 : : }
1783 : : break;
1784 : : case SNDRV_PCM_STATE_RUNNING:
1785 : 0 : runtime->status->state = SNDRV_PCM_STATE_DRAINING;
1786 : 0 : break;
1787 : : case SNDRV_PCM_STATE_XRUN:
1788 : 0 : runtime->status->state = SNDRV_PCM_STATE_SETUP;
1789 : 0 : break;
1790 : : default:
1791 : : break;
1792 : : }
1793 : : } else {
1794 : : /* stop running stream */
1795 [ # # ]: 0 : if (runtime->status->state == SNDRV_PCM_STATE_RUNNING) {
1796 : : int new_state = snd_pcm_capture_avail(runtime) > 0 ?
1797 [ # # ]: 0 : SNDRV_PCM_STATE_DRAINING : SNDRV_PCM_STATE_SETUP;
1798 : 0 : snd_pcm_do_stop(substream, new_state);
1799 : 0 : snd_pcm_post_stop(substream, new_state);
1800 : : }
1801 : : }
1802 : :
1803 [ # # # # ]: 0 : if (runtime->status->state == SNDRV_PCM_STATE_DRAINING &&
1804 [ # # ]: 0 : runtime->trigger_master == substream &&
1805 : 0 : (runtime->hw.info & SNDRV_PCM_INFO_DRAIN_TRIGGER))
1806 : 0 : return substream->ops->trigger(substream,
1807 : : SNDRV_PCM_TRIGGER_DRAIN);
1808 : :
1809 : : return 0;
1810 : : }
1811 : :
1812 : 0 : static void snd_pcm_post_drain_init(struct snd_pcm_substream *substream, int state)
1813 : : {
1814 : 0 : }
1815 : :
1816 : : static const struct action_ops snd_pcm_action_drain_init = {
1817 : : .pre_action = snd_pcm_pre_drain_init,
1818 : : .do_action = snd_pcm_do_drain_init,
1819 : : .post_action = snd_pcm_post_drain_init
1820 : : };
1821 : :
1822 : : /*
1823 : : * Drain the stream(s).
1824 : : * When the substream is linked, sync until the draining of all playback streams
1825 : : * is finished.
1826 : : * After this call, all streams are supposed to be either SETUP or DRAINING
1827 : : * (capture only) state.
1828 : : */
1829 : 0 : static int snd_pcm_drain(struct snd_pcm_substream *substream,
1830 : : struct file *file)
1831 : : {
1832 : : struct snd_card *card;
1833 : : struct snd_pcm_runtime *runtime;
1834 : : struct snd_pcm_substream *s;
1835 : : struct snd_pcm_group *group;
1836 : : wait_queue_entry_t wait;
1837 : : int result = 0;
1838 : : int nonblock = 0;
1839 : :
1840 : 0 : card = substream->pcm->card;
1841 : 0 : runtime = substream->runtime;
1842 : :
1843 [ # # ]: 0 : if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
1844 : : return -EBADFD;
1845 : :
1846 [ # # ]: 0 : if (file) {
1847 [ # # ]: 0 : if (file->f_flags & O_NONBLOCK)
1848 : : nonblock = 1;
1849 [ # # ]: 0 : } else if (substream->f_flags & O_NONBLOCK)
1850 : : nonblock = 1;
1851 : :
1852 : 0 : snd_pcm_stream_lock_irq(substream);
1853 : : /* resume pause */
1854 [ # # ]: 0 : if (runtime->status->state == SNDRV_PCM_STATE_PAUSED)
1855 : : snd_pcm_pause(substream, 0);
1856 : :
1857 : : /* pre-start/stop - all running streams are changed to DRAINING state */
1858 : 0 : result = snd_pcm_action(&snd_pcm_action_drain_init, substream, 0);
1859 [ # # ]: 0 : if (result < 0)
1860 : : goto unlock;
1861 : : /* in non-blocking, we don't wait in ioctl but let caller poll */
1862 [ # # ]: 0 : if (nonblock) {
1863 : : result = -EAGAIN;
1864 : : goto unlock;
1865 : : }
1866 : :
1867 : : for (;;) {
1868 : : long tout;
1869 : : struct snd_pcm_runtime *to_check;
1870 [ # # ]: 0 : if (signal_pending(current)) {
1871 : : result = -ERESTARTSYS;
1872 : : break;
1873 : : }
1874 : : /* find a substream to drain */
1875 : : to_check = NULL;
1876 : 0 : group = snd_pcm_stream_group_ref(substream);
1877 [ # # ]: 0 : snd_pcm_group_for_each_entry(s, substream) {
1878 [ # # ]: 0 : if (s->stream != SNDRV_PCM_STREAM_PLAYBACK)
1879 : 0 : continue;
1880 : 0 : runtime = s->runtime;
1881 [ # # ]: 0 : if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) {
1882 : 0 : to_check = runtime;
1883 : 0 : break;
1884 : : }
1885 : : }
1886 : 0 : snd_pcm_group_unref(group, substream);
1887 [ # # ]: 0 : if (!to_check)
1888 : : break; /* all drained */
1889 : 0 : init_waitqueue_entry(&wait, current);
1890 : 0 : set_current_state(TASK_INTERRUPTIBLE);
1891 : 0 : add_wait_queue(&to_check->sleep, &wait);
1892 : 0 : snd_pcm_stream_unlock_irq(substream);
1893 [ # # ]: 0 : if (runtime->no_period_wakeup)
1894 : : tout = MAX_SCHEDULE_TIMEOUT;
1895 : : else {
1896 : : tout = 10;
1897 [ # # ]: 0 : if (runtime->rate) {
1898 : 0 : long t = runtime->period_size * 2 / runtime->rate;
1899 : 0 : tout = max(t, tout);
1900 : : }
1901 : 0 : tout = msecs_to_jiffies(tout * 1000);
1902 : : }
1903 : 0 : tout = schedule_timeout(tout);
1904 : :
1905 : 0 : snd_pcm_stream_lock_irq(substream);
1906 : 0 : group = snd_pcm_stream_group_ref(substream);
1907 [ # # ]: 0 : snd_pcm_group_for_each_entry(s, substream) {
1908 [ # # ]: 0 : if (s->runtime == to_check) {
1909 : 0 : remove_wait_queue(&to_check->sleep, &wait);
1910 : 0 : break;
1911 : : }
1912 : : }
1913 : 0 : snd_pcm_group_unref(group, substream);
1914 : :
1915 [ # # ]: 0 : if (card->shutdown) {
1916 : : result = -ENODEV;
1917 : : break;
1918 : : }
1919 [ # # ]: 0 : if (tout == 0) {
1920 [ # # ]: 0 : if (substream->runtime->status->state == SNDRV_PCM_STATE_SUSPENDED)
1921 : : result = -ESTRPIPE;
1922 : : else {
1923 : : dev_dbg(substream->pcm->card->dev,
1924 : : "playback drain error (DMA or IRQ trouble?)\n");
1925 : : snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP);
1926 : : result = -EIO;
1927 : : }
1928 : : break;
1929 : : }
1930 : : }
1931 : :
1932 : : unlock:
1933 : 0 : snd_pcm_stream_unlock_irq(substream);
1934 : :
1935 : 0 : return result;
1936 : : }
1937 : :
1938 : : /*
1939 : : * drop ioctl
1940 : : *
1941 : : * Immediately put all linked substreams into SETUP state.
1942 : : */
1943 : 0 : static int snd_pcm_drop(struct snd_pcm_substream *substream)
1944 : : {
1945 : : struct snd_pcm_runtime *runtime;
1946 : : int result = 0;
1947 : :
1948 [ # # # # : 0 : if (PCM_RUNTIME_CHECK(substream))
# # ]
1949 : : return -ENXIO;
1950 : 0 : runtime = substream->runtime;
1951 : :
1952 [ # # ]: 0 : if (runtime->status->state == SNDRV_PCM_STATE_OPEN ||
1953 : : runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED)
1954 : : return -EBADFD;
1955 : :
1956 : 0 : snd_pcm_stream_lock_irq(substream);
1957 : : /* resume pause */
1958 [ # # ]: 0 : if (runtime->status->state == SNDRV_PCM_STATE_PAUSED)
1959 : : snd_pcm_pause(substream, 0);
1960 : :
1961 : : snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP);
1962 : : /* runtime->control->appl_ptr = runtime->status->hw_ptr; */
1963 : 0 : snd_pcm_stream_unlock_irq(substream);
1964 : :
1965 : 0 : return result;
1966 : : }
1967 : :
1968 : :
1969 : 0 : static bool is_pcm_file(struct file *file)
1970 : : {
1971 : : struct inode *inode = file_inode(file);
1972 : : struct snd_pcm *pcm;
1973 : : unsigned int minor;
1974 : :
1975 [ # # # # ]: 0 : if (!S_ISCHR(inode->i_mode) || imajor(inode) != snd_major)
1976 : : return false;
1977 : : minor = iminor(inode);
1978 : 0 : pcm = snd_lookup_minor_data(minor, SNDRV_DEVICE_TYPE_PCM_PLAYBACK);
1979 [ # # ]: 0 : if (!pcm)
1980 : 0 : pcm = snd_lookup_minor_data(minor, SNDRV_DEVICE_TYPE_PCM_CAPTURE);
1981 [ # # ]: 0 : if (!pcm)
1982 : : return false;
1983 : 0 : snd_card_unref(pcm->card);
1984 : 0 : return true;
1985 : : }
1986 : :
1987 : : /*
1988 : : * PCM link handling
1989 : : */
1990 : 0 : static int snd_pcm_link(struct snd_pcm_substream *substream, int fd)
1991 : : {
1992 : : int res = 0;
1993 : : struct snd_pcm_file *pcm_file;
1994 : : struct snd_pcm_substream *substream1;
1995 : : struct snd_pcm_group *group, *target_group;
1996 : 0 : bool nonatomic = substream->pcm->nonatomic;
1997 : 0 : struct fd f = fdget(fd);
1998 : :
1999 [ # # ]: 0 : if (!f.file)
2000 : : return -EBADFD;
2001 [ # # ]: 0 : if (!is_pcm_file(f.file)) {
2002 : : res = -EBADFD;
2003 : : goto _badf;
2004 : : }
2005 : 0 : pcm_file = f.file->private_data;
2006 : 0 : substream1 = pcm_file->substream;
2007 : :
2008 [ # # ]: 0 : if (substream == substream1) {
2009 : : res = -EINVAL;
2010 : : goto _badf;
2011 : : }
2012 : :
2013 : 0 : group = kzalloc(sizeof(*group), GFP_KERNEL);
2014 [ # # ]: 0 : if (!group) {
2015 : : res = -ENOMEM;
2016 : : goto _nolock;
2017 : : }
2018 : : snd_pcm_group_init(group);
2019 : :
2020 : 0 : down_write(&snd_pcm_link_rwsem);
2021 [ # # # # ]: 0 : if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN ||
2022 [ # # ]: 0 : substream->runtime->status->state != substream1->runtime->status->state ||
2023 : 0 : substream->pcm->nonatomic != substream1->pcm->nonatomic) {
2024 : : res = -EBADFD;
2025 : : goto _end;
2026 : : }
2027 [ # # ]: 0 : if (snd_pcm_stream_linked(substream1)) {
2028 : : res = -EALREADY;
2029 : : goto _end;
2030 : : }
2031 : :
2032 : 0 : snd_pcm_stream_lock_irq(substream);
2033 [ # # ]: 0 : if (!snd_pcm_stream_linked(substream)) {
2034 : : snd_pcm_group_assign(substream, group);
2035 : : group = NULL; /* assigned, don't free this one below */
2036 : : }
2037 : 0 : target_group = substream->group;
2038 : 0 : snd_pcm_stream_unlock_irq(substream);
2039 : :
2040 : : snd_pcm_group_lock_irq(target_group, nonatomic);
2041 : 0 : snd_pcm_stream_lock_nested(substream1);
2042 : : snd_pcm_group_assign(substream1, target_group);
2043 : 0 : refcount_inc(&target_group->refs);
2044 : 0 : snd_pcm_stream_unlock(substream1);
2045 : : snd_pcm_group_unlock_irq(target_group, nonatomic);
2046 : : _end:
2047 : 0 : up_write(&snd_pcm_link_rwsem);
2048 : : _nolock:
2049 : 0 : kfree(group);
2050 : : _badf:
2051 : : fdput(f);
2052 : 0 : return res;
2053 : : }
2054 : :
2055 : 0 : static void relink_to_local(struct snd_pcm_substream *substream)
2056 : : {
2057 : 0 : snd_pcm_stream_lock_nested(substream);
2058 : 0 : snd_pcm_group_assign(substream, &substream->self_group);
2059 : 0 : snd_pcm_stream_unlock(substream);
2060 : 0 : }
2061 : :
2062 : 0 : static int snd_pcm_unlink(struct snd_pcm_substream *substream)
2063 : : {
2064 : : struct snd_pcm_group *group;
2065 : 0 : bool nonatomic = substream->pcm->nonatomic;
2066 : : bool do_free = false;
2067 : : int res = 0;
2068 : :
2069 : 0 : down_write(&snd_pcm_link_rwsem);
2070 : :
2071 [ # # ]: 0 : if (!snd_pcm_stream_linked(substream)) {
2072 : : res = -EALREADY;
2073 : : goto _end;
2074 : : }
2075 : :
2076 : : group = substream->group;
2077 : : snd_pcm_group_lock_irq(group, nonatomic);
2078 : :
2079 : 0 : relink_to_local(substream);
2080 : 0 : refcount_dec(&group->refs);
2081 : :
2082 : : /* detach the last stream, too */
2083 [ # # ]: 0 : if (list_is_singular(&group->substreams)) {
2084 : 0 : relink_to_local(list_first_entry(&group->substreams,
2085 : : struct snd_pcm_substream,
2086 : : link_list));
2087 : 0 : do_free = refcount_dec_and_test(&group->refs);
2088 : : }
2089 : :
2090 : : snd_pcm_group_unlock_irq(group, nonatomic);
2091 [ # # ]: 0 : if (do_free)
2092 : 0 : kfree(group);
2093 : :
2094 : : _end:
2095 : 0 : up_write(&snd_pcm_link_rwsem);
2096 : 0 : return res;
2097 : : }
2098 : :
2099 : : /*
2100 : : * hw configurator
2101 : : */
2102 : 0 : static int snd_pcm_hw_rule_mul(struct snd_pcm_hw_params *params,
2103 : : struct snd_pcm_hw_rule *rule)
2104 : : {
2105 : : struct snd_interval t;
2106 : 0 : snd_interval_mul(hw_param_interval_c(params, rule->deps[0]),
2107 : : hw_param_interval_c(params, rule->deps[1]), &t);
2108 : 0 : return snd_interval_refine(hw_param_interval(params, rule->var), &t);
2109 : : }
2110 : :
2111 : 0 : static int snd_pcm_hw_rule_div(struct snd_pcm_hw_params *params,
2112 : : struct snd_pcm_hw_rule *rule)
2113 : : {
2114 : : struct snd_interval t;
2115 : 0 : snd_interval_div(hw_param_interval_c(params, rule->deps[0]),
2116 : : hw_param_interval_c(params, rule->deps[1]), &t);
2117 : 0 : return snd_interval_refine(hw_param_interval(params, rule->var), &t);
2118 : : }
2119 : :
2120 : 0 : static int snd_pcm_hw_rule_muldivk(struct snd_pcm_hw_params *params,
2121 : : struct snd_pcm_hw_rule *rule)
2122 : : {
2123 : : struct snd_interval t;
2124 : 0 : snd_interval_muldivk(hw_param_interval_c(params, rule->deps[0]),
2125 : : hw_param_interval_c(params, rule->deps[1]),
2126 : 0 : (unsigned long) rule->private, &t);
2127 : 0 : return snd_interval_refine(hw_param_interval(params, rule->var), &t);
2128 : : }
2129 : :
2130 : 0 : static int snd_pcm_hw_rule_mulkdiv(struct snd_pcm_hw_params *params,
2131 : : struct snd_pcm_hw_rule *rule)
2132 : : {
2133 : : struct snd_interval t;
2134 : 0 : snd_interval_mulkdiv(hw_param_interval_c(params, rule->deps[0]),
2135 : 0 : (unsigned long) rule->private,
2136 : : hw_param_interval_c(params, rule->deps[1]), &t);
2137 : 0 : return snd_interval_refine(hw_param_interval(params, rule->var), &t);
2138 : : }
2139 : :
2140 : 0 : static int snd_pcm_hw_rule_format(struct snd_pcm_hw_params *params,
2141 : : struct snd_pcm_hw_rule *rule)
2142 : : {
2143 : : unsigned int k;
2144 : : const struct snd_interval *i =
2145 : 0 : hw_param_interval_c(params, rule->deps[0]);
2146 : : struct snd_mask m;
2147 : : struct snd_mask *mask = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
2148 : : snd_mask_any(&m);
2149 [ # # ]: 0 : for (k = 0; k <= SNDRV_PCM_FORMAT_LAST; ++k) {
2150 : : int bits;
2151 [ # # ]: 0 : if (! snd_mask_test(mask, k))
2152 : 0 : continue;
2153 : 0 : bits = snd_pcm_format_physical_width(k);
2154 [ # # ]: 0 : if (bits <= 0)
2155 : 0 : continue; /* ignore invalid formats */
2156 [ # # # # ]: 0 : if ((unsigned)bits < i->min || (unsigned)bits > i->max)
2157 : : snd_mask_reset(&m, k);
2158 : : }
2159 : 0 : return snd_mask_refine(mask, &m);
2160 : : }
2161 : :
2162 : 0 : static int snd_pcm_hw_rule_sample_bits(struct snd_pcm_hw_params *params,
2163 : : struct snd_pcm_hw_rule *rule)
2164 : : {
2165 : : struct snd_interval t;
2166 : : unsigned int k;
2167 : 0 : t.min = UINT_MAX;
2168 : 0 : t.max = 0;
2169 : 0 : t.openmin = 0;
2170 : 0 : t.openmax = 0;
2171 [ # # ]: 0 : for (k = 0; k <= SNDRV_PCM_FORMAT_LAST; ++k) {
2172 : : int bits;
2173 [ # # ]: 0 : if (! snd_mask_test(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT), k))
2174 : 0 : continue;
2175 : 0 : bits = snd_pcm_format_physical_width(k);
2176 [ # # ]: 0 : if (bits <= 0)
2177 : 0 : continue; /* ignore invalid formats */
2178 [ # # ]: 0 : if (t.min > (unsigned)bits)
2179 : 0 : t.min = bits;
2180 [ # # ]: 0 : if (t.max < (unsigned)bits)
2181 : 0 : t.max = bits;
2182 : : }
2183 : 0 : t.integer = 1;
2184 : 0 : return snd_interval_refine(hw_param_interval(params, rule->var), &t);
2185 : : }
2186 : :
2187 : : #if SNDRV_PCM_RATE_5512 != 1 << 0 || SNDRV_PCM_RATE_192000 != 1 << 12
2188 : : #error "Change this table"
2189 : : #endif
2190 : :
2191 : : static const unsigned int rates[] = {
2192 : : 5512, 8000, 11025, 16000, 22050, 32000, 44100,
2193 : : 48000, 64000, 88200, 96000, 176400, 192000, 352800, 384000
2194 : : };
2195 : :
2196 : : const struct snd_pcm_hw_constraint_list snd_pcm_known_rates = {
2197 : : .count = ARRAY_SIZE(rates),
2198 : : .list = rates,
2199 : : };
2200 : :
2201 : 0 : static int snd_pcm_hw_rule_rate(struct snd_pcm_hw_params *params,
2202 : : struct snd_pcm_hw_rule *rule)
2203 : : {
2204 : 0 : struct snd_pcm_hardware *hw = rule->private;
2205 : 0 : return snd_interval_list(hw_param_interval(params, rule->var),
2206 : : snd_pcm_known_rates.count,
2207 : : snd_pcm_known_rates.list, hw->rates);
2208 : : }
2209 : :
2210 : 0 : static int snd_pcm_hw_rule_buffer_bytes_max(struct snd_pcm_hw_params *params,
2211 : : struct snd_pcm_hw_rule *rule)
2212 : : {
2213 : : struct snd_interval t;
2214 : 0 : struct snd_pcm_substream *substream = rule->private;
2215 : 0 : t.min = 0;
2216 : 0 : t.max = substream->buffer_bytes_max;
2217 : 0 : t.openmin = 0;
2218 : 0 : t.openmax = 0;
2219 : 0 : t.integer = 1;
2220 : 0 : return snd_interval_refine(hw_param_interval(params, rule->var), &t);
2221 : : }
2222 : :
2223 : 0 : int snd_pcm_hw_constraints_init(struct snd_pcm_substream *substream)
2224 : : {
2225 : 0 : struct snd_pcm_runtime *runtime = substream->runtime;
2226 : : struct snd_pcm_hw_constraints *constrs = &runtime->hw_constraints;
2227 : : int k, err;
2228 : :
2229 [ # # ]: 0 : for (k = SNDRV_PCM_HW_PARAM_FIRST_MASK; k <= SNDRV_PCM_HW_PARAM_LAST_MASK; k++) {
2230 : : snd_mask_any(constrs_mask(constrs, k));
2231 : : }
2232 : :
2233 [ # # ]: 0 : for (k = SNDRV_PCM_HW_PARAM_FIRST_INTERVAL; k <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; k++) {
2234 : : snd_interval_any(constrs_interval(constrs, k));
2235 : : }
2236 : :
2237 : : snd_interval_setinteger(constrs_interval(constrs, SNDRV_PCM_HW_PARAM_CHANNELS));
2238 : : snd_interval_setinteger(constrs_interval(constrs, SNDRV_PCM_HW_PARAM_BUFFER_SIZE));
2239 : : snd_interval_setinteger(constrs_interval(constrs, SNDRV_PCM_HW_PARAM_BUFFER_BYTES));
2240 : : snd_interval_setinteger(constrs_interval(constrs, SNDRV_PCM_HW_PARAM_SAMPLE_BITS));
2241 : : snd_interval_setinteger(constrs_interval(constrs, SNDRV_PCM_HW_PARAM_FRAME_BITS));
2242 : :
2243 : 0 : err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_FORMAT,
2244 : : snd_pcm_hw_rule_format, NULL,
2245 : : SNDRV_PCM_HW_PARAM_SAMPLE_BITS, -1);
2246 [ # # ]: 0 : if (err < 0)
2247 : : return err;
2248 : 0 : err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
2249 : : snd_pcm_hw_rule_sample_bits, NULL,
2250 : : SNDRV_PCM_HW_PARAM_FORMAT,
2251 : : SNDRV_PCM_HW_PARAM_SAMPLE_BITS, -1);
2252 [ # # ]: 0 : if (err < 0)
2253 : : return err;
2254 : 0 : err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
2255 : : snd_pcm_hw_rule_div, NULL,
2256 : : SNDRV_PCM_HW_PARAM_FRAME_BITS, SNDRV_PCM_HW_PARAM_CHANNELS, -1);
2257 [ # # ]: 0 : if (err < 0)
2258 : : return err;
2259 : 0 : err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_FRAME_BITS,
2260 : : snd_pcm_hw_rule_mul, NULL,
2261 : : SNDRV_PCM_HW_PARAM_SAMPLE_BITS, SNDRV_PCM_HW_PARAM_CHANNELS, -1);
2262 [ # # ]: 0 : if (err < 0)
2263 : : return err;
2264 : 0 : err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_FRAME_BITS,
2265 : : snd_pcm_hw_rule_mulkdiv, (void*) 8,
2266 : : SNDRV_PCM_HW_PARAM_PERIOD_BYTES, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, -1);
2267 [ # # ]: 0 : if (err < 0)
2268 : : return err;
2269 : 0 : err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_FRAME_BITS,
2270 : : snd_pcm_hw_rule_mulkdiv, (void*) 8,
2271 : : SNDRV_PCM_HW_PARAM_BUFFER_BYTES, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, -1);
2272 [ # # ]: 0 : if (err < 0)
2273 : : return err;
2274 : 0 : err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
2275 : : snd_pcm_hw_rule_div, NULL,
2276 : : SNDRV_PCM_HW_PARAM_FRAME_BITS, SNDRV_PCM_HW_PARAM_SAMPLE_BITS, -1);
2277 [ # # ]: 0 : if (err < 0)
2278 : : return err;
2279 : 0 : err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
2280 : : snd_pcm_hw_rule_mulkdiv, (void*) 1000000,
2281 : : SNDRV_PCM_HW_PARAM_PERIOD_SIZE, SNDRV_PCM_HW_PARAM_PERIOD_TIME, -1);
2282 [ # # ]: 0 : if (err < 0)
2283 : : return err;
2284 : 0 : err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
2285 : : snd_pcm_hw_rule_mulkdiv, (void*) 1000000,
2286 : : SNDRV_PCM_HW_PARAM_BUFFER_SIZE, SNDRV_PCM_HW_PARAM_BUFFER_TIME, -1);
2287 [ # # ]: 0 : if (err < 0)
2288 : : return err;
2289 : 0 : err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_PERIODS,
2290 : : snd_pcm_hw_rule_div, NULL,
2291 : : SNDRV_PCM_HW_PARAM_BUFFER_SIZE, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, -1);
2292 [ # # ]: 0 : if (err < 0)
2293 : : return err;
2294 : 0 : err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
2295 : : snd_pcm_hw_rule_div, NULL,
2296 : : SNDRV_PCM_HW_PARAM_BUFFER_SIZE, SNDRV_PCM_HW_PARAM_PERIODS, -1);
2297 [ # # ]: 0 : if (err < 0)
2298 : : return err;
2299 : 0 : err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
2300 : : snd_pcm_hw_rule_mulkdiv, (void*) 8,
2301 : : SNDRV_PCM_HW_PARAM_PERIOD_BYTES, SNDRV_PCM_HW_PARAM_FRAME_BITS, -1);
2302 [ # # ]: 0 : if (err < 0)
2303 : : return err;
2304 : 0 : err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
2305 : : snd_pcm_hw_rule_muldivk, (void*) 1000000,
2306 : : SNDRV_PCM_HW_PARAM_PERIOD_TIME, SNDRV_PCM_HW_PARAM_RATE, -1);
2307 [ # # ]: 0 : if (err < 0)
2308 : : return err;
2309 : 0 : err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
2310 : : snd_pcm_hw_rule_mul, NULL,
2311 : : SNDRV_PCM_HW_PARAM_PERIOD_SIZE, SNDRV_PCM_HW_PARAM_PERIODS, -1);
2312 [ # # ]: 0 : if (err < 0)
2313 : : return err;
2314 : 0 : err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
2315 : : snd_pcm_hw_rule_mulkdiv, (void*) 8,
2316 : : SNDRV_PCM_HW_PARAM_BUFFER_BYTES, SNDRV_PCM_HW_PARAM_FRAME_BITS, -1);
2317 [ # # ]: 0 : if (err < 0)
2318 : : return err;
2319 : 0 : err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
2320 : : snd_pcm_hw_rule_muldivk, (void*) 1000000,
2321 : : SNDRV_PCM_HW_PARAM_BUFFER_TIME, SNDRV_PCM_HW_PARAM_RATE, -1);
2322 [ # # ]: 0 : if (err < 0)
2323 : : return err;
2324 : 0 : err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
2325 : : snd_pcm_hw_rule_muldivk, (void*) 8,
2326 : : SNDRV_PCM_HW_PARAM_PERIOD_SIZE, SNDRV_PCM_HW_PARAM_FRAME_BITS, -1);
2327 [ # # ]: 0 : if (err < 0)
2328 : : return err;
2329 : 0 : err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
2330 : : snd_pcm_hw_rule_muldivk, (void*) 8,
2331 : : SNDRV_PCM_HW_PARAM_BUFFER_SIZE, SNDRV_PCM_HW_PARAM_FRAME_BITS, -1);
2332 [ # # ]: 0 : if (err < 0)
2333 : : return err;
2334 : 0 : err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_TIME,
2335 : : snd_pcm_hw_rule_mulkdiv, (void*) 1000000,
2336 : : SNDRV_PCM_HW_PARAM_PERIOD_SIZE, SNDRV_PCM_HW_PARAM_RATE, -1);
2337 [ # # ]: 0 : if (err < 0)
2338 : : return err;
2339 : 0 : err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_TIME,
2340 : : snd_pcm_hw_rule_mulkdiv, (void*) 1000000,
2341 : : SNDRV_PCM_HW_PARAM_BUFFER_SIZE, SNDRV_PCM_HW_PARAM_RATE, -1);
2342 [ # # ]: 0 : if (err < 0)
2343 : 0 : return err;
2344 : : return 0;
2345 : : }
2346 : :
2347 : 0 : int snd_pcm_hw_constraints_complete(struct snd_pcm_substream *substream)
2348 : : {
2349 : 0 : struct snd_pcm_runtime *runtime = substream->runtime;
2350 : 0 : struct snd_pcm_hardware *hw = &runtime->hw;
2351 : : int err;
2352 : : unsigned int mask = 0;
2353 : :
2354 [ # # ]: 0 : if (hw->info & SNDRV_PCM_INFO_INTERLEAVED)
2355 : : mask |= 1 << SNDRV_PCM_ACCESS_RW_INTERLEAVED;
2356 [ # # ]: 0 : if (hw->info & SNDRV_PCM_INFO_NONINTERLEAVED)
2357 : 0 : mask |= 1 << SNDRV_PCM_ACCESS_RW_NONINTERLEAVED;
2358 [ # # ]: 0 : if (hw_support_mmap(substream)) {
2359 [ # # ]: 0 : if (hw->info & SNDRV_PCM_INFO_INTERLEAVED)
2360 : 0 : mask |= 1 << SNDRV_PCM_ACCESS_MMAP_INTERLEAVED;
2361 [ # # ]: 0 : if (hw->info & SNDRV_PCM_INFO_NONINTERLEAVED)
2362 : 0 : mask |= 1 << SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED;
2363 [ # # ]: 0 : if (hw->info & SNDRV_PCM_INFO_COMPLEX)
2364 : 0 : mask |= 1 << SNDRV_PCM_ACCESS_MMAP_COMPLEX;
2365 : : }
2366 : 0 : err = snd_pcm_hw_constraint_mask(runtime, SNDRV_PCM_HW_PARAM_ACCESS, mask);
2367 [ # # ]: 0 : if (err < 0)
2368 : : return err;
2369 : :
2370 : 0 : err = snd_pcm_hw_constraint_mask64(runtime, SNDRV_PCM_HW_PARAM_FORMAT, hw->formats);
2371 [ # # ]: 0 : if (err < 0)
2372 : : return err;
2373 : :
2374 : 0 : err = snd_pcm_hw_constraint_mask(runtime, SNDRV_PCM_HW_PARAM_SUBFORMAT, 1 << SNDRV_PCM_SUBFORMAT_STD);
2375 [ # # ]: 0 : if (err < 0)
2376 : : return err;
2377 : :
2378 : 0 : err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_CHANNELS,
2379 : : hw->channels_min, hw->channels_max);
2380 [ # # ]: 0 : if (err < 0)
2381 : : return err;
2382 : :
2383 : 0 : err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_RATE,
2384 : : hw->rate_min, hw->rate_max);
2385 [ # # ]: 0 : if (err < 0)
2386 : : return err;
2387 : :
2388 : 0 : err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
2389 : : hw->period_bytes_min, hw->period_bytes_max);
2390 [ # # ]: 0 : if (err < 0)
2391 : : return err;
2392 : :
2393 : 0 : err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIODS,
2394 : : hw->periods_min, hw->periods_max);
2395 [ # # ]: 0 : if (err < 0)
2396 : : return err;
2397 : :
2398 : 0 : err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
2399 : : hw->period_bytes_min, hw->buffer_bytes_max);
2400 [ # # ]: 0 : if (err < 0)
2401 : : return err;
2402 : :
2403 : 0 : err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
2404 : : snd_pcm_hw_rule_buffer_bytes_max, substream,
2405 : : SNDRV_PCM_HW_PARAM_BUFFER_BYTES, -1);
2406 [ # # ]: 0 : if (err < 0)
2407 : : return err;
2408 : :
2409 : : /* FIXME: remove */
2410 [ # # ]: 0 : if (runtime->dma_bytes) {
2411 : 0 : err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 0, runtime->dma_bytes);
2412 [ # # ]: 0 : if (err < 0)
2413 : : return err;
2414 : : }
2415 : :
2416 [ # # ]: 0 : if (!(hw->rates & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))) {
2417 : 0 : err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
2418 : : snd_pcm_hw_rule_rate, hw,
2419 : : SNDRV_PCM_HW_PARAM_RATE, -1);
2420 [ # # ]: 0 : if (err < 0)
2421 : : return err;
2422 : : }
2423 : :
2424 : : /* FIXME: this belong to lowlevel */
2425 : 0 : snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
2426 : :
2427 : 0 : return 0;
2428 : : }
2429 : :
2430 : 0 : static void pcm_release_private(struct snd_pcm_substream *substream)
2431 : : {
2432 [ # # ]: 0 : if (snd_pcm_stream_linked(substream))
2433 : 0 : snd_pcm_unlink(substream);
2434 : 0 : }
2435 : :
2436 : 0 : void snd_pcm_release_substream(struct snd_pcm_substream *substream)
2437 : : {
2438 : 0 : substream->ref_count--;
2439 [ # # ]: 0 : if (substream->ref_count > 0)
2440 : 0 : return;
2441 : :
2442 : 0 : snd_pcm_drop(substream);
2443 [ # # ]: 0 : if (substream->hw_opened) {
2444 [ # # # # ]: 0 : if (substream->ops->hw_free &&
2445 : 0 : substream->runtime->status->state != SNDRV_PCM_STATE_OPEN)
2446 : 0 : substream->ops->hw_free(substream);
2447 : 0 : substream->ops->close(substream);
2448 : 0 : substream->hw_opened = 0;
2449 : : }
2450 [ # # ]: 0 : if (pm_qos_request_active(&substream->latency_pm_qos_req))
2451 : 0 : pm_qos_remove_request(&substream->latency_pm_qos_req);
2452 [ # # ]: 0 : if (substream->pcm_release) {
2453 : 0 : substream->pcm_release(substream);
2454 : 0 : substream->pcm_release = NULL;
2455 : : }
2456 : 0 : snd_pcm_detach_substream(substream);
2457 : : }
2458 : : EXPORT_SYMBOL(snd_pcm_release_substream);
2459 : :
2460 : 0 : int snd_pcm_open_substream(struct snd_pcm *pcm, int stream,
2461 : : struct file *file,
2462 : : struct snd_pcm_substream **rsubstream)
2463 : : {
2464 : : struct snd_pcm_substream *substream;
2465 : : int err;
2466 : :
2467 : 0 : err = snd_pcm_attach_substream(pcm, stream, file, &substream);
2468 [ # # ]: 0 : if (err < 0)
2469 : : return err;
2470 [ # # ]: 0 : if (substream->ref_count > 1) {
2471 : 0 : *rsubstream = substream;
2472 : 0 : return 0;
2473 : : }
2474 : :
2475 : 0 : err = snd_pcm_hw_constraints_init(substream);
2476 [ # # ]: 0 : if (err < 0) {
2477 : : pcm_dbg(pcm, "snd_pcm_hw_constraints_init failed\n");
2478 : : goto error;
2479 : : }
2480 : :
2481 [ # # ]: 0 : if ((err = substream->ops->open(substream)) < 0)
2482 : : goto error;
2483 : :
2484 : 0 : substream->hw_opened = 1;
2485 : :
2486 : 0 : err = snd_pcm_hw_constraints_complete(substream);
2487 [ # # ]: 0 : if (err < 0) {
2488 : : pcm_dbg(pcm, "snd_pcm_hw_constraints_complete failed\n");
2489 : : goto error;
2490 : : }
2491 : :
2492 : 0 : *rsubstream = substream;
2493 : 0 : return 0;
2494 : :
2495 : : error:
2496 : 0 : snd_pcm_release_substream(substream);
2497 : 0 : return err;
2498 : : }
2499 : : EXPORT_SYMBOL(snd_pcm_open_substream);
2500 : :
2501 : 0 : static int snd_pcm_open_file(struct file *file,
2502 : : struct snd_pcm *pcm,
2503 : : int stream)
2504 : : {
2505 : : struct snd_pcm_file *pcm_file;
2506 : : struct snd_pcm_substream *substream;
2507 : : int err;
2508 : :
2509 : 0 : err = snd_pcm_open_substream(pcm, stream, file, &substream);
2510 [ # # ]: 0 : if (err < 0)
2511 : : return err;
2512 : :
2513 : 0 : pcm_file = kzalloc(sizeof(*pcm_file), GFP_KERNEL);
2514 [ # # ]: 0 : if (pcm_file == NULL) {
2515 : 0 : snd_pcm_release_substream(substream);
2516 : 0 : return -ENOMEM;
2517 : : }
2518 : 0 : pcm_file->substream = substream;
2519 [ # # ]: 0 : if (substream->ref_count == 1)
2520 : 0 : substream->pcm_release = pcm_release_private;
2521 : 0 : file->private_data = pcm_file;
2522 : :
2523 : 0 : return 0;
2524 : : }
2525 : :
2526 : 0 : static int snd_pcm_playback_open(struct inode *inode, struct file *file)
2527 : : {
2528 : : struct snd_pcm *pcm;
2529 : 0 : int err = nonseekable_open(inode, file);
2530 [ # # ]: 0 : if (err < 0)
2531 : : return err;
2532 : 0 : pcm = snd_lookup_minor_data(iminor(inode),
2533 : : SNDRV_DEVICE_TYPE_PCM_PLAYBACK);
2534 : 0 : err = snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_PLAYBACK);
2535 [ # # ]: 0 : if (pcm)
2536 : 0 : snd_card_unref(pcm->card);
2537 : 0 : return err;
2538 : : }
2539 : :
2540 : 0 : static int snd_pcm_capture_open(struct inode *inode, struct file *file)
2541 : : {
2542 : : struct snd_pcm *pcm;
2543 : 0 : int err = nonseekable_open(inode, file);
2544 [ # # ]: 0 : if (err < 0)
2545 : : return err;
2546 : 0 : pcm = snd_lookup_minor_data(iminor(inode),
2547 : : SNDRV_DEVICE_TYPE_PCM_CAPTURE);
2548 : 0 : err = snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_CAPTURE);
2549 [ # # ]: 0 : if (pcm)
2550 : 0 : snd_card_unref(pcm->card);
2551 : 0 : return err;
2552 : : }
2553 : :
2554 : 0 : static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream)
2555 : : {
2556 : : int err;
2557 : : wait_queue_entry_t wait;
2558 : :
2559 [ # # ]: 0 : if (pcm == NULL) {
2560 : : err = -ENODEV;
2561 : : goto __error1;
2562 : : }
2563 : 0 : err = snd_card_file_add(pcm->card, file);
2564 [ # # ]: 0 : if (err < 0)
2565 : : goto __error1;
2566 [ # # ]: 0 : if (!try_module_get(pcm->card->module)) {
2567 : : err = -EFAULT;
2568 : : goto __error2;
2569 : : }
2570 : 0 : init_waitqueue_entry(&wait, current);
2571 : 0 : add_wait_queue(&pcm->open_wait, &wait);
2572 : 0 : mutex_lock(&pcm->open_mutex);
2573 : : while (1) {
2574 : 0 : err = snd_pcm_open_file(file, pcm, stream);
2575 [ # # ]: 0 : if (err >= 0)
2576 : : break;
2577 [ # # ]: 0 : if (err == -EAGAIN) {
2578 [ # # ]: 0 : if (file->f_flags & O_NONBLOCK) {
2579 : : err = -EBUSY;
2580 : : break;
2581 : : }
2582 : : } else
2583 : : break;
2584 : 0 : set_current_state(TASK_INTERRUPTIBLE);
2585 : 0 : mutex_unlock(&pcm->open_mutex);
2586 : 0 : schedule();
2587 : 0 : mutex_lock(&pcm->open_mutex);
2588 [ # # ]: 0 : if (pcm->card->shutdown) {
2589 : : err = -ENODEV;
2590 : : break;
2591 : : }
2592 [ # # ]: 0 : if (signal_pending(current)) {
2593 : : err = -ERESTARTSYS;
2594 : : break;
2595 : : }
2596 : : }
2597 : 0 : remove_wait_queue(&pcm->open_wait, &wait);
2598 : 0 : mutex_unlock(&pcm->open_mutex);
2599 [ # # ]: 0 : if (err < 0)
2600 : : goto __error;
2601 : : return err;
2602 : :
2603 : : __error:
2604 : 0 : module_put(pcm->card->module);
2605 : : __error2:
2606 : 0 : snd_card_file_remove(pcm->card, file);
2607 : : __error1:
2608 : 0 : return err;
2609 : : }
2610 : :
2611 : 0 : static int snd_pcm_release(struct inode *inode, struct file *file)
2612 : : {
2613 : : struct snd_pcm *pcm;
2614 : : struct snd_pcm_substream *substream;
2615 : : struct snd_pcm_file *pcm_file;
2616 : :
2617 : 0 : pcm_file = file->private_data;
2618 : 0 : substream = pcm_file->substream;
2619 [ # # ]: 0 : if (snd_BUG_ON(!substream))
2620 : : return -ENXIO;
2621 : 0 : pcm = substream->pcm;
2622 : 0 : mutex_lock(&pcm->open_mutex);
2623 : 0 : snd_pcm_release_substream(substream);
2624 : 0 : kfree(pcm_file);
2625 : 0 : mutex_unlock(&pcm->open_mutex);
2626 : 0 : wake_up(&pcm->open_wait);
2627 : 0 : module_put(pcm->card->module);
2628 : 0 : snd_card_file_remove(pcm->card, file);
2629 : 0 : return 0;
2630 : : }
2631 : :
2632 : : /* check and update PCM state; return 0 or a negative error
2633 : : * call this inside PCM lock
2634 : : */
2635 : 0 : static int do_pcm_hwsync(struct snd_pcm_substream *substream)
2636 : : {
2637 [ # # # # : 0 : switch (substream->runtime->status->state) {
# # ]
2638 : : case SNDRV_PCM_STATE_DRAINING:
2639 [ # # ]: 0 : if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
2640 : : return -EBADFD;
2641 : : /* Fall through */
2642 : : case SNDRV_PCM_STATE_RUNNING:
2643 : 0 : return snd_pcm_update_hw_ptr(substream);
2644 : : case SNDRV_PCM_STATE_PREPARED:
2645 : : case SNDRV_PCM_STATE_PAUSED:
2646 : : return 0;
2647 : : case SNDRV_PCM_STATE_SUSPENDED:
2648 : 0 : return -ESTRPIPE;
2649 : : case SNDRV_PCM_STATE_XRUN:
2650 : 0 : return -EPIPE;
2651 : : default:
2652 : 0 : return -EBADFD;
2653 : : }
2654 : : }
2655 : :
2656 : : /* increase the appl_ptr; returns the processed frames or a negative error */
2657 : 0 : static snd_pcm_sframes_t forward_appl_ptr(struct snd_pcm_substream *substream,
2658 : : snd_pcm_uframes_t frames,
2659 : : snd_pcm_sframes_t avail)
2660 : : {
2661 : 0 : struct snd_pcm_runtime *runtime = substream->runtime;
2662 : : snd_pcm_sframes_t appl_ptr;
2663 : : int ret;
2664 : :
2665 [ # # ]: 0 : if (avail <= 0)
2666 : : return 0;
2667 [ # # ]: 0 : if (frames > (snd_pcm_uframes_t)avail)
2668 : : frames = avail;
2669 : 0 : appl_ptr = runtime->control->appl_ptr + frames;
2670 [ # # ]: 0 : if (appl_ptr >= (snd_pcm_sframes_t)runtime->boundary)
2671 : 0 : appl_ptr -= runtime->boundary;
2672 : 0 : ret = pcm_lib_apply_appl_ptr(substream, appl_ptr);
2673 [ # # ]: 0 : return ret < 0 ? ret : frames;
2674 : : }
2675 : :
2676 : : /* decrease the appl_ptr; returns the processed frames or zero for error */
2677 : 0 : static snd_pcm_sframes_t rewind_appl_ptr(struct snd_pcm_substream *substream,
2678 : : snd_pcm_uframes_t frames,
2679 : : snd_pcm_sframes_t avail)
2680 : : {
2681 : 0 : struct snd_pcm_runtime *runtime = substream->runtime;
2682 : : snd_pcm_sframes_t appl_ptr;
2683 : : int ret;
2684 : :
2685 [ # # ]: 0 : if (avail <= 0)
2686 : : return 0;
2687 [ # # ]: 0 : if (frames > (snd_pcm_uframes_t)avail)
2688 : : frames = avail;
2689 : 0 : appl_ptr = runtime->control->appl_ptr - frames;
2690 [ # # ]: 0 : if (appl_ptr < 0)
2691 : 0 : appl_ptr += runtime->boundary;
2692 : 0 : ret = pcm_lib_apply_appl_ptr(substream, appl_ptr);
2693 : : /* NOTE: we return zero for errors because PulseAudio gets depressed
2694 : : * upon receiving an error from rewind ioctl and stops processing
2695 : : * any longer. Returning zero means that no rewind is done, so
2696 : : * it's not absolutely wrong to answer like that.
2697 : : */
2698 [ # # ]: 0 : return ret < 0 ? 0 : frames;
2699 : : }
2700 : :
2701 : 0 : static snd_pcm_sframes_t snd_pcm_rewind(struct snd_pcm_substream *substream,
2702 : : snd_pcm_uframes_t frames)
2703 : : {
2704 : : snd_pcm_sframes_t ret;
2705 : :
2706 [ # # ]: 0 : if (frames == 0)
2707 : : return 0;
2708 : :
2709 : 0 : snd_pcm_stream_lock_irq(substream);
2710 : 0 : ret = do_pcm_hwsync(substream);
2711 [ # # ]: 0 : if (!ret)
2712 : 0 : ret = rewind_appl_ptr(substream, frames,
2713 : 0 : snd_pcm_hw_avail(substream));
2714 : 0 : snd_pcm_stream_unlock_irq(substream);
2715 : 0 : return ret;
2716 : : }
2717 : :
2718 : 0 : static snd_pcm_sframes_t snd_pcm_forward(struct snd_pcm_substream *substream,
2719 : : snd_pcm_uframes_t frames)
2720 : : {
2721 : : snd_pcm_sframes_t ret;
2722 : :
2723 [ # # ]: 0 : if (frames == 0)
2724 : : return 0;
2725 : :
2726 : 0 : snd_pcm_stream_lock_irq(substream);
2727 : 0 : ret = do_pcm_hwsync(substream);
2728 [ # # ]: 0 : if (!ret)
2729 : 0 : ret = forward_appl_ptr(substream, frames,
2730 : 0 : snd_pcm_avail(substream));
2731 : 0 : snd_pcm_stream_unlock_irq(substream);
2732 : 0 : return ret;
2733 : : }
2734 : :
2735 : 0 : static int snd_pcm_hwsync(struct snd_pcm_substream *substream)
2736 : : {
2737 : : int err;
2738 : :
2739 : 0 : snd_pcm_stream_lock_irq(substream);
2740 : 0 : err = do_pcm_hwsync(substream);
2741 : 0 : snd_pcm_stream_unlock_irq(substream);
2742 : 0 : return err;
2743 : : }
2744 : :
2745 : 0 : static int snd_pcm_delay(struct snd_pcm_substream *substream,
2746 : : snd_pcm_sframes_t *delay)
2747 : : {
2748 : : int err;
2749 : : snd_pcm_sframes_t n = 0;
2750 : :
2751 : 0 : snd_pcm_stream_lock_irq(substream);
2752 : 0 : err = do_pcm_hwsync(substream);
2753 [ # # ]: 0 : if (!err)
2754 : 0 : n = snd_pcm_calc_delay(substream);
2755 : 0 : snd_pcm_stream_unlock_irq(substream);
2756 [ # # ]: 0 : if (!err)
2757 : 0 : *delay = n;
2758 : 0 : return err;
2759 : : }
2760 : :
2761 : 0 : static int snd_pcm_sync_ptr(struct snd_pcm_substream *substream,
2762 : : struct snd_pcm_sync_ptr __user *_sync_ptr)
2763 : : {
2764 : 0 : struct snd_pcm_runtime *runtime = substream->runtime;
2765 : : struct snd_pcm_sync_ptr sync_ptr;
2766 : : volatile struct snd_pcm_mmap_status *status;
2767 : : volatile struct snd_pcm_mmap_control *control;
2768 : : int err;
2769 : :
2770 : 0 : memset(&sync_ptr, 0, sizeof(sync_ptr));
2771 [ # # ]: 0 : if (get_user(sync_ptr.flags, (unsigned __user *)&(_sync_ptr->flags)))
2772 : : return -EFAULT;
2773 [ # # ]: 0 : if (copy_from_user(&sync_ptr.c.control, &(_sync_ptr->c.control), sizeof(struct snd_pcm_mmap_control)))
2774 : : return -EFAULT;
2775 : 0 : status = runtime->status;
2776 : 0 : control = runtime->control;
2777 [ # # ]: 0 : if (sync_ptr.flags & SNDRV_PCM_SYNC_PTR_HWSYNC) {
2778 : 0 : err = snd_pcm_hwsync(substream);
2779 [ # # ]: 0 : if (err < 0)
2780 : : return err;
2781 : : }
2782 : 0 : snd_pcm_stream_lock_irq(substream);
2783 [ # # ]: 0 : if (!(sync_ptr.flags & SNDRV_PCM_SYNC_PTR_APPL)) {
2784 : 0 : err = pcm_lib_apply_appl_ptr(substream,
2785 : : sync_ptr.c.control.appl_ptr);
2786 [ # # ]: 0 : if (err < 0) {
2787 : 0 : snd_pcm_stream_unlock_irq(substream);
2788 : 0 : return err;
2789 : : }
2790 : : } else {
2791 : 0 : sync_ptr.c.control.appl_ptr = control->appl_ptr;
2792 : : }
2793 [ # # ]: 0 : if (!(sync_ptr.flags & SNDRV_PCM_SYNC_PTR_AVAIL_MIN))
2794 : 0 : control->avail_min = sync_ptr.c.control.avail_min;
2795 : : else
2796 : 0 : sync_ptr.c.control.avail_min = control->avail_min;
2797 : 0 : sync_ptr.s.status.state = status->state;
2798 : 0 : sync_ptr.s.status.hw_ptr = status->hw_ptr;
2799 : 0 : sync_ptr.s.status.tstamp = status->tstamp;
2800 : 0 : sync_ptr.s.status.suspended_state = status->suspended_state;
2801 : 0 : sync_ptr.s.status.audio_tstamp = status->audio_tstamp;
2802 : 0 : snd_pcm_stream_unlock_irq(substream);
2803 [ # # ]: 0 : if (copy_to_user(_sync_ptr, &sync_ptr, sizeof(sync_ptr)))
2804 : : return -EFAULT;
2805 : 0 : return 0;
2806 : : }
2807 : :
2808 : 0 : static int snd_pcm_tstamp(struct snd_pcm_substream *substream, int __user *_arg)
2809 : : {
2810 : 0 : struct snd_pcm_runtime *runtime = substream->runtime;
2811 : : int arg;
2812 : :
2813 [ # # ]: 0 : if (get_user(arg, _arg))
2814 : : return -EFAULT;
2815 [ # # ]: 0 : if (arg < 0 || arg > SNDRV_PCM_TSTAMP_TYPE_LAST)
2816 : : return -EINVAL;
2817 : 0 : runtime->tstamp_type = arg;
2818 : 0 : return 0;
2819 : : }
2820 : :
2821 : 0 : static int snd_pcm_xferi_frames_ioctl(struct snd_pcm_substream *substream,
2822 : : struct snd_xferi __user *_xferi)
2823 : : {
2824 : : struct snd_xferi xferi;
2825 : 0 : struct snd_pcm_runtime *runtime = substream->runtime;
2826 : : snd_pcm_sframes_t result;
2827 : :
2828 [ # # ]: 0 : if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
2829 : : return -EBADFD;
2830 [ # # ]: 0 : if (put_user(0, &_xferi->result))
2831 : : return -EFAULT;
2832 [ # # ]: 0 : if (copy_from_user(&xferi, _xferi, sizeof(xferi)))
2833 : : return -EFAULT;
2834 [ # # ]: 0 : if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
2835 : 0 : result = snd_pcm_lib_write(substream, xferi.buf, xferi.frames);
2836 : : else
2837 : 0 : result = snd_pcm_lib_read(substream, xferi.buf, xferi.frames);
2838 : 0 : __put_user(result, &_xferi->result);
2839 : 0 : return result < 0 ? result : 0;
2840 : : }
2841 : :
2842 : 0 : static int snd_pcm_xfern_frames_ioctl(struct snd_pcm_substream *substream,
2843 : : struct snd_xfern __user *_xfern)
2844 : : {
2845 : : struct snd_xfern xfern;
2846 : 0 : struct snd_pcm_runtime *runtime = substream->runtime;
2847 : : void *bufs;
2848 : : snd_pcm_sframes_t result;
2849 : :
2850 [ # # ]: 0 : if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
2851 : : return -EBADFD;
2852 [ # # ]: 0 : if (runtime->channels > 128)
2853 : : return -EINVAL;
2854 [ # # ]: 0 : if (put_user(0, &_xfern->result))
2855 : : return -EFAULT;
2856 [ # # ]: 0 : if (copy_from_user(&xfern, _xfern, sizeof(xfern)))
2857 : : return -EFAULT;
2858 : :
2859 : 0 : bufs = memdup_user(xfern.bufs, sizeof(void *) * runtime->channels);
2860 [ # # ]: 0 : if (IS_ERR(bufs))
2861 : 0 : return PTR_ERR(bufs);
2862 [ # # ]: 0 : if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
2863 : 0 : result = snd_pcm_lib_writev(substream, bufs, xfern.frames);
2864 : : else
2865 : 0 : result = snd_pcm_lib_readv(substream, bufs, xfern.frames);
2866 : 0 : kfree(bufs);
2867 : 0 : __put_user(result, &_xfern->result);
2868 : 0 : return result < 0 ? result : 0;
2869 : : }
2870 : :
2871 : 0 : static int snd_pcm_rewind_ioctl(struct snd_pcm_substream *substream,
2872 : : snd_pcm_uframes_t __user *_frames)
2873 : : {
2874 : : snd_pcm_uframes_t frames;
2875 : : snd_pcm_sframes_t result;
2876 : :
2877 [ # # ]: 0 : if (get_user(frames, _frames))
2878 : : return -EFAULT;
2879 [ # # ]: 0 : if (put_user(0, _frames))
2880 : : return -EFAULT;
2881 : 0 : result = snd_pcm_rewind(substream, frames);
2882 : 0 : __put_user(result, _frames);
2883 : 0 : return result < 0 ? result : 0;
2884 : : }
2885 : :
2886 : 0 : static int snd_pcm_forward_ioctl(struct snd_pcm_substream *substream,
2887 : : snd_pcm_uframes_t __user *_frames)
2888 : : {
2889 : : snd_pcm_uframes_t frames;
2890 : : snd_pcm_sframes_t result;
2891 : :
2892 [ # # ]: 0 : if (get_user(frames, _frames))
2893 : : return -EFAULT;
2894 [ # # ]: 0 : if (put_user(0, _frames))
2895 : : return -EFAULT;
2896 : 0 : result = snd_pcm_forward(substream, frames);
2897 : 0 : __put_user(result, _frames);
2898 : 0 : return result < 0 ? result : 0;
2899 : : }
2900 : :
2901 : 0 : static int snd_pcm_common_ioctl(struct file *file,
2902 : : struct snd_pcm_substream *substream,
2903 : : unsigned int cmd, void __user *arg)
2904 : : {
2905 : 0 : struct snd_pcm_file *pcm_file = file->private_data;
2906 : : int res;
2907 : :
2908 [ # # # # : 0 : if (PCM_RUNTIME_CHECK(substream))
# # ]
2909 : : return -ENXIO;
2910 : :
2911 : 0 : res = snd_power_wait(substream->pcm->card, SNDRV_CTL_POWER_D0);
2912 [ # # ]: 0 : if (res < 0)
2913 : : return res;
2914 : :
2915 [ # # # # : 0 : switch (cmd) {
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # ]
2916 : : case SNDRV_PCM_IOCTL_PVERSION:
2917 [ # # ]: 0 : return put_user(SNDRV_PCM_VERSION, (int __user *)arg) ? -EFAULT : 0;
2918 : : case SNDRV_PCM_IOCTL_INFO:
2919 : 0 : return snd_pcm_info_user(substream, arg);
2920 : : case SNDRV_PCM_IOCTL_TSTAMP: /* just for compatibility */
2921 : : return 0;
2922 : : case SNDRV_PCM_IOCTL_TTSTAMP:
2923 : 0 : return snd_pcm_tstamp(substream, arg);
2924 : : case SNDRV_PCM_IOCTL_USER_PVERSION:
2925 [ # # ]: 0 : if (get_user(pcm_file->user_pversion,
2926 : : (unsigned int __user *)arg))
2927 : : return -EFAULT;
2928 : 0 : return 0;
2929 : : case SNDRV_PCM_IOCTL_HW_REFINE:
2930 : 0 : return snd_pcm_hw_refine_user(substream, arg);
2931 : : case SNDRV_PCM_IOCTL_HW_PARAMS:
2932 : 0 : return snd_pcm_hw_params_user(substream, arg);
2933 : : case SNDRV_PCM_IOCTL_HW_FREE:
2934 : 0 : return snd_pcm_hw_free(substream);
2935 : : case SNDRV_PCM_IOCTL_SW_PARAMS:
2936 : 0 : return snd_pcm_sw_params_user(substream, arg);
2937 : : case SNDRV_PCM_IOCTL_STATUS:
2938 : 0 : return snd_pcm_status_user(substream, arg, false);
2939 : : case SNDRV_PCM_IOCTL_STATUS_EXT:
2940 : 0 : return snd_pcm_status_user(substream, arg, true);
2941 : : case SNDRV_PCM_IOCTL_CHANNEL_INFO:
2942 : 0 : return snd_pcm_channel_info_user(substream, arg);
2943 : : case SNDRV_PCM_IOCTL_PREPARE:
2944 : 0 : return snd_pcm_prepare(substream, file);
2945 : : case SNDRV_PCM_IOCTL_RESET:
2946 : 0 : return snd_pcm_reset(substream);
2947 : : case SNDRV_PCM_IOCTL_START:
2948 : 0 : return snd_pcm_start_lock_irq(substream);
2949 : : case SNDRV_PCM_IOCTL_LINK:
2950 : 0 : return snd_pcm_link(substream, (int)(unsigned long) arg);
2951 : : case SNDRV_PCM_IOCTL_UNLINK:
2952 : 0 : return snd_pcm_unlink(substream);
2953 : : case SNDRV_PCM_IOCTL_RESUME:
2954 : 0 : return snd_pcm_resume(substream);
2955 : : case SNDRV_PCM_IOCTL_XRUN:
2956 : 0 : return snd_pcm_xrun(substream);
2957 : : case SNDRV_PCM_IOCTL_HWSYNC:
2958 : 0 : return snd_pcm_hwsync(substream);
2959 : : case SNDRV_PCM_IOCTL_DELAY:
2960 : : {
2961 : : snd_pcm_sframes_t delay;
2962 : : snd_pcm_sframes_t __user *res = arg;
2963 : : int err;
2964 : :
2965 : 0 : err = snd_pcm_delay(substream, &delay);
2966 [ # # ]: 0 : if (err)
2967 : : return err;
2968 [ # # ]: 0 : if (put_user(delay, res))
2969 : : return -EFAULT;
2970 : 0 : return 0;
2971 : : }
2972 : : case SNDRV_PCM_IOCTL_SYNC_PTR:
2973 : 0 : return snd_pcm_sync_ptr(substream, arg);
2974 : : #ifdef CONFIG_SND_SUPPORT_OLD_API
2975 : : case SNDRV_PCM_IOCTL_HW_REFINE_OLD:
2976 : 0 : return snd_pcm_hw_refine_old_user(substream, arg);
2977 : : case SNDRV_PCM_IOCTL_HW_PARAMS_OLD:
2978 : 0 : return snd_pcm_hw_params_old_user(substream, arg);
2979 : : #endif
2980 : : case SNDRV_PCM_IOCTL_DRAIN:
2981 : 0 : return snd_pcm_drain(substream, file);
2982 : : case SNDRV_PCM_IOCTL_DROP:
2983 : 0 : return snd_pcm_drop(substream);
2984 : : case SNDRV_PCM_IOCTL_PAUSE:
2985 : 0 : return snd_pcm_action_lock_irq(&snd_pcm_action_pause,
2986 : : substream,
2987 : : (int)(unsigned long)arg);
2988 : : case SNDRV_PCM_IOCTL_WRITEI_FRAMES:
2989 : : case SNDRV_PCM_IOCTL_READI_FRAMES:
2990 : 0 : return snd_pcm_xferi_frames_ioctl(substream, arg);
2991 : : case SNDRV_PCM_IOCTL_WRITEN_FRAMES:
2992 : : case SNDRV_PCM_IOCTL_READN_FRAMES:
2993 : 0 : return snd_pcm_xfern_frames_ioctl(substream, arg);
2994 : : case SNDRV_PCM_IOCTL_REWIND:
2995 : 0 : return snd_pcm_rewind_ioctl(substream, arg);
2996 : : case SNDRV_PCM_IOCTL_FORWARD:
2997 : 0 : return snd_pcm_forward_ioctl(substream, arg);
2998 : : }
2999 : : pcm_dbg(substream->pcm, "unknown ioctl = 0x%x\n", cmd);
3000 : 0 : return -ENOTTY;
3001 : : }
3002 : :
3003 : 0 : static long snd_pcm_ioctl(struct file *file, unsigned int cmd,
3004 : : unsigned long arg)
3005 : : {
3006 : : struct snd_pcm_file *pcm_file;
3007 : :
3008 : 0 : pcm_file = file->private_data;
3009 : :
3010 [ # # ]: 0 : if (((cmd >> 8) & 0xff) != 'A')
3011 : : return -ENOTTY;
3012 : :
3013 : 0 : return snd_pcm_common_ioctl(file, pcm_file->substream, cmd,
3014 : : (void __user *)arg);
3015 : : }
3016 : :
3017 : : /**
3018 : : * snd_pcm_kernel_ioctl - Execute PCM ioctl in the kernel-space
3019 : : * @substream: PCM substream
3020 : : * @cmd: IOCTL cmd
3021 : : * @arg: IOCTL argument
3022 : : *
3023 : : * The function is provided primarily for OSS layer and USB gadget drivers,
3024 : : * and it allows only the limited set of ioctls (hw_params, sw_params,
3025 : : * prepare, start, drain, drop, forward).
3026 : : */
3027 : 0 : int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream,
3028 : : unsigned int cmd, void *arg)
3029 : : {
3030 : : snd_pcm_uframes_t *frames = arg;
3031 : : snd_pcm_sframes_t result;
3032 : :
3033 [ # # # # : 0 : switch (cmd) {
# # # #
# ]
3034 : : case SNDRV_PCM_IOCTL_FORWARD:
3035 : : {
3036 : : /* provided only for OSS; capture-only and no value returned */
3037 [ # # ]: 0 : if (substream->stream != SNDRV_PCM_STREAM_CAPTURE)
3038 : : return -EINVAL;
3039 : 0 : result = snd_pcm_forward(substream, *frames);
3040 : 0 : return result < 0 ? result : 0;
3041 : : }
3042 : : case SNDRV_PCM_IOCTL_HW_PARAMS:
3043 : 0 : return snd_pcm_hw_params(substream, arg);
3044 : : case SNDRV_PCM_IOCTL_SW_PARAMS:
3045 : 0 : return snd_pcm_sw_params(substream, arg);
3046 : : case SNDRV_PCM_IOCTL_PREPARE:
3047 : 0 : return snd_pcm_prepare(substream, NULL);
3048 : : case SNDRV_PCM_IOCTL_START:
3049 : 0 : return snd_pcm_start_lock_irq(substream);
3050 : : case SNDRV_PCM_IOCTL_DRAIN:
3051 : 0 : return snd_pcm_drain(substream, NULL);
3052 : : case SNDRV_PCM_IOCTL_DROP:
3053 : 0 : return snd_pcm_drop(substream);
3054 : : case SNDRV_PCM_IOCTL_DELAY:
3055 : 0 : return snd_pcm_delay(substream, frames);
3056 : : default:
3057 : : return -EINVAL;
3058 : : }
3059 : : }
3060 : : EXPORT_SYMBOL(snd_pcm_kernel_ioctl);
3061 : :
3062 : 0 : static ssize_t snd_pcm_read(struct file *file, char __user *buf, size_t count,
3063 : : loff_t * offset)
3064 : : {
3065 : : struct snd_pcm_file *pcm_file;
3066 : : struct snd_pcm_substream *substream;
3067 : : struct snd_pcm_runtime *runtime;
3068 : : snd_pcm_sframes_t result;
3069 : :
3070 : 0 : pcm_file = file->private_data;
3071 : 0 : substream = pcm_file->substream;
3072 [ # # # # : 0 : if (PCM_RUNTIME_CHECK(substream))
# # ]
3073 : : return -ENXIO;
3074 : 0 : runtime = substream->runtime;
3075 [ # # ]: 0 : if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
3076 : : return -EBADFD;
3077 [ # # ]: 0 : if (!frame_aligned(runtime, count))
3078 : : return -EINVAL;
3079 : 0 : count = bytes_to_frames(runtime, count);
3080 : : result = snd_pcm_lib_read(substream, buf, count);
3081 [ # # ]: 0 : if (result > 0)
3082 : : result = frames_to_bytes(runtime, result);
3083 : 0 : return result;
3084 : : }
3085 : :
3086 : 0 : static ssize_t snd_pcm_write(struct file *file, const char __user *buf,
3087 : : size_t count, loff_t * offset)
3088 : : {
3089 : : struct snd_pcm_file *pcm_file;
3090 : : struct snd_pcm_substream *substream;
3091 : : struct snd_pcm_runtime *runtime;
3092 : : snd_pcm_sframes_t result;
3093 : :
3094 : 0 : pcm_file = file->private_data;
3095 : 0 : substream = pcm_file->substream;
3096 [ # # # # : 0 : if (PCM_RUNTIME_CHECK(substream))
# # ]
3097 : : return -ENXIO;
3098 : 0 : runtime = substream->runtime;
3099 [ # # ]: 0 : if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
3100 : : return -EBADFD;
3101 [ # # ]: 0 : if (!frame_aligned(runtime, count))
3102 : : return -EINVAL;
3103 : 0 : count = bytes_to_frames(runtime, count);
3104 : : result = snd_pcm_lib_write(substream, buf, count);
3105 [ # # ]: 0 : if (result > 0)
3106 : : result = frames_to_bytes(runtime, result);
3107 : 0 : return result;
3108 : : }
3109 : :
3110 : 0 : static ssize_t snd_pcm_readv(struct kiocb *iocb, struct iov_iter *to)
3111 : : {
3112 : : struct snd_pcm_file *pcm_file;
3113 : : struct snd_pcm_substream *substream;
3114 : : struct snd_pcm_runtime *runtime;
3115 : : snd_pcm_sframes_t result;
3116 : : unsigned long i;
3117 : : void __user **bufs;
3118 : : snd_pcm_uframes_t frames;
3119 : :
3120 : 0 : pcm_file = iocb->ki_filp->private_data;
3121 : 0 : substream = pcm_file->substream;
3122 [ # # # # : 0 : if (PCM_RUNTIME_CHECK(substream))
# # ]
3123 : : return -ENXIO;
3124 : 0 : runtime = substream->runtime;
3125 [ # # ]: 0 : if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
3126 : : return -EBADFD;
3127 [ # # ]: 0 : if (!iter_is_iovec(to))
3128 : : return -EINVAL;
3129 [ # # # # ]: 0 : if (to->nr_segs > 1024 || to->nr_segs != runtime->channels)
3130 : : return -EINVAL;
3131 [ # # ]: 0 : if (!frame_aligned(runtime, to->iov->iov_len))
3132 : : return -EINVAL;
3133 : 0 : frames = bytes_to_samples(runtime, to->iov->iov_len);
3134 : 0 : bufs = kmalloc_array(to->nr_segs, sizeof(void *), GFP_KERNEL);
3135 [ # # ]: 0 : if (bufs == NULL)
3136 : : return -ENOMEM;
3137 [ # # ]: 0 : for (i = 0; i < to->nr_segs; ++i)
3138 : 0 : bufs[i] = to->iov[i].iov_base;
3139 : : result = snd_pcm_lib_readv(substream, bufs, frames);
3140 [ # # ]: 0 : if (result > 0)
3141 : : result = frames_to_bytes(runtime, result);
3142 : 0 : kfree(bufs);
3143 : 0 : return result;
3144 : : }
3145 : :
3146 : 0 : static ssize_t snd_pcm_writev(struct kiocb *iocb, struct iov_iter *from)
3147 : : {
3148 : : struct snd_pcm_file *pcm_file;
3149 : : struct snd_pcm_substream *substream;
3150 : : struct snd_pcm_runtime *runtime;
3151 : : snd_pcm_sframes_t result;
3152 : : unsigned long i;
3153 : : void __user **bufs;
3154 : : snd_pcm_uframes_t frames;
3155 : :
3156 : 0 : pcm_file = iocb->ki_filp->private_data;
3157 : 0 : substream = pcm_file->substream;
3158 [ # # # # : 0 : if (PCM_RUNTIME_CHECK(substream))
# # ]
3159 : : return -ENXIO;
3160 : 0 : runtime = substream->runtime;
3161 [ # # ]: 0 : if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
3162 : : return -EBADFD;
3163 [ # # ]: 0 : if (!iter_is_iovec(from))
3164 : : return -EINVAL;
3165 [ # # # # : 0 : if (from->nr_segs > 128 || from->nr_segs != runtime->channels ||
# # ]
3166 : 0 : !frame_aligned(runtime, from->iov->iov_len))
3167 : : return -EINVAL;
3168 : 0 : frames = bytes_to_samples(runtime, from->iov->iov_len);
3169 : 0 : bufs = kmalloc_array(from->nr_segs, sizeof(void *), GFP_KERNEL);
3170 [ # # ]: 0 : if (bufs == NULL)
3171 : : return -ENOMEM;
3172 [ # # ]: 0 : for (i = 0; i < from->nr_segs; ++i)
3173 : 0 : bufs[i] = from->iov[i].iov_base;
3174 : : result = snd_pcm_lib_writev(substream, bufs, frames);
3175 [ # # ]: 0 : if (result > 0)
3176 : : result = frames_to_bytes(runtime, result);
3177 : 0 : kfree(bufs);
3178 : 0 : return result;
3179 : : }
3180 : :
3181 : 0 : static __poll_t snd_pcm_poll(struct file *file, poll_table *wait)
3182 : : {
3183 : : struct snd_pcm_file *pcm_file;
3184 : : struct snd_pcm_substream *substream;
3185 : : struct snd_pcm_runtime *runtime;
3186 : : __poll_t mask, ok;
3187 : : snd_pcm_uframes_t avail;
3188 : :
3189 : 0 : pcm_file = file->private_data;
3190 : :
3191 : 0 : substream = pcm_file->substream;
3192 [ # # ]: 0 : if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
3193 : : ok = EPOLLOUT | EPOLLWRNORM;
3194 : : else
3195 : : ok = EPOLLIN | EPOLLRDNORM;
3196 [ # # # # : 0 : if (PCM_RUNTIME_CHECK(substream))
# # ]
3197 : 0 : return ok | EPOLLERR;
3198 : :
3199 : 0 : runtime = substream->runtime;
3200 : 0 : poll_wait(file, &runtime->sleep, wait);
3201 : :
3202 : : mask = 0;
3203 : 0 : snd_pcm_stream_lock_irq(substream);
3204 : 0 : avail = snd_pcm_avail(substream);
3205 [ # # # ]: 0 : switch (runtime->status->state) {
3206 : : case SNDRV_PCM_STATE_RUNNING:
3207 : : case SNDRV_PCM_STATE_PREPARED:
3208 : : case SNDRV_PCM_STATE_PAUSED:
3209 [ # # ]: 0 : if (avail >= runtime->control->avail_min)
3210 : : mask = ok;
3211 : : break;
3212 : : case SNDRV_PCM_STATE_DRAINING:
3213 [ # # ]: 0 : if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
3214 : : mask = ok;
3215 [ # # ]: 0 : if (!avail)
3216 : 0 : mask |= EPOLLERR;
3217 : : }
3218 : : break;
3219 : : default:
3220 : 0 : mask = ok | EPOLLERR;
3221 : 0 : break;
3222 : : }
3223 : 0 : snd_pcm_stream_unlock_irq(substream);
3224 : 0 : return mask;
3225 : : }
3226 : :
3227 : : /*
3228 : : * mmap support
3229 : : */
3230 : :
3231 : : /*
3232 : : * Only on coherent architectures, we can mmap the status and the control records
3233 : : * for effcient data transfer. On others, we have to use HWSYNC ioctl...
3234 : : */
3235 : : #if defined(CONFIG_X86) || defined(CONFIG_PPC) || defined(CONFIG_ALPHA)
3236 : : /*
3237 : : * mmap status record
3238 : : */
3239 : : static vm_fault_t snd_pcm_mmap_status_fault(struct vm_fault *vmf)
3240 : : {
3241 : : struct snd_pcm_substream *substream = vmf->vma->vm_private_data;
3242 : : struct snd_pcm_runtime *runtime;
3243 : :
3244 : : if (substream == NULL)
3245 : : return VM_FAULT_SIGBUS;
3246 : : runtime = substream->runtime;
3247 : : vmf->page = virt_to_page(runtime->status);
3248 : : get_page(vmf->page);
3249 : : return 0;
3250 : : }
3251 : :
3252 : : static const struct vm_operations_struct snd_pcm_vm_ops_status =
3253 : : {
3254 : : .fault = snd_pcm_mmap_status_fault,
3255 : : };
3256 : :
3257 : : static int snd_pcm_mmap_status(struct snd_pcm_substream *substream, struct file *file,
3258 : : struct vm_area_struct *area)
3259 : : {
3260 : : long size;
3261 : : if (!(area->vm_flags & VM_READ))
3262 : : return -EINVAL;
3263 : : size = area->vm_end - area->vm_start;
3264 : : if (size != PAGE_ALIGN(sizeof(struct snd_pcm_mmap_status)))
3265 : : return -EINVAL;
3266 : : area->vm_ops = &snd_pcm_vm_ops_status;
3267 : : area->vm_private_data = substream;
3268 : : area->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
3269 : : return 0;
3270 : : }
3271 : :
3272 : : /*
3273 : : * mmap control record
3274 : : */
3275 : : static vm_fault_t snd_pcm_mmap_control_fault(struct vm_fault *vmf)
3276 : : {
3277 : : struct snd_pcm_substream *substream = vmf->vma->vm_private_data;
3278 : : struct snd_pcm_runtime *runtime;
3279 : :
3280 : : if (substream == NULL)
3281 : : return VM_FAULT_SIGBUS;
3282 : : runtime = substream->runtime;
3283 : : vmf->page = virt_to_page(runtime->control);
3284 : : get_page(vmf->page);
3285 : : return 0;
3286 : : }
3287 : :
3288 : : static const struct vm_operations_struct snd_pcm_vm_ops_control =
3289 : : {
3290 : : .fault = snd_pcm_mmap_control_fault,
3291 : : };
3292 : :
3293 : : static int snd_pcm_mmap_control(struct snd_pcm_substream *substream, struct file *file,
3294 : : struct vm_area_struct *area)
3295 : : {
3296 : : long size;
3297 : : if (!(area->vm_flags & VM_READ))
3298 : : return -EINVAL;
3299 : : size = area->vm_end - area->vm_start;
3300 : : if (size != PAGE_ALIGN(sizeof(struct snd_pcm_mmap_control)))
3301 : : return -EINVAL;
3302 : : area->vm_ops = &snd_pcm_vm_ops_control;
3303 : : area->vm_private_data = substream;
3304 : : area->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
3305 : : return 0;
3306 : : }
3307 : :
3308 : : static bool pcm_status_mmap_allowed(struct snd_pcm_file *pcm_file)
3309 : : {
3310 : : if (pcm_file->no_compat_mmap)
3311 : : return false;
3312 : : /* See pcm_control_mmap_allowed() below.
3313 : : * Since older alsa-lib requires both status and control mmaps to be
3314 : : * coupled, we have to disable the status mmap for old alsa-lib, too.
3315 : : */
3316 : : if (pcm_file->user_pversion < SNDRV_PROTOCOL_VERSION(2, 0, 14) &&
3317 : : (pcm_file->substream->runtime->hw.info & SNDRV_PCM_INFO_SYNC_APPLPTR))
3318 : : return false;
3319 : : return true;
3320 : : }
3321 : :
3322 : : static bool pcm_control_mmap_allowed(struct snd_pcm_file *pcm_file)
3323 : : {
3324 : : if (pcm_file->no_compat_mmap)
3325 : : return false;
3326 : : /* Disallow the control mmap when SYNC_APPLPTR flag is set;
3327 : : * it enforces the user-space to fall back to snd_pcm_sync_ptr(),
3328 : : * thus it effectively assures the manual update of appl_ptr.
3329 : : */
3330 : : if (pcm_file->substream->runtime->hw.info & SNDRV_PCM_INFO_SYNC_APPLPTR)
3331 : : return false;
3332 : : return true;
3333 : : }
3334 : :
3335 : : #else /* ! coherent mmap */
3336 : : /*
3337 : : * don't support mmap for status and control records.
3338 : : */
3339 : : #define pcm_status_mmap_allowed(pcm_file) false
3340 : : #define pcm_control_mmap_allowed(pcm_file) false
3341 : :
3342 : : static int snd_pcm_mmap_status(struct snd_pcm_substream *substream, struct file *file,
3343 : : struct vm_area_struct *area)
3344 : : {
3345 : : return -ENXIO;
3346 : : }
3347 : : static int snd_pcm_mmap_control(struct snd_pcm_substream *substream, struct file *file,
3348 : : struct vm_area_struct *area)
3349 : : {
3350 : : return -ENXIO;
3351 : : }
3352 : : #endif /* coherent mmap */
3353 : :
3354 : : static inline struct page *
3355 : : snd_pcm_default_page_ops(struct snd_pcm_substream *substream, unsigned long ofs)
3356 : : {
3357 : 0 : void *vaddr = substream->runtime->dma_area + ofs;
3358 : 0 : return virt_to_page(vaddr);
3359 : : }
3360 : :
3361 : : /*
3362 : : * fault callback for mmapping a RAM page
3363 : : */
3364 : 0 : static vm_fault_t snd_pcm_mmap_data_fault(struct vm_fault *vmf)
3365 : : {
3366 : 0 : struct snd_pcm_substream *substream = vmf->vma->vm_private_data;
3367 : : struct snd_pcm_runtime *runtime;
3368 : : unsigned long offset;
3369 : : struct page * page;
3370 : : size_t dma_bytes;
3371 : :
3372 [ # # ]: 0 : if (substream == NULL)
3373 : : return VM_FAULT_SIGBUS;
3374 : 0 : runtime = substream->runtime;
3375 : 0 : offset = vmf->pgoff << PAGE_SHIFT;
3376 : 0 : dma_bytes = PAGE_ALIGN(runtime->dma_bytes);
3377 [ # # ]: 0 : if (offset > dma_bytes - PAGE_SIZE)
3378 : : return VM_FAULT_SIGBUS;
3379 [ # # ]: 0 : if (substream->ops->page)
3380 : 0 : page = substream->ops->page(substream, offset);
3381 : : else
3382 : : page = snd_pcm_default_page_ops(substream, offset);
3383 [ # # ]: 0 : if (!page)
3384 : : return VM_FAULT_SIGBUS;
3385 : 0 : get_page(page);
3386 : 0 : vmf->page = page;
3387 : 0 : return 0;
3388 : : }
3389 : :
3390 : : static const struct vm_operations_struct snd_pcm_vm_ops_data = {
3391 : : .open = snd_pcm_mmap_data_open,
3392 : : .close = snd_pcm_mmap_data_close,
3393 : : };
3394 : :
3395 : : static const struct vm_operations_struct snd_pcm_vm_ops_data_fault = {
3396 : : .open = snd_pcm_mmap_data_open,
3397 : : .close = snd_pcm_mmap_data_close,
3398 : : .fault = snd_pcm_mmap_data_fault,
3399 : : };
3400 : :
3401 : : /*
3402 : : * mmap the DMA buffer on RAM
3403 : : */
3404 : :
3405 : : /**
3406 : : * snd_pcm_lib_default_mmap - Default PCM data mmap function
3407 : : * @substream: PCM substream
3408 : : * @area: VMA
3409 : : *
3410 : : * This is the default mmap handler for PCM data. When mmap pcm_ops is NULL,
3411 : : * this function is invoked implicitly.
3412 : : */
3413 : 0 : int snd_pcm_lib_default_mmap(struct snd_pcm_substream *substream,
3414 : : struct vm_area_struct *area)
3415 : : {
3416 : 0 : area->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
3417 : : #ifdef CONFIG_GENERIC_ALLOCATOR
3418 [ # # ]: 0 : if (substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_DEV_IRAM) {
3419 : 0 : area->vm_page_prot = pgprot_writecombine(area->vm_page_prot);
3420 : 0 : return remap_pfn_range(area, area->vm_start,
3421 : 0 : substream->dma_buffer.addr >> PAGE_SHIFT,
3422 : 0 : area->vm_end - area->vm_start, area->vm_page_prot);
3423 : : }
3424 : : #endif /* CONFIG_GENERIC_ALLOCATOR */
3425 : : #ifndef CONFIG_X86 /* for avoiding warnings arch/x86/mm/pat.c */
3426 [ # # # # ]: 0 : if (IS_ENABLED(CONFIG_HAS_DMA) && !substream->ops->page &&
3427 : 0 : (substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_DEV ||
3428 : : substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_DEV_UC))
3429 : 0 : return dma_mmap_coherent(substream->dma_buffer.dev.dev,
3430 : : area,
3431 : : substream->runtime->dma_area,
3432 : : substream->runtime->dma_addr,
3433 : : substream->runtime->dma_bytes);
3434 : : #endif /* CONFIG_X86 */
3435 : : /* mmap with fault handler */
3436 : 0 : area->vm_ops = &snd_pcm_vm_ops_data_fault;
3437 : 0 : return 0;
3438 : : }
3439 : : EXPORT_SYMBOL_GPL(snd_pcm_lib_default_mmap);
3440 : :
3441 : : /*
3442 : : * mmap the DMA buffer on I/O memory area
3443 : : */
3444 : : #if SNDRV_PCM_INFO_MMAP_IOMEM
3445 : : /**
3446 : : * snd_pcm_lib_mmap_iomem - Default PCM data mmap function for I/O mem
3447 : : * @substream: PCM substream
3448 : : * @area: VMA
3449 : : *
3450 : : * When your hardware uses the iomapped pages as the hardware buffer and
3451 : : * wants to mmap it, pass this function as mmap pcm_ops. Note that this
3452 : : * is supposed to work only on limited architectures.
3453 : : */
3454 : : int snd_pcm_lib_mmap_iomem(struct snd_pcm_substream *substream,
3455 : : struct vm_area_struct *area)
3456 : : {
3457 : : struct snd_pcm_runtime *runtime = substream->runtime;
3458 : :
3459 : : area->vm_page_prot = pgprot_noncached(area->vm_page_prot);
3460 : : return vm_iomap_memory(area, runtime->dma_addr, runtime->dma_bytes);
3461 : : }
3462 : : EXPORT_SYMBOL(snd_pcm_lib_mmap_iomem);
3463 : : #endif /* SNDRV_PCM_INFO_MMAP */
3464 : :
3465 : : /*
3466 : : * mmap DMA buffer
3467 : : */
3468 : 0 : int snd_pcm_mmap_data(struct snd_pcm_substream *substream, struct file *file,
3469 : : struct vm_area_struct *area)
3470 : : {
3471 : : struct snd_pcm_runtime *runtime;
3472 : : long size;
3473 : : unsigned long offset;
3474 : : size_t dma_bytes;
3475 : : int err;
3476 : :
3477 [ # # ]: 0 : if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
3478 [ # # ]: 0 : if (!(area->vm_flags & (VM_WRITE|VM_READ)))
3479 : : return -EINVAL;
3480 : : } else {
3481 [ # # ]: 0 : if (!(area->vm_flags & VM_READ))
3482 : : return -EINVAL;
3483 : : }
3484 : 0 : runtime = substream->runtime;
3485 [ # # ]: 0 : if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
3486 : : return -EBADFD;
3487 [ # # ]: 0 : if (!(runtime->info & SNDRV_PCM_INFO_MMAP))
3488 : : return -ENXIO;
3489 [ # # ]: 0 : if (runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED ||
3490 : : runtime->access == SNDRV_PCM_ACCESS_RW_NONINTERLEAVED)
3491 : : return -EINVAL;
3492 : 0 : size = area->vm_end - area->vm_start;
3493 : 0 : offset = area->vm_pgoff << PAGE_SHIFT;
3494 : 0 : dma_bytes = PAGE_ALIGN(runtime->dma_bytes);
3495 [ # # ]: 0 : if ((size_t)size > dma_bytes)
3496 : : return -EINVAL;
3497 [ # # ]: 0 : if (offset > dma_bytes - size)
3498 : : return -EINVAL;
3499 : :
3500 : 0 : area->vm_ops = &snd_pcm_vm_ops_data;
3501 : 0 : area->vm_private_data = substream;
3502 [ # # ]: 0 : if (substream->ops->mmap)
3503 : 0 : err = substream->ops->mmap(substream, area);
3504 : : else
3505 : 0 : err = snd_pcm_lib_default_mmap(substream, area);
3506 [ # # ]: 0 : if (!err)
3507 : 0 : atomic_inc(&substream->mmap_count);
3508 : 0 : return err;
3509 : : }
3510 : : EXPORT_SYMBOL(snd_pcm_mmap_data);
3511 : :
3512 : 0 : static int snd_pcm_mmap(struct file *file, struct vm_area_struct *area)
3513 : : {
3514 : : struct snd_pcm_file * pcm_file;
3515 : : struct snd_pcm_substream *substream;
3516 : : unsigned long offset;
3517 : :
3518 : 0 : pcm_file = file->private_data;
3519 : 0 : substream = pcm_file->substream;
3520 [ # # # # : 0 : if (PCM_RUNTIME_CHECK(substream))
# # ]
3521 : : return -ENXIO;
3522 : :
3523 : 0 : offset = area->vm_pgoff << PAGE_SHIFT;
3524 [ # # ]: 0 : switch (offset) {
3525 : : case SNDRV_PCM_MMAP_OFFSET_STATUS:
3526 : : if (!pcm_status_mmap_allowed(pcm_file))
3527 : : return -ENXIO;
3528 : : return snd_pcm_mmap_status(substream, file, area);
3529 : : case SNDRV_PCM_MMAP_OFFSET_CONTROL:
3530 : : if (!pcm_control_mmap_allowed(pcm_file))
3531 : : return -ENXIO;
3532 : : return snd_pcm_mmap_control(substream, file, area);
3533 : : default:
3534 : 0 : return snd_pcm_mmap_data(substream, file, area);
3535 : : }
3536 : : return 0;
3537 : : }
3538 : :
3539 : 0 : static int snd_pcm_fasync(int fd, struct file * file, int on)
3540 : : {
3541 : : struct snd_pcm_file * pcm_file;
3542 : : struct snd_pcm_substream *substream;
3543 : : struct snd_pcm_runtime *runtime;
3544 : :
3545 : 0 : pcm_file = file->private_data;
3546 : 0 : substream = pcm_file->substream;
3547 [ # # # # : 0 : if (PCM_RUNTIME_CHECK(substream))
# # ]
3548 : : return -ENXIO;
3549 : 0 : runtime = substream->runtime;
3550 : 0 : return fasync_helper(fd, file, on, &runtime->fasync);
3551 : : }
3552 : :
3553 : : /*
3554 : : * ioctl32 compat
3555 : : */
3556 : : #ifdef CONFIG_COMPAT
3557 : : #include "pcm_compat.c"
3558 : : #else
3559 : : #define snd_pcm_ioctl_compat NULL
3560 : : #endif
3561 : :
3562 : : /*
3563 : : * To be removed helpers to keep binary compatibility
3564 : : */
3565 : :
3566 : : #ifdef CONFIG_SND_SUPPORT_OLD_API
3567 : : #define __OLD_TO_NEW_MASK(x) ((x&7)|((x&0x07fffff8)<<5))
3568 : : #define __NEW_TO_OLD_MASK(x) ((x&7)|((x&0xffffff00)>>5))
3569 : :
3570 : 0 : static void snd_pcm_hw_convert_from_old_params(struct snd_pcm_hw_params *params,
3571 : : struct snd_pcm_hw_params_old *oparams)
3572 : : {
3573 : : unsigned int i;
3574 : :
3575 : 0 : memset(params, 0, sizeof(*params));
3576 : 0 : params->flags = oparams->flags;
3577 [ # # ]: 0 : for (i = 0; i < ARRAY_SIZE(oparams->masks); i++)
3578 : 0 : params->masks[i].bits[0] = oparams->masks[i];
3579 : 0 : memcpy(params->intervals, oparams->intervals, sizeof(oparams->intervals));
3580 : 0 : params->rmask = __OLD_TO_NEW_MASK(oparams->rmask);
3581 : 0 : params->cmask = __OLD_TO_NEW_MASK(oparams->cmask);
3582 : 0 : params->info = oparams->info;
3583 : 0 : params->msbits = oparams->msbits;
3584 : 0 : params->rate_num = oparams->rate_num;
3585 : 0 : params->rate_den = oparams->rate_den;
3586 : 0 : params->fifo_size = oparams->fifo_size;
3587 : 0 : }
3588 : :
3589 : 0 : static void snd_pcm_hw_convert_to_old_params(struct snd_pcm_hw_params_old *oparams,
3590 : : struct snd_pcm_hw_params *params)
3591 : : {
3592 : : unsigned int i;
3593 : :
3594 : 0 : memset(oparams, 0, sizeof(*oparams));
3595 : 0 : oparams->flags = params->flags;
3596 [ # # ]: 0 : for (i = 0; i < ARRAY_SIZE(oparams->masks); i++)
3597 : 0 : oparams->masks[i] = params->masks[i].bits[0];
3598 : 0 : memcpy(oparams->intervals, params->intervals, sizeof(oparams->intervals));
3599 : 0 : oparams->rmask = __NEW_TO_OLD_MASK(params->rmask);
3600 : 0 : oparams->cmask = __NEW_TO_OLD_MASK(params->cmask);
3601 : 0 : oparams->info = params->info;
3602 : 0 : oparams->msbits = params->msbits;
3603 : 0 : oparams->rate_num = params->rate_num;
3604 : 0 : oparams->rate_den = params->rate_den;
3605 : 0 : oparams->fifo_size = params->fifo_size;
3606 : 0 : }
3607 : :
3608 : 0 : static int snd_pcm_hw_refine_old_user(struct snd_pcm_substream *substream,
3609 : : struct snd_pcm_hw_params_old __user * _oparams)
3610 : : {
3611 : : struct snd_pcm_hw_params *params;
3612 : : struct snd_pcm_hw_params_old *oparams = NULL;
3613 : : int err;
3614 : :
3615 : : params = kmalloc(sizeof(*params), GFP_KERNEL);
3616 [ # # ]: 0 : if (!params)
3617 : : return -ENOMEM;
3618 : :
3619 : 0 : oparams = memdup_user(_oparams, sizeof(*oparams));
3620 [ # # ]: 0 : if (IS_ERR(oparams)) {
3621 : : err = PTR_ERR(oparams);
3622 : 0 : goto out;
3623 : : }
3624 : 0 : snd_pcm_hw_convert_from_old_params(params, oparams);
3625 : 0 : err = snd_pcm_hw_refine(substream, params);
3626 [ # # ]: 0 : if (err < 0)
3627 : : goto out_old;
3628 : :
3629 : 0 : err = fixup_unreferenced_params(substream, params);
3630 [ # # ]: 0 : if (err < 0)
3631 : : goto out_old;
3632 : :
3633 : 0 : snd_pcm_hw_convert_to_old_params(oparams, params);
3634 [ # # ]: 0 : if (copy_to_user(_oparams, oparams, sizeof(*oparams)))
3635 : : err = -EFAULT;
3636 : : out_old:
3637 : 0 : kfree(oparams);
3638 : : out:
3639 : 0 : kfree(params);
3640 : 0 : return err;
3641 : : }
3642 : :
3643 : 0 : static int snd_pcm_hw_params_old_user(struct snd_pcm_substream *substream,
3644 : : struct snd_pcm_hw_params_old __user * _oparams)
3645 : : {
3646 : : struct snd_pcm_hw_params *params;
3647 : : struct snd_pcm_hw_params_old *oparams = NULL;
3648 : : int err;
3649 : :
3650 : : params = kmalloc(sizeof(*params), GFP_KERNEL);
3651 [ # # ]: 0 : if (!params)
3652 : : return -ENOMEM;
3653 : :
3654 : 0 : oparams = memdup_user(_oparams, sizeof(*oparams));
3655 [ # # ]: 0 : if (IS_ERR(oparams)) {
3656 : : err = PTR_ERR(oparams);
3657 : 0 : goto out;
3658 : : }
3659 : :
3660 : 0 : snd_pcm_hw_convert_from_old_params(params, oparams);
3661 : 0 : err = snd_pcm_hw_params(substream, params);
3662 [ # # ]: 0 : if (err < 0)
3663 : : goto out_old;
3664 : :
3665 : 0 : snd_pcm_hw_convert_to_old_params(oparams, params);
3666 [ # # ]: 0 : if (copy_to_user(_oparams, oparams, sizeof(*oparams)))
3667 : : err = -EFAULT;
3668 : : out_old:
3669 : 0 : kfree(oparams);
3670 : : out:
3671 : 0 : kfree(params);
3672 : 0 : return err;
3673 : : }
3674 : : #endif /* CONFIG_SND_SUPPORT_OLD_API */
3675 : :
3676 : : #ifndef CONFIG_MMU
3677 : : static unsigned long snd_pcm_get_unmapped_area(struct file *file,
3678 : : unsigned long addr,
3679 : : unsigned long len,
3680 : : unsigned long pgoff,
3681 : : unsigned long flags)
3682 : : {
3683 : : struct snd_pcm_file *pcm_file = file->private_data;
3684 : : struct snd_pcm_substream *substream = pcm_file->substream;
3685 : : struct snd_pcm_runtime *runtime = substream->runtime;
3686 : : unsigned long offset = pgoff << PAGE_SHIFT;
3687 : :
3688 : : switch (offset) {
3689 : : case SNDRV_PCM_MMAP_OFFSET_STATUS:
3690 : : return (unsigned long)runtime->status;
3691 : : case SNDRV_PCM_MMAP_OFFSET_CONTROL:
3692 : : return (unsigned long)runtime->control;
3693 : : default:
3694 : : return (unsigned long)runtime->dma_area + offset;
3695 : : }
3696 : : }
3697 : : #else
3698 : : # define snd_pcm_get_unmapped_area NULL
3699 : : #endif
3700 : :
3701 : : /*
3702 : : * Register section
3703 : : */
3704 : :
3705 : : const struct file_operations snd_pcm_f_ops[2] = {
3706 : : {
3707 : : .owner = THIS_MODULE,
3708 : : .write = snd_pcm_write,
3709 : : .write_iter = snd_pcm_writev,
3710 : : .open = snd_pcm_playback_open,
3711 : : .release = snd_pcm_release,
3712 : : .llseek = no_llseek,
3713 : : .poll = snd_pcm_poll,
3714 : : .unlocked_ioctl = snd_pcm_ioctl,
3715 : : .compat_ioctl = snd_pcm_ioctl_compat,
3716 : : .mmap = snd_pcm_mmap,
3717 : : .fasync = snd_pcm_fasync,
3718 : : .get_unmapped_area = snd_pcm_get_unmapped_area,
3719 : : },
3720 : : {
3721 : : .owner = THIS_MODULE,
3722 : : .read = snd_pcm_read,
3723 : : .read_iter = snd_pcm_readv,
3724 : : .open = snd_pcm_capture_open,
3725 : : .release = snd_pcm_release,
3726 : : .llseek = no_llseek,
3727 : : .poll = snd_pcm_poll,
3728 : : .unlocked_ioctl = snd_pcm_ioctl,
3729 : : .compat_ioctl = snd_pcm_ioctl_compat,
3730 : : .mmap = snd_pcm_mmap,
3731 : : .fasync = snd_pcm_fasync,
3732 : : .get_unmapped_area = snd_pcm_get_unmapped_area,
3733 : : }
3734 : : };
|