linux 2.6.16.38 w/ vs2.0.3-rc1
[linux-2.6.git] / sound / core / pcm.c
index 7581edd..28ca61e 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/time.h>
-#include <linux/mutex.h>
 #include <sound/core.h>
 #include <sound/minors.h>
 #include <sound/pcm.h>
@@ -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(&register_mutex);
+                       down(&register_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(&register_mutex);
+                       up(&register_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(&register_mutex);
+                       down(&register_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(&register_mutex);
+                       up(&register_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 <linux/soundcard.h>
-
 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(&register_mutex);
+       down(&register_mutex);
        if (snd_pcm_search(pcm->card, pcm->device)) {
-               mutex_unlock(&register_mutex);
+               up(&register_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(&register_mutex);
+                       up(&register_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(&register_mutex);
+       up(&register_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(&register_mutex);
+       down(&register_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(&register_mutex);
+       up(&register_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(&register_mutex);
+       down(&register_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(&register_mutex);
+       up(&register_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(&register_mutex);
+       down(&register_mutex);
        if (nfree) {
                list_del(&notify->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(&register_mutex);
+       up(&register_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(&register_mutex);
+       down(&register_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(&register_mutex);
+       up(&register_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);