From: Richard Fitzgerald <rf@opensource.wolfsonmicro.com>
To: sameo@linux.intel.com, lee.jones@linaro.org,
ckeepax@opensource.wolfsonmicro.com, broonie@kernel.org,
lgirdwood@gmail.com, perex@perex.cz, tiwai@suse.de
Cc: alsa-devel@alsa-project.org, patches@opensource.wolfsonmicro.com,
linux-kernel@vger.kernel.org
Subject: [PATCH 2/4] ASoC: wm_adsp: Move DVFS control into codec driver
Date: Mon, 9 Jun 2014 16:03:14 +0100 [thread overview]
Message-ID: <20140609150314.GC5229@opensource.wolfsonmicro.com> (raw)
In-Reply-To: <20140609150013.GA5229@opensource.wolfsonmicro.com>
In theory the ADSP driver should not need to know
anything about the codec it is part of. But some codecs
need DVFS control based on ADSP clocking speed. This was
being handled by bundling part of the knowledge of this
into the ADSP driver.
This change removes this handling out of the ADSP driver.
A new macro WM_ADSP2_E() takes a callback function to be
called by the preloader widget in place of the default
handler, and this can be used to do codec-specific power
control.
The WM5102 driver has been updated to implement the DVFS.
Signed-off-by: Richard Fitzgerald <rf@opensource.wolfsonmicro.com>
---
sound/soc/codecs/wm5102.c | 47 ++++++++++++++++++++++++++-
sound/soc/codecs/wm5110.c | 2 +-
sound/soc/codecs/wm_adsp.c | 76 +-------------------------------------------
sound/soc/codecs/wm_adsp.h | 11 +++---
4 files changed, 53 insertions(+), 83 deletions(-)
diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c
index dcf1d12..47cc404 100644
--- a/sound/soc/codecs/wm5102.c
+++ b/sound/soc/codecs/wm5102.c
@@ -612,6 +612,49 @@ static int wm5102_sysclk_ev(struct snd_soc_dapm_widget *w,
return 0;
}
+static int wm5102_adsp_power_ev(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ struct arizona *arizona = dev_get_drvdata(codec->dev->parent);
+ unsigned int v;
+ int ret;
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ ret = regmap_read(arizona->regmap, ARIZONA_SYSTEM_CLOCK_1, &v);
+ if (ret != 0) {
+ dev_err(codec->dev,
+ "Failed to read SYSCLK state: %d\n", ret);
+ return -EIO;
+ }
+
+ v = (v & ARIZONA_SYSCLK_FREQ_MASK) >> ARIZONA_SYSCLK_FREQ_SHIFT;
+
+ if (v >= 3) {
+ ret = arizona_dvfs_up(arizona, ARIZONA_DVFS_ADSP1_RQ);
+ if (ret != 0) {
+ dev_err(codec->dev,
+ "Failed to raise DVFS: %d\n", ret);
+ return ret;
+ }
+ }
+ break;
+
+ case SND_SOC_DAPM_PRE_PMD:
+ ret = arizona_dvfs_down(arizona, ARIZONA_DVFS_ADSP1_RQ);
+ if (ret != 0)
+ dev_warn(codec->dev,
+ "Failed to lower DVFS: %d\n", ret);
+ break;
+
+ default:
+ break;
+ }
+
+ return wm_adsp2_early_event(w, kcontrol, event);
+}
+
static const char *wm5102_osr_text[] = {
"Low power", "Normal", "High performance",
};
@@ -1300,7 +1343,7 @@ ARIZONA_MUX_WIDGETS(ISRC2DEC2, "ISRC2DEC2"),
ARIZONA_MUX_WIDGETS(ISRC2INT1, "ISRC2INT1"),
ARIZONA_MUX_WIDGETS(ISRC2INT2, "ISRC2INT2"),
-WM_ADSP2("DSP1", 0),
+WM_ADSP2_E("DSP1", 0, wm5102_adsp_power_ev),
SND_SOC_DAPM_OUTPUT("HPOUT1L"),
SND_SOC_DAPM_OUTPUT("HPOUT1R"),
@@ -1843,7 +1886,7 @@ static int wm5102_probe(struct platform_device *pdev)
wm5102->core.adsp[0].mem = wm5102_dsp1_regions;
wm5102->core.adsp[0].num_mems = ARRAY_SIZE(wm5102_dsp1_regions);
- ret = wm_adsp2_init(&wm5102->core.adsp[0], true);
+ ret = wm_adsp2_init(&wm5102->core.adsp[0]);
if (ret != 0)
return ret;
diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c
index 83a7e2f..a5c9f62 100644
--- a/sound/soc/codecs/wm5110.c
+++ b/sound/soc/codecs/wm5110.c
@@ -1683,7 +1683,7 @@ static int wm5110_probe(struct platform_device *pdev)
wm5110->core.adsp[i].num_mems
= ARRAY_SIZE(wm5110_dsp1_regions);
- ret = wm_adsp2_init(&wm5110->core.adsp[i], false);
+ ret = wm_adsp2_init(&wm5110->core.adsp[i]);
if (ret != 0)
return ret;
}
diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c
index 53e3ab5..875a802 100644
--- a/sound/soc/codecs/wm_adsp.c
+++ b/sound/soc/codecs/wm_adsp.c
@@ -1539,35 +1539,6 @@ static void wm_adsp2_boot_work(struct work_struct *work)
return;
}
- if (dsp->dvfs) {
- ret = regmap_read(dsp->regmap,
- dsp->base + ADSP2_CLOCKING, &val);
- if (ret != 0) {
- dev_err(dsp->dev, "Failed to read clocking: %d\n", ret);
- return;
- }
-
- if ((val & ADSP2_CLK_SEL_MASK) >= 3) {
- ret = regulator_enable(dsp->dvfs);
- if (ret != 0) {
- dev_err(dsp->dev,
- "Failed to enable supply: %d\n",
- ret);
- return;
- }
-
- ret = regulator_set_voltage(dsp->dvfs,
- 1800000,
- 1800000);
- if (ret != 0) {
- dev_err(dsp->dev,
- "Failed to raise supply: %d\n",
- ret);
- return;
- }
- }
- }
-
ret = wm_adsp2_ena(dsp);
if (ret != 0)
return;
@@ -1668,21 +1639,6 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w,
regmap_write(dsp->regmap, dsp->base + ADSP2_WDMA_CONFIG_2, 0);
regmap_write(dsp->regmap, dsp->base + ADSP2_RDMA_CONFIG_1, 0);
- if (dsp->dvfs) {
- ret = regulator_set_voltage(dsp->dvfs, 1200000,
- 1800000);
- if (ret != 0)
- dev_warn(dsp->dev,
- "Failed to lower supply: %d\n",
- ret);
-
- ret = regulator_disable(dsp->dvfs);
- if (ret != 0)
- dev_err(dsp->dev,
- "Failed to enable supply: %d\n",
- ret);
- }
-
list_for_each_entry(ctl, &dsp->ctl_list, list)
ctl->enabled = 0;
@@ -1709,7 +1665,7 @@ err:
}
EXPORT_SYMBOL_GPL(wm_adsp2_event);
-int wm_adsp2_init(struct wm_adsp *adsp, bool dvfs)
+int wm_adsp2_init(struct wm_adsp *adsp)
{
int ret;
@@ -1728,36 +1684,6 @@ int wm_adsp2_init(struct wm_adsp *adsp, bool dvfs)
INIT_LIST_HEAD(&adsp->ctl_list);
INIT_WORK(&adsp->boot_work, wm_adsp2_boot_work);
- if (dvfs) {
- adsp->dvfs = devm_regulator_get(adsp->dev, "DCVDD");
- if (IS_ERR(adsp->dvfs)) {
- ret = PTR_ERR(adsp->dvfs);
- dev_err(adsp->dev, "Failed to get DCVDD: %d\n", ret);
- return ret;
- }
-
- ret = regulator_enable(adsp->dvfs);
- if (ret != 0) {
- dev_err(adsp->dev, "Failed to enable DCVDD: %d\n",
- ret);
- return ret;
- }
-
- ret = regulator_set_voltage(adsp->dvfs, 1200000, 1800000);
- if (ret != 0) {
- dev_err(adsp->dev, "Failed to initialise DVFS: %d\n",
- ret);
- return ret;
- }
-
- ret = regulator_disable(adsp->dvfs);
- if (ret != 0) {
- dev_err(adsp->dev, "Failed to disable DCVDD: %d\n",
- ret);
- return ret;
- }
- }
-
return 0;
}
EXPORT_SYMBOL_GPL(wm_adsp2_init);
diff --git a/sound/soc/codecs/wm_adsp.h b/sound/soc/codecs/wm_adsp.h
index a4f6b64..8b208d1 100644
--- a/sound/soc/codecs/wm_adsp.h
+++ b/sound/soc/codecs/wm_adsp.h
@@ -56,8 +56,6 @@ struct wm_adsp {
int fw;
bool running;
- struct regulator *dvfs;
-
struct list_head ctl_list;
struct work_struct boot_work;
@@ -67,19 +65,22 @@ struct wm_adsp {
SND_SOC_DAPM_PGA_E(wname, SND_SOC_NOPM, num, 0, NULL, 0, \
wm_adsp1_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD)
-#define WM_ADSP2(wname, num) \
+#define WM_ADSP2_E(wname, num, event_fn) \
{ .id = snd_soc_dapm_dai_link, .name = wname " Preloader", \
- .reg = SND_SOC_NOPM, .shift = num, .event = wm_adsp2_early_event, \
+ .reg = SND_SOC_NOPM, .shift = num, .event = event_fn, \
.event_flags = SND_SOC_DAPM_PRE_PMU }, \
{ .id = snd_soc_dapm_out_drv, .name = wname, \
.reg = SND_SOC_NOPM, .shift = num, .event = wm_adsp2_event, \
.event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD }
+#define WM_ADSP2(wname, num) \
+ WM_ADSP2_E(wname, num, wm_adsp2_early_event)
+
extern const struct snd_kcontrol_new wm_adsp1_fw_controls[];
extern const struct snd_kcontrol_new wm_adsp2_fw_controls[];
int wm_adsp1_init(struct wm_adsp *adsp);
-int wm_adsp2_init(struct wm_adsp *adsp, bool dvfs);
+int wm_adsp2_init(struct wm_adsp *adsp);
int wm_adsp1_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event);
int wm_adsp2_early_event(struct snd_soc_dapm_widget *w,
--
1.7.2.5
next prev parent reply other threads:[~2014-06-09 15:03 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-06-09 15:00 [PATCH 0/4] arizona: Improvements to codec DVFS control Richard Fitzgerald
2014-06-09 15:02 ` [PATCH 1/4] mfd: arizona: Export function to control subsystem DVFS Richard Fitzgerald
2014-06-16 16:42 ` Lee Jones
2014-06-16 16:48 ` Mark Brown
2014-06-16 17:09 ` Charles Keepax
2014-06-16 17:06 ` Charles Keepax
2014-06-09 15:03 ` Richard Fitzgerald [this message]
2014-06-11 10:54 ` [PATCH 2/4] ASoC: wm_adsp: Move DVFS control into codec driver Charles Keepax
2014-06-09 15:03 ` [PATCH 3/4] ASoC: arizona: Add DVFS handling for sample rate control Richard Fitzgerald
2014-06-09 15:04 ` [PATCH 4/4] regulator: arizona-ldo1: Do not control clocking from regulator Richard Fitzgerald
2014-06-09 18:43 ` Mark Brown
2014-06-11 10:59 ` Charles Keepax
2014-06-11 13:54 ` Mark Brown
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20140609150314.GC5229@opensource.wolfsonmicro.com \
--to=rf@opensource.wolfsonmicro.com \
--cc=alsa-devel@alsa-project.org \
--cc=broonie@kernel.org \
--cc=ckeepax@opensource.wolfsonmicro.com \
--cc=lee.jones@linaro.org \
--cc=lgirdwood@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=patches@opensource.wolfsonmicro.com \
--cc=perex@perex.cz \
--cc=sameo@linux.intel.com \
--cc=tiwai@suse.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).