aboutsummaryrefslogtreecommitdiffstats
path: root/sound/core/pcm_native.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/core/pcm_native.c')
-rw-r--r--sound/core/pcm_native.c157
1 files changed, 75 insertions, 82 deletions
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 01f150f0990e..964e4c47a7f1 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -1170,7 +1170,7 @@ static int snd_pcm_resume(struct snd_pcm_substream *substream)
1170 int res; 1170 int res;
1171 1171
1172 snd_power_lock(card); 1172 snd_power_lock(card);
1173 if ((res = snd_power_wait(card, SNDRV_CTL_POWER_D0, substream->ffile)) >= 0) 1173 if ((res = snd_power_wait(card, SNDRV_CTL_POWER_D0)) >= 0)
1174 res = snd_pcm_action_lock_irq(&snd_pcm_action_resume, substream, 0); 1174 res = snd_pcm_action_lock_irq(&snd_pcm_action_resume, substream, 0);
1175 snd_power_unlock(card); 1175 snd_power_unlock(card);
1176 return res; 1176 return res;
@@ -1198,7 +1198,7 @@ static int snd_pcm_xrun(struct snd_pcm_substream *substream)
1198 1198
1199 snd_power_lock(card); 1199 snd_power_lock(card);
1200 if (runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { 1200 if (runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
1201 result = snd_power_wait(card, SNDRV_CTL_POWER_D0, substream->ffile); 1201 result = snd_power_wait(card, SNDRV_CTL_POWER_D0);
1202 if (result < 0) 1202 if (result < 0)
1203 goto _unlock; 1203 goto _unlock;
1204 } 1204 }
@@ -1313,13 +1313,13 @@ static struct action_ops snd_pcm_action_prepare = {
1313 * 1313 *
1314 * Prepare the PCM substream to be triggerable. 1314 * Prepare the PCM substream to be triggerable.
1315 */ 1315 */
1316int snd_pcm_prepare(struct snd_pcm_substream *substream) 1316static int snd_pcm_prepare(struct snd_pcm_substream *substream)
1317{ 1317{
1318 int res; 1318 int res;
1319 struct snd_card *card = substream->pcm->card; 1319 struct snd_card *card = substream->pcm->card;
1320 1320
1321 snd_power_lock(card); 1321 snd_power_lock(card);
1322 if ((res = snd_power_wait(card, SNDRV_CTL_POWER_D0, substream->ffile)) >= 0) 1322 if ((res = snd_power_wait(card, SNDRV_CTL_POWER_D0)) >= 0)
1323 res = snd_pcm_action_nonatomic(&snd_pcm_action_prepare, substream, 0); 1323 res = snd_pcm_action_nonatomic(&snd_pcm_action_prepare, substream, 0);
1324 snd_power_unlock(card); 1324 snd_power_unlock(card);
1325 return res; 1325 return res;
@@ -1410,7 +1410,7 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream)
1410 1410
1411 snd_power_lock(card); 1411 snd_power_lock(card);
1412 if (runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { 1412 if (runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
1413 result = snd_power_wait(card, SNDRV_CTL_POWER_D0, substream->ffile); 1413 result = snd_power_wait(card, SNDRV_CTL_POWER_D0);
1414 if (result < 0) { 1414 if (result < 0) {
1415 snd_power_unlock(card); 1415 snd_power_unlock(card);
1416 return result; 1416 return result;
@@ -1533,7 +1533,7 @@ static int snd_pcm_drop(struct snd_pcm_substream *substream)
1533 1533
1534 snd_power_lock(card); 1534 snd_power_lock(card);
1535 if (runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { 1535 if (runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
1536 result = snd_power_wait(card, SNDRV_CTL_POWER_D0, substream->ffile); 1536 result = snd_power_wait(card, SNDRV_CTL_POWER_D0);
1537 if (result < 0) 1537 if (result < 0)
1538 goto _unlock; 1538 goto _unlock;
1539 } 1539 }
@@ -1995,28 +1995,63 @@ static void snd_pcm_remove_file(struct snd_pcm_str *str,
1995 } 1995 }
1996} 1996}
1997 1997
1998static int snd_pcm_release_file(struct snd_pcm_file * pcm_file) 1998static void pcm_release_private(struct snd_pcm_substream *substream)
1999{ 1999{
2000 struct snd_pcm_substream *substream; 2000 struct snd_pcm_file *pcm_file = substream->file;
2001 struct snd_pcm_runtime *runtime;
2002 struct snd_pcm_str * str;
2003 2001
2004 snd_assert(pcm_file != NULL, return -ENXIO);
2005 substream = pcm_file->substream;
2006 snd_assert(substream != NULL, return -ENXIO);
2007 runtime = substream->runtime;
2008 str = substream->pstr;
2009 snd_pcm_unlink(substream); 2002 snd_pcm_unlink(substream);
2010 if (substream->ffile != NULL) { 2003 snd_pcm_remove_file(substream->pstr, pcm_file);
2004 kfree(pcm_file);
2005}
2006
2007void snd_pcm_release_substream(struct snd_pcm_substream *substream)
2008{
2009 snd_pcm_drop(substream);
2010 if (substream->pcm_release)
2011 substream->pcm_release(substream);
2012 if (substream->hw_opened) {
2011 if (substream->ops->hw_free != NULL) 2013 if (substream->ops->hw_free != NULL)
2012 substream->ops->hw_free(substream); 2014 substream->ops->hw_free(substream);
2013 substream->ops->close(substream); 2015 substream->ops->close(substream);
2014 substream->ffile = NULL; 2016 substream->hw_opened = 0;
2015 } 2017 }
2016 snd_pcm_remove_file(str, pcm_file); 2018 snd_pcm_detach_substream(substream);
2017 snd_pcm_release_substream(substream); 2019}
2018 kfree(pcm_file); 2020
2021int snd_pcm_open_substream(struct snd_pcm *pcm, int stream,
2022 struct file *file,
2023 struct snd_pcm_substream **rsubstream)
2024{
2025 struct snd_pcm_substream *substream;
2026 int err;
2027
2028 err = snd_pcm_attach_substream(pcm, stream, file, &substream);
2029 if (err < 0)
2030 return err;
2031 substream->no_mmap_ctrl = 0;
2032 err = snd_pcm_hw_constraints_init(substream);
2033 if (err < 0) {
2034 snd_printd("snd_pcm_hw_constraints_init failed\n");
2035 goto error;
2036 }
2037
2038 if ((err = substream->ops->open(substream)) < 0)
2039 goto error;
2040
2041 substream->hw_opened = 1;
2042
2043 err = snd_pcm_hw_constraints_complete(substream);
2044 if (err < 0) {
2045 snd_printd("snd_pcm_hw_constraints_complete failed\n");
2046 goto error;
2047 }
2048
2049 *rsubstream = substream;
2019 return 0; 2050 return 0;
2051
2052 error:
2053 snd_pcm_release_substream(substream);
2054 return err;
2020} 2055}
2021 2056
2022static int snd_pcm_open_file(struct file *file, 2057static int snd_pcm_open_file(struct file *file,
@@ -2024,52 +2059,29 @@ static int snd_pcm_open_file(struct file *file,
2024 int stream, 2059 int stream,
2025 struct snd_pcm_file **rpcm_file) 2060 struct snd_pcm_file **rpcm_file)
2026{ 2061{
2027 int err = 0;
2028 struct snd_pcm_file *pcm_file; 2062 struct snd_pcm_file *pcm_file;
2029 struct snd_pcm_substream *substream; 2063 struct snd_pcm_substream *substream;
2030 struct snd_pcm_str *str; 2064 struct snd_pcm_str *str;
2065 int err;
2031 2066
2032 snd_assert(rpcm_file != NULL, return -EINVAL); 2067 snd_assert(rpcm_file != NULL, return -EINVAL);
2033 *rpcm_file = NULL; 2068 *rpcm_file = NULL;
2034 2069
2070 err = snd_pcm_open_substream(pcm, stream, file, &substream);
2071 if (err < 0)
2072 return err;
2073
2035 pcm_file = kzalloc(sizeof(*pcm_file), GFP_KERNEL); 2074 pcm_file = kzalloc(sizeof(*pcm_file), GFP_KERNEL);
2036 if (pcm_file == NULL) { 2075 if (pcm_file == NULL) {
2076 snd_pcm_release_substream(substream);
2037 return -ENOMEM; 2077 return -ENOMEM;
2038 } 2078 }
2039
2040 if ((err = snd_pcm_open_substream(pcm, stream, &substream)) < 0) {
2041 kfree(pcm_file);
2042 return err;
2043 }
2044
2045 str = substream->pstr; 2079 str = substream->pstr;
2046 substream->file = pcm_file; 2080 substream->file = pcm_file;
2047 substream->no_mmap_ctrl = 0; 2081 substream->pcm_release = pcm_release_private;
2048
2049 pcm_file->substream = substream; 2082 pcm_file->substream = substream;
2050
2051 snd_pcm_add_file(str, pcm_file); 2083 snd_pcm_add_file(str, pcm_file);
2052 2084
2053 err = snd_pcm_hw_constraints_init(substream);
2054 if (err < 0) {
2055 snd_printd("snd_pcm_hw_constraints_init failed\n");
2056 snd_pcm_release_file(pcm_file);
2057 return err;
2058 }
2059
2060 if ((err = substream->ops->open(substream)) < 0) {
2061 snd_pcm_release_file(pcm_file);
2062 return err;
2063 }
2064 substream->ffile = file;
2065
2066 err = snd_pcm_hw_constraints_complete(substream);
2067 if (err < 0) {
2068 snd_printd("snd_pcm_hw_constraints_complete failed\n");
2069 snd_pcm_release_file(pcm_file);
2070 return err;
2071 }
2072
2073 file->private_data = pcm_file; 2085 file->private_data = pcm_file;
2074 *rpcm_file = pcm_file; 2086 *rpcm_file = pcm_file;
2075 return 0; 2087 return 0;
@@ -2158,10 +2170,9 @@ static int snd_pcm_release(struct inode *inode, struct file *file)
2158 snd_assert(substream != NULL, return -ENXIO); 2170 snd_assert(substream != NULL, return -ENXIO);
2159 snd_assert(!atomic_read(&substream->runtime->mmap_count), ); 2171 snd_assert(!atomic_read(&substream->runtime->mmap_count), );
2160 pcm = substream->pcm; 2172 pcm = substream->pcm;
2161 snd_pcm_drop(substream);
2162 fasync_helper(-1, file, 0, &substream->runtime->fasync); 2173 fasync_helper(-1, file, 0, &substream->runtime->fasync);
2163 mutex_lock(&pcm->open_mutex); 2174 mutex_lock(&pcm->open_mutex);
2164 snd_pcm_release_file(pcm_file); 2175 snd_pcm_release_substream(substream);
2165 mutex_unlock(&pcm->open_mutex); 2176 mutex_unlock(&pcm->open_mutex);
2166 wake_up(&pcm->open_wait); 2177 wake_up(&pcm->open_wait);
2167 module_put(pcm->card->module); 2178 module_put(pcm->card->module);
@@ -2480,11 +2491,6 @@ static int snd_pcm_sync_ptr(struct snd_pcm_substream *substream,
2480 return 0; 2491 return 0;
2481} 2492}
2482 2493
2483static int snd_pcm_playback_ioctl1(struct snd_pcm_substream *substream,
2484 unsigned int cmd, void __user *arg);
2485static int snd_pcm_capture_ioctl1(struct snd_pcm_substream *substream,
2486 unsigned int cmd, void __user *arg);
2487
2488static int snd_pcm_common_ioctl1(struct snd_pcm_substream *substream, 2494static int snd_pcm_common_ioctl1(struct snd_pcm_substream *substream,
2489 unsigned int cmd, void __user *arg) 2495 unsigned int cmd, void __user *arg)
2490{ 2496{
@@ -2736,41 +2742,28 @@ static long snd_pcm_capture_ioctl(struct file *file, unsigned int cmd,
2736 return snd_pcm_capture_ioctl1(pcm_file->substream, cmd, (void __user *)arg); 2742 return snd_pcm_capture_ioctl1(pcm_file->substream, cmd, (void __user *)arg);
2737} 2743}
2738 2744
2739int snd_pcm_kernel_playback_ioctl(struct snd_pcm_substream *substream, 2745int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream,
2740 unsigned int cmd, void *arg) 2746 unsigned int cmd, void *arg)
2741{
2742 mm_segment_t fs;
2743 int result;
2744
2745 fs = snd_enter_user();
2746 result = snd_pcm_playback_ioctl1(substream, cmd, (void __user *)arg);
2747 snd_leave_user(fs);
2748 return result;
2749}
2750
2751int snd_pcm_kernel_capture_ioctl(struct snd_pcm_substream *substream,
2752 unsigned int cmd, void *arg)
2753{ 2747{
2754 mm_segment_t fs; 2748 mm_segment_t fs;
2755 int result; 2749 int result;
2756 2750
2757 fs = snd_enter_user(); 2751 fs = snd_enter_user();
2758 result = snd_pcm_capture_ioctl1(substream, cmd, (void __user *)arg);
2759 snd_leave_user(fs);
2760 return result;
2761}
2762
2763int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream,
2764 unsigned int cmd, void *arg)
2765{
2766 switch (substream->stream) { 2752 switch (substream->stream) {
2767 case SNDRV_PCM_STREAM_PLAYBACK: 2753 case SNDRV_PCM_STREAM_PLAYBACK:
2768 return snd_pcm_kernel_playback_ioctl(substream, cmd, arg); 2754 result = snd_pcm_playback_ioctl1(substream,
2755 cmd, (void __user *)arg);
2756 break;
2769 case SNDRV_PCM_STREAM_CAPTURE: 2757 case SNDRV_PCM_STREAM_CAPTURE:
2770 return snd_pcm_kernel_capture_ioctl(substream, cmd, arg); 2758 result = snd_pcm_capture_ioctl1(substream,
2759 cmd, (void __user *)arg);
2760 break;
2771 default: 2761 default:
2772 return -EINVAL; 2762 result = -EINVAL;
2763 break;
2773 } 2764 }
2765 snd_leave_user(fs);
2766 return result;
2774} 2767}
2775 2768
2776static ssize_t snd_pcm_read(struct file *file, char __user *buf, size_t count, 2769static ssize_t snd_pcm_read(struct file *file, char __user *buf, size_t count,