Revert "ASoC: soc-pcm: Fix and cleanup DPCM locking"
This reverts commit 703ebcf64a which is
commit b7898396f4bbe160f546d0c5e9fa17cca9a7d153 upstream.
It is part of a series of ASoC patches that break the Android abi. If
they are needed in the future they can be brought back in an ABI-safe
way.
Bug: 161946584
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
Change-Id: I48f7a83c14b11ac22163e77431a303a08aa9e1da
This commit is contained in:
@@ -907,6 +907,8 @@ struct snd_soc_card {
|
||||
struct mutex pcm_mutex;
|
||||
enum snd_soc_pcm_subclass pcm_subclass;
|
||||
|
||||
spinlock_t dpcm_lock;
|
||||
|
||||
int (*probe)(struct snd_soc_card *card);
|
||||
int (*late_probe)(struct snd_soc_card *card);
|
||||
int (*remove)(struct snd_soc_card *card);
|
||||
|
||||
@@ -2339,6 +2339,7 @@ int snd_soc_register_card(struct snd_soc_card *card)
|
||||
mutex_init(&card->mutex);
|
||||
mutex_init(&card->dapm_mutex);
|
||||
mutex_init(&card->pcm_mutex);
|
||||
spin_lock_init(&card->dpcm_lock);
|
||||
|
||||
return snd_soc_bind_card(card);
|
||||
}
|
||||
|
||||
@@ -27,31 +27,6 @@
|
||||
#include <sound/soc-link.h>
|
||||
#include <sound/initval.h>
|
||||
|
||||
static inline void snd_soc_dpcm_mutex_lock(struct snd_soc_pcm_runtime *rtd)
|
||||
{
|
||||
mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
|
||||
}
|
||||
|
||||
static inline void snd_soc_dpcm_mutex_unlock(struct snd_soc_pcm_runtime *rtd)
|
||||
{
|
||||
mutex_unlock(&rtd->card->pcm_mutex);
|
||||
}
|
||||
|
||||
#define snd_soc_dpcm_mutex_assert_held(rtd) \
|
||||
lockdep_assert_held(&(rtd)->card->pcm_mutex)
|
||||
|
||||
static inline void snd_soc_dpcm_stream_lock_irq(struct snd_soc_pcm_runtime *rtd,
|
||||
int stream)
|
||||
{
|
||||
snd_pcm_stream_lock_irq(snd_soc_dpcm_get_substream(rtd, stream));
|
||||
}
|
||||
|
||||
static inline void snd_soc_dpcm_stream_unlock_irq(struct snd_soc_pcm_runtime *rtd,
|
||||
int stream)
|
||||
{
|
||||
snd_pcm_stream_unlock_irq(snd_soc_dpcm_get_substream(rtd, stream));
|
||||
}
|
||||
|
||||
#define DPCM_MAX_BE_USERS 8
|
||||
|
||||
static inline const char *soc_cpu_dai_name(struct snd_soc_pcm_runtime *rtd)
|
||||
@@ -98,6 +73,7 @@ static ssize_t dpcm_show_state(struct snd_soc_pcm_runtime *fe,
|
||||
struct snd_pcm_hw_params *params = &fe->dpcm[stream].hw_params;
|
||||
struct snd_soc_dpcm *dpcm;
|
||||
ssize_t offset = 0;
|
||||
unsigned long flags;
|
||||
|
||||
/* FE state */
|
||||
offset += scnprintf(buf + offset, size - offset,
|
||||
@@ -125,6 +101,7 @@ static ssize_t dpcm_show_state(struct snd_soc_pcm_runtime *fe,
|
||||
goto out;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&fe->card->dpcm_lock, flags);
|
||||
for_each_dpcm_be(fe, stream, dpcm) {
|
||||
struct snd_soc_pcm_runtime *be = dpcm->be;
|
||||
params = &dpcm->hw_params;
|
||||
@@ -145,6 +122,7 @@ static ssize_t dpcm_show_state(struct snd_soc_pcm_runtime *fe,
|
||||
params_channels(params),
|
||||
params_rate(params));
|
||||
}
|
||||
spin_unlock_irqrestore(&fe->card->dpcm_lock, flags);
|
||||
out:
|
||||
return offset;
|
||||
}
|
||||
@@ -167,13 +145,11 @@ static ssize_t dpcm_state_read_file(struct file *file, char __user *user_buf,
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
snd_soc_dpcm_mutex_lock(fe);
|
||||
for_each_pcm_streams(stream)
|
||||
if (snd_soc_dai_stream_valid(asoc_rtd_to_cpu(fe, 0), stream))
|
||||
offset += dpcm_show_state(fe, stream,
|
||||
buf + offset,
|
||||
out_count - offset);
|
||||
snd_soc_dpcm_mutex_unlock(fe);
|
||||
|
||||
ret = simple_read_from_buffer(user_buf, count, ppos, buf, offset);
|
||||
|
||||
@@ -245,14 +221,14 @@ static void dpcm_set_fe_update_state(struct snd_soc_pcm_runtime *fe,
|
||||
struct snd_pcm_substream *substream =
|
||||
snd_soc_dpcm_get_substream(fe, stream);
|
||||
|
||||
snd_soc_dpcm_stream_lock_irq(fe, stream);
|
||||
snd_pcm_stream_lock_irq(substream);
|
||||
if (state == SND_SOC_DPCM_UPDATE_NO && fe->dpcm[stream].trigger_pending) {
|
||||
dpcm_fe_dai_do_trigger(substream,
|
||||
fe->dpcm[stream].trigger_pending - 1);
|
||||
fe->dpcm[stream].trigger_pending = 0;
|
||||
}
|
||||
fe->dpcm[stream].runtime_update = state;
|
||||
snd_soc_dpcm_stream_unlock_irq(fe, stream);
|
||||
snd_pcm_stream_unlock_irq(substream);
|
||||
}
|
||||
|
||||
static void dpcm_set_be_update_state(struct snd_soc_pcm_runtime *be,
|
||||
@@ -280,7 +256,7 @@ void snd_soc_runtime_action(struct snd_soc_pcm_runtime *rtd,
|
||||
struct snd_soc_dai *dai;
|
||||
int i;
|
||||
|
||||
snd_soc_dpcm_mutex_assert_held(rtd);
|
||||
lockdep_assert_held(&rtd->card->pcm_mutex);
|
||||
|
||||
for_each_rtd_dais(rtd, i, dai)
|
||||
snd_soc_dai_action(dai, stream, action);
|
||||
@@ -333,8 +309,6 @@ int dpcm_dapm_stream_event(struct snd_soc_pcm_runtime *fe, int dir,
|
||||
{
|
||||
struct snd_soc_dpcm *dpcm;
|
||||
|
||||
snd_soc_dpcm_mutex_assert_held(fe);
|
||||
|
||||
for_each_dpcm_be(fe, dir, dpcm) {
|
||||
|
||||
struct snd_soc_pcm_runtime *be = dpcm->be;
|
||||
@@ -672,14 +646,14 @@ static int soc_pcm_components_close(struct snd_pcm_substream *substream,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int soc_pcm_clean(struct snd_soc_pcm_runtime *rtd,
|
||||
struct snd_pcm_substream *substream, int rollback)
|
||||
static int soc_pcm_clean(struct snd_pcm_substream *substream, int rollback)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
|
||||
struct snd_soc_component *component;
|
||||
struct snd_soc_dai *dai;
|
||||
int i;
|
||||
|
||||
snd_soc_dpcm_mutex_assert_held(rtd);
|
||||
mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
|
||||
|
||||
if (!rollback)
|
||||
snd_soc_runtime_deactivate(rtd, substream->stream);
|
||||
@@ -691,6 +665,9 @@ static int soc_pcm_clean(struct snd_soc_pcm_runtime *rtd,
|
||||
|
||||
soc_pcm_components_close(substream, rollback);
|
||||
|
||||
|
||||
mutex_unlock(&rtd->card->pcm_mutex);
|
||||
|
||||
snd_soc_pcm_component_pm_runtime_put(rtd, substream, rollback);
|
||||
|
||||
for_each_rtd_components(rtd, i, component)
|
||||
@@ -705,21 +682,9 @@ static int soc_pcm_clean(struct snd_soc_pcm_runtime *rtd,
|
||||
* freed here. The cpu DAI, codec DAI, machine and components are also
|
||||
* shutdown.
|
||||
*/
|
||||
static int __soc_pcm_close(struct snd_soc_pcm_runtime *rtd,
|
||||
struct snd_pcm_substream *substream)
|
||||
{
|
||||
return soc_pcm_clean(rtd, substream, 0);
|
||||
}
|
||||
|
||||
/* PCM close ops for non-DPCM streams */
|
||||
static int soc_pcm_close(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
|
||||
|
||||
snd_soc_dpcm_mutex_lock(rtd);
|
||||
soc_pcm_clean(rtd, substream, 0);
|
||||
snd_soc_dpcm_mutex_unlock(rtd);
|
||||
return 0;
|
||||
return soc_pcm_clean(substream, 0);
|
||||
}
|
||||
|
||||
static int soc_hw_sanity_check(struct snd_pcm_substream *substream)
|
||||
@@ -765,21 +730,21 @@ config_err:
|
||||
* then initialized and any private data can be allocated. This also calls
|
||||
* startup for the cpu DAI, component, machine and codec DAI.
|
||||
*/
|
||||
static int __soc_pcm_open(struct snd_soc_pcm_runtime *rtd,
|
||||
struct snd_pcm_substream *substream)
|
||||
static int soc_pcm_open(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
|
||||
struct snd_soc_component *component;
|
||||
struct snd_soc_dai *dai;
|
||||
int i, ret = 0;
|
||||
|
||||
snd_soc_dpcm_mutex_assert_held(rtd);
|
||||
|
||||
for_each_rtd_components(rtd, i, component)
|
||||
pinctrl_pm_select_default_state(component->dev);
|
||||
|
||||
ret = snd_soc_pcm_component_pm_runtime_get(rtd, substream);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
goto pm_err;
|
||||
|
||||
mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
|
||||
|
||||
ret = soc_pcm_components_open(substream);
|
||||
if (ret < 0)
|
||||
@@ -821,26 +786,16 @@ dynamic:
|
||||
snd_soc_runtime_activate(rtd, substream->stream);
|
||||
ret = 0;
|
||||
err:
|
||||
mutex_unlock(&rtd->card->pcm_mutex);
|
||||
pm_err:
|
||||
if (ret < 0) {
|
||||
soc_pcm_clean(rtd, substream, 1);
|
||||
soc_pcm_clean(substream, 1);
|
||||
dev_err(rtd->dev, "%s() failed (%d)", __func__, ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* PCM open ops for non-DPCM streams */
|
||||
static int soc_pcm_open(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
|
||||
int ret;
|
||||
|
||||
snd_soc_dpcm_mutex_lock(rtd);
|
||||
ret = __soc_pcm_open(rtd, substream);
|
||||
snd_soc_dpcm_mutex_unlock(rtd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void codec2codec_close_delayed_work(struct snd_soc_pcm_runtime *rtd)
|
||||
{
|
||||
/*
|
||||
@@ -856,13 +811,13 @@ static void codec2codec_close_delayed_work(struct snd_soc_pcm_runtime *rtd)
|
||||
* rate, etc. This function is non atomic and can be called multiple times,
|
||||
* it can refer to the runtime info.
|
||||
*/
|
||||
static int __soc_pcm_prepare(struct snd_soc_pcm_runtime *rtd,
|
||||
struct snd_pcm_substream *substream)
|
||||
static int soc_pcm_prepare(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
|
||||
struct snd_soc_dai *dai;
|
||||
int i, ret = 0;
|
||||
|
||||
snd_soc_dpcm_mutex_assert_held(rtd);
|
||||
mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
|
||||
|
||||
ret = snd_soc_link_prepare(substream);
|
||||
if (ret < 0)
|
||||
@@ -890,24 +845,14 @@ static int __soc_pcm_prepare(struct snd_soc_pcm_runtime *rtd,
|
||||
snd_soc_dai_digital_mute(dai, 0, substream->stream);
|
||||
|
||||
out:
|
||||
mutex_unlock(&rtd->card->pcm_mutex);
|
||||
|
||||
if (ret < 0)
|
||||
dev_err(rtd->dev, "ASoC: %s() failed (%d)\n", __func__, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* PCM prepare ops for non-DPCM streams */
|
||||
static int soc_pcm_prepare(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
|
||||
int ret;
|
||||
|
||||
snd_soc_dpcm_mutex_lock(rtd);
|
||||
ret = __soc_pcm_prepare(rtd, substream);
|
||||
snd_soc_dpcm_mutex_unlock(rtd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void soc_pcm_codec_params_fixup(struct snd_pcm_hw_params *params,
|
||||
unsigned int mask)
|
||||
{
|
||||
@@ -919,13 +864,13 @@ static void soc_pcm_codec_params_fixup(struct snd_pcm_hw_params *params,
|
||||
interval->max = channels;
|
||||
}
|
||||
|
||||
static int soc_pcm_hw_clean(struct snd_soc_pcm_runtime *rtd,
|
||||
struct snd_pcm_substream *substream, int rollback)
|
||||
static int soc_pcm_hw_clean(struct snd_pcm_substream *substream, int rollback)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
|
||||
struct snd_soc_dai *dai;
|
||||
int i;
|
||||
|
||||
snd_soc_dpcm_mutex_assert_held(rtd);
|
||||
mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
|
||||
|
||||
/* clear the corresponding DAIs parameters when going to be inactive */
|
||||
for_each_rtd_dais(rtd, i, dai) {
|
||||
@@ -955,28 +900,16 @@ static int soc_pcm_hw_clean(struct snd_soc_pcm_runtime *rtd,
|
||||
snd_soc_dai_hw_free(dai, substream, rollback);
|
||||
}
|
||||
|
||||
mutex_unlock(&rtd->card->pcm_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Frees resources allocated by hw_params, can be called multiple times
|
||||
*/
|
||||
static int __soc_pcm_hw_free(struct snd_soc_pcm_runtime *rtd,
|
||||
struct snd_pcm_substream *substream)
|
||||
{
|
||||
return soc_pcm_hw_clean(rtd, substream, 0);
|
||||
}
|
||||
|
||||
/* hw_free PCM ops for non-DPCM streams */
|
||||
static int soc_pcm_hw_free(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
|
||||
int ret;
|
||||
|
||||
snd_soc_dpcm_mutex_lock(rtd);
|
||||
ret = __soc_pcm_hw_free(rtd, substream);
|
||||
snd_soc_dpcm_mutex_unlock(rtd);
|
||||
return ret;
|
||||
return soc_pcm_hw_clean(substream, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -984,15 +917,15 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream)
|
||||
* function can also be called multiple times and can allocate buffers
|
||||
* (using snd_pcm_lib_* ). It's non-atomic.
|
||||
*/
|
||||
static int __soc_pcm_hw_params(struct snd_soc_pcm_runtime *rtd,
|
||||
struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params)
|
||||
static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
|
||||
struct snd_soc_dai *cpu_dai;
|
||||
struct snd_soc_dai *codec_dai;
|
||||
int i, ret = 0;
|
||||
|
||||
snd_soc_dpcm_mutex_assert_held(rtd);
|
||||
mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
|
||||
|
||||
ret = soc_pcm_params_symmetry(substream, params);
|
||||
if (ret)
|
||||
@@ -1064,27 +997,16 @@ static int __soc_pcm_hw_params(struct snd_soc_pcm_runtime *rtd,
|
||||
|
||||
ret = snd_soc_pcm_component_hw_params(substream, params);
|
||||
out:
|
||||
mutex_unlock(&rtd->card->pcm_mutex);
|
||||
|
||||
if (ret < 0) {
|
||||
soc_pcm_hw_clean(rtd, substream, 1);
|
||||
soc_pcm_hw_clean(substream, 1);
|
||||
dev_err(rtd->dev, "ASoC: %s() failed (%d)\n", __func__, ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* hw_params PCM ops for non-DPCM streams */
|
||||
static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
|
||||
int ret;
|
||||
|
||||
snd_soc_dpcm_mutex_lock(rtd);
|
||||
ret = __soc_pcm_hw_params(rtd, substream, params);
|
||||
snd_soc_dpcm_mutex_unlock(rtd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
|
||||
@@ -1204,8 +1126,7 @@ static int dpcm_be_connect(struct snd_soc_pcm_runtime *fe,
|
||||
struct snd_pcm_substream *fe_substream;
|
||||
struct snd_pcm_substream *be_substream;
|
||||
struct snd_soc_dpcm *dpcm;
|
||||
|
||||
snd_soc_dpcm_mutex_assert_held(fe);
|
||||
unsigned long flags;
|
||||
|
||||
/* only add new dpcms */
|
||||
for_each_dpcm_be(fe, stream, dpcm) {
|
||||
@@ -1235,10 +1156,10 @@ static int dpcm_be_connect(struct snd_soc_pcm_runtime *fe,
|
||||
dpcm->fe = fe;
|
||||
be->dpcm[stream].runtime = fe->dpcm[stream].runtime;
|
||||
dpcm->state = SND_SOC_DPCM_LINK_STATE_NEW;
|
||||
snd_soc_dpcm_stream_lock_irq(fe, stream);
|
||||
spin_lock_irqsave(&fe->card->dpcm_lock, flags);
|
||||
list_add(&dpcm->list_be, &fe->dpcm[stream].be_clients);
|
||||
list_add(&dpcm->list_fe, &be->dpcm[stream].fe_clients);
|
||||
snd_soc_dpcm_stream_unlock_irq(fe, stream);
|
||||
spin_unlock_irqrestore(&fe->card->dpcm_lock, flags);
|
||||
|
||||
dev_dbg(fe->dev, "connected new DPCM %s path %s %s %s\n",
|
||||
stream ? "capture" : "playback", fe->dai_link->name,
|
||||
@@ -1283,10 +1204,8 @@ static void dpcm_be_reparent(struct snd_soc_pcm_runtime *fe,
|
||||
void dpcm_be_disconnect(struct snd_soc_pcm_runtime *fe, int stream)
|
||||
{
|
||||
struct snd_soc_dpcm *dpcm, *d;
|
||||
unsigned long flags;
|
||||
|
||||
snd_soc_dpcm_mutex_assert_held(fe);
|
||||
|
||||
snd_soc_dpcm_stream_lock_irq(fe, stream);
|
||||
for_each_dpcm_be_safe(fe, stream, dpcm, d) {
|
||||
dev_dbg(fe->dev, "ASoC: BE %s disconnect check for %s\n",
|
||||
stream ? "capture" : "playback",
|
||||
@@ -1304,11 +1223,12 @@ void dpcm_be_disconnect(struct snd_soc_pcm_runtime *fe, int stream)
|
||||
|
||||
dpcm_remove_debugfs_state(dpcm);
|
||||
|
||||
spin_lock_irqsave(&fe->card->dpcm_lock, flags);
|
||||
list_del(&dpcm->list_be);
|
||||
list_del(&dpcm->list_fe);
|
||||
spin_unlock_irqrestore(&fe->card->dpcm_lock, flags);
|
||||
kfree(dpcm);
|
||||
}
|
||||
snd_soc_dpcm_stream_unlock_irq(fe, stream);
|
||||
}
|
||||
|
||||
/* get BE for DAI widget and stream */
|
||||
@@ -1525,9 +1445,12 @@ int dpcm_process_paths(struct snd_soc_pcm_runtime *fe,
|
||||
void dpcm_clear_pending_state(struct snd_soc_pcm_runtime *fe, int stream)
|
||||
{
|
||||
struct snd_soc_dpcm *dpcm;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&fe->card->dpcm_lock, flags);
|
||||
for_each_dpcm_be(fe, stream, dpcm)
|
||||
dpcm_set_be_update_state(dpcm->be, stream, SND_SOC_DPCM_UPDATE_NO);
|
||||
spin_unlock_irqrestore(&fe->card->dpcm_lock, flags);
|
||||
}
|
||||
|
||||
void dpcm_be_dai_stop(struct snd_soc_pcm_runtime *fe, int stream,
|
||||
@@ -1563,12 +1486,12 @@ void dpcm_be_dai_stop(struct snd_soc_pcm_runtime *fe, int stream,
|
||||
continue;
|
||||
|
||||
if (be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_FREE) {
|
||||
__soc_pcm_hw_free(be, be_substream);
|
||||
soc_pcm_hw_free(be_substream);
|
||||
be->dpcm[stream].state = SND_SOC_DPCM_STATE_HW_FREE;
|
||||
}
|
||||
}
|
||||
|
||||
__soc_pcm_close(be, be_substream);
|
||||
soc_pcm_close(be_substream);
|
||||
be_substream->runtime = NULL;
|
||||
be->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE;
|
||||
}
|
||||
@@ -1616,7 +1539,7 @@ int dpcm_be_dai_startup(struct snd_soc_pcm_runtime *fe, int stream)
|
||||
stream ? "capture" : "playback", be->dai_link->name);
|
||||
|
||||
be_substream->runtime = be->dpcm[stream].runtime;
|
||||
err = __soc_pcm_open(be, be_substream);
|
||||
err = soc_pcm_open(be_substream);
|
||||
if (err < 0) {
|
||||
be->dpcm[stream].users--;
|
||||
if (be->dpcm[stream].users < 0)
|
||||
@@ -1864,7 +1787,7 @@ static int dpcm_fe_dai_startup(struct snd_pcm_substream *fe_substream)
|
||||
dev_dbg(fe->dev, "ASoC: open FE %s\n", fe->dai_link->name);
|
||||
|
||||
/* start the DAI frontend */
|
||||
ret = __soc_pcm_open(fe, fe_substream);
|
||||
ret = soc_pcm_open(fe_substream);
|
||||
if (ret < 0)
|
||||
goto unwind;
|
||||
|
||||
@@ -1895,8 +1818,6 @@ static int dpcm_fe_dai_shutdown(struct snd_pcm_substream *substream)
|
||||
struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(substream);
|
||||
int stream = substream->stream;
|
||||
|
||||
snd_soc_dpcm_mutex_assert_held(fe);
|
||||
|
||||
dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_FE);
|
||||
|
||||
/* shutdown the BEs */
|
||||
@@ -1905,7 +1826,7 @@ static int dpcm_fe_dai_shutdown(struct snd_pcm_substream *substream)
|
||||
dev_dbg(fe->dev, "ASoC: close FE %s\n", fe->dai_link->name);
|
||||
|
||||
/* now shutdown the frontend */
|
||||
__soc_pcm_close(fe, substream);
|
||||
soc_pcm_close(substream);
|
||||
|
||||
/* run the stream stop event */
|
||||
dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_STOP);
|
||||
@@ -1950,7 +1871,7 @@ void dpcm_be_dai_hw_free(struct snd_soc_pcm_runtime *fe, int stream)
|
||||
dev_dbg(be->dev, "ASoC: hw_free BE %s\n",
|
||||
be->dai_link->name);
|
||||
|
||||
__soc_pcm_hw_free(be, be_substream);
|
||||
soc_pcm_hw_free(be_substream);
|
||||
|
||||
be->dpcm[stream].state = SND_SOC_DPCM_STATE_HW_FREE;
|
||||
}
|
||||
@@ -1961,13 +1882,13 @@ static int dpcm_fe_dai_hw_free(struct snd_pcm_substream *substream)
|
||||
struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(substream);
|
||||
int stream = substream->stream;
|
||||
|
||||
snd_soc_dpcm_mutex_lock(fe);
|
||||
mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
|
||||
dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_FE);
|
||||
|
||||
dev_dbg(fe->dev, "ASoC: hw_free FE %s\n", fe->dai_link->name);
|
||||
|
||||
/* call hw_free on the frontend */
|
||||
soc_pcm_hw_clean(fe, substream, 0);
|
||||
soc_pcm_hw_free(substream);
|
||||
|
||||
/* only hw_params backends that are either sinks or sources
|
||||
* to this frontend DAI */
|
||||
@@ -1976,7 +1897,7 @@ static int dpcm_fe_dai_hw_free(struct snd_pcm_substream *substream)
|
||||
fe->dpcm[stream].state = SND_SOC_DPCM_STATE_HW_FREE;
|
||||
dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO);
|
||||
|
||||
snd_soc_dpcm_mutex_unlock(fe);
|
||||
mutex_unlock(&fe->card->mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2020,7 +1941,7 @@ int dpcm_be_dai_hw_params(struct snd_soc_pcm_runtime *fe, int stream)
|
||||
dev_dbg(be->dev, "ASoC: hw_params BE %s\n",
|
||||
be->dai_link->name);
|
||||
|
||||
ret = __soc_pcm_hw_params(be, be_substream, &dpcm->hw_params);
|
||||
ret = soc_pcm_hw_params(be_substream, &dpcm->hw_params);
|
||||
if (ret < 0)
|
||||
goto unwind;
|
||||
|
||||
@@ -2050,7 +1971,7 @@ unwind:
|
||||
(be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP))
|
||||
continue;
|
||||
|
||||
__soc_pcm_hw_free(be, be_substream);
|
||||
soc_pcm_hw_free(be_substream);
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -2062,7 +1983,7 @@ static int dpcm_fe_dai_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(substream);
|
||||
int ret, stream = substream->stream;
|
||||
|
||||
snd_soc_dpcm_mutex_lock(fe);
|
||||
mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
|
||||
dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_FE);
|
||||
|
||||
memcpy(&fe->dpcm[stream].hw_params, params,
|
||||
@@ -2076,7 +1997,7 @@ static int dpcm_fe_dai_hw_params(struct snd_pcm_substream *substream,
|
||||
params_channels(params), params_format(params));
|
||||
|
||||
/* call hw_params on the frontend */
|
||||
ret = __soc_pcm_hw_params(fe, substream, params);
|
||||
ret = soc_pcm_hw_params(substream, params);
|
||||
if (ret < 0)
|
||||
dpcm_be_dai_hw_free(fe, stream);
|
||||
else
|
||||
@@ -2084,7 +2005,7 @@ static int dpcm_fe_dai_hw_params(struct snd_pcm_substream *substream,
|
||||
|
||||
out:
|
||||
dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO);
|
||||
snd_soc_dpcm_mutex_unlock(fe);
|
||||
mutex_unlock(&fe->card->mutex);
|
||||
|
||||
if (ret < 0)
|
||||
dev_err(fe->dev, "ASoC: %s failed (%d)\n", __func__, ret);
|
||||
@@ -2355,7 +2276,7 @@ int dpcm_be_dai_prepare(struct snd_soc_pcm_runtime *fe, int stream)
|
||||
dev_dbg(be->dev, "ASoC: prepare BE %s\n",
|
||||
be->dai_link->name);
|
||||
|
||||
ret = __soc_pcm_prepare(be, be_substream);
|
||||
ret = soc_pcm_prepare(be_substream);
|
||||
if (ret < 0)
|
||||
break;
|
||||
|
||||
@@ -2373,7 +2294,7 @@ static int dpcm_fe_dai_prepare(struct snd_pcm_substream *substream)
|
||||
struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(substream);
|
||||
int stream = substream->stream, ret = 0;
|
||||
|
||||
snd_soc_dpcm_mutex_lock(fe);
|
||||
mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
|
||||
|
||||
dev_dbg(fe->dev, "ASoC: prepare FE %s\n", fe->dai_link->name);
|
||||
|
||||
@@ -2392,7 +2313,7 @@ static int dpcm_fe_dai_prepare(struct snd_pcm_substream *substream)
|
||||
goto out;
|
||||
|
||||
/* call prepare on the frontend */
|
||||
ret = __soc_pcm_prepare(fe, substream);
|
||||
ret = soc_pcm_prepare(substream);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
@@ -2400,7 +2321,7 @@ static int dpcm_fe_dai_prepare(struct snd_pcm_substream *substream)
|
||||
|
||||
out:
|
||||
dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO);
|
||||
snd_soc_dpcm_mutex_unlock(fe);
|
||||
mutex_unlock(&fe->card->mutex);
|
||||
|
||||
if (ret < 0)
|
||||
dev_err(fe->dev, "ASoC: %s() failed (%d)\n", __func__, ret);
|
||||
@@ -2451,6 +2372,7 @@ static int dpcm_run_update_startup(struct snd_soc_pcm_runtime *fe, int stream)
|
||||
struct snd_soc_dpcm *dpcm;
|
||||
enum snd_soc_dpcm_trigger trigger = fe->dai_link->trigger[stream];
|
||||
int ret = 0;
|
||||
unsigned long flags;
|
||||
|
||||
dev_dbg(fe->dev, "ASoC: runtime %s open on FE %s\n",
|
||||
stream ? "capture" : "playback", fe->dai_link->name);
|
||||
@@ -2519,6 +2441,7 @@ close:
|
||||
dpcm_be_dai_shutdown(fe, stream);
|
||||
disconnect:
|
||||
/* disconnect any pending BEs */
|
||||
spin_lock_irqsave(&fe->card->dpcm_lock, flags);
|
||||
for_each_dpcm_be(fe, stream, dpcm) {
|
||||
struct snd_soc_pcm_runtime *be = dpcm->be;
|
||||
|
||||
@@ -2530,6 +2453,7 @@ disconnect:
|
||||
be->dpcm[stream].state == SND_SOC_DPCM_STATE_NEW)
|
||||
dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
|
||||
}
|
||||
spin_unlock_irqrestore(&fe->card->dpcm_lock, flags);
|
||||
|
||||
if (ret < 0)
|
||||
dev_err(fe->dev, "ASoC: %s() failed (%d)\n", __func__, ret);
|
||||
@@ -2604,7 +2528,7 @@ int snd_soc_dpcm_runtime_update(struct snd_soc_card *card)
|
||||
struct snd_soc_pcm_runtime *fe;
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock_nested(&card->pcm_mutex, card->pcm_subclass);
|
||||
mutex_lock_nested(&card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
|
||||
/* shutdown all old paths first */
|
||||
for_each_card_rtds(card, fe) {
|
||||
ret = soc_dpcm_fe_runtime_update(fe, 0);
|
||||
@@ -2620,7 +2544,7 @@ int snd_soc_dpcm_runtime_update(struct snd_soc_card *card)
|
||||
}
|
||||
|
||||
out:
|
||||
mutex_unlock(&card->pcm_mutex);
|
||||
mutex_unlock(&card->mutex);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_soc_dpcm_runtime_update);
|
||||
@@ -2631,8 +2555,6 @@ static void dpcm_fe_dai_cleanup(struct snd_pcm_substream *fe_substream)
|
||||
struct snd_soc_dpcm *dpcm;
|
||||
int stream = fe_substream->stream;
|
||||
|
||||
snd_soc_dpcm_mutex_assert_held(fe);
|
||||
|
||||
/* mark FE's links ready to prune */
|
||||
for_each_dpcm_be(fe, stream, dpcm)
|
||||
dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
|
||||
@@ -2647,12 +2569,12 @@ static int dpcm_fe_dai_close(struct snd_pcm_substream *fe_substream)
|
||||
struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(fe_substream);
|
||||
int ret;
|
||||
|
||||
snd_soc_dpcm_mutex_lock(fe);
|
||||
mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
|
||||
ret = dpcm_fe_dai_shutdown(fe_substream);
|
||||
|
||||
dpcm_fe_dai_cleanup(fe_substream);
|
||||
|
||||
snd_soc_dpcm_mutex_unlock(fe);
|
||||
mutex_unlock(&fe->card->mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -2663,7 +2585,7 @@ static int dpcm_fe_dai_open(struct snd_pcm_substream *fe_substream)
|
||||
int ret;
|
||||
int stream = fe_substream->stream;
|
||||
|
||||
snd_soc_dpcm_mutex_lock(fe);
|
||||
mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
|
||||
fe->dpcm[stream].runtime = fe_substream->runtime;
|
||||
|
||||
ret = dpcm_path_get(fe, stream, &list);
|
||||
@@ -2680,7 +2602,7 @@ static int dpcm_fe_dai_open(struct snd_pcm_substream *fe_substream)
|
||||
dpcm_clear_pending_state(fe, stream);
|
||||
dpcm_path_put(&list);
|
||||
open_end:
|
||||
snd_soc_dpcm_mutex_unlock(fe);
|
||||
mutex_unlock(&fe->card->mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -2941,8 +2863,10 @@ static int snd_soc_dpcm_check_state(struct snd_soc_pcm_runtime *fe,
|
||||
struct snd_soc_dpcm *dpcm;
|
||||
int state;
|
||||
int ret = 1;
|
||||
unsigned long flags;
|
||||
int i;
|
||||
|
||||
spin_lock_irqsave(&fe->card->dpcm_lock, flags);
|
||||
for_each_dpcm_fe(be, stream, dpcm) {
|
||||
|
||||
if (dpcm->fe == fe)
|
||||
@@ -2956,6 +2880,7 @@ static int snd_soc_dpcm_check_state(struct snd_soc_pcm_runtime *fe,
|
||||
}
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&fe->card->dpcm_lock, flags);
|
||||
|
||||
/* it's safe to do this BE DAI */
|
||||
return ret;
|
||||
|
||||
Reference in New Issue
Block a user