Release 4.11 sound/core/pcm.c
/*
* Digital Audio (PCM) abstract layer
* Copyright (c) by Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/time.h>
#include <linux/mutex.h>
#include <linux/device.h>
#include <sound/core.h>
#include <sound/minors.h>
#include <sound/pcm.h>
#include <sound/control.h>
#include <sound/info.h>
MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>, Abramo Bagnara <abramo@alsa-project.org>");
MODULE_DESCRIPTION("Midlevel PCM code for ALSA.");
MODULE_LICENSE("GPL");
static LIST_HEAD(snd_pcm_devices);
static LIST_HEAD(snd_pcm_notify_list);
static DEFINE_MUTEX(register_mutex);
static int snd_pcm_free(struct snd_pcm *pcm);
static int snd_pcm_dev_free(struct snd_device *device);
static int snd_pcm_dev_register(struct snd_device *device);
static int snd_pcm_dev_disconnect(struct snd_device *device);
static struct snd_pcm *snd_pcm_get(struct snd_card *card, int device)
{
struct snd_pcm *pcm;
list_for_each_entry(pcm, &snd_pcm_devices, list) {
if (pcm->card == card && pcm->device == device)
return pcm;
}
return NULL;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Clemens Ladisch | 46 | 90.20% | 1 | 33.33% |
Johannes Berg | 4 | 7.84% | 1 | 33.33% |
Pawel Moll | 1 | 1.96% | 1 | 33.33% |
Total | 51 | 100.00% | 3 | 100.00% |
static int snd_pcm_next(struct snd_card *card, int device)
{
struct snd_pcm *pcm;
list_for_each_entry(pcm, &snd_pcm_devices, list) {
if (pcm->card == card && pcm->device > device)
return pcm->device;
else if (pcm->card->number > card->number)
return -1;
}
return -1;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Pawel Moll | 69 | 100.00% | 1 | 100.00% |
Total | 69 | 100.00% | 1 | 100.00% |
static int snd_pcm_add(struct snd_pcm *newpcm)
{
struct snd_pcm *pcm;
if (newpcm->internal)
return 0;
list_for_each_entry(pcm, &snd_pcm_devices, list) {
if (pcm->card == newpcm->card && pcm->device == newpcm->device)
return -EBUSY;
if (pcm->card->number > newpcm->card->number ||
(pcm->card == newpcm->card &&
pcm->device > newpcm->device)) {
list_add(&newpcm->list, pcm->list.prev);
return 0;
}
}
list_add_tail(&newpcm->list, &snd_pcm_devices);
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Pawel Moll | 113 | 92.62% | 1 | 50.00% |
Takashi Iwai | 9 | 7.38% | 1 | 50.00% |
Total | 122 | 100.00% | 2 | 100.00% |
static int snd_pcm_control_ioctl(struct snd_card *card,
struct snd_ctl_file *control,
unsigned int cmd, unsigned long arg)
{
switch (cmd) {
case SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE:
{
int device;
if (get_user(device, (int __user *)arg))
return -EFAULT;
mutex_lock(®ister_mutex);
device = snd_pcm_next(card, device);
mutex_unlock(®ister_mutex);
if (put_user(device, (int __user *)arg))
return -EFAULT;
return 0;
}
case SNDRV_CTL_IOCTL_PCM_INFO:
{
struct snd_pcm_info __user *info;
unsigned int device, subdevice;
int stream;
struct snd_pcm *pcm;
struct snd_pcm_str *pstr;
struct snd_pcm_substream *substream;
int err;
info = (struct snd_pcm_info __user *)arg;
if (get_user(device, &info->device))
return -EFAULT;
if (get_user(stream, &info->stream))
return -EFAULT;
if (stream < 0 || stream > 1)
return -EINVAL;
if (get_user(subdevice, &info->subdevice))
return -EFAULT;
mutex_lock(®ister_mutex);
pcm = snd_pcm_get(card, device);
if (pcm == NULL) {
err = -ENXIO;
goto _error;
}
pstr = &pcm->streams[stream];
if (pstr->substream_count == 0) {
err = -ENOENT;
goto _error;
}
if (subdevice >= pstr->substream_count) {
err = -ENXIO;
goto _error;
}
for (substream = pstr->substream; substream;
substream = substream->next)
if (substream->number == (int)subdevice)
break;
if (substream == NULL) {
err = -ENXIO;
goto _error;
}
err = snd_pcm_info_user(substream, info);
_error:
mutex_unlock(®ister_mutex);
return err;
}
case SNDRV_CTL_IOCTL_PCM_PREFER_SUBDEVICE:
{
int val;
if (get_user(val, (int __user *)arg))
return -EFAULT;
control->preferred_subdevice[SND_CTL_SUBDEV_PCM] = val;
return 0;
}
}
return -ENOIOCTLCMD;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Jaroslav Kysela | 256 | 65.47% | 2 | 25.00% |
Clemens Ladisch | 98 | 25.06% | 1 | 12.50% |
Takashi Iwai | 19 | 4.86% | 2 | 25.00% |
Al Viro | 12 | 3.07% | 1 | 12.50% |
Ingo Molnar | 4 | 1.02% | 1 | 12.50% |
Pawel Moll | 2 | 0.51% | 1 | 12.50% |
Total | 391 | 100.00% | 8 | 100.00% |
#define FORMAT(v) [SNDRV_PCM_FORMAT_##v] = #v
static char *snd_pcm_format_names[] = {
FORMAT(S8),
FORMAT(U8),
FORMAT(S16_LE),
FORMAT(S16_BE),
FORMAT(U16_LE),
FORMAT(U16_BE),
FORMAT(S24_LE),
FORMAT(S24_BE),
FORMAT(U24_LE),
FORMAT(U24_BE),
FORMAT(S32_LE),
FORMAT(S32_BE),
FORMAT(U32_LE),
FORMAT(U32_BE),
FORMAT(FLOAT_LE),
FORMAT(FLOAT_BE),
FORMAT(FLOAT64_LE),
FORMAT(FLOAT64_BE),
FORMAT(IEC958_SUBFRAME_LE),
FORMAT(IEC958_SUBFRAME_BE),
FORMAT(MU_LAW),
FORMAT(A_LAW),
FORMAT(IMA_ADPCM),
FORMAT(MPEG),
FORMAT(GSM),
FORMAT(SPECIAL),
FORMAT(S24_3LE),
FORMAT(S24_3BE),
FORMAT(U24_3LE),
FORMAT(U24_3BE),
FORMAT(S20_3LE),
FORMAT(S20_3BE),
FORMAT(U20_3LE),
FORMAT(U20_3BE),
FORMAT(S18_3LE),
FORMAT(S18_3BE),
FORMAT(U18_3LE),
FORMAT(U18_3BE),
FORMAT(G723_24),
FORMAT(G723_24_1B),
FORMAT(G723_40),
FORMAT(G723_40_1B),
FORMAT(DSD_U8),
FORMAT(DSD_U16_LE),
FORMAT(DSD_U32_LE),
FORMAT(DSD_U16_BE),
FORMAT(DSD_U32_BE),
};
/**
* snd_pcm_format_name - Return a name string for the given PCM format
* @format: PCM format
*/
const char *snd_pcm_format_name(snd_pcm_format_t format)
{
if ((__force unsigned int)format >= ARRAY_SIZE(snd_pcm_format_names))
return "Unknown";
return snd_pcm_format_names[(__force unsigned int)format];
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Takashi Iwai | 16 | 42.11% | 1 | 33.33% |
Dan Carpenter | 12 | 31.58% | 1 | 33.33% |
Clemens Ladisch | 10 | 26.32% | 1 | 33.33% |
Total | 38 | 100.00% | 3 | 100.00% |
EXPORT_SYMBOL_GPL(snd_pcm_format_name);
#ifdef CONFIG_SND_VERBOSE_PROCFS
#define STATE(v) [SNDRV_PCM_STATE_##v] = #v
#define STREAM(v) [SNDRV_PCM_STREAM_##v] = #v
#define READY(v) [SNDRV_PCM_READY_##v] = #v
#define XRUN(v) [SNDRV_PCM_XRUN_##v] = #v
#define SILENCE(v) [SNDRV_PCM_SILENCE_##v] = #v
#define TSTAMP(v) [SNDRV_PCM_TSTAMP_##v] = #v
#define ACCESS(v) [SNDRV_PCM_ACCESS_##v] = #v
#define START(v) [SNDRV_PCM_START_##v] = #v
#define SUBFORMAT(v) [SNDRV_PCM_SUBFORMAT_##v] = #v
static char *snd_pcm_stream_names[] = {
STREAM(PLAYBACK),
STREAM(CAPTURE),
};
static char *snd_pcm_state_names[] = {
STATE(OPEN),
STATE(SETUP),
STATE(PREPARED),
STATE(RUNNING),
STATE(XRUN),
STATE(DRAINING),
STATE(PAUSED),
STATE(SUSPENDED),
};
static char *snd_pcm_access_names[] = {
ACCESS(MMAP_INTERLEAVED),
ACCESS(MMAP_NONINTERLEAVED),
ACCESS(MMAP_COMPLEX),
ACCESS(RW_INTERLEAVED),
ACCESS(RW_NONINTERLEAVED),
};
static char *snd_pcm_subformat_names[] = {
SUBFORMAT(STD),
};
static char *snd_pcm_tstamp_mode_names[] = {
TSTAMP(NONE),
TSTAMP(ENABLE),
};
static const char *snd_pcm_stream_name(int stream)
{
return snd_pcm_stream_names[stream];
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Jaroslav Kysela | 16 | 94.12% | 2 | 66.67% |
Takashi Iwai | 1 | 5.88% | 1 | 33.33% |
Total | 17 | 100.00% | 3 | 100.00% |
static const char *snd_pcm_access_name(snd_pcm_access_t access)
{
return snd_pcm_access_names[(__force int)access];
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Jaroslav Kysela | 17 | 80.95% | 2 | 66.67% |
Clemens Ladisch | 4 | 19.05% | 1 | 33.33% |
Total | 21 | 100.00% | 3 | 100.00% |
static const char *snd_pcm_subformat_name(snd_pcm_subformat_t subformat)
{
return snd_pcm_subformat_names[(__force int)subformat];
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Jaroslav Kysela | 17 | 80.95% | 2 | 66.67% |
Clemens Ladisch | 4 | 19.05% | 1 | 33.33% |
Total | 21 | 100.00% | 3 | 100.00% |
static const char *snd_pcm_tstamp_mode_name(int mode)
{
return snd_pcm_tstamp_mode_names[mode];
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Jaroslav Kysela | 16 | 94.12% | 2 | 66.67% |
Takashi Iwai | 1 | 5.88% | 1 | 33.33% |
Total | 17 | 100.00% | 3 | 100.00% |
static const char *snd_pcm_state_name(snd_pcm_state_t state)
{
return snd_pcm_state_names[(__force int)state];
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Jaroslav Kysela | 17 | 80.95% | 2 | 66.67% |
Clemens Ladisch | 4 | 19.05% | 1 | 33.33% |
Total | 21 | 100.00% | 3 | 100.00% |
#if IS_ENABLED(CONFIG_SND_PCM_OSS)
#include <linux/soundcard.h>
static const char *snd_pcm_oss_format_name(int format)
{
switch (format) {
case AFMT_MU_LAW:
return "MU_LAW";
case AFMT_A_LAW:
return "A_LAW";
case AFMT_IMA_ADPCM:
return "IMA_ADPCM";
case AFMT_U8:
return "U8";
case AFMT_S16_LE:
return "S16_LE";
case AFMT_S16_BE:
return "S16_BE";
case AFMT_S8:
return "S8";
case AFMT_U16_LE:
return "U16_LE";
case AFMT_U16_BE:
return "U16_BE";
case AFMT_MPEG:
return "MPEG";
default:
return "unknown";
}
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Jaroslav Kysela | 81 | 100.00% | 2 | 100.00% |
Total | 81 | 100.00% | 2 | 100.00% |
#endif
static void snd_pcm_proc_info_read(struct snd_pcm_substream *substream,
struct snd_info_buffer *buffer)
{
struct snd_pcm_info *info;
int err;
if (! substream)
return;
info = kmalloc(sizeof(*info), GFP_KERNEL);
if (!info)
return;
err = snd_pcm_info(substream, info);
if (err < 0) {
snd_iprintf(buffer, "error %d\n", err);
kfree(info);
return;
}
snd_iprintf(buffer, "card: %d\n", info->card);
snd_iprintf(buffer, "device: %d\n", info->device);
snd_iprintf(buffer, "subdevice: %d\n", info->subdevice);
snd_iprintf(buffer, "stream: %s\n", snd_pcm_stream_name(info->stream));
snd_iprintf(buffer, "id: %s\n", info->id);
snd_iprintf(buffer, "name: %s\n", info->name);
snd_iprintf(buffer, "subname: %s\n", info->subname);
snd_iprintf(buffer, "class: %d\n", info->dev_class);
snd_iprintf(buffer, "subclass: %d\n", info->dev_subclass);
snd_iprintf(buffer, "subdevices_count: %d\n", info->subdevices_count);
snd_iprintf(buffer, "subdevices_avail: %d\n", info->subdevices_avail);
kfree(info);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Jaroslav Kysela | 198 | 94.29% | 2 | 50.00% |
Takashi Iwai | 12 | 5.71% | 2 | 50.00% |
Total | 210 | 100.00% | 4 | 100.00% |
static void snd_pcm_stream_proc_info_read(struct snd_info_entry *entry,
struct snd_info_buffer *buffer)
{
snd_pcm_proc_info_read(((struct snd_pcm_str *)entry->private_data)->substream,
buffer);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Jaroslav Kysela | 28 | 82.35% | 1 | 50.00% |
Takashi Iwai | 6 | 17.65% | 1 | 50.00% |
Total | 34 | 100.00% | 2 | 100.00% |
static void snd_pcm_substream_proc_info_read(struct snd_info_entry *entry,
struct snd_info_buffer *buffer)
{
snd_pcm_proc_info_read(entry->private_data, buffer);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Jaroslav Kysela | 21 | 84.00% | 1 | 50.00% |
Takashi Iwai | 4 | 16.00% | 1 | 50.00% |
Total | 25 | 100.00% | 2 | 100.00% |
static void snd_pcm_substream_proc_hw_params_read(struct snd_info_entry *entry,
struct snd_info_buffer *buffer)
{
struct snd_pcm_substream *substream = entry->private_data;
struct snd_pcm_runtime *runtime;
mutex_lock(&substream->pcm->open_mutex);
runtime = substream->runtime;
if (!runtime) {
snd_iprintf(buffer, "closed\n");
goto unlock;
}
if (runtime->status->state == SNDRV_PCM_STATE_OPEN) {
snd_iprintf(buffer, "no setup\n");
goto unlock;
}
snd_iprintf(buffer, "access: %s\n", snd_pcm_access_name(runtime->access));
snd_iprintf(buffer, "format: %s\n", snd_pcm_format_name(runtime->format));
snd_iprintf(buffer, "subformat: %s\n", snd_pcm_subformat_name(runtime->subformat));
snd_iprintf(buffer, "channels: %u\n", runtime->channels);
snd_iprintf(buffer, "rate: %u (%u/%u)\n", runtime->rate, runtime->rate_num, runtime->rate_den);
snd_iprintf(buffer, "period_size: %lu\n", runtime->period_size);
snd_iprintf(buffer, "buffer_size: %lu\n", runtime->buffer_size);
#if IS_ENABLED(CONFIG_SND_PCM_OSS)
if (substream->oss.oss) {
snd_iprintf(buffer, "OSS format: %s\n", snd_pcm_oss_format_name(runtime->oss.format));
snd_iprintf(buffer, "OSS channels: %u\n", runtime->oss.channels);
snd_iprintf(buffer, "OSS rate: %u\n", runtime->oss.rate);
snd_iprintf(buffer, "OSS period bytes: %lu\n", (unsigned long)runtime->oss.period_bytes);
snd_iprintf(buffer, "OSS periods: %u\n", runtime->oss.periods);
snd_iprintf(buffer, "OSS period frames: %lu\n", (unsigned long)runtime->oss.period_frames);
}
#endif
unlock:
mutex_unlock(&substream->pcm->open_mutex);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Jaroslav Kysela | 257 | 86.24% | 3 | 50.00% |
Takashi Iwai | 41 | 13.76% | 3 | 50.00% |
Total | 298 | 100.00% | 6 | 100.00% |
static void snd_pcm_substream_proc_sw_params_read(struct snd_info_entry *entry,
struct snd_info_buffer *buffer)
{
struct snd_pcm_substream *substream = entry->private_data;
struct snd_pcm_runtime *runtime;
mutex_lock(&substream->pcm->open_mutex);
runtime = substream->runtime;
if (!runtime) {
snd_iprintf(buffer, "closed\n");
goto unlock;
}
if (runtime->status->state == SNDRV_PCM_STATE_OPEN) {
snd_iprintf(buffer, "no setup\n");
goto unlock;
}
snd_iprintf(buffer, "tstamp_mode: %s\n", snd_pcm_tstamp_mode_name(runtime->tstamp_mode));
snd_iprintf(buffer, "period_step: %u\n", runtime->period_step);
snd_iprintf(buffer, "avail_min: %lu\n", runtime->control->avail_min);
snd_iprintf(buffer, "start_threshold: %lu\n", runtime->start_threshold);
snd_iprintf(buffer, "stop_threshold: %lu\n", runtime->stop_threshold);
snd_iprintf(buffer, "silence_threshold: %lu\n", runtime->silence_threshold);
snd_iprintf(buffer, "silence_size: %lu\n", runtime->silence_size);
snd_iprintf(buffer, "boundary: %lu\n", runtime->boundary);
unlock:
mutex_unlock(&substream->pcm->open_mutex);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Jaroslav Kysela | 150 | 78.95% | 1 | 33.33% |
Takashi Iwai | 40 | 21.05% | 2 | 66.67% |
Total | 190 | 100.00% | 3 | 100.00% |
static void snd_pcm_substream_proc_status_read(struct snd_info_entry *entry,
struct snd_info_buffer *buffer)
{
struct snd_pcm_substream *substream = entry->private_data;
struct snd_pcm_runtime *runtime;
struct snd_pcm_status status;
int err;
mutex_lock(&substream->pcm->open_mutex);
runtime = substream->runtime;
if (!runtime) {
snd_iprintf(buffer, "closed\n");
goto unlock;
}
memset(&status, 0, sizeof(status));
err = snd_pcm_status(substream, &status);
if (err < 0) {
snd_iprintf(buffer, "error %d\n", err);
goto unlock;
}
snd_iprintf(buffer, "state: %s\n", snd_pcm_state_name(status.state));
snd_iprintf(buffer, "owner_pid : %d\n", pid_vnr(substream->pid));
snd_iprintf(buffer, "trigger_time: %ld.%09ld\n",
status.trigger_tstamp.tv_sec, status.trigger_tstamp.tv_nsec);
snd_iprintf(buffer, "tstamp : %ld.%09ld\n",
status.tstamp.tv_sec, status.tstamp.tv_nsec);
snd_iprintf(buffer, "delay : %ld\n", status.delay);
snd_iprintf(buffer, "avail : %ld\n", status.avail);
snd_iprintf(buffer, "avail_max : %ld\n", status.avail_max);
snd_iprintf(buffer, "-----\n");
snd_iprintf(buffer, "hw_ptr : %ld\n", runtime->status->hw_ptr);
snd_iprintf(buffer, "appl_ptr : %ld\n", runtime->control->appl_ptr);
unlock:
mutex_unlock(&substream->pcm->open_mutex);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Jaroslav Kysela | 199 | 77.43% | 4 | 57.14% |
Takashi Iwai | 44 | 17.12% | 2 | 28.57% |
Clemens Ladisch | 14 | 5.45% | 1 | 14.29% |
Total | 257 | 100.00% | 7 | 100.00% |
#ifdef CONFIG_SND_PCM_XRUN_DEBUG
static void snd_pcm_xrun_injection_write(struct snd_info_entry *entry,
struct snd_info_buffer *buffer)
{
struct snd_pcm_substream *substream = entry->private_data;
struct snd_pcm_runtime *runtime;
snd_pcm_stream_lock_irq(substream);
runtime = substream->runtime;
if (runtime && runtime->status->state == SNDRV_PCM_STATE_RUNNING)
snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
snd_pcm_stream_unlock_irq(substream);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Takashi Iwai | 65 | 100.00% | 1 | 100.00% |
Total | 65 | 100.00% | 1 | 100.00% |
static void snd_pcm_xrun_debug_read(struct snd_info_entry *entry,
struct snd_info_buffer *buffer)
{
struct snd_pcm_str *pstr = entry->private_data;
snd_iprintf(buffer, "%d\n", pstr->xrun_debug);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Jaroslav Kysela | 30 | 83.33% | 1 | 50.00% |
Takashi Iwai | 6 | 16.67% | 1 | 50.00% |
Total | 36 | 100.00% | 2 | 100.00% |
static void snd_pcm_xrun_debug_write(struct snd_info_entry *entry,
struct snd_info_buffer *buffer)
{
struct snd_pcm_str *pstr = entry->private_data;
char line[64];
if (!snd_info_get_line(buffer, line, sizeof(line)))
pstr->xrun_debug = simple_strtoul(line, NULL, 10);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Jaroslav Kysela | 53 | 89.83% | 1 | 50.00% |
Takashi Iwai | 6 | 10.17% | 1 | 50.00% |
Total | 59 | 100.00% | 2 | 100.00% |
#endif
static int snd_pcm_stream_proc_init(struct snd_pcm_str *pstr)
{
struct snd_pcm *pcm = pstr->pcm;
struct snd_info_entry *entry;
char name[16];
sprintf(name, "pcm%i%c", pcm->device,
pstr->stream == SNDRV_PCM_STREAM_PLAYBACK ? 'p' : 'c');
if ((entry = snd_info_create_card_entry(pcm->card, name, pcm->card->proc_root)) == NULL)
return -ENOMEM;
entry->mode = S_IFDIR | S_IRUGO | S_IXUGO;
if (snd_info_register(entry) < 0) {
snd_info_free_entry(entry);
return -ENOMEM;
}
pstr->proc_root = entry;
if ((entry = snd_info_create_card_entry(pcm->card, "info", pstr->proc_root)) != NULL) {
snd_info_set_text_ops(entry, pstr, snd_pcm_stream_proc_info_read);
if (snd_info_register(entry) < 0) {
snd_info_free_entry(entry);
entry = NULL;
}
}
pstr->proc_info_entry = entry;
#ifdef CONFIG_SND_PCM_XRUN_DEBUG
if ((entry = snd_info_create_card_entry(pcm->card, "xrun_debug",
pstr->proc_root)) != NULL) {
entry->c.text.read = snd_pcm_xrun_debug_read;
entry->c.text.write = snd_pcm_xrun_debug_write;
entry->mode |= S_IWUSR;
entry->private_data = pstr;
if (snd_info_register(entry) < 0) {
snd_info_free_entry(entry);
entry = NULL;
}
}
pstr->proc_xrun_debug_entry = entry;
#endif
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Jaroslav Kysela | 250 | 95.42% | 4 | 66.67% |
Takashi Iwai | 12 | 4.58% | 2 | 33.33% |
Total | 262 | 100.00% | 6 | 100.00% |
static int snd_pcm_stream_proc_done(struct snd_pcm_str *pstr)
{
#ifdef CONFIG_SND_PCM_XRUN_DEBUG
snd_info_free_entry(pstr->proc_xrun_debug_entry);
pstr->proc_xrun_debug_entry = NULL;
#endif
snd_info_free_entry(pstr->proc_info_entry);
pstr->proc_info_entry = NULL;
snd_info_free_entry(pstr->proc_root);
pstr->proc_root = NULL;
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Jaroslav Kysela | 53 | 91.38% | 3 | 60.00% |
Takashi Iwai | 5 | 8.62% | 2 | 40.00% |
Total | 58 | 100.00% | 5 | 100.00% |
static int snd_pcm_substream_proc_init(struct snd_pcm_substream *substream)
{
struct snd_info_entry *entry;
struct snd_card *card;
char name[16];
card = substream->pcm->card;
sprintf(name, "sub%i", substream->number);
if ((entry = snd_info_create_card_entry(card, name, substream->pstr->proc_root)) == NULL)
return -ENOMEM;
entry->mode = S_IFDIR | S_IRUGO | S_IXUGO;
if (snd_info_register(entry) < 0) {
snd_info_free_entry(entry);
return -ENOMEM;
}
substream->proc_root = entry;
if ((entry = snd_info_create_card_entry(card, "info", substream->proc_root)) != NULL) {
snd_info_set_text_ops(entry, substream,
snd_pcm_substream_proc_info_read);
if (snd_info_register(entry) < 0) {
snd_info_free_entry(entry);
entry = NULL;
}
}
substream->proc_info_entry = entry;
if ((entry = snd_info_create_card_entry(card, "hw_params", substream->proc_root)) != NULL) {
snd_info_set_text_ops(entry, substream,
snd_pcm_substream_proc_hw_params_read);
if (snd_info_register(entry) < 0) {
snd_info_free_entry(entry);
entry = NULL;
}
}
substream->proc_hw_params_entry = entry;
if ((entry = snd_info_create_card_entry(card, "sw_params", substream->proc_root)) != NULL) {
snd_info_set_text_ops(entry, substream,
snd_pcm_substream_proc_sw_params_read);
if (snd_info_register(entry) < 0) {
snd_info_free_entry(entry);
entry = NULL;
}
}
substream->proc_sw_params_entry = entry;
if ((entry = snd_info_create_card_entry(card, "status", substream->proc_root)) != NULL) {
snd_info_set_text_ops(entry, substream,
snd_pcm_substream_proc_status_read);
if (snd_info_register(entry) < 0) {
snd_info_free_entry(entry);
entry = NULL;
}
}
substream->proc_status_entry = entry;
#ifdef CONFIG_SND_PCM_XRUN_DEBUG
entry = snd_info_create_card_entry(card, "xrun_injection",
substream->proc_root);
if (entry) {
entry->private_data = substream;
entry->c.text.read = NULL;
entry->c.text.write = snd_pcm_xrun_injection_write;
entry->mode = S_IFREG | S_IWUSR;
if (snd_info_register(entry) < 0) {
snd_info_free_entry(entry);
entry = NULL;
}
}
substream->proc_xrun_injection_entry = entry;
#endif /* CONFIG_SND_PCM_XRUN_DEBUG */
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Jaroslav Kysela | 328 | 78.28% | 2 | 50.00% |
Takashi Iwai | 91 | 21.72% | 2 | 50.00% |
Total | 419 | 100.00% | 4 | 100.00% |
static int snd_pcm_substream_proc_done(struct snd_pcm_substream *substream)
{
snd_info_free_entry(substream->proc_info_entry);
substream->proc_info_entry = NULL;
snd_info_free_entry(substream->proc_hw_params_entry);
substream->proc_hw_params_entry = NULL;
snd_info_free_entry(substream->proc_sw_params_entry);
substream->proc_sw_params_entry = NULL;
snd_info_free_entry(substream->proc_status_entry);
substream->proc_status_entry = NULL;
#ifdef CONFIG_SND_PCM_XRUN_DEBUG
snd_info_free_entry(substream->proc_xrun_injection_entry);
substream->proc_xrun_injection_entry = NULL;
#endif
snd_info_free_entry(substream->proc_root);
substream->proc_root = NULL;
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Jaroslav Kysela | 72 | 74.23% | 2 | 40.00% |
Takashi Iwai | 25 | 25.77% | 3 | 60.00% |
Total | 97 | 100.00% | 5 | 100.00% |
#else /* !CONFIG_SND_VERBOSE_PROCFS */
static inline int snd_pcm_stream_proc_init(struct snd_pcm_str *pstr) { return 0; }
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Takashi Iwai | 15 | 100.00% | 1 | 100.00% |
Total | 15 | 100.00% | 1 | 100.00% |
static inline int snd_pcm_stream_proc_done(struct snd_pcm_str *pstr) { return 0; }
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Takashi Iwai | 15 | 100.00% | 1 | 100.00% |
Total | 15 | 100.00% | 1 | 100.00% |
static inline int snd_pcm_substream_proc_init(struct snd_pcm_substream *substream) { return 0; }
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Takashi Iwai | 15 | 100.00% | 1 | 100.00% |
Total | 15 | 100.00% | 1 | 100.00% |
static inline int snd_pcm_substream_proc_done(struct snd_pcm_substream *substream) { return 0; }
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Takashi Iwai | 15 | 100.00% | 1 | 100.00% |
Total | 15 | 100.00% | 1 | 100.00% |
#endif /* CONFIG_SND_VERBOSE_PROCFS */
static const struct attribute_group *pcm_dev_attr_groups[];
/**
* snd_pcm_new_stream - create a new PCM stream
* @pcm: the pcm instance
* @stream: the stream direction, SNDRV_PCM_STREAM_XXX
* @substream_count: the number of substreams
*
* Creates a new stream for the pcm.
* The corresponding stream on the pcm must have been empty before
* calling this, i.e. zero must be given to the argument of
* snd_pcm_new().
*
* Return: Zero if successful, or a negative error code on failure.
*/
int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count)
{
int idx, err;
struct snd_pcm_str *pstr = &pcm->streams[stream];
struct snd_pcm_substream *substream, *prev;
#if IS_ENABLED(CONFIG_SND_PCM_OSS)
mutex_init(&pstr->oss.setup_mutex);
#endif
pstr->stream = stream;
pstr->pcm = pcm;
pstr->substream_count = substream_count;
if (!substream_count)
return 0;
snd_device_initialize(&pstr->dev, pcm->card);
pstr->dev.groups = pcm_dev_attr_groups;
dev_set_name(&pstr->dev, "pcmC%iD%i%c", pcm->card->number, pcm->device,
stream == SNDRV_PCM_STREAM_PLAYBACK ? 'p' : 'c');
if (!pcm->internal) {
err = snd_pcm_stream_proc_init(pstr);
if (err < 0) {
pcm_err(pcm, "Error in snd_pcm_stream_proc_init\n");
return err;
}
}
prev = NULL;
for (idx = 0, prev = NULL; idx < substream_count; idx++) {
substream = kzalloc(sizeof(*substream), GFP_KERNEL);
if (!substream)
return -ENOMEM;
substream->pcm = pcm;
substream->pstr = pstr;
substream->number = idx;
substream->stream = stream;
sprintf(substream->name, "subdevice #%i", idx);
substream->buffer_bytes_max = UINT_MAX;
if (prev == NULL)
pstr->substream = substream;
else
prev->next = substream;
if (!pcm->internal) {
err = snd_pcm_substream_proc_init(substream);
if (err < 0) {
pcm_err(pcm,
"Error in snd_pcm_stream_proc_init\n");
if (prev == NULL)
pstr->substream = NULL;
else
prev->next = NULL;
kfree(substream);
return err;
}
}
substream->group = &substream->self_group;
spin_lock_init(&substream->self_group.lock);
mutex_init(&substream->self_group.mutex);
INIT_LIST_HEAD(&substream->self_group.substreams);
list_add_tail(&substream->link_list, &substream->self_group.substreams);
atomic_set(&substream->mmap_count, 0);
prev = substream;
}
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Jaroslav Kysela | 267 | 66.42% | 5 | 27.78% |
Takashi Iwai | 102 | 25.37% | 10 | 55.56% |
Akinobu Mita | 19 | 4.73% | 1 | 5.56% |
Liam Girdwood | 13 | 3.23% | 1 | 5.56% |
Ingo Molnar | 1 | 0.25% | 1 | 5.56% |
Total | 402 | 100.00% | 18 | 100.00% |
EXPORT_SYMBOL(snd_pcm_new_stream);
static int _snd_pcm_new(struct snd_card *card, const char *id, int device,
int playback_count, int capture_count, bool internal,
struct snd_pcm **rpcm)
{
struct snd_pcm *pcm;
int err;
static struct snd_device_ops ops = {
.dev_free = snd_pcm_dev_free,
.dev_register = snd_pcm_dev_register,
.dev_disconnect = snd_pcm_dev_disconnect,
};
if (snd_BUG_ON(!card))
return -ENXIO;
if (rpcm)
*rpcm = NULL;
pcm = kzalloc(sizeof(*pcm), GFP_KERNEL);
if (!pcm)
return -ENOMEM;
pcm->card = card;
pcm->device = device;
pcm->internal = internal;
mutex_init(&pcm->open_mutex);
init_waitqueue_head(&pcm->open_wait);
INIT_LIST_HEAD(&pcm->list);
if (id)
strlcpy(pcm->id, id, sizeof(pcm->id));
if ((err = snd_pcm_new_stream(pcm, SNDRV_PCM_STREAM_PLAYBACK, playback_count)) < 0) {
snd_pcm_free(pcm);
return err;
}
if ((err = snd_pcm_new_stream(pcm, SNDRV_PCM_STREAM_CAPTURE, capture_count)) < 0) {
snd_pcm_free(pcm);
return err;
}
if ((err = snd_device_new(card, SNDRV_DEV_PCM, pcm, &ops)) < 0) {
snd_pcm_free(pcm);
return err;
}
if (rpcm)
*rpcm = pcm;
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Jaroslav Kysela | 199 | 75.09% | 4 | 30.77% |
Takashi Iwai | 53 | 20.00% | 6 | 46.15% |
Liam Girdwood | 11 | 4.15% | 1 | 7.69% |
Tim Blechmann | 1 | 0.38% | 1 | 7.69% |
Benjamin Collins | 1 | 0.38% | 1 | 7.69% |
Total | 265 | 100.00% | 13 | 100.00% |
/**
* snd_pcm_new - create a new PCM instance
* @card: the card instance
* @id: the id string
* @device: the device index (zero based)
* @playback_count: the number of substreams for playback
* @capture_count: the number of substreams for capture
* @rpcm: the pointer to store the new pcm instance
*
* Creates a new PCM instance.
*
* The pcm operators have to be set afterwards to the new instance
* via snd_pcm_set_ops().
*
* Return: Zero if successful, or a negative error code on failure.
*/
int snd_pcm_new(struct snd_card *card, const char *id, int device,
int playback_count, int capture_count, struct snd_pcm **rpcm)
{
return _snd_pcm_new(card, id, device, playback_count, capture_count,
false, rpcm);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Liam Girdwood | 48 | 100.00% | 1 | 100.00% |
Total | 48 | 100.00% | 1 | 100.00% |
EXPORT_SYMBOL(snd_pcm_new);
/**
* snd_pcm_new_internal - create a new internal PCM instance
* @card: the card instance
* @id: the id string
* @device: the device index (zero based - shared with normal PCMs)
* @playback_count: the number of substreams for playback
* @capture_count: the number of substreams for capture
* @rpcm: the pointer to store the new pcm instance
*
* Creates a new internal PCM instance with no userspace device or procfs
* entries. This is used by ASoC Back End PCMs in order to create a PCM that
* will only be used internally by kernel drivers. i.e. it cannot be opened
* by userspace. It provides existing ASoC components drivers with a substream
* and access to any private data.
*
* The pcm operators have to be set afterwards to the new instance
* via snd_pcm_set_ops().
*
* Return: Zero if successful, or a negative error code on failure.
*/
int snd_pcm_new_internal(struct snd_card *card, const char *id, int device,
int playback_count, int capture_count,
struct snd_pcm **rpcm)
{
return _snd_pcm_new(card, id, device, playback_count, capture_count,
true, rpcm);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Liam Girdwood | 48 | 100.00% | 1 | 100.00% |
Total | 48 | 100.00% | 1 | 100.00% |
EXPORT_SYMBOL(snd_pcm_new_internal);
static void free_chmap(struct snd_pcm_str *pstr)
{
if (pstr->chmap_kctl) {
snd_ctl_remove(pstr->pcm->card, pstr->chmap_kctl);
pstr->chmap_kctl = NULL;
}
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Takashi Iwai | 38 | 100.00% | 1 | 100.00% |
Total | 38 | 100.00% | 1 | 100.00% |
static void snd_pcm_free_stream(struct snd_pcm_str * pstr)
{
struct snd_pcm_substream *substream, *substream_next;
#if IS_ENABLED(CONFIG_SND_PCM_OSS)
struct snd_pcm_oss_setup *setup, *setupn;
#endif
substream = pstr->substream;
while (substream) {
substream_next = substream->next;
snd_pcm_timer_done(substream);
snd_pcm_substream_proc_done(substream);
kfree(substream);
substream = substream_next;
}
snd_pcm_stream_proc_done(pstr);
#if IS_ENABLED(CONFIG_SND_PCM_OSS)
for (setup = pstr->oss.setup_list; setup; setup = setupn) {
setupn = setup->next;
kfree(setup->task_name);
kfree(setup);
}
#endif
free_chmap(pstr);
if (pstr->substream_count)
put_device(&pstr->dev);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Jaroslav Kysela | 108 | 77.14% | 3 | 37.50% |
Takashi Iwai | 32 | 22.86% | 5 | 62.50% |
Total | 140 | 100.00% | 8 | 100.00% |
static int snd_pcm_free(struct snd_pcm *pcm)
{
struct snd_pcm_notify *notify;
if (!pcm)
return 0;
if (!pcm->internal) {
list_for_each_entry(notify, &snd_pcm_notify_list, list)
notify->n_unregister(pcm);
}
if (pcm->private_free)
pcm->private_free(pcm);
snd_pcm_lib_preallocate_free_for_all(pcm);
snd_pcm_free_stream(&pcm->streams[SNDRV_PCM_STREAM_PLAYBACK]);
snd_pcm_free_stream(&pcm->streams[SNDRV_PCM_STREAM_CAPTURE]);
kfree(pcm);
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Jaroslav Kysela | 57 | 59.38% | 4 | 50.00% |
Takashi Iwai | 39 | 40.62% | 4 | 50.00% |
Total | 96 | 100.00% | 8 | 100.00% |
static int snd_pcm_dev_free(struct snd_device *device)
{
struct snd_pcm *pcm = device->device_data;
return snd_pcm_free(pcm);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Jaroslav Kysela | 22 | 84.62% | 3 | 75.00% |
Takashi Iwai | 4 | 15.38% | 1 | 25.00% |
Total | 26 | 100.00% | 4 | 100.00% |
int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream,
struct file *file,
struct snd_pcm_substream **rsubstream)
{
struct snd_pcm_str * pstr;
struct snd_pcm_substream *substream;
struct snd_pcm_runtime *runtime;
struct snd_card *card;
int prefer_subdevice;
size_t size;
if (snd_BUG_ON(!pcm || !rsubstream))
return -ENXIO;
if (snd_BUG_ON(stream != SNDRV_PCM_STREAM_PLAYBACK &&
stream != SNDRV_PCM_STREAM_CAPTURE))
return -EINVAL;
*rsubstream = NULL;
pstr = &pcm->streams[stream];
if (pstr->substream == NULL || pstr->substream_count == 0)
return -ENODEV;
card = pcm->card;
prefer_subdevice = snd_ctl_get_preferred_subdevice(card, SND_CTL_SUBDEV_PCM);
if (pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX) {
int opposite = !stream;
for (substream = pcm->streams[opposite].substream; substream;
substream = substream->next) {
if (SUBSTREAM_BUSY(substream))
return -EAGAIN;
}
}
if (file->f_flags & O_APPEND) {
if (prefer_subdevice < 0) {
if (pstr->substream_count > 1)
return -EINVAL; /* must be unique */
substream = pstr->substream;
} else {
for (substream = pstr->substream; substream;
substream = substream->next)
if (substream->number == prefer_subdevice)
break;
}
if (! substream)
return -ENODEV;
if (! SUBSTREAM_BUSY(substream))
return -EBADFD;
substream->ref_count++;
*rsubstream = substream;
return 0;
}
for (substream = pstr->substream; substream; substream = substream->next) {
if (!SUBSTREAM_BUSY(substream) &&
(prefer_subdevice == -1 ||
substream->number == prefer_subdevice))
break;
}
if (substream == NULL)
return -EAGAIN;
runtime = kzalloc(sizeof(*runtime), GFP_KERNEL);
if (runtime == NULL)
return -ENOMEM;
size = PAGE_ALIGN(sizeof(struct snd_pcm_mmap_status));
runtime->status = snd_malloc_pages(size, GFP_KERNEL);
if (runtime->status == NULL) {
kfree(runtime);
return -ENOMEM;
}
memset((void*)runtime->status, 0, size);
size = PAGE_ALIGN(sizeof(struct snd_pcm_mmap_control));
runtime->control = snd_malloc_pages(size, GFP_KERNEL);
if (runtime->control == NULL) {
snd_free_pages((void*)runtime->status,
PAGE_ALIGN(sizeof(struct snd_pcm_mmap_status)));
kfree(runtime);
return -ENOMEM;
}
memset((void*)runtime->control, 0, size);
init_waitqueue_head(&runtime->sleep);
init_waitqueue_head(&runtime->tsleep);
runtime->status->state = SNDRV_PCM_STATE_OPEN;
substream->runtime = runtime;
substream->private_data = pcm->private_data;
substream->ref_count = 1;
substream->f_flags = file->f_flags;
substream->pid = get_pid(task_pid(current));
pstr->substream_opened++;
*rsubstream = substream;
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Jaroslav Kysela | 358 | 63.81% | 5 | 38.46% |
Takashi Iwai | 191 | 34.05% | 7 | 53.85% |
Clemens Ladisch | 12 | 2.14% | 1 | 7.69% |
Total | 561 | 100.00% | 13 | 100.00% |
void snd_pcm_detach_substream(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime;
if (PCM_RUNTIME_CHECK(substream))
return;
runtime = substream->runtime;
if (runtime->private_free != NULL)
runtime->private_free(runtime);
snd_free_pages((void*)runtime->status,
PAGE_ALIGN(sizeof(struct snd_pcm_mmap_status)));
snd_free_pages((void*)runtime->control,
PAGE_ALIGN(sizeof(struct snd_pcm_mmap_control)));
kfree(runtime->hw_constraints.rules);
kfree(runtime);
substream->runtime = NULL;
put_pid(substream->pid);
substream->pid = NULL;
substream->pstr->substream_opened--;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Jaroslav Kysela | 94 | 75.81% | 1 | 20.00% |
Takashi Iwai | 17 | 13.71% | 3 | 60.00% |
Clemens Ladisch | 13 | 10.48% | 1 | 20.00% |
Total | 124 | 100.00% | 5 | 100.00% |
static ssize_t show_pcm_class(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct snd_pcm_str *pstr = container_of(dev, struct snd_pcm_str, dev);
struct snd_pcm *pcm = pstr->pcm;
const char *str;
static const char *strs[SNDRV_PCM_CLASS_LAST + 1] = {
[SNDRV_PCM_CLASS_GENERIC] = "generic",
[SNDRV_PCM_CLASS_MULTI] = "multi",
[SNDRV_PCM_CLASS_MODEM] = "modem",
[SNDRV_PCM_CLASS_DIGITIZER] = "digitizer",
};
if (pcm->dev_class > SNDRV_PCM_CLASS_LAST)
str = "none";
else
str = strs[pcm->dev_class];
return snprintf(buf, PAGE_SIZE, "%s\n", str);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Takashi Iwai | 113 | 94.17% | 2 | 66.67% |
Greg Kroah-Hartman | 7 | 5.83% | 1 | 33.33% |
Total | 120 | 100.00% | 3 | 100.00% |
static DEVICE_ATTR(pcm_class, S_IRUGO, show_pcm_class, NULL);
static struct attribute *pcm_dev_attrs[] = {
&dev_attr_pcm_class.attr,
NULL
};
static struct attribute_group pcm_dev_attr_group = {
.attrs = pcm_dev_attrs,
};
static const struct attribute_group *pcm_dev_attr_groups[] = {
&pcm_dev_attr_group,
NULL
};
static int snd_pcm_dev_register(struct snd_device *device)
{
int cidx, err;
struct snd_pcm_substream *substream;
struct snd_pcm_notify *notify;
struct snd_pcm *pcm;
if (snd_BUG_ON(!device || !device->device_data))
return -ENXIO;
pcm = device->device_data;
if (pcm->internal)
return 0;
mutex_lock(®ister_mutex);
err = snd_pcm_add(pcm);
if (err)
goto unlock;
for (cidx = 0; cidx < 2; cidx++) {
int devtype = -1;
if (pcm->streams[cidx].substream == NULL)
continue;
switch (cidx) {
case SNDRV_PCM_STREAM_PLAYBACK:
devtype = SNDRV_DEVICE_TYPE_PCM_PLAYBACK;
break;
case SNDRV_PCM_STREAM_CAPTURE:
devtype = SNDRV_DEVICE_TYPE_PCM_CAPTURE;
break;
}
/* register pcm */
err = snd_register_device(devtype, pcm->card, pcm->device,
&snd_pcm_f_ops[cidx], pcm,
&pcm->streams[cidx].dev);
if (err < 0) {
list_del_init(&pcm->list);
goto unlock;
}
for (substream = pcm->streams[cidx].substream; substream; substream = substream->next)
snd_pcm_timer_init(substream);
}
list_for_each_entry(notify, &snd_pcm_notify_list, list)
notify->n_register(pcm);
unlock:
mutex_unlock(®ister_mutex);
return err;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Jaroslav Kysela | 158 | 64.49% | 3 | 20.00% |
Takashi Iwai | 46 | 18.78% | 5 | 33.33% |
Clemens Ladisch | 12 | 4.90% | 2 | 13.33% |
Johannes Berg | 11 | 4.49% | 2 | 13.33% |
Julia Lawall | 9 | 3.67% | 1 | 6.67% |
Pawel Moll | 7 | 2.86% | 1 | 6.67% |
Ingo Molnar | 2 | 0.82% | 1 | 6.67% |
Total | 245 | 100.00% | 15 | 100.00% |
static int snd_pcm_dev_disconnect(struct snd_device *device)
{
struct snd_pcm *pcm = device->device_data;
struct snd_pcm_notify *notify;
struct snd_pcm_substream *substream;
int cidx;
mutex_lock(®ister_mutex);
mutex_lock(&pcm->open_mutex);
wake_up(&pcm->open_wait);
list_del_init(&pcm->list);
for (cidx = 0; cidx < 2; cidx++) {
for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) {
snd_pcm_stream_lock_irq(substream);
if (substream->runtime) {
substream->runtime->status->state = SNDRV_PCM_STATE_DISCONNECTED;
wake_up(&substream->runtime->sleep);
wake_up(&substream->runtime->tsleep);
}
snd_pcm_stream_unlock_irq(substream);
}
}
if (!pcm->internal) {
list_for_each_entry(notify, &snd_pcm_notify_list, list)
notify->n_disconnect(pcm);
}
for (cidx = 0; cidx < 2; cidx++) {
if (!pcm->internal)
snd_unregister_device(&pcm->streams[cidx].dev);
free_chmap(&pcm->streams[cidx]);
}
mutex_unlock(&pcm->open_mutex);
mutex_unlock(®ister_mutex);
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Jaroslav Kysela | 124 | 52.54% | 6 | 35.29% |
Takashi Iwai | 105 | 44.49% | 9 | 52.94% |
Clemens Ladisch | 5 | 2.12% | 1 | 5.88% |
Ingo Molnar | 2 | 0.85% | 1 | 5.88% |
Total | 236 | 100.00% | 17 | 100.00% |
/**
* snd_pcm_notify - Add/remove the notify list
* @notify: PCM notify list
* @nfree: 0 = register, 1 = unregister
*
* This adds the given notifier to the global list so that the callback is
* called for each registered PCM devices. This exists only for PCM OSS
* emulation, so far.
*/
int snd_pcm_notify(struct snd_pcm_notify *notify, int nfree)
{
struct snd_pcm *pcm;
if (snd_BUG_ON(!notify ||
!notify->n_register ||
!notify->n_unregister ||
!notify->n_disconnect))
return -EINVAL;
mutex_lock(®ister_mutex);
if (nfree) {
list_del(¬ify->list);
list_for_each_entry(pcm, &snd_pcm_devices, list)
notify->n_unregister(pcm);
} else {
list_add_tail(¬ify->list, &snd_pcm_notify_list);
list_for_each_entry(pcm, &snd_pcm_devices, list)
notify->n_register(pcm);
}
mutex_unlock(®ister_mutex);
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Jaroslav Kysela | 67 | 56.78% | 2 | 28.57% |
Takashi Iwai | 27 | 22.88% | 2 | 28.57% |
Johannes Berg | 12 | 10.17% | 1 | 14.29% |
Clemens Ladisch | 10 | 8.47% | 1 | 14.29% |
Ingo Molnar | 2 | 1.69% | 1 | 14.29% |
Total | 118 | 100.00% | 7 | 100.00% |
EXPORT_SYMBOL(snd_pcm_notify);
#ifdef CONFIG_SND_PROC_FS
/*
* Info interface
*/
static void snd_pcm_proc_read(struct snd_info_entry *entry,
struct snd_info_buffer *buffer)
{
struct snd_pcm *pcm;
mutex_lock(®ister_mutex);
list_for_each_entry(pcm, &snd_pcm_devices, list) {
snd_iprintf(buffer, "%02i-%02i: %s : %s",
pcm->card->number, pcm->device, pcm->id, pcm->name);
if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream)
snd_iprintf(buffer, " : playback %i",
pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream_count);
if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream)
snd_iprintf(buffer, " : capture %i",
pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream_count);
snd_iprintf(buffer, "\n");
}
mutex_unlock(®ister_mutex);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Jaroslav Kysela | 104 | 80.62% | 1 | 20.00% |
Clemens Ladisch | 14 | 10.85% | 1 | 20.00% |
Takashi Iwai | 5 | 3.88% | 1 | 20.00% |
Johannes Berg | 4 | 3.10% | 1 | 20.00% |
Ingo Molnar | 2 | 1.55% | 1 | 20.00% |
Total | 129 | 100.00% | 5 | 100.00% |
static struct snd_info_entry *snd_pcm_proc_entry;
static void snd_pcm_proc_init(void)
{
struct snd_info_entry *entry;
if ((entry = snd_info_create_module_entry(THIS_MODULE, "pcm", NULL)) != NULL) {
snd_info_set_text_ops(entry, NULL, snd_pcm_proc_read);
if (snd_info_register(entry) < 0) {
snd_info_free_entry(entry);
entry = NULL;
}
}
snd_pcm_proc_entry = entry;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Jaroslav Kysela | 60 | 92.31% | 2 | 50.00% |
Takashi Iwai | 5 | 7.69% | 2 | 50.00% |
Total | 65 | 100.00% | 4 | 100.00% |
static void snd_pcm_proc_done(void)
{
snd_info_free_entry(snd_pcm_proc_entry);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Takashi Iwai | 13 | 100.00% | 2 | 100.00% |
Total | 13 | 100.00% | 2 | 100.00% |
#else /* !CONFIG_SND_PROC_FS */
#define snd_pcm_proc_init()
#define snd_pcm_proc_done()
#endif /* CONFIG_SND_PROC_FS */
/*
* ENTRY functions
*/
static int __init alsa_pcm_init(void)
{
snd_ctl_register_ioctl(snd_pcm_control_ioctl);
snd_ctl_register_ioctl_compat(snd_pcm_control_ioctl);
snd_pcm_proc_init();
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Takashi Iwai | 21 | 84.00% | 1 | 50.00% |
Jaroslav Kysela | 4 | 16.00% | 1 | 50.00% |
Total | 25 | 100.00% | 2 | 100.00% |
static void __exit alsa_pcm_exit(void)
{
snd_ctl_unregister_ioctl(snd_pcm_control_ioctl);
snd_ctl_unregister_ioctl_compat(snd_pcm_control_ioctl);
snd_pcm_proc_done();
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Jaroslav Kysela | 20 | 90.91% | 2 | 66.67% |
Takashi Iwai | 2 | 9.09% | 1 | 33.33% |
Total | 22 | 100.00% | 3 | 100.00% |
module_init(alsa_pcm_init)
module_exit(alsa_pcm_exit)
Overall Contributors
Person | Tokens | Prop | Commits | CommitProp |
Jaroslav Kysela | 4049 | 63.85% | 28 | 31.82% |
Takashi Iwai | 1558 | 24.57% | 37 | 42.05% |
Clemens Ladisch | 251 | 3.96% | 4 | 4.55% |
Pawel Moll | 192 | 3.03% | 1 | 1.14% |
Liam Girdwood | 125 | 1.97% | 1 | 1.14% |
Dan Carpenter | 32 | 0.50% | 1 | 1.14% |
Johannes Berg | 31 | 0.49% | 2 | 2.27% |
Akinobu Mita | 19 | 0.30% | 1 | 1.14% |
Ingo Molnar | 17 | 0.27% | 1 | 1.14% |
Al Viro | 12 | 0.19% | 1 | 1.14% |
Daniel Mack | 10 | 0.16% | 1 | 1.14% |
Jussi Laako | 10 | 0.16% | 1 | 1.14% |
Julia Lawall | 9 | 0.14% | 1 | 1.14% |
Greg Kroah-Hartman | 7 | 0.11% | 1 | 1.14% |
Paul Gortmaker | 6 | 0.09% | 2 | 2.27% |
Jurgen Kramer | 5 | 0.08% | 1 | 1.14% |
Yacine Belkadi | 3 | 0.05% | 1 | 1.14% |
Jie Yang | 3 | 0.05% | 1 | 1.14% |
Tim Blechmann | 1 | 0.02% | 1 | 1.14% |
Benjamin Collins | 1 | 0.02% | 1 | 1.14% |
Total | 6341 | 100.00% | 88 | 100.00% |
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.