git.openpandora.org
/
pandora-kernel.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
ALSA: timer: Fix broken compat timer user status ioctl
[pandora-kernel.git]
/
sound
/
usb
/
pcm.c
diff --git
a/sound/usb/pcm.c
b/sound/usb/pcm.c
index
0220b0f
..
983e071
100644
(file)
--- a/
sound/usb/pcm.c
+++ b/
sound/usb/pcm.c
@@
-67,6
+67,8
@@
static snd_pcm_uframes_t snd_usb_pcm_pointer(struct snd_pcm_substream *substream
unsigned int hwptr_done;
subs = (struct snd_usb_substream *)substream->runtime->private_data;
unsigned int hwptr_done;
subs = (struct snd_usb_substream *)substream->runtime->private_data;
+ if (subs->stream->chip->shutdown)
+ return SNDRV_PCM_POS_XRUN;
spin_lock(&subs->lock);
hwptr_done = subs->hwptr_done;
substream->runtime->delay = snd_usb_pcm_delay(subs,
spin_lock(&subs->lock);
hwptr_done = subs->hwptr_done;
substream->runtime->delay = snd_usb_pcm_delay(subs,
@@
-373,8
+375,14
@@
static int snd_usb_hw_params(struct snd_pcm_substream *substream,
changed = subs->cur_audiofmt != fmt ||
subs->period_bytes != params_period_bytes(hw_params) ||
subs->cur_rate != rate;
changed = subs->cur_audiofmt != fmt ||
subs->period_bytes != params_period_bytes(hw_params) ||
subs->cur_rate != rate;
+
+ down_read(&subs->stream->chip->shutdown_rwsem);
+ if (subs->stream->chip->shutdown) {
+ ret = -ENODEV;
+ goto unlock;
+ }
if ((ret = set_format(subs, fmt)) < 0)
if ((ret = set_format(subs, fmt)) < 0)
-
return ret
;
+
goto unlock
;
if (subs->cur_rate != rate) {
struct usb_host_interface *alts;
if (subs->cur_rate != rate) {
struct usb_host_interface *alts;
@@
-383,12
+391,11
@@
static int snd_usb_hw_params(struct snd_pcm_substream *substream,
alts = &iface->altsetting[fmt->altset_idx];
ret = snd_usb_init_sample_rate(subs->stream->chip, subs->interface, alts, fmt, rate);
if (ret < 0)
alts = &iface->altsetting[fmt->altset_idx];
ret = snd_usb_init_sample_rate(subs->stream->chip, subs->interface, alts, fmt, rate);
if (ret < 0)
-
return ret
;
+
goto unlock
;
subs->cur_rate = rate;
}
if (changed) {
subs->cur_rate = rate;
}
if (changed) {
- mutex_lock(&subs->stream->chip->shutdown_mutex);
/* format changed */
snd_usb_release_substream_urbs(subs, 0);
/* influenced: period_bytes, channels, rate, format, */
/* format changed */
snd_usb_release_substream_urbs(subs, 0);
/* influenced: period_bytes, channels, rate, format, */
@@
-396,9
+403,10
@@
static int snd_usb_hw_params(struct snd_pcm_substream *substream,
params_rate(hw_params),
snd_pcm_format_physical_width(params_format(hw_params)) *
params_channels(hw_params));
params_rate(hw_params),
snd_pcm_format_physical_width(params_format(hw_params)) *
params_channels(hw_params));
- mutex_unlock(&subs->stream->chip->shutdown_mutex);
}
}
+unlock:
+ up_read(&subs->stream->chip->shutdown_rwsem);
return ret;
}
return ret;
}
@@
-414,9
+422,9
@@
static int snd_usb_hw_free(struct snd_pcm_substream *substream)
subs->cur_audiofmt = NULL;
subs->cur_rate = 0;
subs->period_bytes = 0;
subs->cur_audiofmt = NULL;
subs->cur_rate = 0;
subs->period_bytes = 0;
-
mutex_lock(&subs->stream->chip->shutdown_mutex
);
+
down_read(&subs->stream->chip->shutdown_rwsem
);
snd_usb_release_substream_urbs(subs, 0);
snd_usb_release_substream_urbs(subs, 0);
-
mutex_unlock(&subs->stream->chip->shutdown_mutex
);
+
up_read(&subs->stream->chip->shutdown_rwsem
);
return snd_pcm_lib_free_vmalloc_buffer(substream);
}
return snd_pcm_lib_free_vmalloc_buffer(substream);
}
@@
-429,12
+437,18
@@
static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_usb_substream *subs = runtime->private_data;
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_usb_substream *subs = runtime->private_data;
+ int ret = 0;
if (! subs->cur_audiofmt) {
snd_printk(KERN_ERR "usbaudio: no format is specified!\n");
return -ENXIO;
}
if (! subs->cur_audiofmt) {
snd_printk(KERN_ERR "usbaudio: no format is specified!\n");
return -ENXIO;
}
+ down_read(&subs->stream->chip->shutdown_rwsem);
+ if (subs->stream->chip->shutdown) {
+ ret = -ENODEV;
+ goto unlock;
+ }
/* some unit conversions in runtime */
subs->maxframesize = bytes_to_frames(runtime, subs->maxpacksize);
subs->curframesize = bytes_to_frames(runtime, subs->curpacksize);
/* some unit conversions in runtime */
subs->maxframesize = bytes_to_frames(runtime, subs->maxpacksize);
subs->curframesize = bytes_to_frames(runtime, subs->curpacksize);
@@
-447,7
+461,10
@@
static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)
subs->last_frame_number = 0;
runtime->delay = 0;
subs->last_frame_number = 0;
runtime->delay = 0;
- return snd_usb_substream_prepare(subs, runtime);
+ ret = snd_usb_substream_prepare(subs, runtime);
+ unlock:
+ up_read(&subs->stream->chip->shutdown_rwsem);
+ return ret;
}
static struct snd_pcm_hardware snd_usb_hardware =
}
static struct snd_pcm_hardware snd_usb_hardware =
@@
-500,7
+517,7
@@
static int hw_check_valid_format(struct snd_usb_substream *subs,
return 0;
}
/* check whether the period time is >= the data packet interval */
return 0;
}
/* check whether the period time is >= the data packet interval */
- if (s
nd_usb_get_speed(subs->dev)
!= USB_SPEED_FULL) {
+ if (s
ubs->speed
!= USB_SPEED_FULL) {
ptime = 125 * (1 << fp->datainterval);
if (ptime > pt->max || (ptime == pt->max && pt->openmax)) {
hwc_debug(" > check: ptime %u > max %u\n", ptime, pt->max);
ptime = 125 * (1 << fp->datainterval);
if (ptime > pt->max || (ptime == pt->max && pt->openmax)) {
hwc_debug(" > check: ptime %u > max %u\n", ptime, pt->max);
@@
-698,6
+715,9
@@
static int snd_usb_pcm_check_knot(struct snd_pcm_runtime *runtime,
int count = 0, needs_knot = 0;
int err;
int count = 0, needs_knot = 0;
int err;
+ kfree(subs->rate_list.list);
+ subs->rate_list.list = NULL;
+
list_for_each_entry(fp, &subs->fmt_list, list) {
if (fp->rates & SNDRV_PCM_RATE_CONTINUOUS)
return 0;
list_for_each_entry(fp, &subs->fmt_list, list) {
if (fp->rates & SNDRV_PCM_RATE_CONTINUOUS)
return 0;
@@
-773,7
+793,7
@@
static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre
return err;
param_period_time_if_needed = SNDRV_PCM_HW_PARAM_PERIOD_TIME;
return err;
param_period_time_if_needed = SNDRV_PCM_HW_PARAM_PERIOD_TIME;
- if (s
nd_usb_get_speed(subs->dev)
== USB_SPEED_FULL)
+ if (s
ubs->speed
== USB_SPEED_FULL)
/* full speed devices have fixed data packet interval */
ptmin = 1000;
if (ptmin == 1000)
/* full speed devices have fixed data packet interval */
ptmin = 1000;
if (ptmin == 1000)