Commit 34906633 authored by Mauro Carvalho Chehab's avatar Mauro Carvalho Chehab

[media] em28xx-audio: don't wait for lock in non-block mode

Pulseaudio has the bad habit of stopping a streaming audio if
a device, opened in non-block mode, waits.

It is impossible to avoid em28xx to wait, as it will send commands
via I2C, and other I2C operations may be happening (firmware
transfers, Remote Controller polling, etc). Yet, as each em28xx
subdriver locks em28xx-dev to protect the access to the hardware,
it is possible to minimize the audio glitches by returning -EAGAIN
to pulseaudio, if the lock is already taken by another subdriver.
Reported-by: default avatarAntti Palosaari <crope@iki.fi>
Tested-by: default avatarAntti Palosaari <crope@iki.fi>
Signed-off-by: default avatarMauro Carvalho Chehab <m.chehab@samsung.com>
parent 49677aef
...@@ -258,6 +258,13 @@ static int snd_em28xx_capture_open(struct snd_pcm_substream *substream) ...@@ -258,6 +258,13 @@ static int snd_em28xx_capture_open(struct snd_pcm_substream *substream)
runtime->hw = snd_em28xx_hw_capture; runtime->hw = snd_em28xx_hw_capture;
if ((dev->alt == 0 || dev->audio_ifnum) && dev->adev.users == 0) { if ((dev->alt == 0 || dev->audio_ifnum) && dev->adev.users == 0) {
int nonblock = !!(substream->f_flags & O_NONBLOCK);
if (nonblock) {
if (!mutex_trylock(&dev->lock))
return -EAGAIN;
} else
mutex_lock(&dev->lock);
if (dev->audio_ifnum) if (dev->audio_ifnum)
dev->alt = 1; dev->alt = 1;
else else
...@@ -269,7 +276,6 @@ static int snd_em28xx_capture_open(struct snd_pcm_substream *substream) ...@@ -269,7 +276,6 @@ static int snd_em28xx_capture_open(struct snd_pcm_substream *substream)
/* Sets volume, mute, etc */ /* Sets volume, mute, etc */
dev->mute = 0; dev->mute = 0;
mutex_lock(&dev->lock);
ret = em28xx_audio_analog_set(dev); ret = em28xx_audio_analog_set(dev);
if (ret < 0) if (ret < 0)
goto err; goto err;
...@@ -441,11 +447,19 @@ static int em28xx_vol_put(struct snd_kcontrol *kcontrol, ...@@ -441,11 +447,19 @@ static int em28xx_vol_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *value) struct snd_ctl_elem_value *value)
{ {
struct em28xx *dev = snd_kcontrol_chip(kcontrol); struct em28xx *dev = snd_kcontrol_chip(kcontrol);
struct snd_pcm_substream *substream = dev->adev.capture_pcm_substream;
u16 val = (0x1f - (value->value.integer.value[0] & 0x1f)) | u16 val = (0x1f - (value->value.integer.value[0] & 0x1f)) |
(0x1f - (value->value.integer.value[1] & 0x1f)) << 8; (0x1f - (value->value.integer.value[1] & 0x1f)) << 8;
int nonblock = 0;
int rc; int rc;
mutex_lock(&dev->lock); if (substream)
nonblock = !!(substream->f_flags & O_NONBLOCK);
if (nonblock) {
if (!mutex_trylock(&dev->lock))
return -EAGAIN;
} else
mutex_lock(&dev->lock);
rc = em28xx_read_ac97(dev, kcontrol->private_value); rc = em28xx_read_ac97(dev, kcontrol->private_value);
if (rc < 0) if (rc < 0)
goto err; goto err;
...@@ -470,9 +484,17 @@ static int em28xx_vol_get(struct snd_kcontrol *kcontrol, ...@@ -470,9 +484,17 @@ static int em28xx_vol_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *value) struct snd_ctl_elem_value *value)
{ {
struct em28xx *dev = snd_kcontrol_chip(kcontrol); struct em28xx *dev = snd_kcontrol_chip(kcontrol);
struct snd_pcm_substream *substream = dev->adev.capture_pcm_substream;
int nonblock = 0;
int val; int val;
mutex_lock(&dev->lock); if (substream)
nonblock = !!(substream->f_flags & O_NONBLOCK);
if (nonblock) {
if (!mutex_trylock(&dev->lock))
return -EAGAIN;
} else
mutex_lock(&dev->lock);
val = em28xx_read_ac97(dev, kcontrol->private_value); val = em28xx_read_ac97(dev, kcontrol->private_value);
mutex_unlock(&dev->lock); mutex_unlock(&dev->lock);
if (val < 0) if (val < 0)
...@@ -494,9 +516,17 @@ static int em28xx_vol_put_mute(struct snd_kcontrol *kcontrol, ...@@ -494,9 +516,17 @@ static int em28xx_vol_put_mute(struct snd_kcontrol *kcontrol,
{ {
struct em28xx *dev = snd_kcontrol_chip(kcontrol); struct em28xx *dev = snd_kcontrol_chip(kcontrol);
u16 val = value->value.integer.value[0]; u16 val = value->value.integer.value[0];
struct snd_pcm_substream *substream = dev->adev.capture_pcm_substream;
int nonblock = 0;
int rc; int rc;
mutex_lock(&dev->lock); if (substream)
nonblock = !!(substream->f_flags & O_NONBLOCK);
if (nonblock) {
if (!mutex_trylock(&dev->lock))
return -EAGAIN;
} else
mutex_lock(&dev->lock);
rc = em28xx_read_ac97(dev, kcontrol->private_value); rc = em28xx_read_ac97(dev, kcontrol->private_value);
if (rc < 0) if (rc < 0)
goto err; goto err;
...@@ -524,9 +554,17 @@ static int em28xx_vol_get_mute(struct snd_kcontrol *kcontrol, ...@@ -524,9 +554,17 @@ static int em28xx_vol_get_mute(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *value) struct snd_ctl_elem_value *value)
{ {
struct em28xx *dev = snd_kcontrol_chip(kcontrol); struct em28xx *dev = snd_kcontrol_chip(kcontrol);
struct snd_pcm_substream *substream = dev->adev.capture_pcm_substream;
int nonblock = 0;
int val; int val;
mutex_lock(&dev->lock); if (substream)
nonblock = !!(substream->f_flags & O_NONBLOCK);
if (nonblock) {
if (!mutex_trylock(&dev->lock))
return -EAGAIN;
} else
mutex_lock(&dev->lock);
val = em28xx_read_ac97(dev, kcontrol->private_value); val = em28xx_read_ac97(dev, kcontrol->private_value);
mutex_unlock(&dev->lock); mutex_unlock(&dev->lock);
if (val < 0) if (val < 0)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment