aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/soc-dapm.c
diff options
context:
space:
mode:
authorMark Brown <broonie@linaro.org>2013-10-09 08:52:52 -0400
committerMark Brown <broonie@linaro.org>2013-10-10 07:51:58 -0400
commiteb270e98e15b9f4303b074ba5d88ee98110bc451 (patch)
tree999fcf2cbf5c25ae5c5966e30ca716eb0617dfd2 /sound/soc/soc-dapm.c
parent40aaddd0438944b41ae507a01b0842309bb9ea79 (diff)
ASoC: dapm: Use async I/O for DAPM sequences
Within a DAPM sequence we normally don't care about when exactly a register write has completed so long as they happen in the order we requested. This means that we can issue most of the writes we do asynchronously which should maximise the ability of the underlying frameworks to keep the hardware busy, providing a small performance improvement on some systems. We currently ensure that all writes are completed both when changing to a different device and when calling into the regulator and clock frameworks. This should ensure that the previous ordering is maintained. We also ensure that writes are completed prior to calling into widget event functions since some event functions implement delays. This should be improved in future so that widgets can disable this sync in order to add extra writes. Signed-off-by: Mark Brown <broonie@linaro.org>
Diffstat (limited to 'sound/soc/soc-dapm.c')
-rw-r--r--sound/soc/soc-dapm.c24
1 files changed, 22 insertions, 2 deletions
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 9273216f22fc..1dbc5f8cdc98 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -409,6 +409,12 @@ static inline void soc_widget_unlock(struct snd_soc_dapm_widget *w)
409 mutex_unlock(&w->platform->mutex); 409 mutex_unlock(&w->platform->mutex);
410} 410}
411 411
412static void soc_dapm_async_complete(struct snd_soc_dapm_context *dapm)
413{
414 if (dapm->codec && dapm->codec->using_regmap)
415 regmap_async_complete(dapm->codec->control_data);
416}
417
412static int soc_widget_update_bits_locked(struct snd_soc_dapm_widget *w, 418static int soc_widget_update_bits_locked(struct snd_soc_dapm_widget *w,
413 unsigned short reg, unsigned int mask, unsigned int value) 419 unsigned short reg, unsigned int mask, unsigned int value)
414{ 420{
@@ -417,8 +423,9 @@ static int soc_widget_update_bits_locked(struct snd_soc_dapm_widget *w,
417 int ret; 423 int ret;
418 424
419 if (w->codec && w->codec->using_regmap) { 425 if (w->codec && w->codec->using_regmap) {
420 ret = regmap_update_bits_check(w->codec->control_data, 426 ret = regmap_update_bits_check_async(w->codec->control_data,
421 reg, mask, value, &change); 427 reg, mask, value,
428 &change);
422 if (ret != 0) 429 if (ret != 0)
423 return ret; 430 return ret;
424 } else { 431 } else {
@@ -1201,6 +1208,8 @@ int dapm_regulator_event(struct snd_soc_dapm_widget *w,
1201{ 1208{
1202 int ret; 1209 int ret;
1203 1210
1211 soc_dapm_async_complete(w->dapm);
1212
1204 if (SND_SOC_DAPM_EVENT_ON(event)) { 1213 if (SND_SOC_DAPM_EVENT_ON(event)) {
1205 if (w->on_val & SND_SOC_DAPM_REGULATOR_BYPASS) { 1214 if (w->on_val & SND_SOC_DAPM_REGULATOR_BYPASS) {
1206 ret = regulator_allow_bypass(w->regulator, false); 1215 ret = regulator_allow_bypass(w->regulator, false);
@@ -1234,6 +1243,8 @@ int dapm_clock_event(struct snd_soc_dapm_widget *w,
1234 if (!w->clk) 1243 if (!w->clk)
1235 return -EIO; 1244 return -EIO;
1236 1245
1246 soc_dapm_async_complete(w->dapm);
1247
1237#ifdef CONFIG_HAVE_CLK 1248#ifdef CONFIG_HAVE_CLK
1238 if (SND_SOC_DAPM_EVENT_ON(event)) { 1249 if (SND_SOC_DAPM_EVENT_ON(event)) {
1239 return clk_prepare_enable(w->clk); 1250 return clk_prepare_enable(w->clk);
@@ -1426,6 +1437,7 @@ static void dapm_seq_check_event(struct snd_soc_card *card,
1426 if (w->event && (w->event_flags & event)) { 1437 if (w->event && (w->event_flags & event)) {
1427 pop_dbg(w->dapm->dev, card->pop_time, "pop test : %s %s\n", 1438 pop_dbg(w->dapm->dev, card->pop_time, "pop test : %s %s\n",
1428 w->name, ev_name); 1439 w->name, ev_name);
1440 soc_dapm_async_complete(w->dapm);
1429 trace_snd_soc_dapm_widget_event_start(w, event); 1441 trace_snd_soc_dapm_widget_event_start(w, event);
1430 ret = w->event(w, NULL, event); 1442 ret = w->event(w, NULL, event);
1431 trace_snd_soc_dapm_widget_event_done(w, event); 1443 trace_snd_soc_dapm_widget_event_done(w, event);
@@ -1498,6 +1510,7 @@ static void dapm_seq_run(struct snd_soc_card *card,
1498 struct list_head *list, int event, bool power_up) 1510 struct list_head *list, int event, bool power_up)
1499{ 1511{
1500 struct snd_soc_dapm_widget *w, *n; 1512 struct snd_soc_dapm_widget *w, *n;
1513 struct snd_soc_dapm_context *d;
1501 LIST_HEAD(pending); 1514 LIST_HEAD(pending);
1502 int cur_sort = -1; 1515 int cur_sort = -1;
1503 int cur_subseq = -1; 1516 int cur_subseq = -1;
@@ -1528,6 +1541,9 @@ static void dapm_seq_run(struct snd_soc_card *card,
1528 cur_subseq); 1541 cur_subseq);
1529 } 1542 }
1530 1543
1544 if (cur_dapm && w->dapm != cur_dapm)
1545 soc_dapm_async_complete(cur_dapm);
1546
1531 INIT_LIST_HEAD(&pending); 1547 INIT_LIST_HEAD(&pending);
1532 cur_sort = -1; 1548 cur_sort = -1;
1533 cur_subseq = INT_MIN; 1549 cur_subseq = INT_MIN;
@@ -1586,6 +1602,10 @@ static void dapm_seq_run(struct snd_soc_card *card,
1586 cur_dapm->seq_notifier(cur_dapm, 1602 cur_dapm->seq_notifier(cur_dapm,
1587 i, cur_subseq); 1603 i, cur_subseq);
1588 } 1604 }
1605
1606 list_for_each_entry(d, &card->dapm_list, list) {
1607 soc_dapm_async_complete(d);
1608 }
1589} 1609}
1590 1610
1591static void dapm_widget_update(struct snd_soc_card *card) 1611static void dapm_widget_update(struct snd_soc_card *card)