hc
2024-10-22 8ac6c7a54ed1b98d142dce24b11c6de6a1e239a5
kernel/sound/core/pcm_lib.c
....@@ -1,23 +1,8 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * Digital Audio (PCM) abstract layer
34 * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
45 * Abramo Bagnara <abramo@alsa-project.org>
5
- *
6
- *
7
- * This program is free software; you can redistribute it and/or modify
8
- * it under the terms of the GNU General Public License as published by
9
- * the Free Software Foundation; either version 2 of the License, or
10
- * (at your option) any later version.
11
- *
12
- * This program is distributed in the hope that it will be useful,
13
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
- * GNU General Public License for more details.
16
- *
17
- * You should have received a copy of the GNU General Public License
18
- * along with this program; if not, write to the Free Software
19
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
- *
216 */
227
238 #include <linux/slab.h>
....@@ -43,10 +28,8 @@
4328 #define trace_xrun(substream)
4429 #define trace_hw_ptr_error(substream, reason)
4530 #define trace_applptr(substream, prev, curr)
31
+#define trace_applptr_start(substream, frame)
4632 #endif
47
-
48
-#define STRING_LENGTH_OF_INT 12
49
-#define MAX_USR_CTRL_CNT 128
5033
5134 static int fill_silence_frames(struct snd_pcm_substream *substream,
5235 snd_pcm_uframes_t off, snd_pcm_uframes_t frames);
....@@ -162,8 +145,13 @@
162145 struct snd_pcm_runtime *runtime = substream->runtime;
163146
164147 trace_xrun(substream);
165
- if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE)
166
- snd_pcm_gettime(runtime, (struct timespec *)&runtime->status->tstamp);
148
+ if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE) {
149
+ struct timespec64 tstamp;
150
+
151
+ snd_pcm_gettime(runtime, &tstamp);
152
+ runtime->status->tstamp.tv_sec = tstamp.tv_sec;
153
+ runtime->status->tstamp.tv_nsec = tstamp.tv_nsec;
154
+ }
167155 snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
168156 if (xrun_debug(substream, XRUN_DEBUG_BASIC)) {
169157 char name[16];
....@@ -218,12 +206,12 @@
218206 }
219207
220208 static void update_audio_tstamp(struct snd_pcm_substream *substream,
221
- struct timespec *curr_tstamp,
222
- struct timespec *audio_tstamp)
209
+ struct timespec64 *curr_tstamp,
210
+ struct timespec64 *audio_tstamp)
223211 {
224212 struct snd_pcm_runtime *runtime = substream->runtime;
225213 u64 audio_frames, audio_nsecs;
226
- struct timespec driver_tstamp;
214
+ struct timespec64 driver_tstamp;
227215
228216 if (runtime->tstamp_mode != SNDRV_PCM_TSTAMP_ENABLE)
229217 return;
....@@ -247,18 +235,23 @@
247235 }
248236 audio_nsecs = div_u64(audio_frames * 1000000000LL,
249237 runtime->rate);
250
- *audio_tstamp = ns_to_timespec(audio_nsecs);
238
+ *audio_tstamp = ns_to_timespec64(audio_nsecs);
251239 }
252
- if (!timespec_equal(&runtime->status->audio_tstamp, audio_tstamp)) {
253
- runtime->status->audio_tstamp = *audio_tstamp;
254
- runtime->status->tstamp = *curr_tstamp;
240
+
241
+ if (runtime->status->audio_tstamp.tv_sec != audio_tstamp->tv_sec ||
242
+ runtime->status->audio_tstamp.tv_nsec != audio_tstamp->tv_nsec) {
243
+ runtime->status->audio_tstamp.tv_sec = audio_tstamp->tv_sec;
244
+ runtime->status->audio_tstamp.tv_nsec = audio_tstamp->tv_nsec;
245
+ runtime->status->tstamp.tv_sec = curr_tstamp->tv_sec;
246
+ runtime->status->tstamp.tv_nsec = curr_tstamp->tv_nsec;
255247 }
248
+
256249
257250 /*
258251 * re-take a driver timestamp to let apps detect if the reference tstamp
259252 * read by low-level hardware was provided with a delay
260253 */
261
- snd_pcm_gettime(substream->runtime, (struct timespec *)&driver_tstamp);
254
+ snd_pcm_gettime(substream->runtime, &driver_tstamp);
262255 runtime->driver_tstamp = driver_tstamp;
263256 }
264257
....@@ -271,8 +264,8 @@
271264 snd_pcm_sframes_t hdelta, delta;
272265 unsigned long jdelta;
273266 unsigned long curr_jiffies;
274
- struct timespec curr_tstamp;
275
- struct timespec audio_tstamp;
267
+ struct timespec64 curr_tstamp;
268
+ struct timespec64 audio_tstamp;
276269 int crossed_boundary = 0;
277270
278271 old_hw_ptr = runtime->status->hw_ptr;
....@@ -295,9 +288,9 @@
295288
296289 /* re-test in case tstamp type is not supported in hardware and was demoted to DEFAULT */
297290 if (runtime->audio_tstamp_report.actual_type == SNDRV_PCM_AUDIO_TSTAMP_TYPE_DEFAULT)
298
- snd_pcm_gettime(runtime, (struct timespec *)&curr_tstamp);
291
+ snd_pcm_gettime(runtime, &curr_tstamp);
299292 } else
300
- snd_pcm_gettime(runtime, (struct timespec *)&curr_tstamp);
293
+ snd_pcm_gettime(runtime, &curr_tstamp);
301294 }
302295
303296 if (pos == SNDRV_PCM_POS_XRUN) {
....@@ -498,7 +491,7 @@
498491 EXPORT_SYMBOL(snd_pcm_set_ops);
499492
500493 /**
501
- * snd_pcm_sync - set the PCM sync id
494
+ * snd_pcm_set_sync - set the PCM sync id
502495 * @substream: the pcm substream
503496 *
504497 * Sets the PCM sync identifier for the card.
....@@ -1461,7 +1454,7 @@
14611454
14621455 static int snd_pcm_hw_rule_pow2(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule)
14631456 {
1464
- static unsigned int pow2_sizes[] = {
1457
+ static const unsigned int pow2_sizes[] = {
14651458 1<<0, 1<<1, 1<<2, 1<<3, 1<<4, 1<<5, 1<<6, 1<<7,
14661459 1<<8, 1<<9, 1<<10, 1<<11, 1<<12, 1<<13, 1<<14, 1<<15,
14671460 1<<16, 1<<17, 1<<18, 1<<19, 1<<20, 1<<21, 1<<22, 1<<23,
....@@ -2139,6 +2132,8 @@
21392132 if (err < 0)
21402133 return err;
21412134
2135
+ trace_applptr_start(substream, size);
2136
+
21422137 is_playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
21432138 if (interleaved) {
21442139 if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED &&
....@@ -2180,6 +2175,14 @@
21802175 if (err < 0)
21812176 goto _end_unlock;
21822177
2178
+ runtime->twake = runtime->control->avail_min ? : 1;
2179
+ if (runtime->status->state == SNDRV_PCM_STATE_RUNNING)
2180
+ snd_pcm_update_hw_ptr(substream);
2181
+
2182
+ /*
2183
+ * If size < start_threshold, wait indefinitely. Another
2184
+ * thread may start capture
2185
+ */
21832186 if (!is_playback &&
21842187 runtime->status->state == SNDRV_PCM_STATE_PREPARED &&
21852188 size >= runtime->start_threshold) {
....@@ -2188,10 +2191,8 @@
21882191 goto _end_unlock;
21892192 }
21902193
2191
- runtime->twake = runtime->control->avail_min ? : 1;
2192
- if (runtime->status->state == SNDRV_PCM_STATE_RUNNING)
2193
- snd_pcm_update_hw_ptr(substream);
21942194 avail = snd_pcm_avail(substream);
2195
+
21952196 while (size > 0) {
21962197 snd_pcm_uframes_t frames, appl_ptr, appl_ofs;
21972198 snd_pcm_uframes_t cont;
....@@ -2220,14 +2221,18 @@
22202221 if (frames > cont)
22212222 frames = cont;
22222223 if (snd_BUG_ON(!frames)) {
2223
- runtime->twake = 0;
2224
- snd_pcm_stream_unlock_irq(substream);
2225
- return -EINVAL;
2224
+ err = -EINVAL;
2225
+ goto _end_unlock;
2226
+ }
2227
+ if (!atomic_inc_unless_negative(&runtime->buffer_accessing)) {
2228
+ err = -EBUSY;
2229
+ goto _end_unlock;
22262230 }
22272231 snd_pcm_stream_unlock_irq(substream);
22282232 err = writer(substream, appl_ofs, data, offset, frames,
22292233 transfer);
22302234 snd_pcm_stream_lock_irq(substream);
2235
+ atomic_dec(&runtime->buffer_accessing);
22312236 if (err < 0)
22322237 goto _end_unlock;
22332238 err = pcm_accessible_state(runtime);
....@@ -2322,7 +2327,6 @@
23222327 struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
23232328
23242329 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
2325
- uinfo->count = 0;
23262330 uinfo->count = info->max_channels;
23272331 uinfo->value.integer.min = 0;
23282332 uinfo->value.integer.max = SNDRV_CHMAP_LAST;
....@@ -2346,7 +2350,7 @@
23462350 if (!substream)
23472351 return -ENODEV;
23482352 memset(ucontrol->value.integer.value, 0,
2349
- sizeof(ucontrol->value.integer.value));
2353
+ sizeof(long) * info->max_channels);
23502354 if (!substream->runtime)
23512355 return 0; /* no channels set */
23522356 for (map = info->chmap; map->channels; map++) {
....@@ -2414,24 +2418,6 @@
24142418 kfree(info);
24152419 }
24162420
2417
-static int pcm_volume_ctl_info(struct snd_kcontrol *kcontrol,
2418
- struct snd_ctl_elem_info *uinfo)
2419
-{
2420
- uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
2421
- uinfo->count = 1;
2422
- uinfo->value.integer.min = 0;
2423
- uinfo->value.integer.max = 0x2000;
2424
- return 0;
2425
-}
2426
-
2427
-static void pcm_volume_ctl_private_free(struct snd_kcontrol *kcontrol)
2428
-{
2429
- struct snd_pcm_volume *info = snd_kcontrol_chip(kcontrol);
2430
-
2431
- info->pcm->streams[info->stream].vol_kctl = NULL;
2432
- kfree(info);
2433
-}
2434
-
24352421 /**
24362422 * snd_pcm_add_chmap_ctls - create channel-mapping control elements
24372423 * @pcm: the assigned PCM instance
....@@ -2493,166 +2479,3 @@
24932479 return 0;
24942480 }
24952481 EXPORT_SYMBOL_GPL(snd_pcm_add_chmap_ctls);
2496
-
2497
-/**
2498
- * snd_pcm_add_volume_ctls - create volume control elements
2499
- * @pcm: the assigned PCM instance
2500
- * @stream: stream direction
2501
- * @max_length: the max length of the volume parameter of stream
2502
- * @private_value: the value passed to each kcontrol's private_value field
2503
- * @info_ret: store struct snd_pcm_volume instance if non-NULL
2504
- *
2505
- * Create volume control elements assigned to the given PCM stream(s).
2506
- * Returns zero if succeed, or a negative error value.
2507
- */
2508
-int snd_pcm_add_volume_ctls(struct snd_pcm *pcm, int stream,
2509
- const struct snd_pcm_volume_elem *volume,
2510
- int max_length,
2511
- unsigned long private_value,
2512
- struct snd_pcm_volume **info_ret)
2513
-{
2514
- struct snd_pcm_volume *info;
2515
- struct snd_kcontrol_new knew = {
2516
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2517
- .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |
2518
- SNDRV_CTL_ELEM_ACCESS_READWRITE,
2519
- .info = pcm_volume_ctl_info,
2520
- };
2521
- int err;
2522
- int size;
2523
-
2524
- info = kzalloc(sizeof(*info), GFP_KERNEL);
2525
- if (!info)
2526
- return -ENOMEM;
2527
- info->pcm = pcm;
2528
- info->stream = stream;
2529
- info->volume = volume;
2530
- info->max_length = max_length;
2531
- size = sizeof("Playback ") + sizeof(" Volume") +
2532
- STRING_LENGTH_OF_INT*sizeof(char) + 1;
2533
- knew.name = kzalloc(size, GFP_KERNEL);
2534
- if (!knew.name) {
2535
- kfree(info);
2536
- return -ENOMEM;
2537
- }
2538
- if (stream == SNDRV_PCM_STREAM_PLAYBACK)
2539
- snprintf((char *)knew.name, size, "%s %d %s",
2540
- "Playback", pcm->device, "Volume");
2541
- else
2542
- snprintf((char *)knew.name, size, "%s %d %s",
2543
- "Capture", pcm->device, "Volume");
2544
- knew.device = pcm->device;
2545
- knew.count = pcm->streams[stream].substream_count;
2546
- knew.private_value = private_value;
2547
- info->kctl = snd_ctl_new1(&knew, info);
2548
- if (!info->kctl) {
2549
- kfree(info);
2550
- kfree(knew.name);
2551
- return -ENOMEM;
2552
- }
2553
- info->kctl->private_free = pcm_volume_ctl_private_free;
2554
- err = snd_ctl_add(pcm->card, info->kctl);
2555
- if (err < 0) {
2556
- kfree(info);
2557
- kfree(knew.name);
2558
- return -ENOMEM;
2559
- }
2560
- pcm->streams[stream].vol_kctl = info->kctl;
2561
- if (info_ret)
2562
- *info_ret = info;
2563
- kfree(knew.name);
2564
- return 0;
2565
-}
2566
-EXPORT_SYMBOL(snd_pcm_add_volume_ctls);
2567
-
2568
-static int pcm_usr_ctl_info(struct snd_kcontrol *kcontrol,
2569
- struct snd_ctl_elem_info *uinfo)
2570
-{
2571
- uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
2572
- uinfo->count = MAX_USR_CTRL_CNT;
2573
- uinfo->value.integer.min = 0;
2574
- uinfo->value.integer.max = INT_MAX;
2575
- return 0;
2576
-}
2577
-
2578
-static void pcm_usr_ctl_private_free(struct snd_kcontrol *kcontrol)
2579
-{
2580
- struct snd_pcm_usr *info = snd_kcontrol_chip(kcontrol);
2581
-
2582
- info->pcm->streams[info->stream].usr_kctl = NULL;
2583
- kfree(info);
2584
-}
2585
-
2586
-/**
2587
- * snd_pcm_add_usr_ctls - create user control elements
2588
- * @pcm: the assigned PCM instance
2589
- * @stream: stream direction
2590
- * @max_length: the max length of the user parameter of stream
2591
- * @private_value: the value passed to each kcontrol's private_value field
2592
- * @info_ret: store struct snd_pcm_usr instance if non-NULL
2593
- *
2594
- * Create usr control elements assigned to the given PCM stream(s).
2595
- * Returns zero if succeed, or a negative error value.
2596
- */
2597
-int snd_pcm_add_usr_ctls(struct snd_pcm *pcm, int stream,
2598
- const struct snd_pcm_usr_elem *usr,
2599
- int max_length, int max_kctrl_str_len,
2600
- unsigned long private_value,
2601
- struct snd_pcm_usr **info_ret)
2602
-{
2603
- struct snd_pcm_usr *info;
2604
- struct snd_kcontrol_new knew = {
2605
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2606
- .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
2607
- .info = pcm_usr_ctl_info,
2608
- };
2609
- int err;
2610
- char *buf;
2611
-
2612
- info = kzalloc(sizeof(*info), GFP_KERNEL);
2613
- if (!info)
2614
- return -ENOMEM;
2615
-
2616
- info->pcm = pcm;
2617
- info->stream = stream;
2618
- info->usr = usr;
2619
- info->max_length = max_length;
2620
- buf = kzalloc(max_kctrl_str_len, GFP_KERNEL);
2621
- if (!buf) {
2622
- pr_err("%s: buffer allocation failed\n", __func__);
2623
- kfree(info);
2624
- return -ENOMEM;
2625
- }
2626
- knew.name = buf;
2627
- if (stream == SNDRV_PCM_STREAM_PLAYBACK)
2628
- snprintf(buf, max_kctrl_str_len, "%s %d %s",
2629
- "Playback", pcm->device, "User kcontrol");
2630
- else
2631
- snprintf(buf, max_kctrl_str_len, "%s %d %s",
2632
- "Capture", pcm->device, "User kcontrol");
2633
- knew.device = pcm->device;
2634
- knew.count = pcm->streams[stream].substream_count;
2635
- knew.private_value = private_value;
2636
- info->kctl = snd_ctl_new1(&knew, info);
2637
- if (!info->kctl) {
2638
- kfree(info);
2639
- kfree(knew.name);
2640
- pr_err("%s: snd_ctl_new failed\n", __func__);
2641
- return -ENOMEM;
2642
- }
2643
- info->kctl->private_free = pcm_usr_ctl_private_free;
2644
- err = snd_ctl_add(pcm->card, info->kctl);
2645
- if (err < 0) {
2646
- kfree(info);
2647
- kfree(knew.name);
2648
- pr_err("%s: snd_ctl_add failed:%d\n", __func__,
2649
- err);
2650
- return -ENOMEM;
2651
- }
2652
- pcm->streams[stream].usr_kctl = info->kctl;
2653
- if (info_ret)
2654
- *info_ret = info;
2655
- kfree(knew.name);
2656
- return 0;
2657
-}
2658
-EXPORT_SYMBOL(snd_pcm_add_usr_ctls);