Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 305663
b: refs/heads/master
c: 618dae1
h: refs/heads/master
i:
  305661: 47c80bd
  305659: d395938
  305655: 207e643
  305647: 8d4e7d6
  305631: 06dd040
  305599: 8b334ef
  305535: 1415f00
  305407: 41e60bf
  305151: 19a987b
v: v3
  • Loading branch information
Liam Girdwood authored and Mark Brown committed Apr 26, 2012
1 parent ede4f64 commit 5482f56
Show file tree
Hide file tree
Showing 4 changed files with 229 additions and 3 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: f86dcef87b771935c223334324a93c1d71f7a84c
refs/heads/master: 618dae11f809aaccd05710aa8cee8c46a9cef1a7
1 change: 1 addition & 0 deletions trunk/include/sound/soc-dpcm.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,5 +132,6 @@ void snd_soc_dpcm_be_set_state(struct snd_soc_pcm_runtime *be, int stream,
/* internal use only */
int soc_dpcm_be_digital_mute(struct snd_soc_pcm_runtime *fe, int mute);
int soc_dpcm_debugfs_add(struct snd_soc_pcm_runtime *rtd);
int soc_dpcm_runtime_update(struct snd_soc_dapm_widget *);

#endif
8 changes: 6 additions & 2 deletions trunk/sound/soc/soc-dapm.c
Original file line number Diff line number Diff line change
Expand Up @@ -1846,7 +1846,7 @@ static int soc_dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
dapm_power_widgets(widget->dapm, SND_SOC_DAPM_STREAM_NOP);
}

return 0;
return found;
}

int snd_soc_dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
Expand All @@ -1858,6 +1858,8 @@ int snd_soc_dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
ret = soc_dapm_mux_update_power(widget, kcontrol, mux, e);
mutex_unlock(&card->dapm_mutex);
if (ret > 0)
soc_dpcm_runtime_update(widget);
return ret;
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_mux_update_power);
Expand Down Expand Up @@ -1890,7 +1892,7 @@ static int soc_dapm_mixer_update_power(struct snd_soc_dapm_widget *widget,
dapm_power_widgets(widget->dapm, SND_SOC_DAPM_STREAM_NOP);
}

return 0;
return found;
}

int snd_soc_dapm_mixer_update_power(struct snd_soc_dapm_widget *widget,
Expand All @@ -1902,6 +1904,8 @@ int snd_soc_dapm_mixer_update_power(struct snd_soc_dapm_widget *widget,
mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
ret = soc_dapm_mixer_update_power(widget, kcontrol, connect);
mutex_unlock(&card->dapm_mutex);
if (ret > 0)
soc_dpcm_runtime_update(widget);
return ret;
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_mixer_update_power);
Expand Down
221 changes: 221 additions & 0 deletions trunk/sound/soc/soc-pcm.c
Original file line number Diff line number Diff line change
Expand Up @@ -1608,7 +1608,228 @@ int dpcm_fe_dai_prepare(struct snd_pcm_substream *substream)
return ret;
}

static int dpcm_run_update_shutdown(struct snd_soc_pcm_runtime *fe, int stream)
{
int err;

dev_dbg(fe->dev, "runtime %s close on FE %s\n",
stream ? "capture" : "playback", fe->dai_link->name);

err = dpcm_be_dai_trigger(fe, stream, SNDRV_PCM_TRIGGER_STOP);
if (err < 0)
dev_err(fe->dev,"dpcm: trigger FE failed %d\n", err);

err = dpcm_be_dai_hw_free(fe, stream);
if (err < 0)
dev_err(fe->dev,"dpcm: hw_free FE failed %d\n", err);

err = dpcm_be_dai_shutdown(fe, stream);
if (err < 0)
dev_err(fe->dev,"dpcm: shutdown FE failed %d\n", err);

/* run the stream event for each BE */
dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_NOP);

return 0;
}

static int dpcm_run_update_startup(struct snd_soc_pcm_runtime *fe, int stream)
{
struct snd_soc_dpcm *dpcm;
int ret;

dev_dbg(fe->dev, "runtime %s open on FE %s\n",
stream ? "capture" : "playback", fe->dai_link->name);

/* Only start the BE if the FE is ready */
if (fe->dpcm[stream].state == SND_SOC_DPCM_STATE_HW_FREE ||
fe->dpcm[stream].state == SND_SOC_DPCM_STATE_CLOSE)
return -EINVAL;

/* startup must always be called for new BEs */
ret = dpcm_be_dai_startup(fe, stream);
if (ret < 0) {
goto disconnect;
return ret;
}

/* keep going if FE state is > open */
if (fe->dpcm[stream].state == SND_SOC_DPCM_STATE_OPEN)
return 0;

ret = dpcm_be_dai_hw_params(fe, stream);
if (ret < 0) {
goto close;
return ret;
}

/* keep going if FE state is > hw_params */
if (fe->dpcm[stream].state == SND_SOC_DPCM_STATE_HW_PARAMS)
return 0;


ret = dpcm_be_dai_prepare(fe, stream);
if (ret < 0) {
goto hw_free;
return ret;
}

/* run the stream event for each BE */
dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_NOP);

/* keep going if FE state is > prepare */
if (fe->dpcm[stream].state == SND_SOC_DPCM_STATE_PREPARE ||
fe->dpcm[stream].state == SND_SOC_DPCM_STATE_STOP)
return 0;

dev_dbg(fe->dev, "dpcm: trigger FE %s cmd start\n",
fe->dai_link->name);

ret = dpcm_be_dai_trigger(fe, stream,
SNDRV_PCM_TRIGGER_START);
if (ret < 0) {
dev_err(fe->dev,"dpcm: trigger FE failed %d\n", ret);
goto hw_free;
}

return 0;

hw_free:
dpcm_be_dai_hw_free(fe, stream);
close:
dpcm_be_dai_shutdown(fe, stream);
disconnect:
/* disconnect any non started BEs */
list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) {
struct snd_soc_pcm_runtime *be = dpcm->be;
if (be->dpcm[stream].state != SND_SOC_DPCM_STATE_START)
dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
}

return ret;
}

static int dpcm_run_new_update(struct snd_soc_pcm_runtime *fe, int stream)
{
int ret;

fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_BE;
ret = dpcm_run_update_startup(fe, stream);
if (ret < 0)
dev_err(fe->dev, "failed to startup some BEs\n");
fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;

return ret;
}

static int dpcm_run_old_update(struct snd_soc_pcm_runtime *fe, int stream)
{
int ret;

fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_BE;
ret = dpcm_run_update_shutdown(fe, stream);
if (ret < 0)
dev_err(fe->dev, "failed to shutdown some BEs\n");
fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;

return ret;
}

/* Called by DAPM mixer/mux changes to update audio routing between PCMs and
* any DAI links.
*/
int soc_dpcm_runtime_update(struct snd_soc_dapm_widget *widget)
{
struct snd_soc_card *card;
int i, old, new, paths;

if (widget->codec)
card = widget->codec->card;
else if (widget->platform)
card = widget->platform->card;
else
return -EINVAL;

mutex_lock_nested(&card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
for (i = 0; i < card->num_rtd; i++) {
struct snd_soc_dapm_widget_list *list;
struct snd_soc_pcm_runtime *fe = &card->rtd[i];

/* make sure link is FE */
if (!fe->dai_link->dynamic)
continue;

/* only check active links */
if (!fe->cpu_dai->active)
continue;

/* DAPM sync will call this to update DSP paths */
dev_dbg(fe->dev, "DPCM runtime update for FE %s\n",
fe->dai_link->name);

/* skip if FE doesn't have playback capability */
if (!fe->cpu_dai->driver->playback.channels_min)
goto capture;

paths = dpcm_path_get(fe, SNDRV_PCM_STREAM_PLAYBACK, &list);
if (paths < 0) {
dev_warn(fe->dev, "%s no valid %s path\n",
fe->dai_link->name, "playback");
mutex_unlock(&card->mutex);
return paths;
}

/* update any new playback paths */
new = dpcm_process_paths(fe, SNDRV_PCM_STREAM_PLAYBACK, &list, 1);
if (new) {
dpcm_run_new_update(fe, SNDRV_PCM_STREAM_PLAYBACK);
dpcm_clear_pending_state(fe, SNDRV_PCM_STREAM_PLAYBACK);
dpcm_be_disconnect(fe, SNDRV_PCM_STREAM_PLAYBACK);
}

/* update any old playback paths */
old = dpcm_process_paths(fe, SNDRV_PCM_STREAM_PLAYBACK, &list, 0);
if (old) {
dpcm_run_old_update(fe, SNDRV_PCM_STREAM_PLAYBACK);
dpcm_clear_pending_state(fe, SNDRV_PCM_STREAM_PLAYBACK);
dpcm_be_disconnect(fe, SNDRV_PCM_STREAM_PLAYBACK);
}

capture:
/* skip if FE doesn't have capture capability */
if (!fe->cpu_dai->driver->capture.channels_min)
continue;

paths = dpcm_path_get(fe, SNDRV_PCM_STREAM_CAPTURE, &list);
if (paths < 0) {
dev_warn(fe->dev, "%s no valid %s path\n",
fe->dai_link->name, "capture");
mutex_unlock(&card->mutex);
return paths;
}

/* update any new capture paths */
new = dpcm_process_paths(fe, SNDRV_PCM_STREAM_CAPTURE, &list, 1);
if (new) {
dpcm_run_new_update(fe, SNDRV_PCM_STREAM_CAPTURE);
dpcm_clear_pending_state(fe, SNDRV_PCM_STREAM_CAPTURE);
dpcm_be_disconnect(fe, SNDRV_PCM_STREAM_CAPTURE);
}

/* update any old capture paths */
old = dpcm_process_paths(fe, SNDRV_PCM_STREAM_CAPTURE, &list, 0);
if (old) {
dpcm_run_old_update(fe, SNDRV_PCM_STREAM_CAPTURE);
dpcm_clear_pending_state(fe, SNDRV_PCM_STREAM_CAPTURE);
dpcm_be_disconnect(fe, SNDRV_PCM_STREAM_CAPTURE);
}

dpcm_path_put(&list);
}

mutex_unlock(&card->mutex);
return 0;
}
int soc_dpcm_be_digital_mute(struct snd_soc_pcm_runtime *fe, int mute)
{
struct snd_soc_dpcm *dpcm;
Expand Down

0 comments on commit 5482f56

Please sign in to comment.