X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=sound%2Fcore%2Fpcm.c;fp=sound%2Fcore%2Fpcm.c;h=28ca61eb0b0d9948515985a687e71e5543e9866e;hb=64ba3f394c830ec48a1c31b53dcae312c56f1604;hp=7581edd7b9ffbf354d8542b010aa16d671cfca63;hpb=be1e6109ac94a859551f8e1774eb9a8469fe055c;p=linux-2.6.git diff --git a/sound/core/pcm.c b/sound/core/pcm.c index 7581edd7b..28ca61eb0 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include @@ -36,7 +35,7 @@ MODULE_LICENSE("GPL"); static LIST_HEAD(snd_pcm_devices); static LIST_HEAD(snd_pcm_notify_list); -static DEFINE_MUTEX(register_mutex); +static DECLARE_MUTEX(register_mutex); static int snd_pcm_free(struct snd_pcm *pcm); static int snd_pcm_dev_free(struct snd_device *device); @@ -68,7 +67,7 @@ static int snd_pcm_control_ioctl(struct snd_card *card, if (get_user(device, (int __user *)arg)) return -EFAULT; - mutex_lock(®ister_mutex); + down(®ister_mutex); device = device < 0 ? 0 : device + 1; while (device < SNDRV_PCM_DEVICES) { if (snd_pcm_search(card, device)) @@ -77,7 +76,7 @@ static int snd_pcm_control_ioctl(struct snd_card *card, } if (device == SNDRV_PCM_DEVICES) device = -1; - mutex_unlock(®ister_mutex); + up(®ister_mutex); if (put_user(device, (int __user *)arg)) return -EFAULT; return 0; @@ -101,7 +100,7 @@ static int snd_pcm_control_ioctl(struct snd_card *card, return -EINVAL; if (get_user(subdevice, &info->subdevice)) return -EFAULT; - mutex_lock(®ister_mutex); + down(®ister_mutex); pcm = snd_pcm_search(card, device); if (pcm == NULL) { err = -ENXIO; @@ -126,7 +125,7 @@ static int snd_pcm_control_ioctl(struct snd_card *card, } err = snd_pcm_info_user(substream, info); _error: - mutex_unlock(®ister_mutex); + up(®ister_mutex); return err; } case SNDRV_CTL_IOCTL_PCM_PREFER_SUBDEVICE: @@ -141,9 +140,6 @@ static int snd_pcm_control_ioctl(struct snd_card *card, } return -ENOIOCTLCMD; } - -#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 @@ -196,11 +192,12 @@ static char *snd_pcm_format_names[] = { FORMAT(U18_3BE), }; -static const char *snd_pcm_format_name(snd_pcm_format_t format) +const char *snd_pcm_format_name(snd_pcm_format_t format) { return snd_pcm_format_names[format]; } +#ifdef CONFIG_PROC_FS static char *snd_pcm_stream_names[] = { STREAM(PLAYBACK), STREAM(CAPTURE), @@ -263,7 +260,6 @@ static const char *snd_pcm_state_name(snd_pcm_state_t state) #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) #include - static const char *snd_pcm_oss_format_name(int format) { switch (format) { @@ -351,8 +347,10 @@ static void snd_pcm_substream_proc_hw_params_read(struct snd_info_entry *entry, snd_iprintf(buffer, "closed\n"); return; } + snd_pcm_stream_lock_irq(substream); if (runtime->status->state == SNDRV_PCM_STATE_OPEN) { snd_iprintf(buffer, "no setup\n"); + snd_pcm_stream_unlock_irq(substream); return; } snd_iprintf(buffer, "access: %s\n", snd_pcm_access_name(runtime->access)); @@ -373,6 +371,7 @@ static void snd_pcm_substream_proc_hw_params_read(struct snd_info_entry *entry, snd_iprintf(buffer, "OSS period frames: %lu\n", (unsigned long)runtime->oss.period_frames); } #endif + snd_pcm_stream_unlock_irq(substream); } static void snd_pcm_substream_proc_sw_params_read(struct snd_info_entry *entry, @@ -384,8 +383,10 @@ static void snd_pcm_substream_proc_sw_params_read(struct snd_info_entry *entry, snd_iprintf(buffer, "closed\n"); return; } + snd_pcm_stream_lock_irq(substream); if (runtime->status->state == SNDRV_PCM_STATE_OPEN) { snd_iprintf(buffer, "no setup\n"); + snd_pcm_stream_unlock_irq(substream); return; } snd_iprintf(buffer, "tstamp_mode: %s\n", snd_pcm_tstamp_mode_name(runtime->tstamp_mode)); @@ -398,6 +399,7 @@ static void snd_pcm_substream_proc_sw_params_read(struct snd_info_entry *entry, 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); + snd_pcm_stream_unlock_irq(substream); } static void snd_pcm_substream_proc_status_read(struct snd_info_entry *entry, @@ -430,7 +432,7 @@ static void snd_pcm_substream_proc_status_read(struct snd_info_entry *entry, snd_iprintf(buffer, "appl_ptr : %ld\n", runtime->control->appl_ptr); } -#ifdef CONFIG_SND_PCM_XRUN_DEBUG +#ifdef CONFIG_SND_DEBUG static void snd_pcm_xrun_debug_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) { @@ -466,7 +468,7 @@ static int snd_pcm_stream_proc_init(struct snd_pcm_str *pstr) 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); + snd_info_set_text_ops(entry, pstr, 256, snd_pcm_stream_proc_info_read); if (snd_info_register(entry) < 0) { snd_info_free_entry(entry); entry = NULL; @@ -474,10 +476,12 @@ static int snd_pcm_stream_proc_init(struct snd_pcm_str *pstr) } pstr->proc_info_entry = entry; -#ifdef CONFIG_SND_PCM_XRUN_DEBUG +#ifdef CONFIG_SND_DEBUG if ((entry = snd_info_create_card_entry(pcm->card, "xrun_debug", pstr->proc_root)) != NULL) { + entry->c.text.read_size = 64; entry->c.text.read = snd_pcm_xrun_debug_read; + entry->c.text.write_size = 64; entry->c.text.write = snd_pcm_xrun_debug_write; entry->mode |= S_IWUSR; entry->private_data = pstr; @@ -493,7 +497,7 @@ static int snd_pcm_stream_proc_init(struct snd_pcm_str *pstr) static int snd_pcm_stream_proc_done(struct snd_pcm_str *pstr) { -#ifdef CONFIG_SND_PCM_XRUN_DEBUG +#ifdef CONFIG_SND_DEBUG if (pstr->proc_xrun_debug_entry) { snd_info_unregister(pstr->proc_xrun_debug_entry); pstr->proc_xrun_debug_entry = NULL; @@ -529,8 +533,7 @@ static int snd_pcm_substream_proc_init(struct snd_pcm_substream *substream) 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); + snd_info_set_text_ops(entry, substream, 256, snd_pcm_substream_proc_info_read); if (snd_info_register(entry) < 0) { snd_info_free_entry(entry); entry = NULL; @@ -539,8 +542,7 @@ static int snd_pcm_substream_proc_init(struct snd_pcm_substream *substream) 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); + snd_info_set_text_ops(entry, substream, 256, snd_pcm_substream_proc_hw_params_read); if (snd_info_register(entry) < 0) { snd_info_free_entry(entry); entry = NULL; @@ -549,8 +551,7 @@ static int snd_pcm_substream_proc_init(struct snd_pcm_substream *substream) 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); + snd_info_set_text_ops(entry, substream, 256, snd_pcm_substream_proc_sw_params_read); if (snd_info_register(entry) < 0) { snd_info_free_entry(entry); entry = NULL; @@ -559,8 +560,7 @@ static int snd_pcm_substream_proc_init(struct snd_pcm_substream *substream) 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); + snd_info_set_text_ops(entry, substream, 256, snd_pcm_substream_proc_status_read); if (snd_info_register(entry) < 0) { snd_info_free_entry(entry); entry = NULL; @@ -595,12 +595,12 @@ static int snd_pcm_substream_proc_done(struct snd_pcm_substream *substream) } return 0; } -#else /* !CONFIG_SND_VERBOSE_PROCFS */ +#else /* !CONFIG_PROC_FS */ static inline int snd_pcm_stream_proc_init(struct snd_pcm_str *pstr) { return 0; } static inline int snd_pcm_stream_proc_done(struct snd_pcm_str *pstr) { return 0; } static inline int snd_pcm_substream_proc_init(struct snd_pcm_substream *substream) { return 0; } static inline int snd_pcm_substream_proc_done(struct snd_pcm_substream *substream) { return 0; } -#endif /* CONFIG_SND_VERBOSE_PROCFS */ +#endif /* CONFIG_PROC_FS */ /** * snd_pcm_new_stream - create a new PCM stream @@ -622,7 +622,7 @@ int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count) struct snd_pcm_substream *substream, *prev; #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) - mutex_init(&pstr->oss.setup_mutex); + init_MUTEX(&pstr->oss.setup_mutex); #endif pstr->stream = stream; pstr->pcm = pcm; @@ -662,14 +662,11 @@ int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count) INIT_LIST_HEAD(&substream->self_group.substreams); list_add_tail(&substream->link_list, &substream->self_group.substreams); spin_lock_init(&substream->timer_lock); - atomic_set(&substream->mmap_count, 0); prev = substream; } return 0; } -EXPORT_SYMBOL(snd_pcm_new_stream); - /** * snd_pcm_new - create a new PCM instance * @card: the card instance @@ -719,7 +716,7 @@ int snd_pcm_new(struct snd_card *card, char *id, int device, snd_pcm_free(pcm); return err; } - mutex_init(&pcm->open_mutex); + init_MUTEX(&pcm->open_mutex); init_waitqueue_head(&pcm->open_wait); if ((err = snd_device_new(card, SNDRV_DEV_PCM, pcm, &ops)) < 0) { snd_pcm_free(pcm); @@ -729,8 +726,6 @@ int snd_pcm_new(struct snd_card *card, char *id, int device, return 0; } -EXPORT_SYMBOL(snd_pcm_new); - static void snd_pcm_free_stream(struct snd_pcm_str * pstr) { struct snd_pcm_substream *substream, *substream_next; @@ -778,9 +773,8 @@ static void snd_pcm_tick_timer_func(unsigned long data) snd_pcm_tick_elapsed(substream); } -int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream, - struct file *file, - struct snd_pcm_substream **rsubstream) +int snd_pcm_open_substream(struct snd_pcm *pcm, int stream, + struct snd_pcm_substream **rsubstream) { struct snd_pcm_str * pstr; struct snd_pcm_substream *substream; @@ -795,7 +789,7 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream, *rsubstream = NULL; snd_assert(pcm != NULL, return -ENXIO); pstr = &pcm->streams[stream]; - if (pstr->substream == NULL || pstr->substream_count == 0) + if (pstr->substream == NULL) return -ENODEV; card = pcm->card; @@ -809,6 +803,8 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream, } up_read(&card->controls_rwsem); + if (pstr->substream_count == 0) + return -ENODEV; switch (stream) { case SNDRV_PCM_STREAM_PLAYBACK: if (pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX) { @@ -830,26 +826,6 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream, return -EINVAL; } - 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; - } - if (prefer_subdevice >= 0) { for (substream = pstr->substream; substream; substream = substream->next) if (!SUBSTREAM_BUSY(substream) && substream->number == prefer_subdevice) @@ -885,6 +861,7 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream, memset((void*)runtime->control, 0, size); init_waitqueue_head(&runtime->sleep); + atomic_set(&runtime->mmap_count, 0); init_timer(&runtime->tick_timer); runtime->tick_timer.function = snd_pcm_tick_timer_func; runtime->tick_timer.data = (unsigned long) substream; @@ -893,17 +870,15 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream, substream->runtime = runtime; substream->private_data = pcm->private_data; - substream->ref_count = 1; - substream->f_flags = file->f_flags; pstr->substream_opened++; *rsubstream = substream; return 0; } -void snd_pcm_detach_substream(struct snd_pcm_substream *substream) +void snd_pcm_release_substream(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime; - + substream->file = NULL; runtime = substream->runtime; snd_assert(runtime != NULL, return); if (runtime->private_free != NULL) @@ -927,9 +902,9 @@ static int snd_pcm_dev_register(struct snd_device *device) struct snd_pcm *pcm = device->device_data; snd_assert(pcm != NULL && device != NULL, return -ENXIO); - mutex_lock(®ister_mutex); + down(®ister_mutex); if (snd_pcm_search(pcm->card, pcm->device)) { - mutex_unlock(®ister_mutex); + up(®ister_mutex); return -EBUSY; } list_add_tail(&pcm->list, &snd_pcm_devices); @@ -953,7 +928,7 @@ static int snd_pcm_dev_register(struct snd_device *device) pcm, str)) < 0) { list_del(&pcm->list); - mutex_unlock(®ister_mutex); + up(®ister_mutex); return err; } for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) @@ -964,7 +939,7 @@ static int snd_pcm_dev_register(struct snd_device *device) notify = list_entry(list, struct snd_pcm_notify, list); notify->n_register(pcm); } - mutex_unlock(®ister_mutex); + up(®ister_mutex); return 0; } @@ -975,7 +950,7 @@ static int snd_pcm_dev_disconnect(struct snd_device *device) struct snd_pcm_substream *substream; int cidx; - mutex_lock(®ister_mutex); + down(®ister_mutex); list_del_init(&pcm->list); for (cidx = 0; cidx < 2; cidx++) for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) @@ -986,7 +961,7 @@ static int snd_pcm_dev_disconnect(struct snd_device *device) notify = list_entry(list, struct snd_pcm_notify, list); notify->n_disconnect(pcm); } - mutex_unlock(®ister_mutex); + up(®ister_mutex); return 0; } @@ -998,7 +973,7 @@ static int snd_pcm_dev_unregister(struct snd_device *device) struct snd_pcm *pcm = device->device_data; snd_assert(pcm != NULL, return -ENXIO); - mutex_lock(®ister_mutex); + down(®ister_mutex); list_del(&pcm->list); for (cidx = 0; cidx < 2; cidx++) { devtype = -1; @@ -1019,7 +994,7 @@ static int snd_pcm_dev_unregister(struct snd_device *device) notify = list_entry(list, struct snd_pcm_notify, list); notify->n_unregister(pcm); } - mutex_unlock(®ister_mutex); + up(®ister_mutex); return snd_pcm_free(pcm); } @@ -1028,7 +1003,7 @@ int snd_pcm_notify(struct snd_pcm_notify *notify, int nfree) struct list_head *p; snd_assert(notify != NULL && notify->n_register != NULL && notify->n_unregister != NULL, return -EINVAL); - mutex_lock(®ister_mutex); + down(®ister_mutex); if (nfree) { list_del(¬ify->list); list_for_each(p, &snd_pcm_devices) @@ -1039,12 +1014,10 @@ int snd_pcm_notify(struct snd_pcm_notify *notify, int nfree) list_for_each(p, &snd_pcm_devices) notify->n_register(list_entry(p, struct snd_pcm, list)); } - mutex_unlock(®ister_mutex); + up(®ister_mutex); return 0; } -EXPORT_SYMBOL(snd_pcm_notify); - #ifdef CONFIG_PROC_FS /* * Info interface @@ -1056,7 +1029,7 @@ static void snd_pcm_proc_read(struct snd_info_entry *entry, struct list_head *p; struct snd_pcm *pcm; - mutex_lock(®ister_mutex); + down(®ister_mutex); list_for_each(p, &snd_pcm_devices) { pcm = list_entry(p, struct snd_pcm, list); snd_iprintf(buffer, "%02i-%02i: %s : %s", @@ -1069,17 +1042,18 @@ static void snd_pcm_proc_read(struct snd_info_entry *entry, pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream_count); snd_iprintf(buffer, "\n"); } - mutex_unlock(®ister_mutex); + up(®ister_mutex); } -static struct snd_info_entry *snd_pcm_proc_entry; +static struct snd_info_entry *snd_pcm_proc_entry = NULL; 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); + snd_info_set_text_ops(entry, NULL, SNDRV_CARDS * SNDRV_PCM_DEVICES * 128, + snd_pcm_proc_read); if (snd_info_register(entry) < 0) { snd_info_free_entry(entry); entry = NULL; @@ -1121,3 +1095,36 @@ static void __exit alsa_pcm_exit(void) module_init(alsa_pcm_init) module_exit(alsa_pcm_exit) + +EXPORT_SYMBOL(snd_pcm_new); +EXPORT_SYMBOL(snd_pcm_new_stream); +EXPORT_SYMBOL(snd_pcm_notify); +EXPORT_SYMBOL(snd_pcm_open_substream); +EXPORT_SYMBOL(snd_pcm_release_substream); +EXPORT_SYMBOL(snd_pcm_format_name); + /* pcm_native.c */ +EXPORT_SYMBOL(snd_pcm_link_rwlock); +#ifdef CONFIG_PM +EXPORT_SYMBOL(snd_pcm_suspend); +EXPORT_SYMBOL(snd_pcm_suspend_all); +#endif +EXPORT_SYMBOL(snd_pcm_kernel_playback_ioctl); +EXPORT_SYMBOL(snd_pcm_kernel_capture_ioctl); +EXPORT_SYMBOL(snd_pcm_kernel_ioctl); +EXPORT_SYMBOL(snd_pcm_mmap_data); +#if SNDRV_PCM_INFO_MMAP_IOMEM +EXPORT_SYMBOL(snd_pcm_lib_mmap_iomem); +#endif + /* pcm_misc.c */ +EXPORT_SYMBOL(snd_pcm_format_signed); +EXPORT_SYMBOL(snd_pcm_format_unsigned); +EXPORT_SYMBOL(snd_pcm_format_linear); +EXPORT_SYMBOL(snd_pcm_format_little_endian); +EXPORT_SYMBOL(snd_pcm_format_big_endian); +EXPORT_SYMBOL(snd_pcm_format_width); +EXPORT_SYMBOL(snd_pcm_format_physical_width); +EXPORT_SYMBOL(snd_pcm_format_size); +EXPORT_SYMBOL(snd_pcm_format_silence_64); +EXPORT_SYMBOL(snd_pcm_format_set_silence); +EXPORT_SYMBOL(snd_pcm_build_linear_format); +EXPORT_SYMBOL(snd_pcm_limit_hw_rates);