Commit d82d767f authored by Charles Keepax's avatar Charles Keepax Committed by Mark Brown

ASoC: wm_adsp: Move setting of DSP speed into CODEC specific code

The ADSP code should be agnostic of which CODEC it runs upon, currently
there is only one remaining part of the implementation that doesn't
follow this. When the DSP is booted on ADSP2 we read
ARIZONA_SYSTEM_CLOCK_1 and use that to set the initial speed for the DSP
clock. This patch factors that out into CODEC specific code, leaving the
ADSP code entirely CODEC agnostic.
Signed-off-by: default avatarCharles Keepax <ckeepax@opensource.wolfsonmicro.com>
Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent 7ce4283c
...@@ -57,6 +57,25 @@ static const struct wm_adsp_region *cs47l24_dsp_regions[] = { ...@@ -57,6 +57,25 @@ static const struct wm_adsp_region *cs47l24_dsp_regions[] = {
cs47l24_dsp3_regions, cs47l24_dsp3_regions,
}; };
static int cs47l24_adsp_power_ev(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct arizona *arizona = dev_get_drvdata(codec->dev->parent);
unsigned int v;
int ret;
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 ret;
}
v = (v & ARIZONA_SYSCLK_FREQ_MASK) >> ARIZONA_SYSCLK_FREQ_SHIFT;
return wm_adsp2_early_event(w, kcontrol, event, v);
}
static DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); static DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0);
static DECLARE_TLV_DB_SCALE(digital_tlv, -6400, 50, 0); static DECLARE_TLV_DB_SCALE(digital_tlv, -6400, 50, 0);
static DECLARE_TLV_DB_SCALE(noise_tlv, -13200, 600, 0); static DECLARE_TLV_DB_SCALE(noise_tlv, -13200, 600, 0);
...@@ -405,8 +424,8 @@ SND_SOC_DAPM_PGA("ASRC2L", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC2L_ENA_SHIFT, 0, ...@@ -405,8 +424,8 @@ SND_SOC_DAPM_PGA("ASRC2L", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC2L_ENA_SHIFT, 0,
SND_SOC_DAPM_PGA("ASRC2R", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC2R_ENA_SHIFT, 0, SND_SOC_DAPM_PGA("ASRC2R", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC2R_ENA_SHIFT, 0,
NULL, 0), NULL, 0),
WM_ADSP2("DSP2", 1), WM_ADSP2("DSP2", 1, cs47l24_adsp_power_ev),
WM_ADSP2("DSP3", 2), WM_ADSP2("DSP3", 2, cs47l24_adsp_power_ev),
SND_SOC_DAPM_PGA("ISRC1INT1", ARIZONA_ISRC_1_CTRL_3, SND_SOC_DAPM_PGA("ISRC1INT1", ARIZONA_ISRC_1_CTRL_3,
ARIZONA_ISRC1_INT0_ENA_SHIFT, 0, NULL, 0), ARIZONA_ISRC1_INT0_ENA_SHIFT, 0, NULL, 0),
......
...@@ -619,7 +619,7 @@ static int wm5102_adsp_power_ev(struct snd_soc_dapm_widget *w, ...@@ -619,7 +619,7 @@ static int wm5102_adsp_power_ev(struct snd_soc_dapm_widget *w,
{ {
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct arizona *arizona = dev_get_drvdata(codec->dev->parent); struct arizona *arizona = dev_get_drvdata(codec->dev->parent);
unsigned int v; unsigned int v = 0;
int ret; int ret;
switch (event) { switch (event) {
...@@ -654,7 +654,7 @@ static int wm5102_adsp_power_ev(struct snd_soc_dapm_widget *w, ...@@ -654,7 +654,7 @@ static int wm5102_adsp_power_ev(struct snd_soc_dapm_widget *w,
break; break;
} }
return wm_adsp2_early_event(w, kcontrol, event); return wm_adsp2_early_event(w, kcontrol, event, v);
} }
static int wm5102_out_comp_coeff_get(struct snd_kcontrol *kcontrol, static int wm5102_out_comp_coeff_get(struct snd_kcontrol *kcontrol,
...@@ -1408,7 +1408,7 @@ ARIZONA_MUX_WIDGETS(ISRC2DEC2, "ISRC2DEC2"), ...@@ -1408,7 +1408,7 @@ ARIZONA_MUX_WIDGETS(ISRC2DEC2, "ISRC2DEC2"),
ARIZONA_MUX_WIDGETS(ISRC2INT1, "ISRC2INT1"), ARIZONA_MUX_WIDGETS(ISRC2INT1, "ISRC2INT1"),
ARIZONA_MUX_WIDGETS(ISRC2INT2, "ISRC2INT2"), ARIZONA_MUX_WIDGETS(ISRC2INT2, "ISRC2INT2"),
WM_ADSP2_E("DSP1", 0, wm5102_adsp_power_ev), WM_ADSP2("DSP1", 0, wm5102_adsp_power_ev),
SND_SOC_DAPM_OUTPUT("HPOUT1L"), SND_SOC_DAPM_OUTPUT("HPOUT1L"),
SND_SOC_DAPM_OUTPUT("HPOUT1R"), SND_SOC_DAPM_OUTPUT("HPOUT1R"),
......
...@@ -191,6 +191,25 @@ static int wm5110_sysclk_ev(struct snd_soc_dapm_widget *w, ...@@ -191,6 +191,25 @@ static int wm5110_sysclk_ev(struct snd_soc_dapm_widget *w,
return 0; return 0;
} }
static int wm5110_adsp_power_ev(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct arizona *arizona = dev_get_drvdata(codec->dev->parent);
unsigned int v;
int ret;
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 ret;
}
v = (v & ARIZONA_SYSCLK_FREQ_MASK) >> ARIZONA_SYSCLK_FREQ_SHIFT;
return wm_adsp2_early_event(w, kcontrol, event, v);
}
static const struct reg_sequence wm5110_no_dre_left_enable[] = { static const struct reg_sequence wm5110_no_dre_left_enable[] = {
{ 0x3024, 0xE410 }, { 0x3024, 0xE410 },
{ 0x3025, 0x0056 }, { 0x3025, 0x0056 },
...@@ -1179,10 +1198,10 @@ SND_SOC_DAPM_PGA("ASRC2L", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC2L_ENA_SHIFT, 0, ...@@ -1179,10 +1198,10 @@ SND_SOC_DAPM_PGA("ASRC2L", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC2L_ENA_SHIFT, 0,
SND_SOC_DAPM_PGA("ASRC2R", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC2R_ENA_SHIFT, 0, SND_SOC_DAPM_PGA("ASRC2R", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC2R_ENA_SHIFT, 0,
NULL, 0), NULL, 0),
WM_ADSP2("DSP1", 0), WM_ADSP2("DSP1", 0, wm5110_adsp_power_ev),
WM_ADSP2("DSP2", 1), WM_ADSP2("DSP2", 1, wm5110_adsp_power_ev),
WM_ADSP2("DSP3", 2), WM_ADSP2("DSP3", 2, wm5110_adsp_power_ev),
WM_ADSP2("DSP4", 3), WM_ADSP2("DSP4", 3, wm5110_adsp_power_ev),
SND_SOC_DAPM_PGA("ISRC1INT1", ARIZONA_ISRC_1_CTRL_3, SND_SOC_DAPM_PGA("ISRC1INT1", ARIZONA_ISRC_1_CTRL_3,
ARIZONA_ISRC1_INT0_ENA_SHIFT, 0, NULL, 0), ARIZONA_ISRC1_INT0_ENA_SHIFT, 0, NULL, 0),
......
...@@ -32,9 +32,6 @@ ...@@ -32,9 +32,6 @@
#include <sound/initval.h> #include <sound/initval.h>
#include <sound/tlv.h> #include <sound/tlv.h>
#include <linux/mfd/arizona/registers.h>
#include "arizona.h"
#include "wm_adsp.h" #include "wm_adsp.h"
#define adsp_crit(_dsp, fmt, ...) \ #define adsp_crit(_dsp, fmt, ...) \
...@@ -2146,30 +2143,9 @@ static void wm_adsp2_boot_work(struct work_struct *work) ...@@ -2146,30 +2143,9 @@ static void wm_adsp2_boot_work(struct work_struct *work)
struct wm_adsp, struct wm_adsp,
boot_work); boot_work);
int ret; int ret;
unsigned int val;
mutex_lock(&dsp->pwr_lock); mutex_lock(&dsp->pwr_lock);
/*
* For simplicity set the DSP clock rate to be the
* SYSCLK rate rather than making it configurable.
*/
ret = regmap_read(dsp->regmap, ARIZONA_SYSTEM_CLOCK_1, &val);
if (ret != 0) {
adsp_err(dsp, "Failed to read SYSCLK state: %d\n", ret);
goto err_mutex;
}
val = (val & ARIZONA_SYSCLK_FREQ_MASK)
>> ARIZONA_SYSCLK_FREQ_SHIFT;
ret = regmap_update_bits_async(dsp->regmap,
dsp->base + ADSP2_CLOCKING,
ADSP2_CLK_SEL_MASK, val);
if (ret != 0) {
adsp_err(dsp, "Failed to set clock rate: %d\n", ret);
goto err_mutex;
}
ret = wm_adsp2_ena(dsp); ret = wm_adsp2_ena(dsp);
if (ret != 0) if (ret != 0)
goto err_mutex; goto err_mutex;
...@@ -2209,8 +2185,21 @@ static void wm_adsp2_boot_work(struct work_struct *work) ...@@ -2209,8 +2185,21 @@ static void wm_adsp2_boot_work(struct work_struct *work)
mutex_unlock(&dsp->pwr_lock); mutex_unlock(&dsp->pwr_lock);
} }
static void wm_adsp2_set_dspclk(struct wm_adsp *dsp, unsigned int freq)
{
int ret;
ret = regmap_update_bits_async(dsp->regmap,
dsp->base + ADSP2_CLOCKING,
ADSP2_CLK_SEL_MASK,
freq << ADSP2_CLK_SEL_SHIFT);
if (ret != 0)
adsp_err(dsp, "Failed to set clock rate: %d\n", ret);
}
int wm_adsp2_early_event(struct snd_soc_dapm_widget *w, int wm_adsp2_early_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event) struct snd_kcontrol *kcontrol, int event,
unsigned int freq)
{ {
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec); struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec);
...@@ -2220,6 +2209,7 @@ int wm_adsp2_early_event(struct snd_soc_dapm_widget *w, ...@@ -2220,6 +2209,7 @@ int wm_adsp2_early_event(struct snd_soc_dapm_widget *w,
switch (event) { switch (event) {
case SND_SOC_DAPM_PRE_PMU: case SND_SOC_DAPM_PRE_PMU:
wm_adsp2_set_dspclk(dsp, freq);
queue_work(system_unbound_wq, &dsp->boot_work); queue_work(system_unbound_wq, &dsp->boot_work);
break; break;
default: default:
......
...@@ -80,7 +80,7 @@ struct wm_adsp { ...@@ -80,7 +80,7 @@ struct wm_adsp {
SND_SOC_DAPM_PGA_E(wname, SND_SOC_NOPM, num, 0, NULL, 0, \ 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) wm_adsp1_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD)
#define WM_ADSP2_E(wname, num, event_fn) \ #define WM_ADSP2(wname, num, event_fn) \
{ .id = snd_soc_dapm_dai_link, .name = wname " Preloader", \ { .id = snd_soc_dapm_dai_link, .name = wname " Preloader", \
.reg = SND_SOC_NOPM, .shift = num, .event = event_fn, \ .reg = SND_SOC_NOPM, .shift = num, .event = event_fn, \
.event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD }, \ .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD }, \
...@@ -88,9 +88,6 @@ struct wm_adsp { ...@@ -88,9 +88,6 @@ struct wm_adsp {
.reg = SND_SOC_NOPM, .shift = num, .event = wm_adsp2_event, \ .reg = SND_SOC_NOPM, .shift = num, .event = wm_adsp2_event, \
.event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD } .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_adsp_fw_controls[]; extern const struct snd_kcontrol_new wm_adsp_fw_controls[];
int wm_adsp1_init(struct wm_adsp *dsp); int wm_adsp1_init(struct wm_adsp *dsp);
...@@ -100,7 +97,8 @@ int wm_adsp2_codec_remove(struct wm_adsp *dsp, struct snd_soc_codec *codec); ...@@ -100,7 +97,8 @@ int wm_adsp2_codec_remove(struct wm_adsp *dsp, struct snd_soc_codec *codec);
int wm_adsp1_event(struct snd_soc_dapm_widget *w, int wm_adsp1_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event); struct snd_kcontrol *kcontrol, int event);
int wm_adsp2_early_event(struct snd_soc_dapm_widget *w, int wm_adsp2_early_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event); struct snd_kcontrol *kcontrol, int event,
unsigned int freq);
int wm_adsp2_event(struct snd_soc_dapm_widget *w, int wm_adsp2_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event); struct snd_kcontrol *kcontrol, int event);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment