aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Fitzgerald <rf@opensource.wolfsonmicro.com>2015-06-02 06:53:34 -0400
committerMark Brown <broonie@kernel.org>2015-06-02 16:07:20 -0400
commit81ac58b13f815d7c7838bc347dd5d102707a11b7 (patch)
treeb6c06e91a8b2a6222cfd71bb398ef99c7469525f
parent346d96836ca4af39dbfe65eceb7db812b1bfe68f (diff)
ASoC: wm_adsp: Move DVFS control into codec driver
In theory the ADSP driver should not need to know anything about the codec it is part of. But the WM5102 needs 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 moves this handling out of the ADSP driver and into the WM5102 driver. Signed-off-by: Richard Fitzgerald <rf@opensource.wolfsonmicro.com> Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--sound/soc/codecs/wm5102.c47
-rw-r--r--sound/soc/codecs/wm5110.c2
-rw-r--r--sound/soc/codecs/wm_adsp.c73
-rw-r--r--sound/soc/codecs/wm_adsp.h15
4 files changed, 54 insertions, 83 deletions
diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c
index b73e3a3da2d2..11eba0e58fc0 100644
--- a/sound/soc/codecs/wm5102.c
+++ b/sound/soc/codecs/wm5102.c
@@ -614,6 +614,49 @@ static int wm5102_sysclk_ev(struct snd_soc_dapm_widget *w,
614 return arizona_dvfs_sysclk_ev(w, kcontrol, event); 614 return arizona_dvfs_sysclk_ev(w, kcontrol, event);
615} 615}
616 616
617static int wm5102_adsp_power_ev(struct snd_soc_dapm_widget *w,
618 struct snd_kcontrol *kcontrol, int event)
619{
620 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
621 struct arizona *arizona = dev_get_drvdata(codec->dev->parent);
622 unsigned int v;
623 int ret;
624
625 switch (event) {
626 case SND_SOC_DAPM_PRE_PMU:
627 ret = regmap_read(arizona->regmap, ARIZONA_SYSTEM_CLOCK_1, &v);
628 if (ret != 0) {
629 dev_err(codec->dev,
630 "Failed to read SYSCLK state: %d\n", ret);
631 return -EIO;
632 }
633
634 v = (v & ARIZONA_SYSCLK_FREQ_MASK) >> ARIZONA_SYSCLK_FREQ_SHIFT;
635
636 if (v >= 3) {
637 ret = arizona_dvfs_up(codec, ARIZONA_DVFS_ADSP1_RQ);
638 if (ret) {
639 dev_err(codec->dev,
640 "Failed to raise DVFS: %d\n", ret);
641 return ret;
642 }
643 }
644 break;
645
646 case SND_SOC_DAPM_POST_PMD:
647 ret = arizona_dvfs_down(codec, ARIZONA_DVFS_ADSP1_RQ);
648 if (ret)
649 dev_warn(codec->dev,
650 "Failed to lower DVFS: %d\n", ret);
651 break;
652
653 default:
654 break;
655 }
656
657 return wm_adsp2_early_event(w, kcontrol, event);
658}
659
617static int wm5102_out_comp_coeff_get(struct snd_kcontrol *kcontrol, 660static int wm5102_out_comp_coeff_get(struct snd_kcontrol *kcontrol,
618 struct snd_ctl_elem_value *ucontrol) 661 struct snd_ctl_elem_value *ucontrol)
619{ 662{
@@ -1369,7 +1412,7 @@ ARIZONA_MUX_WIDGETS(ISRC2DEC2, "ISRC2DEC2"),
1369ARIZONA_MUX_WIDGETS(ISRC2INT1, "ISRC2INT1"), 1412ARIZONA_MUX_WIDGETS(ISRC2INT1, "ISRC2INT1"),
1370ARIZONA_MUX_WIDGETS(ISRC2INT2, "ISRC2INT2"), 1413ARIZONA_MUX_WIDGETS(ISRC2INT2, "ISRC2INT2"),
1371 1414
1372WM_ADSP2("DSP1", 0), 1415WM_ADSP2_E("DSP1", 0, wm5102_adsp_power_ev),
1373 1416
1374SND_SOC_DAPM_OUTPUT("HPOUT1L"), 1417SND_SOC_DAPM_OUTPUT("HPOUT1L"),
1375SND_SOC_DAPM_OUTPUT("HPOUT1R"), 1418SND_SOC_DAPM_OUTPUT("HPOUT1R"),
@@ -1922,7 +1965,7 @@ static int wm5102_probe(struct platform_device *pdev)
1922 wm5102->core.adsp[0].mem = wm5102_dsp1_regions; 1965 wm5102->core.adsp[0].mem = wm5102_dsp1_regions;
1923 wm5102->core.adsp[0].num_mems = ARRAY_SIZE(wm5102_dsp1_regions); 1966 wm5102->core.adsp[0].num_mems = ARRAY_SIZE(wm5102_dsp1_regions);
1924 1967
1925 ret = wm_adsp2_init(&wm5102->core.adsp[0], true); 1968 ret = wm_adsp2_init(&wm5102->core.adsp[0]);
1926 if (ret != 0) 1969 if (ret != 0)
1927 return ret; 1970 return ret;
1928 1971
diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c
index fbaeddb3e903..d65364e91532 100644
--- a/sound/soc/codecs/wm5110.c
+++ b/sound/soc/codecs/wm5110.c
@@ -1697,7 +1697,7 @@ static int wm5110_probe(struct platform_device *pdev)
1697 wm5110->core.adsp[i].num_mems 1697 wm5110->core.adsp[i].num_mems
1698 = ARRAY_SIZE(wm5110_dsp1_regions); 1698 = ARRAY_SIZE(wm5110_dsp1_regions);
1699 1699
1700 ret = wm_adsp2_init(&wm5110->core.adsp[i], false); 1700 ret = wm_adsp2_init(&wm5110->core.adsp[i]);
1701 if (ret != 0) 1701 if (ret != 0)
1702 return ret; 1702 return ret;
1703 } 1703 }
diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c
index 477390ad9c6d..b62ffd0c133e 100644
--- a/sound/soc/codecs/wm_adsp.c
+++ b/sound/soc/codecs/wm_adsp.c
@@ -1811,35 +1811,6 @@ static void wm_adsp2_boot_work(struct work_struct *work)
1811 return; 1811 return;
1812 } 1812 }
1813 1813
1814 if (dsp->dvfs) {
1815 ret = regmap_read(dsp->regmap,
1816 dsp->base + ADSP2_CLOCKING, &val);
1817 if (ret != 0) {
1818 adsp_err(dsp, "Failed to read clocking: %d\n", ret);
1819 return;
1820 }
1821
1822 if ((val & ADSP2_CLK_SEL_MASK) >= 3) {
1823 ret = regulator_enable(dsp->dvfs);
1824 if (ret != 0) {
1825 adsp_err(dsp,
1826 "Failed to enable supply: %d\n",
1827 ret);
1828 return;
1829 }
1830
1831 ret = regulator_set_voltage(dsp->dvfs,
1832 1800000,
1833 1800000);
1834 if (ret != 0) {
1835 adsp_err(dsp,
1836 "Failed to raise supply: %d\n",
1837 ret);
1838 return;
1839 }
1840 }
1841 }
1842
1843 ret = wm_adsp2_ena(dsp); 1814 ret = wm_adsp2_ena(dsp);
1844 if (ret != 0) 1815 if (ret != 0)
1845 return; 1816 return;
@@ -1936,21 +1907,6 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w,
1936 regmap_write(dsp->regmap, dsp->base + ADSP2_WDMA_CONFIG_2, 0); 1907 regmap_write(dsp->regmap, dsp->base + ADSP2_WDMA_CONFIG_2, 0);
1937 regmap_write(dsp->regmap, dsp->base + ADSP2_RDMA_CONFIG_1, 0); 1908 regmap_write(dsp->regmap, dsp->base + ADSP2_RDMA_CONFIG_1, 0);
1938 1909
1939 if (dsp->dvfs) {
1940 ret = regulator_set_voltage(dsp->dvfs, 1200000,
1941 1800000);
1942 if (ret != 0)
1943 adsp_warn(dsp,
1944 "Failed to lower supply: %d\n",
1945 ret);
1946
1947 ret = regulator_disable(dsp->dvfs);
1948 if (ret != 0)
1949 adsp_err(dsp,
1950 "Failed to enable supply: %d\n",
1951 ret);
1952 }
1953
1954 list_for_each_entry(ctl, &dsp->ctl_list, list) 1910 list_for_each_entry(ctl, &dsp->ctl_list, list)
1955 ctl->enabled = 0; 1911 ctl->enabled = 0;
1956 1912
@@ -1977,7 +1933,7 @@ err:
1977} 1933}
1978EXPORT_SYMBOL_GPL(wm_adsp2_event); 1934EXPORT_SYMBOL_GPL(wm_adsp2_event);
1979 1935
1980int wm_adsp2_init(struct wm_adsp *dsp, bool dvfs) 1936int wm_adsp2_init(struct wm_adsp *dsp)
1981{ 1937{
1982 int ret; 1938 int ret;
1983 1939
@@ -1996,33 +1952,6 @@ int wm_adsp2_init(struct wm_adsp *dsp, bool dvfs)
1996 INIT_LIST_HEAD(&dsp->ctl_list); 1952 INIT_LIST_HEAD(&dsp->ctl_list);
1997 INIT_WORK(&dsp->boot_work, wm_adsp2_boot_work); 1953 INIT_WORK(&dsp->boot_work, wm_adsp2_boot_work);
1998 1954
1999 if (dvfs) {
2000 dsp->dvfs = devm_regulator_get(dsp->dev, "DCVDD");
2001 if (IS_ERR(dsp->dvfs)) {
2002 ret = PTR_ERR(dsp->dvfs);
2003 adsp_err(dsp, "Failed to get DCVDD: %d\n", ret);
2004 return ret;
2005 }
2006
2007 ret = regulator_enable(dsp->dvfs);
2008 if (ret != 0) {
2009 adsp_err(dsp, "Failed to enable DCVDD: %d\n", ret);
2010 return ret;
2011 }
2012
2013 ret = regulator_set_voltage(dsp->dvfs, 1200000, 1800000);
2014 if (ret != 0) {
2015 adsp_err(dsp, "Failed to initialise DVFS: %d\n", ret);
2016 return ret;
2017 }
2018
2019 ret = regulator_disable(dsp->dvfs);
2020 if (ret != 0) {
2021 adsp_err(dsp, "Failed to disable DCVDD: %d\n", ret);
2022 return ret;
2023 }
2024 }
2025
2026 return 0; 1955 return 0;
2027} 1956}
2028EXPORT_SYMBOL_GPL(wm_adsp2_init); 1957EXPORT_SYMBOL_GPL(wm_adsp2_init);
diff --git a/sound/soc/codecs/wm_adsp.h b/sound/soc/codecs/wm_adsp.h
index 4fe066745377..0e5f07c35d50 100644
--- a/sound/soc/codecs/wm_adsp.h
+++ b/sound/soc/codecs/wm_adsp.h
@@ -18,8 +18,6 @@
18 18
19#include "wmfw.h" 19#include "wmfw.h"
20 20
21struct regulator;
22
23struct wm_adsp_region { 21struct wm_adsp_region {
24 int type; 22 int type;
25 unsigned int base; 23 unsigned int base;
@@ -56,8 +54,6 @@ struct wm_adsp {
56 int fw_ver; 54 int fw_ver;
57 bool running; 55 bool running;
58 56
59 struct regulator *dvfs;
60
61 struct list_head ctl_list; 57 struct list_head ctl_list;
62 58
63 struct work_struct boot_work; 59 struct work_struct boot_work;
@@ -67,19 +63,22 @@ struct wm_adsp {
67 SND_SOC_DAPM_PGA_E(wname, SND_SOC_NOPM, num, 0, NULL, 0, \ 63 SND_SOC_DAPM_PGA_E(wname, SND_SOC_NOPM, num, 0, NULL, 0, \
68 wm_adsp1_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD) 64 wm_adsp1_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD)
69 65
70#define WM_ADSP2(wname, num) \ 66#define WM_ADSP2_E(wname, num, event_fn) \
71{ .id = snd_soc_dapm_dai_link, .name = wname " Preloader", \ 67{ .id = snd_soc_dapm_dai_link, .name = wname " Preloader", \
72 .reg = SND_SOC_NOPM, .shift = num, .event = wm_adsp2_early_event, \ 68 .reg = SND_SOC_NOPM, .shift = num, .event = event_fn, \
73 .event_flags = SND_SOC_DAPM_PRE_PMU }, \ 69 .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD }, \
74{ .id = snd_soc_dapm_out_drv, .name = wname, \ 70{ .id = snd_soc_dapm_out_drv, .name = wname, \
75 .reg = SND_SOC_NOPM, .shift = num, .event = wm_adsp2_event, \ 71 .reg = SND_SOC_NOPM, .shift = num, .event = wm_adsp2_event, \
76 .event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD } 72 .event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD }
77 73
74#define WM_ADSP2(wname, num) \
75 WM_ADSP2_E(wname, num, wm_adsp2_early_event)
76
78extern const struct snd_kcontrol_new wm_adsp1_fw_controls[]; 77extern const struct snd_kcontrol_new wm_adsp1_fw_controls[];
79extern const struct snd_kcontrol_new wm_adsp2_fw_controls[]; 78extern const struct snd_kcontrol_new wm_adsp2_fw_controls[];
80 79
81int wm_adsp1_init(struct wm_adsp *dsp); 80int wm_adsp1_init(struct wm_adsp *dsp);
82int wm_adsp2_init(struct wm_adsp *dsp, bool dvfs); 81int wm_adsp2_init(struct wm_adsp *dsp);
83int wm_adsp1_event(struct snd_soc_dapm_widget *w, 82int wm_adsp1_event(struct snd_soc_dapm_widget *w,
84 struct snd_kcontrol *kcontrol, int event); 83 struct snd_kcontrol *kcontrol, int event);
85int wm_adsp2_early_event(struct snd_soc_dapm_widget *w, 84int wm_adsp2_early_event(struct snd_soc_dapm_widget *w,