Merge remote-tracking branches 'asoc/topic/adau1977', 'asoc/topic/adav80x', 'asoc/topic/arizona' and 'asoc/topic/atmel' into asoc-next
This commit is contained in:
commit
202f5ecb4f
14 changed files with 1020 additions and 578 deletions
|
@ -78,11 +78,6 @@ static int arizona_ldo1_hc_set_voltage_sel(struct regulator_dev *rdev,
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
ret = regmap_update_bits(regmap, ARIZONA_DYNAMIC_FREQUENCY_SCALING_1,
|
|
||||||
ARIZONA_SUBSYS_MAX_FREQ, val);
|
|
||||||
if (ret != 0)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
if (val)
|
if (val)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
|
@ -6,27 +6,22 @@ config SND_ATMEL_SOC
|
||||||
the ATMEL SSC interface. You will also need
|
the ATMEL SSC interface. You will also need
|
||||||
to select the audio interfaces to support below.
|
to select the audio interfaces to support below.
|
||||||
|
|
||||||
|
if SND_ATMEL_SOC
|
||||||
|
|
||||||
config SND_ATMEL_SOC_PDC
|
config SND_ATMEL_SOC_PDC
|
||||||
tristate
|
bool
|
||||||
depends on SND_ATMEL_SOC
|
|
||||||
|
|
||||||
config SND_ATMEL_SOC_DMA
|
config SND_ATMEL_SOC_DMA
|
||||||
tristate
|
bool
|
||||||
depends on SND_ATMEL_SOC
|
|
||||||
select SND_SOC_GENERIC_DMAENGINE_PCM
|
select SND_SOC_GENERIC_DMAENGINE_PCM
|
||||||
|
|
||||||
config SND_ATMEL_SOC_SSC
|
config SND_ATMEL_SOC_SSC
|
||||||
tristate
|
tristate
|
||||||
depends on SND_ATMEL_SOC
|
|
||||||
help
|
|
||||||
Say Y or M if you want to add support for codecs the
|
|
||||||
ATMEL SSC interface. You will also needs to select the individual
|
|
||||||
machine drivers to support below.
|
|
||||||
|
|
||||||
config SND_AT91_SOC_SAM9G20_WM8731
|
config SND_AT91_SOC_SAM9G20_WM8731
|
||||||
tristate "SoC Audio support for WM8731-based At91sam9g20 evaluation board"
|
tristate "SoC Audio support for WM8731-based At91sam9g20 evaluation board"
|
||||||
depends on ARCH_AT91 || COMPILE_TEST
|
depends on ARCH_AT91 || COMPILE_TEST
|
||||||
depends on ATMEL_SSC && SND_ATMEL_SOC && SND_SOC_I2C_AND_SPI
|
depends on ATMEL_SSC && SND_SOC_I2C_AND_SPI
|
||||||
select SND_ATMEL_SOC_PDC
|
select SND_ATMEL_SOC_PDC
|
||||||
select SND_ATMEL_SOC_SSC
|
select SND_ATMEL_SOC_SSC
|
||||||
select SND_SOC_WM8731
|
select SND_SOC_WM8731
|
||||||
|
@ -37,7 +32,7 @@ config SND_AT91_SOC_SAM9G20_WM8731
|
||||||
config SND_ATMEL_SOC_WM8904
|
config SND_ATMEL_SOC_WM8904
|
||||||
tristate "Atmel ASoC driver for boards using WM8904 codec"
|
tristate "Atmel ASoC driver for boards using WM8904 codec"
|
||||||
depends on ARCH_AT91 || COMPILE_TEST
|
depends on ARCH_AT91 || COMPILE_TEST
|
||||||
depends on ATMEL_SSC && SND_ATMEL_SOC && I2C
|
depends on ATMEL_SSC && I2C
|
||||||
select SND_ATMEL_SOC_SSC
|
select SND_ATMEL_SOC_SSC
|
||||||
select SND_ATMEL_SOC_DMA
|
select SND_ATMEL_SOC_DMA
|
||||||
select SND_SOC_WM8904
|
select SND_SOC_WM8904
|
||||||
|
@ -48,10 +43,11 @@ config SND_ATMEL_SOC_WM8904
|
||||||
config SND_AT91_SOC_SAM9X5_WM8731
|
config SND_AT91_SOC_SAM9X5_WM8731
|
||||||
tristate "SoC Audio support for WM8731-based at91sam9x5 board"
|
tristate "SoC Audio support for WM8731-based at91sam9x5 board"
|
||||||
depends on ARCH_AT91 || COMPILE_TEST
|
depends on ARCH_AT91 || COMPILE_TEST
|
||||||
depends on ATMEL_SSC && SND_ATMEL_SOC && SND_SOC_I2C_AND_SPI
|
depends on ATMEL_SSC && SND_SOC_I2C_AND_SPI
|
||||||
select SND_ATMEL_SOC_SSC
|
select SND_ATMEL_SOC_SSC
|
||||||
select SND_ATMEL_SOC_DMA
|
select SND_ATMEL_SOC_DMA
|
||||||
select SND_SOC_WM8731
|
select SND_SOC_WM8731
|
||||||
help
|
help
|
||||||
Say Y if you want to add support for audio SoC on an
|
Say Y if you want to add support for audio SoC on an
|
||||||
at91sam9x5 based board that is using WM8731 codec.
|
at91sam9x5 based board that is using WM8731 codec.
|
||||||
|
endif
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
# AT91 Platform Support
|
# AT91 Platform Support
|
||||||
snd-soc-atmel-pcm-pdc-objs := atmel-pcm-pdc.o
|
snd-soc-atmel-pcm-$(CONFIG_SND_ATMEL_SOC_PDC) := atmel-pcm-pdc.o
|
||||||
snd-soc-atmel-pcm-dma-objs := atmel-pcm-dma.o
|
snd-soc-atmel-pcm-$(CONFIG_SND_ATMEL_SOC_DMA) += atmel-pcm-dma.o
|
||||||
snd-soc-atmel_ssc_dai-objs := atmel_ssc_dai.o
|
snd-soc-atmel_ssc_dai-objs := atmel_ssc_dai.o $(snd-soc-atmel-pcm-y)
|
||||||
|
|
||||||
obj-$(CONFIG_SND_ATMEL_SOC_PDC) += snd-soc-atmel-pcm-pdc.o
|
|
||||||
obj-$(CONFIG_SND_ATMEL_SOC_DMA) += snd-soc-atmel-pcm-dma.o
|
|
||||||
obj-$(CONFIG_SND_ATMEL_SOC_SSC) += snd-soc-atmel_ssc_dai.o
|
obj-$(CONFIG_SND_ATMEL_SOC_SSC) += snd-soc-atmel_ssc_dai.o
|
||||||
|
|
||||||
# AT91 Machine Support
|
# AT91 Machine Support
|
||||||
|
|
|
@ -95,8 +95,9 @@ static const struct snd_soc_dapm_widget at91sam9g20ek_dapm_widgets[] = {
|
||||||
|
|
||||||
static const struct snd_soc_dapm_route intercon[] = {
|
static const struct snd_soc_dapm_route intercon[] = {
|
||||||
|
|
||||||
/* speaker connected to LHPOUT */
|
/* speaker connected to LHPOUT/RHPOUT */
|
||||||
{"Ext Spk", NULL, "LHPOUT"},
|
{"Ext Spk", NULL, "LHPOUT"},
|
||||||
|
{"Ext Spk", NULL, "RHPOUT"},
|
||||||
|
|
||||||
/* mic is connected to Mic Jack, with WM8731 Mic Bias */
|
/* mic is connected to Mic Jack, with WM8731 Mic Bias */
|
||||||
{"MICIN", NULL, "Mic Bias"},
|
{"MICIN", NULL, "Mic Bias"},
|
||||||
|
@ -108,9 +109,7 @@ static const struct snd_soc_dapm_route intercon[] = {
|
||||||
*/
|
*/
|
||||||
static int at91sam9g20ek_wm8731_init(struct snd_soc_pcm_runtime *rtd)
|
static int at91sam9g20ek_wm8731_init(struct snd_soc_pcm_runtime *rtd)
|
||||||
{
|
{
|
||||||
struct snd_soc_codec *codec = rtd->codec;
|
|
||||||
struct snd_soc_dai *codec_dai = rtd->codec_dai;
|
struct snd_soc_dai *codec_dai = rtd->codec_dai;
|
||||||
struct snd_soc_dapm_context *dapm = &codec->dapm;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
printk(KERN_DEBUG
|
printk(KERN_DEBUG
|
||||||
|
@ -124,10 +123,6 @@ static int at91sam9g20ek_wm8731_init(struct snd_soc_pcm_runtime *rtd)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* not connected */
|
|
||||||
snd_soc_dapm_nc_pin(dapm, "RLINEIN");
|
|
||||||
snd_soc_dapm_nc_pin(dapm, "LLINEIN");
|
|
||||||
|
|
||||||
#ifndef ENABLE_MIC_INPUT
|
#ifndef ENABLE_MIC_INPUT
|
||||||
snd_soc_dapm_nc_pin(&rtd->card->dapm, "Int Mic");
|
snd_soc_dapm_nc_pin(&rtd->card->dapm, "Int Mic");
|
||||||
#endif
|
#endif
|
||||||
|
@ -158,6 +153,7 @@ static struct snd_soc_card snd_soc_at91sam9g20ek = {
|
||||||
.num_dapm_widgets = ARRAY_SIZE(at91sam9g20ek_dapm_widgets),
|
.num_dapm_widgets = ARRAY_SIZE(at91sam9g20ek_dapm_widgets),
|
||||||
.dapm_routes = intercon,
|
.dapm_routes = intercon,
|
||||||
.num_dapm_routes = ARRAY_SIZE(intercon),
|
.num_dapm_routes = ARRAY_SIZE(intercon),
|
||||||
|
.fully_routed = true,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int at91sam9g20ek_audio_probe(struct platform_device *pdev)
|
static int at91sam9g20ek_audio_probe(struct platform_device *pdev)
|
||||||
|
|
|
@ -202,7 +202,7 @@ static const struct snd_soc_dapm_route adau1977_dapm_routes[] = {
|
||||||
ADAU1977_REG_DC_HPF_CAL, (x) - 1, 1, 0)
|
ADAU1977_REG_DC_HPF_CAL, (x) - 1, 1, 0)
|
||||||
|
|
||||||
#define ADAU1977_DC_SUB_SWITCH(x) \
|
#define ADAU1977_DC_SUB_SWITCH(x) \
|
||||||
SOC_SINGLE("ADC" #x " DC Substraction Capture Switch", \
|
SOC_SINGLE("ADC" #x " DC Subtraction Capture Switch", \
|
||||||
ADAU1977_REG_DC_HPF_CAL, (x) + 3, 1, 0)
|
ADAU1977_REG_DC_HPF_CAL, (x) + 3, 1, 0)
|
||||||
|
|
||||||
static const struct snd_kcontrol_new adau1977_snd_controls[] = {
|
static const struct snd_kcontrol_new adau1977_snd_controls[] = {
|
||||||
|
|
|
@ -539,7 +539,7 @@ static int adav80x_set_sysclk(struct snd_soc_codec *codec,
|
||||||
unsigned int freq, int dir)
|
unsigned int freq, int dir)
|
||||||
{
|
{
|
||||||
struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
|
struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
|
||||||
struct snd_soc_dapm_context *dapm = &codec->dapm;
|
struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
|
||||||
|
|
||||||
if (dir == SND_SOC_CLOCK_IN) {
|
if (dir == SND_SOC_CLOCK_IN) {
|
||||||
switch (clk_id) {
|
switch (clk_id) {
|
||||||
|
@ -622,6 +622,7 @@ static int adav80x_set_sysclk(struct snd_soc_codec *codec,
|
||||||
static int adav80x_set_pll(struct snd_soc_codec *codec, int pll_id,
|
static int adav80x_set_pll(struct snd_soc_codec *codec, int pll_id,
|
||||||
int source, unsigned int freq_in, unsigned int freq_out)
|
int source, unsigned int freq_in, unsigned int freq_out)
|
||||||
{
|
{
|
||||||
|
struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
|
||||||
struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
|
struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
|
||||||
unsigned int pll_ctrl1 = 0;
|
unsigned int pll_ctrl1 = 0;
|
||||||
unsigned int pll_ctrl2 = 0;
|
unsigned int pll_ctrl2 = 0;
|
||||||
|
@ -687,7 +688,7 @@ static int adav80x_set_pll(struct snd_soc_codec *codec, int pll_id,
|
||||||
|
|
||||||
adav80x->pll_src = source;
|
adav80x->pll_src = source;
|
||||||
|
|
||||||
snd_soc_dapm_sync(&codec->dapm);
|
snd_soc_dapm_sync(dapm);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -800,11 +801,12 @@ static struct snd_soc_dai_driver adav80x_dais[] = {
|
||||||
|
|
||||||
static int adav80x_probe(struct snd_soc_codec *codec)
|
static int adav80x_probe(struct snd_soc_codec *codec)
|
||||||
{
|
{
|
||||||
|
struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
|
||||||
struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
|
struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
|
||||||
|
|
||||||
/* Force PLLs on for SYSCLK output */
|
/* Force PLLs on for SYSCLK output */
|
||||||
snd_soc_dapm_force_enable_pin(&codec->dapm, "PLL1");
|
snd_soc_dapm_force_enable_pin(dapm, "PLL1");
|
||||||
snd_soc_dapm_force_enable_pin(&codec->dapm, "PLL2");
|
snd_soc_dapm_force_enable_pin(dapm, "PLL2");
|
||||||
|
|
||||||
/* Power down S/PDIF receiver, since it is currently not supported */
|
/* Power down S/PDIF receiver, since it is currently not supported */
|
||||||
regmap_write(adav80x->regmap, ADAV80X_PLL_OUTE, 0x20);
|
regmap_write(adav80x->regmap, ADAV80X_PLL_OUTE, 0x20);
|
||||||
|
|
|
@ -851,6 +851,134 @@ int arizona_hp_ev(struct snd_soc_dapm_widget *w,
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(arizona_hp_ev);
|
EXPORT_SYMBOL_GPL(arizona_hp_ev);
|
||||||
|
|
||||||
|
static int arizona_dvfs_enable(struct snd_soc_codec *codec)
|
||||||
|
{
|
||||||
|
const struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
|
||||||
|
struct arizona *arizona = priv->arizona;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = regulator_set_voltage(arizona->dcvdd, 1800000, 1800000);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(codec->dev, "Failed to boost DCVDD: %d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = regmap_update_bits(arizona->regmap,
|
||||||
|
ARIZONA_DYNAMIC_FREQUENCY_SCALING_1,
|
||||||
|
ARIZONA_SUBSYS_MAX_FREQ,
|
||||||
|
ARIZONA_SUBSYS_MAX_FREQ);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(codec->dev, "Failed to enable subsys max: %d\n", ret);
|
||||||
|
regulator_set_voltage(arizona->dcvdd, 1200000, 1800000);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int arizona_dvfs_disable(struct snd_soc_codec *codec)
|
||||||
|
{
|
||||||
|
const struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
|
||||||
|
struct arizona *arizona = priv->arizona;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = regmap_update_bits(arizona->regmap,
|
||||||
|
ARIZONA_DYNAMIC_FREQUENCY_SCALING_1,
|
||||||
|
ARIZONA_SUBSYS_MAX_FREQ, 0);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(codec->dev, "Failed to disable subsys max: %d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = regulator_set_voltage(arizona->dcvdd, 1200000, 1800000);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(codec->dev, "Failed to unboost DCVDD: %d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int arizona_dvfs_up(struct snd_soc_codec *codec, unsigned int flags)
|
||||||
|
{
|
||||||
|
struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
mutex_lock(&priv->dvfs_lock);
|
||||||
|
|
||||||
|
if (!priv->dvfs_cached && !priv->dvfs_reqs) {
|
||||||
|
ret = arizona_dvfs_enable(codec);
|
||||||
|
if (ret)
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
priv->dvfs_reqs |= flags;
|
||||||
|
err:
|
||||||
|
mutex_unlock(&priv->dvfs_lock);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(arizona_dvfs_up);
|
||||||
|
|
||||||
|
int arizona_dvfs_down(struct snd_soc_codec *codec, unsigned int flags)
|
||||||
|
{
|
||||||
|
struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
|
||||||
|
unsigned int old_reqs;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
mutex_lock(&priv->dvfs_lock);
|
||||||
|
|
||||||
|
old_reqs = priv->dvfs_reqs;
|
||||||
|
priv->dvfs_reqs &= ~flags;
|
||||||
|
|
||||||
|
if (!priv->dvfs_cached && old_reqs && !priv->dvfs_reqs)
|
||||||
|
ret = arizona_dvfs_disable(codec);
|
||||||
|
|
||||||
|
mutex_unlock(&priv->dvfs_lock);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(arizona_dvfs_down);
|
||||||
|
|
||||||
|
int arizona_dvfs_sysclk_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_priv *priv = snd_soc_codec_get_drvdata(codec);
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
mutex_lock(&priv->dvfs_lock);
|
||||||
|
|
||||||
|
switch (event) {
|
||||||
|
case SND_SOC_DAPM_POST_PMU:
|
||||||
|
if (priv->dvfs_reqs)
|
||||||
|
ret = arizona_dvfs_enable(codec);
|
||||||
|
|
||||||
|
priv->dvfs_cached = false;
|
||||||
|
break;
|
||||||
|
case SND_SOC_DAPM_PRE_PMD:
|
||||||
|
/* We must ensure DVFS is disabled before the codec goes into
|
||||||
|
* suspend so that we are never in an illegal state of DVFS
|
||||||
|
* enabled without enough DCVDD
|
||||||
|
*/
|
||||||
|
priv->dvfs_cached = true;
|
||||||
|
|
||||||
|
if (priv->dvfs_reqs)
|
||||||
|
ret = arizona_dvfs_disable(codec);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex_unlock(&priv->dvfs_lock);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(arizona_dvfs_sysclk_ev);
|
||||||
|
|
||||||
|
void arizona_init_dvfs(struct arizona_priv *priv)
|
||||||
|
{
|
||||||
|
mutex_init(&priv->dvfs_lock);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(arizona_init_dvfs);
|
||||||
|
|
||||||
static unsigned int arizona_sysclk_48k_rates[] = {
|
static unsigned int arizona_sysclk_48k_rates[] = {
|
||||||
6144000,
|
6144000,
|
||||||
12288000,
|
12288000,
|
||||||
|
@ -1266,7 +1394,7 @@ static int arizona_hw_params_rate(struct snd_pcm_substream *substream,
|
||||||
struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
|
struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
|
||||||
struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1];
|
struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1];
|
||||||
int base = dai->driver->base;
|
int base = dai->driver->base;
|
||||||
int i, sr_val;
|
int i, sr_val, ret;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We will need to be more flexible than this in future,
|
* We will need to be more flexible than this in future,
|
||||||
|
@ -1282,6 +1410,23 @@ static int arizona_hw_params_rate(struct snd_pcm_substream *substream,
|
||||||
}
|
}
|
||||||
sr_val = i;
|
sr_val = i;
|
||||||
|
|
||||||
|
switch (priv->arizona->type) {
|
||||||
|
case WM5102:
|
||||||
|
case WM8997:
|
||||||
|
if (arizona_sr_vals[sr_val] >= 88200)
|
||||||
|
ret = arizona_dvfs_up(codec, ARIZONA_DVFS_SR1_RQ);
|
||||||
|
else
|
||||||
|
ret = arizona_dvfs_down(codec, ARIZONA_DVFS_SR1_RQ);
|
||||||
|
|
||||||
|
if (ret) {
|
||||||
|
arizona_aif_err(dai, "Failed to change DVFS %d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
switch (dai_priv->clk) {
|
switch (dai_priv->clk) {
|
||||||
case ARIZONA_CLK_SYSCLK:
|
case ARIZONA_CLK_SYSCLK:
|
||||||
switch (priv->arizona->type) {
|
switch (priv->arizona->type) {
|
||||||
|
|
|
@ -60,6 +60,9 @@
|
||||||
#define ARIZONA_MAX_DAI 6
|
#define ARIZONA_MAX_DAI 6
|
||||||
#define ARIZONA_MAX_ADSP 4
|
#define ARIZONA_MAX_ADSP 4
|
||||||
|
|
||||||
|
#define ARIZONA_DVFS_SR1_RQ 0x001
|
||||||
|
#define ARIZONA_DVFS_ADSP1_RQ 0x100
|
||||||
|
|
||||||
struct arizona;
|
struct arizona;
|
||||||
struct wm_adsp;
|
struct wm_adsp;
|
||||||
|
|
||||||
|
@ -84,6 +87,10 @@ struct arizona_priv {
|
||||||
|
|
||||||
unsigned int spk_ena:2;
|
unsigned int spk_ena:2;
|
||||||
unsigned int spk_ena_pending:1;
|
unsigned int spk_ena_pending:1;
|
||||||
|
|
||||||
|
unsigned int dvfs_reqs;
|
||||||
|
struct mutex dvfs_lock;
|
||||||
|
bool dvfs_cached;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define ARIZONA_NUM_MIXER_INPUTS 103
|
#define ARIZONA_NUM_MIXER_INPUTS 103
|
||||||
|
@ -107,8 +114,8 @@ extern int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS];
|
||||||
arizona_mixer_tlv)
|
arizona_mixer_tlv)
|
||||||
|
|
||||||
#define ARIZONA_MUX_ENUM_DECL(name, reg) \
|
#define ARIZONA_MUX_ENUM_DECL(name, reg) \
|
||||||
SOC_VALUE_ENUM_SINGLE_DECL(name, reg, 0, 0xff, \
|
SOC_VALUE_ENUM_SINGLE_AUTODISABLE_DECL( \
|
||||||
arizona_mixer_texts, arizona_mixer_values)
|
name, reg, 0, 0xff, arizona_mixer_texts, arizona_mixer_values)
|
||||||
|
|
||||||
#define ARIZONA_MUX_CTL_DECL(name) \
|
#define ARIZONA_MUX_CTL_DECL(name) \
|
||||||
const struct snd_kcontrol_new name##_mux = \
|
const struct snd_kcontrol_new name##_mux = \
|
||||||
|
@ -245,6 +252,12 @@ struct arizona_fll {
|
||||||
char clock_ok_name[ARIZONA_FLL_NAME_LEN];
|
char clock_ok_name[ARIZONA_FLL_NAME_LEN];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern int arizona_dvfs_up(struct snd_soc_codec *codec, unsigned int flags);
|
||||||
|
extern int arizona_dvfs_down(struct snd_soc_codec *codec, unsigned int flags);
|
||||||
|
extern int arizona_dvfs_sysclk_ev(struct snd_soc_dapm_widget *w,
|
||||||
|
struct snd_kcontrol *kcontrol, int event);
|
||||||
|
extern void arizona_init_dvfs(struct arizona_priv *priv);
|
||||||
|
|
||||||
extern int arizona_init_fll(struct arizona *arizona, int id, int base,
|
extern int arizona_init_fll(struct arizona *arizona, int id, int base,
|
||||||
int lock_irq, int ok_irq, struct arizona_fll *fll);
|
int lock_irq, int ok_irq, struct arizona_fll *fll);
|
||||||
extern int arizona_set_fll_refclk(struct arizona_fll *fll, int source,
|
extern int arizona_set_fll_refclk(struct arizona_fll *fll, int source,
|
||||||
|
|
|
@ -605,12 +605,56 @@ static int wm5102_sysclk_ev(struct snd_soc_dapm_widget *w,
|
||||||
regmap_write_async(regmap, patch[i].reg,
|
regmap_write_async(regmap, patch[i].reg,
|
||||||
patch[i].def);
|
patch[i].def);
|
||||||
break;
|
break;
|
||||||
|
case SND_SOC_DAPM_PRE_PMD:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return arizona_dvfs_sysclk_ev(w, kcontrol, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int wm5102_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;
|
||||||
|
|
||||||
|
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(codec, ARIZONA_DVFS_ADSP1_RQ);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(codec->dev,
|
||||||
|
"Failed to raise DVFS: %d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SND_SOC_DAPM_POST_PMD:
|
||||||
|
ret = arizona_dvfs_down(codec, ARIZONA_DVFS_ADSP1_RQ);
|
||||||
|
if (ret)
|
||||||
|
dev_warn(codec->dev,
|
||||||
|
"Failed to lower DVFS: %d\n", ret);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return wm_adsp2_early_event(w, kcontrol, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int wm5102_out_comp_coeff_get(struct snd_kcontrol *kcontrol,
|
static int wm5102_out_comp_coeff_get(struct snd_kcontrol *kcontrol,
|
||||||
|
@ -1036,7 +1080,8 @@ static const struct snd_kcontrol_new wm5102_aec_loopback_mux =
|
||||||
|
|
||||||
static const struct snd_soc_dapm_widget wm5102_dapm_widgets[] = {
|
static const struct snd_soc_dapm_widget wm5102_dapm_widgets[] = {
|
||||||
SND_SOC_DAPM_SUPPLY("SYSCLK", ARIZONA_SYSTEM_CLOCK_1, ARIZONA_SYSCLK_ENA_SHIFT,
|
SND_SOC_DAPM_SUPPLY("SYSCLK", ARIZONA_SYSTEM_CLOCK_1, ARIZONA_SYSCLK_ENA_SHIFT,
|
||||||
0, wm5102_sysclk_ev, SND_SOC_DAPM_POST_PMU),
|
0, wm5102_sysclk_ev,
|
||||||
|
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
|
||||||
SND_SOC_DAPM_SUPPLY("ASYNCCLK", ARIZONA_ASYNC_CLOCK_1,
|
SND_SOC_DAPM_SUPPLY("ASYNCCLK", ARIZONA_ASYNC_CLOCK_1,
|
||||||
ARIZONA_ASYNC_CLK_ENA_SHIFT, 0, NULL, 0),
|
ARIZONA_ASYNC_CLK_ENA_SHIFT, 0, NULL, 0),
|
||||||
SND_SOC_DAPM_SUPPLY("OPCLK", ARIZONA_OUTPUT_SYSTEM_CLOCK,
|
SND_SOC_DAPM_SUPPLY("OPCLK", ARIZONA_OUTPUT_SYSTEM_CLOCK,
|
||||||
|
@ -1367,7 +1412,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("DSP1", 0),
|
WM_ADSP2_E("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"),
|
||||||
|
@ -1910,6 +1955,8 @@ static int wm5102_probe(struct platform_device *pdev)
|
||||||
wm5102->core.arizona = arizona;
|
wm5102->core.arizona = arizona;
|
||||||
wm5102->core.num_inputs = 6;
|
wm5102->core.num_inputs = 6;
|
||||||
|
|
||||||
|
arizona_init_dvfs(&wm5102->core);
|
||||||
|
|
||||||
wm5102->core.adsp[0].part = "wm5102";
|
wm5102->core.adsp[0].part = "wm5102";
|
||||||
wm5102->core.adsp[0].num = 1;
|
wm5102->core.adsp[0].num = 1;
|
||||||
wm5102->core.adsp[0].type = WMFW_ADSP2;
|
wm5102->core.adsp[0].type = WMFW_ADSP2;
|
||||||
|
@ -1919,7 +1966,7 @@ static int wm5102_probe(struct platform_device *pdev)
|
||||||
wm5102->core.adsp[0].mem = wm5102_dsp1_regions;
|
wm5102->core.adsp[0].mem = wm5102_dsp1_regions;
|
||||||
wm5102->core.adsp[0].num_mems = ARRAY_SIZE(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)
|
if (ret != 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
|
|
@ -1696,7 +1696,7 @@ static int wm5110_probe(struct platform_device *pdev)
|
||||||
wm5110->core.adsp[i].num_mems
|
wm5110->core.adsp[i].num_mems
|
||||||
= ARRAY_SIZE(wm5110_dsp1_regions);
|
= 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)
|
if (ret != 0)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -106,11 +106,13 @@ static int wm8997_sysclk_ev(struct snd_soc_dapm_widget *w,
|
||||||
regmap_write_async(regmap, patch[i].reg,
|
regmap_write_async(regmap, patch[i].reg,
|
||||||
patch[i].def);
|
patch[i].def);
|
||||||
break;
|
break;
|
||||||
default:
|
case SND_SOC_DAPM_PRE_PMD:
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return arizona_dvfs_sysclk_ev(w, kcontrol, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *wm8997_osr_text[] = {
|
static const char *wm8997_osr_text[] = {
|
||||||
|
@ -409,7 +411,8 @@ static const struct snd_kcontrol_new wm8997_aec_loopback_mux =
|
||||||
|
|
||||||
static const struct snd_soc_dapm_widget wm8997_dapm_widgets[] = {
|
static const struct snd_soc_dapm_widget wm8997_dapm_widgets[] = {
|
||||||
SND_SOC_DAPM_SUPPLY("SYSCLK", ARIZONA_SYSTEM_CLOCK_1, ARIZONA_SYSCLK_ENA_SHIFT,
|
SND_SOC_DAPM_SUPPLY("SYSCLK", ARIZONA_SYSTEM_CLOCK_1, ARIZONA_SYSCLK_ENA_SHIFT,
|
||||||
0, wm8997_sysclk_ev, SND_SOC_DAPM_POST_PMU),
|
0, wm8997_sysclk_ev,
|
||||||
|
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
|
||||||
SND_SOC_DAPM_SUPPLY("ASYNCCLK", ARIZONA_ASYNC_CLOCK_1,
|
SND_SOC_DAPM_SUPPLY("ASYNCCLK", ARIZONA_ASYNC_CLOCK_1,
|
||||||
ARIZONA_ASYNC_CLK_ENA_SHIFT, 0, NULL, 0),
|
ARIZONA_ASYNC_CLK_ENA_SHIFT, 0, NULL, 0),
|
||||||
SND_SOC_DAPM_SUPPLY("OPCLK", ARIZONA_OUTPUT_SYSTEM_CLOCK,
|
SND_SOC_DAPM_SUPPLY("OPCLK", ARIZONA_OUTPUT_SYSTEM_CLOCK,
|
||||||
|
@ -1127,6 +1130,8 @@ static int wm8997_probe(struct platform_device *pdev)
|
||||||
wm8997->core.arizona = arizona;
|
wm8997->core.arizona = arizona;
|
||||||
wm8997->core.num_inputs = 4;
|
wm8997->core.num_inputs = 4;
|
||||||
|
|
||||||
|
arizona_init_dvfs(&wm8997->core);
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(wm8997->fll); i++)
|
for (i = 0; i < ARRAY_SIZE(wm8997->fll); i++)
|
||||||
wm8997->fll[i].vco_mult = 1;
|
wm8997->fll[i].vco_mult = 1;
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -18,8 +18,6 @@
|
||||||
|
|
||||||
#include "wmfw.h"
|
#include "wmfw.h"
|
||||||
|
|
||||||
struct regulator;
|
|
||||||
|
|
||||||
struct wm_adsp_region {
|
struct wm_adsp_region {
|
||||||
int type;
|
int type;
|
||||||
unsigned int base;
|
unsigned int base;
|
||||||
|
@ -30,7 +28,6 @@ struct wm_adsp_alg_region {
|
||||||
unsigned int alg;
|
unsigned int alg;
|
||||||
int type;
|
int type;
|
||||||
unsigned int base;
|
unsigned int base;
|
||||||
size_t len;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct wm_adsp {
|
struct wm_adsp {
|
||||||
|
@ -54,10 +51,9 @@ struct wm_adsp {
|
||||||
int num_mems;
|
int num_mems;
|
||||||
|
|
||||||
int fw;
|
int fw;
|
||||||
|
int fw_ver;
|
||||||
bool running;
|
bool running;
|
||||||
|
|
||||||
struct regulator *dvfs;
|
|
||||||
|
|
||||||
struct list_head ctl_list;
|
struct list_head ctl_list;
|
||||||
|
|
||||||
struct work_struct boot_work;
|
struct work_struct boot_work;
|
||||||
|
@ -67,19 +63,22 @@ 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(wname, num) \
|
#define WM_ADSP2_E(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 = wm_adsp2_early_event, \
|
.reg = SND_SOC_NOPM, .shift = num, .event = event_fn, \
|
||||||
.event_flags = SND_SOC_DAPM_PRE_PMU }, \
|
.event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD }, \
|
||||||
{ .id = snd_soc_dapm_out_drv, .name = wname, \
|
{ .id = snd_soc_dapm_out_drv, .name = wname, \
|
||||||
.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_adsp1_fw_controls[];
|
extern const struct snd_kcontrol_new wm_adsp1_fw_controls[];
|
||||||
extern const struct snd_kcontrol_new wm_adsp2_fw_controls[];
|
extern const struct snd_kcontrol_new wm_adsp2_fw_controls[];
|
||||||
|
|
||||||
int wm_adsp1_init(struct wm_adsp *adsp);
|
int wm_adsp1_init(struct wm_adsp *dsp);
|
||||||
int wm_adsp2_init(struct wm_adsp *adsp, bool dvfs);
|
int wm_adsp2_init(struct wm_adsp *dsp);
|
||||||
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,
|
||||||
|
|
|
@ -15,6 +15,17 @@
|
||||||
|
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
|
|
||||||
|
#define WMFW_MAX_ALG_NAME 256
|
||||||
|
#define WMFW_MAX_ALG_DESCR_NAME 256
|
||||||
|
|
||||||
|
#define WMFW_MAX_COEFF_NAME 256
|
||||||
|
#define WMFW_MAX_COEFF_DESCR_NAME 256
|
||||||
|
|
||||||
|
#define WMFW_CTL_FLAG_SYS 0x8000
|
||||||
|
#define WMFW_CTL_FLAG_VOLATILE 0x0004
|
||||||
|
#define WMFW_CTL_FLAG_WRITEABLE 0x0002
|
||||||
|
#define WMFW_CTL_FLAG_READABLE 0x0001
|
||||||
|
|
||||||
struct wmfw_header {
|
struct wmfw_header {
|
||||||
char magic[4];
|
char magic[4];
|
||||||
__le32 len;
|
__le32 len;
|
||||||
|
@ -61,7 +72,7 @@ struct wmfw_adsp1_id_hdr {
|
||||||
struct wmfw_id_hdr fw;
|
struct wmfw_id_hdr fw;
|
||||||
__be32 zm;
|
__be32 zm;
|
||||||
__be32 dm;
|
__be32 dm;
|
||||||
__be32 algs;
|
__be32 n_algs;
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
struct wmfw_adsp2_id_hdr {
|
struct wmfw_adsp2_id_hdr {
|
||||||
|
@ -69,7 +80,7 @@ struct wmfw_adsp2_id_hdr {
|
||||||
__be32 zm;
|
__be32 zm;
|
||||||
__be32 xm;
|
__be32 xm;
|
||||||
__be32 ym;
|
__be32 ym;
|
||||||
__be32 algs;
|
__be32 n_algs;
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
struct wmfw_alg_hdr {
|
struct wmfw_alg_hdr {
|
||||||
|
@ -90,6 +101,28 @@ struct wmfw_adsp2_alg_hdr {
|
||||||
__be32 ym;
|
__be32 ym;
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
|
struct wmfw_adsp_alg_data {
|
||||||
|
__le32 id;
|
||||||
|
u8 name[WMFW_MAX_ALG_NAME];
|
||||||
|
u8 descr[WMFW_MAX_ALG_DESCR_NAME];
|
||||||
|
__le32 ncoeff;
|
||||||
|
u8 data[];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
struct wmfw_adsp_coeff_data {
|
||||||
|
struct {
|
||||||
|
__le16 offset;
|
||||||
|
__le16 type;
|
||||||
|
__le32 size;
|
||||||
|
} hdr;
|
||||||
|
u8 name[WMFW_MAX_COEFF_NAME];
|
||||||
|
u8 descr[WMFW_MAX_COEFF_DESCR_NAME];
|
||||||
|
__le16 ctl_type;
|
||||||
|
__le16 flags;
|
||||||
|
__le32 len;
|
||||||
|
u8 data[];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
struct wmfw_coeff_hdr {
|
struct wmfw_coeff_hdr {
|
||||||
u8 magic[4];
|
u8 magic[4];
|
||||||
__le32 len;
|
__le32 len;
|
||||||
|
@ -117,9 +150,10 @@ struct wmfw_coeff_item {
|
||||||
#define WMFW_ADSP1 1
|
#define WMFW_ADSP1 1
|
||||||
#define WMFW_ADSP2 2
|
#define WMFW_ADSP2 2
|
||||||
|
|
||||||
#define WMFW_ABSOLUTE 0xf0
|
#define WMFW_ABSOLUTE 0xf0
|
||||||
#define WMFW_NAME_TEXT 0xfe
|
#define WMFW_ALGORITHM_DATA 0xf2
|
||||||
#define WMFW_INFO_TEXT 0xff
|
#define WMFW_NAME_TEXT 0xfe
|
||||||
|
#define WMFW_INFO_TEXT 0xff
|
||||||
|
|
||||||
#define WMFW_ADSP1_PM 2
|
#define WMFW_ADSP1_PM 2
|
||||||
#define WMFW_ADSP1_DM 3
|
#define WMFW_ADSP1_DM 3
|
||||||
|
|
Loading…
Add table
Reference in a new issue