Commit 4db68e62 authored by Mark Brown's avatar Mark Brown

Merge branch 'asoc-5.9' into asoc-5.10

parents d70a4412 244ac15d
...@@ -1193,6 +1193,8 @@ struct snd_soc_pcm_runtime { ...@@ -1193,6 +1193,8 @@ struct snd_soc_pcm_runtime {
((i) < (rtd)->num_cpus + (rtd)->num_codecs) && \ ((i) < (rtd)->num_cpus + (rtd)->num_codecs) && \
((dai) = (rtd)->dais[i]); \ ((dai) = (rtd)->dais[i]); \
(i)++) (i)++)
#define for_each_rtd_dais_rollback(rtd, i, dai) \
for (; (--(i) >= 0) && ((dai) = (rtd)->dais[i]);)
void snd_soc_close_delayed_work(struct snd_soc_pcm_runtime *rtd); void snd_soc_close_delayed_work(struct snd_soc_pcm_runtime *rtd);
......
...@@ -841,8 +841,8 @@ static int max98373_sdw_probe(struct sdw_slave *slave, ...@@ -841,8 +841,8 @@ static int max98373_sdw_probe(struct sdw_slave *slave,
/* Regmap Initialization */ /* Regmap Initialization */
regmap = devm_regmap_init_sdw(slave, &max98373_sdw_regmap); regmap = devm_regmap_init_sdw(slave, &max98373_sdw_regmap);
if (!regmap) if (IS_ERR(regmap))
return -EINVAL; return PTR_ERR(regmap);
return max98373_init(slave, regmap); return max98373_init(slave, regmap);
} }
......
...@@ -306,6 +306,13 @@ static int pcm3168a_set_dai_sysclk(struct snd_soc_dai *dai, ...@@ -306,6 +306,13 @@ static int pcm3168a_set_dai_sysclk(struct snd_soc_dai *dai,
struct pcm3168a_priv *pcm3168a = snd_soc_component_get_drvdata(dai->component); struct pcm3168a_priv *pcm3168a = snd_soc_component_get_drvdata(dai->component);
int ret; int ret;
/*
* Some sound card sets 0 Hz as reset,
* but it is impossible to set. Ignore it here
*/
if (freq == 0)
return 0;
if (freq > PCM3168A_MAX_SYSCLK) if (freq > PCM3168A_MAX_SYSCLK)
return -EINVAL; return -EINVAL;
......
...@@ -484,6 +484,33 @@ static int rt1015_bypass_boost_get(struct snd_kcontrol *kcontrol, ...@@ -484,6 +484,33 @@ static int rt1015_bypass_boost_get(struct snd_kcontrol *kcontrol,
return 0; return 0;
} }
static void rt1015_calibrate(struct rt1015_priv *rt1015)
{
struct snd_soc_component *component = rt1015->component;
struct regmap *regmap = rt1015->regmap;
snd_soc_dapm_mutex_lock(&component->dapm);
regcache_cache_bypass(regmap, true);
regmap_write(regmap, RT1015_PWR1, 0xd7df);
regmap_write(regmap, RT1015_PWR4, 0x00b2);
regmap_write(regmap, RT1015_CLSD_INTERNAL8, 0x2008);
regmap_write(regmap, RT1015_CLSD_INTERNAL9, 0x0140);
regmap_write(regmap, RT1015_GAT_BOOST, 0x0efe);
regmap_write(regmap, RT1015_PWR_STATE_CTRL, 0x000d);
regmap_write(regmap, RT1015_PWR_STATE_CTRL, 0x000e);
regmap_write(regmap, RT1015_DC_CALIB_CLSD1, 0x5a00);
regmap_write(regmap, RT1015_DC_CALIB_CLSD1, 0x5a01);
regmap_write(regmap, RT1015_DC_CALIB_CLSD1, 0x5a05);
msleep(500);
regmap_write(regmap, RT1015_PWR1, 0x0);
regcache_cache_bypass(regmap, false);
regcache_mark_dirty(regmap);
regcache_sync(regmap);
snd_soc_dapm_mutex_unlock(&component->dapm);
}
static int rt1015_bypass_boost_put(struct snd_kcontrol *kcontrol, static int rt1015_bypass_boost_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol) struct snd_ctl_elem_value *ucontrol)
{ {
...@@ -494,20 +521,12 @@ static int rt1015_bypass_boost_put(struct snd_kcontrol *kcontrol, ...@@ -494,20 +521,12 @@ static int rt1015_bypass_boost_put(struct snd_kcontrol *kcontrol,
if (!rt1015->dac_is_used) { if (!rt1015->dac_is_used) {
rt1015->bypass_boost = ucontrol->value.integer.value[0]; rt1015->bypass_boost = ucontrol->value.integer.value[0];
if (rt1015->bypass_boost == RT1015_Bypass_Boost) { if (rt1015->bypass_boost == RT1015_Bypass_Boost &&
snd_soc_component_write(component, !rt1015->cali_done) {
RT1015_PWR4, 0x00b2); rt1015_calibrate(rt1015);
snd_soc_component_write(component, rt1015->cali_done = 1;
RT1015_CLSD_INTERNAL8, 0x2008);
snd_soc_component_write(component, regmap_write(rt1015->regmap, RT1015_MONO_DYNA_CTRL, 0x0010);
RT1015_CLSD_INTERNAL9, 0x0140);
snd_soc_component_write(component,
RT1015_GAT_BOOST, 0x0efe);
snd_soc_component_write(component,
RT1015_PWR_STATE_CTRL, 0x000d);
msleep(500);
snd_soc_component_write(component,
RT1015_PWR_STATE_CTRL, 0x000e);
} }
} else } else
dev_err(component->dev, "DAC is being used!\n"); dev_err(component->dev, "DAC is being used!\n");
...@@ -515,6 +534,32 @@ static int rt1015_bypass_boost_put(struct snd_kcontrol *kcontrol, ...@@ -515,6 +534,32 @@ static int rt1015_bypass_boost_put(struct snd_kcontrol *kcontrol,
return 0; return 0;
} }
static void rt1015_flush_work(struct work_struct *work)
{
struct rt1015_priv *rt1015 = container_of(work, struct rt1015_priv,
flush_work.work);
struct snd_soc_component *component = rt1015->component;
unsigned int val, i = 0, count = 20;
while (i < count) {
usleep_range(1000, 1500);
dev_dbg(component->dev, "Flush DAC (retry:%u)\n", i);
regmap_read(rt1015->regmap, RT1015_CLK_DET, &val);
if (val & 0x800)
break;
i++;
}
regmap_write(rt1015->regmap, RT1015_SYS_RST1, 0x0597);
regmap_write(rt1015->regmap, RT1015_SYS_RST1, 0x05f7);
regmap_write(rt1015->regmap, RT1015_MAN_I2C, 0x0028);
if (val & 0x800)
dev_dbg(component->dev, "Flush DAC completed.\n");
else
dev_warn(component->dev, "Fail to flush DAC data.\n");
}
static const struct snd_kcontrol_new rt1015_snd_controls[] = { static const struct snd_kcontrol_new rt1015_snd_controls[] = {
SOC_SINGLE_TLV("DAC Playback Volume", RT1015_DAC1, RT1015_DAC_VOL_SFT, SOC_SINGLE_TLV("DAC Playback Volume", RT1015_DAC1, RT1015_DAC_VOL_SFT,
127, 0, dac_vol_tlv), 127, 0, dac_vol_tlv),
...@@ -568,12 +613,7 @@ static int r1015_dac_event(struct snd_soc_dapm_widget *w, ...@@ -568,12 +613,7 @@ static int r1015_dac_event(struct snd_soc_dapm_widget *w,
break; break;
case SND_SOC_DAPM_POST_PMU: case SND_SOC_DAPM_POST_PMU:
if (rt1015->bypass_boost == RT1015_Bypass_Boost) {
regmap_write(rt1015->regmap, RT1015_MAN_I2C, 0x00a8); regmap_write(rt1015->regmap, RT1015_MAN_I2C, 0x00a8);
regmap_write(rt1015->regmap, RT1015_SYS_RST1, 0x0597);
regmap_write(rt1015->regmap, RT1015_SYS_RST1, 0x05f7);
regmap_write(rt1015->regmap, RT1015_MAN_I2C, 0x0028);
}
break; break;
case SND_SOC_DAPM_POST_PMD: case SND_SOC_DAPM_POST_PMD:
...@@ -589,6 +629,8 @@ static int r1015_dac_event(struct snd_soc_dapm_widget *w, ...@@ -589,6 +629,8 @@ static int r1015_dac_event(struct snd_soc_dapm_widget *w,
RT1015_SYS_RST1, 0x05f5); RT1015_SYS_RST1, 0x05f5);
} }
rt1015->dac_is_used = 0; rt1015->dac_is_used = 0;
cancel_delayed_work_sync(&rt1015->flush_work);
break; break;
default: default:
...@@ -597,6 +639,24 @@ static int r1015_dac_event(struct snd_soc_dapm_widget *w, ...@@ -597,6 +639,24 @@ static int r1015_dac_event(struct snd_soc_dapm_widget *w,
return 0; return 0;
} }
static int rt1015_amp_drv_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_component *component =
snd_soc_dapm_to_component(w->dapm);
struct rt1015_priv *rt1015 = snd_soc_component_get_drvdata(component);
switch (event) {
case SND_SOC_DAPM_POST_PMU:
if (rt1015->hw_config == RT1015_HW_28)
schedule_delayed_work(&rt1015->flush_work, msecs_to_jiffies(10));
break;
default:
break;
}
return 0;
}
static const struct snd_soc_dapm_widget rt1015_dapm_widgets[] = { static const struct snd_soc_dapm_widget rt1015_dapm_widgets[] = {
SND_SOC_DAPM_SUPPLY("LDO2", RT1015_PWR1, RT1015_PWR_LDO2_BIT, 0, SND_SOC_DAPM_SUPPLY("LDO2", RT1015_PWR1, RT1015_PWR_LDO2_BIT, 0,
NULL, 0), NULL, 0),
...@@ -630,6 +690,8 @@ static const struct snd_soc_dapm_widget rt1015_dapm_widgets[] = { ...@@ -630,6 +690,8 @@ static const struct snd_soc_dapm_widget rt1015_dapm_widgets[] = {
r1015_dac_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | r1015_dac_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_OUT_DRV_E("Amp Drv", SND_SOC_NOPM, 0, 0, NULL, 0,
rt1015_amp_drv_event, SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_OUTPUT("SPO"), SND_SOC_DAPM_OUTPUT("SPO"),
}; };
...@@ -648,7 +710,8 @@ static const struct snd_soc_dapm_route rt1015_dapm_routes[] = { ...@@ -648,7 +710,8 @@ static const struct snd_soc_dapm_route rt1015_dapm_routes[] = {
{ "DAC", NULL, "MIXERV" }, { "DAC", NULL, "MIXERV" },
{ "DAC", NULL, "SUMV" }, { "DAC", NULL, "SUMV" },
{ "DAC", NULL, "VREFLV" }, { "DAC", NULL, "VREFLV" },
{ "SPO", NULL, "DAC" }, { "Amp Drv", NULL, "DAC" },
{ "SPO", NULL, "Amp Drv" },
}; };
static int rt1015_hw_params(struct snd_pcm_substream *substream, static int rt1015_hw_params(struct snd_pcm_substream *substream,
...@@ -888,8 +951,11 @@ static int rt1015_probe(struct snd_soc_component *component) ...@@ -888,8 +951,11 @@ static int rt1015_probe(struct snd_soc_component *component)
rt1015->component = component; rt1015->component = component;
rt1015->bclk_ratio = 0; rt1015->bclk_ratio = 0;
rt1015->cali_done = 0;
snd_soc_component_write(component, RT1015_BAT_RPO_STEP1, 0x061c); snd_soc_component_write(component, RT1015_BAT_RPO_STEP1, 0x061c);
INIT_DELAYED_WORK(&rt1015->flush_work, rt1015_flush_work);
return 0; return 0;
} }
...@@ -897,6 +963,7 @@ static void rt1015_remove(struct snd_soc_component *component) ...@@ -897,6 +963,7 @@ static void rt1015_remove(struct snd_soc_component *component)
{ {
struct rt1015_priv *rt1015 = snd_soc_component_get_drvdata(component); struct rt1015_priv *rt1015 = snd_soc_component_get_drvdata(component);
cancel_delayed_work_sync(&rt1015->flush_work);
regmap_write(rt1015->regmap, RT1015_RESET, 0); regmap_write(rt1015->regmap, RT1015_RESET, 0);
} }
...@@ -1022,6 +1089,8 @@ static int rt1015_i2c_probe(struct i2c_client *i2c, ...@@ -1022,6 +1089,8 @@ static int rt1015_i2c_probe(struct i2c_client *i2c,
return ret; return ret;
} }
rt1015->hw_config = (i2c->addr == 0x29) ? RT1015_HW_29 : RT1015_HW_28;
regmap_read(rt1015->regmap, RT1015_DEVICE_ID, &val); regmap_read(rt1015->regmap, RT1015_DEVICE_ID, &val);
if ((val != RT1015_DEVICE_ID_VAL) && (val != RT1015_DEVICE_ID_VAL2)) { if ((val != RT1015_DEVICE_ID_VAL) && (val != RT1015_DEVICE_ID_VAL2)) {
dev_err(&i2c->dev, dev_err(&i2c->dev,
......
...@@ -373,6 +373,11 @@ enum { ...@@ -373,6 +373,11 @@ enum {
RT1015_Bypass_Boost, RT1015_Bypass_Boost,
}; };
enum {
RT1015_HW_28 = 0,
RT1015_HW_29,
};
struct rt1015_priv { struct rt1015_priv {
struct snd_soc_component *component; struct snd_soc_component *component;
struct regmap *regmap; struct regmap *regmap;
...@@ -389,6 +394,9 @@ struct rt1015_priv { ...@@ -389,6 +394,9 @@ struct rt1015_priv {
int bypass_boost; int bypass_boost;
int amp_ver; int amp_ver;
int dac_is_used; int dac_is_used;
int cali_done;
int hw_config;
struct delayed_work flush_work;
}; };
#endif /* __RT1015_H__ */ #endif /* __RT1015_H__ */
...@@ -684,8 +684,8 @@ static int rt1308_sdw_probe(struct sdw_slave *slave, ...@@ -684,8 +684,8 @@ static int rt1308_sdw_probe(struct sdw_slave *slave,
/* Regmap Initialization */ /* Regmap Initialization */
regmap = devm_regmap_init_sdw(slave, &rt1308_sdw_regmap); regmap = devm_regmap_init_sdw(slave, &rt1308_sdw_regmap);
if (!regmap) if (IS_ERR(regmap))
return -EINVAL; return PTR_ERR(regmap);
rt1308_sdw_init(&slave->dev, regmap, slave); rt1308_sdw_init(&slave->dev, regmap, slave);
......
...@@ -452,8 +452,8 @@ static int rt700_sdw_probe(struct sdw_slave *slave, ...@@ -452,8 +452,8 @@ static int rt700_sdw_probe(struct sdw_slave *slave,
/* Regmap Initialization */ /* Regmap Initialization */
sdw_regmap = devm_regmap_init_sdw(slave, &rt700_sdw_regmap); sdw_regmap = devm_regmap_init_sdw(slave, &rt700_sdw_regmap);
if (!sdw_regmap) if (IS_ERR(sdw_regmap))
return -EINVAL; return PTR_ERR(sdw_regmap);
regmap = devm_regmap_init(&slave->dev, NULL, regmap = devm_regmap_init(&slave->dev, NULL,
&slave->dev, &rt700_regmap); &slave->dev, &rt700_regmap);
......
...@@ -452,8 +452,8 @@ static int rt711_sdw_probe(struct sdw_slave *slave, ...@@ -452,8 +452,8 @@ static int rt711_sdw_probe(struct sdw_slave *slave,
/* Regmap Initialization */ /* Regmap Initialization */
sdw_regmap = devm_regmap_init_sdw(slave, &rt711_sdw_regmap); sdw_regmap = devm_regmap_init_sdw(slave, &rt711_sdw_regmap);
if (!sdw_regmap) if (IS_ERR(sdw_regmap))
return -EINVAL; return PTR_ERR(sdw_regmap);
regmap = devm_regmap_init(&slave->dev, NULL, regmap = devm_regmap_init(&slave->dev, NULL,
&slave->dev, &rt711_regmap); &slave->dev, &rt711_regmap);
......
...@@ -527,8 +527,8 @@ static int rt715_sdw_probe(struct sdw_slave *slave, ...@@ -527,8 +527,8 @@ static int rt715_sdw_probe(struct sdw_slave *slave,
/* Regmap Initialization */ /* Regmap Initialization */
sdw_regmap = devm_regmap_init_sdw(slave, &rt715_sdw_regmap); sdw_regmap = devm_regmap_init_sdw(slave, &rt715_sdw_regmap);
if (!sdw_regmap) if (IS_ERR(sdw_regmap))
return -EINVAL; return PTR_ERR(sdw_regmap);
regmap = devm_regmap_init(&slave->dev, NULL, &slave->dev, regmap = devm_regmap_init(&slave->dev, NULL, &slave->dev,
&rt715_regmap); &rt715_regmap);
......
...@@ -30,7 +30,7 @@ struct adcx140_priv { ...@@ -30,7 +30,7 @@ struct adcx140_priv {
struct regmap *regmap; struct regmap *regmap;
struct device *dev; struct device *dev;
int micbias_vg; bool micbias_vg;
unsigned int dai_fmt; unsigned int dai_fmt;
unsigned int tdm_delay; unsigned int tdm_delay;
...@@ -161,7 +161,7 @@ static const struct regmap_config adcx140_i2c_regmap = { ...@@ -161,7 +161,7 @@ static const struct regmap_config adcx140_i2c_regmap = {
}; };
/* Digital Volume control. From -100 to 27 dB in 0.5 dB steps */ /* Digital Volume control. From -100 to 27 dB in 0.5 dB steps */
static DECLARE_TLV_DB_SCALE(dig_vol_tlv, -10000, 50, 0); static DECLARE_TLV_DB_SCALE(dig_vol_tlv, -10050, 50, 0);
/* ADC gain. From 0 to 42 dB in 1 dB steps */ /* ADC gain. From 0 to 42 dB in 1 dB steps */
static DECLARE_TLV_DB_SCALE(adc_tlv, 0, 100, 0); static DECLARE_TLV_DB_SCALE(adc_tlv, 0, 100, 0);
...@@ -651,11 +651,26 @@ static int adcx140_reset(struct adcx140_priv *adcx140) ...@@ -651,11 +651,26 @@ static int adcx140_reset(struct adcx140_priv *adcx140)
return ret; return ret;
} }
static void adcx140_pwr_ctrl(struct adcx140_priv *adcx140, bool power_state)
{
int pwr_ctrl = 0;
if (power_state)
pwr_ctrl = ADCX140_PWR_CFG_ADC_PDZ | ADCX140_PWR_CFG_PLL_PDZ;
if (adcx140->micbias_vg && power_state)
pwr_ctrl |= ADCX140_PWR_CFG_BIAS_PDZ;
regmap_update_bits(adcx140->regmap, ADCX140_PWR_CFG,
ADCX140_PWR_CTRL_MSK, pwr_ctrl);
}
static int adcx140_hw_params(struct snd_pcm_substream *substream, static int adcx140_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params, struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai) struct snd_soc_dai *dai)
{ {
struct snd_soc_component *component = dai->component; struct snd_soc_component *component = dai->component;
struct adcx140_priv *adcx140 = snd_soc_component_get_drvdata(component);
u8 data = 0; u8 data = 0;
switch (params_width(params)) { switch (params_width(params)) {
...@@ -677,9 +692,13 @@ static int adcx140_hw_params(struct snd_pcm_substream *substream, ...@@ -677,9 +692,13 @@ static int adcx140_hw_params(struct snd_pcm_substream *substream,
return -EINVAL; return -EINVAL;
} }
adcx140_pwr_ctrl(adcx140, false);
snd_soc_component_update_bits(component, ADCX140_ASI_CFG0, snd_soc_component_update_bits(component, ADCX140_ASI_CFG0,
ADCX140_WORD_LEN_MSK, data); ADCX140_WORD_LEN_MSK, data);
adcx140_pwr_ctrl(adcx140, true);
return 0; return 0;
} }
...@@ -691,7 +710,7 @@ static int adcx140_set_dai_fmt(struct snd_soc_dai *codec_dai, ...@@ -691,7 +710,7 @@ static int adcx140_set_dai_fmt(struct snd_soc_dai *codec_dai,
u8 iface_reg1 = 0; u8 iface_reg1 = 0;
u8 iface_reg2 = 0; u8 iface_reg2 = 0;
int offset = 0; int offset = 0;
int width = adcx140->slot_width; bool inverted_bclk = false;
/* set master/slave audio interface */ /* set master/slave audio interface */
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
...@@ -707,24 +726,6 @@ static int adcx140_set_dai_fmt(struct snd_soc_dai *codec_dai, ...@@ -707,24 +726,6 @@ static int adcx140_set_dai_fmt(struct snd_soc_dai *codec_dai,
return -EINVAL; return -EINVAL;
} }
/* signal polarity */
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
case SND_SOC_DAIFMT_NB_IF:
iface_reg1 |= ADCX140_FSYNCINV_BIT;
break;
case SND_SOC_DAIFMT_IB_IF:
iface_reg1 |= ADCX140_BCLKINV_BIT | ADCX140_FSYNCINV_BIT;
break;
case SND_SOC_DAIFMT_IB_NF:
iface_reg1 |= ADCX140_BCLKINV_BIT;
break;
case SND_SOC_DAIFMT_NB_NF:
break;
default:
dev_err(component->dev, "Invalid DAI clock signal polarity\n");
return -EINVAL;
}
/* interface format */ /* interface format */
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_I2S: case SND_SOC_DAIFMT_I2S:
...@@ -734,18 +735,40 @@ static int adcx140_set_dai_fmt(struct snd_soc_dai *codec_dai, ...@@ -734,18 +735,40 @@ static int adcx140_set_dai_fmt(struct snd_soc_dai *codec_dai,
iface_reg1 |= ADCX140_LEFT_JUST_BIT; iface_reg1 |= ADCX140_LEFT_JUST_BIT;
break; break;
case SND_SOC_DAIFMT_DSP_A: case SND_SOC_DAIFMT_DSP_A:
offset += (adcx140->tdm_delay * width + 1); offset = 1;
inverted_bclk = true;
break; break;
case SND_SOC_DAIFMT_DSP_B: case SND_SOC_DAIFMT_DSP_B:
offset += adcx140->tdm_delay * width; inverted_bclk = true;
break; break;
default: default:
dev_err(component->dev, "Invalid DAI interface format\n"); dev_err(component->dev, "Invalid DAI interface format\n");
return -EINVAL; return -EINVAL;
} }
/* signal polarity */
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
case SND_SOC_DAIFMT_IB_NF:
case SND_SOC_DAIFMT_IB_IF:
inverted_bclk = !inverted_bclk;
break;
case SND_SOC_DAIFMT_NB_IF:
iface_reg1 |= ADCX140_FSYNCINV_BIT;
break;
case SND_SOC_DAIFMT_NB_NF:
break;
default:
dev_err(component->dev, "Invalid DAI clock signal polarity\n");
return -EINVAL;
}
if (inverted_bclk)
iface_reg1 |= ADCX140_BCLKINV_BIT;
adcx140->dai_fmt = fmt & SND_SOC_DAIFMT_FORMAT_MASK; adcx140->dai_fmt = fmt & SND_SOC_DAIFMT_FORMAT_MASK;
adcx140_pwr_ctrl(adcx140, false);
snd_soc_component_update_bits(component, ADCX140_ASI_CFG0, snd_soc_component_update_bits(component, ADCX140_ASI_CFG0,
ADCX140_FSYNCINV_BIT | ADCX140_FSYNCINV_BIT |
ADCX140_BCLKINV_BIT | ADCX140_BCLKINV_BIT |
...@@ -758,6 +781,7 @@ static int adcx140_set_dai_fmt(struct snd_soc_dai *codec_dai, ...@@ -758,6 +781,7 @@ static int adcx140_set_dai_fmt(struct snd_soc_dai *codec_dai,
snd_soc_component_update_bits(component, ADCX140_ASI_CFG1, snd_soc_component_update_bits(component, ADCX140_ASI_CFG1,
ADCX140_TX_OFFSET_MASK, offset); ADCX140_TX_OFFSET_MASK, offset);
adcx140_pwr_ctrl(adcx140, true);
return 0; return 0;
} }
...@@ -855,12 +879,11 @@ static int adcx140_codec_probe(struct snd_soc_component *component) ...@@ -855,12 +879,11 @@ static int adcx140_codec_probe(struct snd_soc_component *component)
ret = device_property_read_u32(adcx140->dev, "ti,mic-bias-source", ret = device_property_read_u32(adcx140->dev, "ti,mic-bias-source",
&bias_source); &bias_source);
if (ret) if (ret || bias_source > ADCX140_MIC_BIAS_VAL_AVDD) {
bias_source = ADCX140_MIC_BIAS_VAL_VREF; bias_source = ADCX140_MIC_BIAS_VAL_VREF;
adcx140->micbias_vg = false;
if (bias_source > ADCX140_MIC_BIAS_VAL_AVDD) { } else {
dev_err(adcx140->dev, "Mic Bias source value is invalid\n"); adcx140->micbias_vg = true;
return -EINVAL;
} }
ret = device_property_read_u32(adcx140->dev, "ti,vref-source", ret = device_property_read_u32(adcx140->dev, "ti,vref-source",
...@@ -879,6 +902,18 @@ static int adcx140_codec_probe(struct snd_soc_component *component) ...@@ -879,6 +902,18 @@ static int adcx140_codec_probe(struct snd_soc_component *component)
if (ret) if (ret)
goto out; goto out;
if (adcx140->supply_areg == NULL)
sleep_cfg_val |= ADCX140_AREG_INTERNAL;
ret = regmap_write(adcx140->regmap, ADCX140_SLEEP_CFG, sleep_cfg_val);
if (ret) {
dev_err(adcx140->dev, "setting sleep config failed %d\n", ret);
goto out;
}
/* 8.4.3: Wait >= 1ms after entering active mode. */
usleep_range(1000, 100000);
pdm_count = device_property_count_u32(adcx140->dev, pdm_count = device_property_count_u32(adcx140->dev,
"ti,pdm-edge-select"); "ti,pdm-edge-select");
if (pdm_count <= ADCX140_NUM_PDM_EDGES && pdm_count > 0) { if (pdm_count <= ADCX140_NUM_PDM_EDGES && pdm_count > 0) {
...@@ -926,23 +961,13 @@ static int adcx140_codec_probe(struct snd_soc_component *component) ...@@ -926,23 +961,13 @@ static int adcx140_codec_probe(struct snd_soc_component *component)
if (ret) if (ret)
goto out; goto out;
if (adcx140->supply_areg == NULL)
sleep_cfg_val |= ADCX140_AREG_INTERNAL;
ret = regmap_write(adcx140->regmap, ADCX140_SLEEP_CFG, sleep_cfg_val);
if (ret) {
dev_err(adcx140->dev, "setting sleep config failed %d\n", ret);
goto out;
}
/* 8.4.3: Wait >= 1ms after entering active mode. */
usleep_range(1000, 100000);
ret = regmap_update_bits(adcx140->regmap, ADCX140_BIAS_CFG, ret = regmap_update_bits(adcx140->regmap, ADCX140_BIAS_CFG,
ADCX140_MIC_BIAS_VAL_MSK | ADCX140_MIC_BIAS_VAL_MSK |
ADCX140_MIC_BIAS_VREF_MSK, bias_cfg); ADCX140_MIC_BIAS_VREF_MSK, bias_cfg);
if (ret) if (ret)
dev_err(adcx140->dev, "setting MIC bias failed %d\n", ret); dev_err(adcx140->dev, "setting MIC bias failed %d\n", ret);
adcx140_pwr_ctrl(adcx140, true);
out: out:
return ret; return ret;
} }
...@@ -951,21 +976,19 @@ static int adcx140_set_bias_level(struct snd_soc_component *component, ...@@ -951,21 +976,19 @@ static int adcx140_set_bias_level(struct snd_soc_component *component,
enum snd_soc_bias_level level) enum snd_soc_bias_level level)
{ {
struct adcx140_priv *adcx140 = snd_soc_component_get_drvdata(component); struct adcx140_priv *adcx140 = snd_soc_component_get_drvdata(component);
int pwr_cfg = 0;
switch (level) { switch (level) {
case SND_SOC_BIAS_ON: case SND_SOC_BIAS_ON:
case SND_SOC_BIAS_PREPARE: case SND_SOC_BIAS_PREPARE:
case SND_SOC_BIAS_STANDBY: case SND_SOC_BIAS_STANDBY:
pwr_cfg = ADCX140_PWR_CFG_BIAS_PDZ | ADCX140_PWR_CFG_PLL_PDZ | adcx140_pwr_ctrl(adcx140, true);
ADCX140_PWR_CFG_ADC_PDZ;
break; break;
case SND_SOC_BIAS_OFF: case SND_SOC_BIAS_OFF:
pwr_cfg = 0x0; adcx140_pwr_ctrl(adcx140, false);
break; break;
} }
return regmap_write(adcx140->regmap, ADCX140_PWR_CFG, pwr_cfg); return 0;
} }
static const struct snd_soc_component_driver soc_codec_driver_adcx140 = { static const struct snd_soc_component_driver soc_codec_driver_adcx140 = {
...@@ -1017,6 +1040,8 @@ static int adcx140_i2c_probe(struct i2c_client *i2c, ...@@ -1017,6 +1040,8 @@ static int adcx140_i2c_probe(struct i2c_client *i2c,
if (!adcx140) if (!adcx140)
return -ENOMEM; return -ENOMEM;
adcx140->dev = &i2c->dev;
adcx140->gpio_reset = devm_gpiod_get_optional(adcx140->dev, adcx140->gpio_reset = devm_gpiod_get_optional(adcx140->dev,
"reset", GPIOD_OUT_LOW); "reset", GPIOD_OUT_LOW);
if (IS_ERR(adcx140->gpio_reset)) if (IS_ERR(adcx140->gpio_reset))
...@@ -1044,7 +1069,7 @@ static int adcx140_i2c_probe(struct i2c_client *i2c, ...@@ -1044,7 +1069,7 @@ static int adcx140_i2c_probe(struct i2c_client *i2c,
ret); ret);
return ret; return ret;
} }
adcx140->dev = &i2c->dev;
i2c_set_clientdata(i2c, adcx140); i2c_set_clientdata(i2c, adcx140);
return devm_snd_soc_register_component(&i2c->dev, return devm_snd_soc_register_component(&i2c->dev,
......
...@@ -123,6 +123,7 @@ ...@@ -123,6 +123,7 @@
#define ADCX140_MIC_BIAS_VREF_1375V 2 #define ADCX140_MIC_BIAS_VREF_1375V 2
#define ADCX140_MIC_BIAS_VREF_MSK GENMASK(1, 0) #define ADCX140_MIC_BIAS_VREF_MSK GENMASK(1, 0)
#define ADCX140_PWR_CTRL_MSK GENMASK(7, 5)
#define ADCX140_PWR_CFG_BIAS_PDZ BIT(7) #define ADCX140_PWR_CFG_BIAS_PDZ BIT(7)
#define ADCX140_PWR_CFG_ADC_PDZ BIT(6) #define ADCX140_PWR_CFG_ADC_PDZ BIT(6)
#define ADCX140_PWR_CFG_PLL_PDZ BIT(5) #define ADCX140_PWR_CFG_PLL_PDZ BIT(5)
...@@ -145,4 +146,5 @@ ...@@ -145,4 +146,5 @@
#define ADCX140_GPO_CFG_MAX 4 #define ADCX140_GPO_CFG_MAX 4
#define ADCX140_GPO_DRV_MAX 5 #define ADCX140_GPO_DRV_MAX 5
#endif /* _TLV320ADCX140_ */ #endif /* _TLV320ADCX140_ */
...@@ -3514,6 +3514,8 @@ int wm8994_mic_detect(struct snd_soc_component *component, struct snd_soc_jack * ...@@ -3514,6 +3514,8 @@ int wm8994_mic_detect(struct snd_soc_component *component, struct snd_soc_jack *
return -EINVAL; return -EINVAL;
} }
pm_runtime_get_sync(component->dev);
switch (micbias) { switch (micbias) {
case 1: case 1:
micdet = &wm8994->micdet[0]; micdet = &wm8994->micdet[0];
...@@ -3561,6 +3563,8 @@ int wm8994_mic_detect(struct snd_soc_component *component, struct snd_soc_jack * ...@@ -3561,6 +3563,8 @@ int wm8994_mic_detect(struct snd_soc_component *component, struct snd_soc_jack *
snd_soc_dapm_sync(dapm); snd_soc_dapm_sync(dapm);
pm_runtime_put(component->dev);
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(wm8994_mic_detect); EXPORT_SYMBOL_GPL(wm8994_mic_detect);
...@@ -3932,6 +3936,8 @@ int wm8958_mic_detect(struct snd_soc_component *component, struct snd_soc_jack * ...@@ -3932,6 +3936,8 @@ int wm8958_mic_detect(struct snd_soc_component *component, struct snd_soc_jack *
return -EINVAL; return -EINVAL;
} }
pm_runtime_get_sync(component->dev);
if (jack) { if (jack) {
snd_soc_dapm_force_enable_pin(dapm, "CLK_SYS"); snd_soc_dapm_force_enable_pin(dapm, "CLK_SYS");
snd_soc_dapm_sync(dapm); snd_soc_dapm_sync(dapm);
...@@ -4000,6 +4006,8 @@ int wm8958_mic_detect(struct snd_soc_component *component, struct snd_soc_jack * ...@@ -4000,6 +4006,8 @@ int wm8958_mic_detect(struct snd_soc_component *component, struct snd_soc_jack *
snd_soc_dapm_sync(dapm); snd_soc_dapm_sync(dapm);
} }
pm_runtime_put(component->dev);
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(wm8958_mic_detect); EXPORT_SYMBOL_GPL(wm8958_mic_detect);
...@@ -4193,11 +4201,13 @@ static int wm8994_component_probe(struct snd_soc_component *component) ...@@ -4193,11 +4201,13 @@ static int wm8994_component_probe(struct snd_soc_component *component)
wm8994->hubs.dcs_readback_mode = 2; wm8994->hubs.dcs_readback_mode = 2;
break; break;
} }
wm8994->hubs.micd_scthr = true;
break; break;
case WM8958: case WM8958:
wm8994->hubs.dcs_readback_mode = 1; wm8994->hubs.dcs_readback_mode = 1;
wm8994->hubs.hp_startup_mode = 1; wm8994->hubs.hp_startup_mode = 1;
wm8994->hubs.micd_scthr = true;
switch (control->revision) { switch (control->revision) {
case 0: case 0:
......
...@@ -1223,6 +1223,9 @@ int wm_hubs_handle_analogue_pdata(struct snd_soc_component *component, ...@@ -1223,6 +1223,9 @@ int wm_hubs_handle_analogue_pdata(struct snd_soc_component *component,
snd_soc_component_update_bits(component, WM8993_ADDITIONAL_CONTROL, snd_soc_component_update_bits(component, WM8993_ADDITIONAL_CONTROL,
WM8993_LINEOUT2_FB, WM8993_LINEOUT2_FB); WM8993_LINEOUT2_FB, WM8993_LINEOUT2_FB);
if (!hubs->micd_scthr)
return 0;
snd_soc_component_update_bits(component, WM8993_MICBIAS, snd_soc_component_update_bits(component, WM8993_MICBIAS,
WM8993_JD_SCTHR_MASK | WM8993_JD_THR_MASK | WM8993_JD_SCTHR_MASK | WM8993_JD_THR_MASK |
WM8993_MICB1_LVL | WM8993_MICB2_LVL, WM8993_MICB1_LVL | WM8993_MICB2_LVL,
......
...@@ -27,6 +27,7 @@ struct wm_hubs_data { ...@@ -27,6 +27,7 @@ struct wm_hubs_data {
int hp_startup_mode; int hp_startup_mode;
int series_startup; int series_startup;
int no_series_update; int no_series_update;
bool micd_scthr;
bool no_cache_dac_hp_direct; bool no_cache_dac_hp_direct;
struct list_head dcs_cache; struct list_head dcs_cache;
......
...@@ -199,10 +199,18 @@ static int fsl_audmix_put_out_src(struct snd_kcontrol *kcontrol, ...@@ -199,10 +199,18 @@ static int fsl_audmix_put_out_src(struct snd_kcontrol *kcontrol,
static const struct snd_kcontrol_new fsl_audmix_snd_controls[] = { static const struct snd_kcontrol_new fsl_audmix_snd_controls[] = {
/* FSL_AUDMIX_CTR controls */ /* FSL_AUDMIX_CTR controls */
SOC_ENUM_EXT("Mixing Clock Source", fsl_audmix_enum[0], { .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
snd_soc_get_enum_double, fsl_audmix_put_mix_clk_src), .name = "Mixing Clock Source",
SOC_ENUM_EXT("Output Source", fsl_audmix_enum[1], .info = snd_soc_info_enum_double,
snd_soc_get_enum_double, fsl_audmix_put_out_src), .access = SNDRV_CTL_ELEM_ACCESS_WRITE,
.put = fsl_audmix_put_mix_clk_src,
.private_value = (unsigned long)&fsl_audmix_enum[0] },
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Output Source",
.info = snd_soc_info_enum_double,
.access = SNDRV_CTL_ELEM_ACCESS_WRITE,
.put = fsl_audmix_put_out_src,
.private_value = (unsigned long)&fsl_audmix_enum[1] },
SOC_ENUM("Output Width", fsl_audmix_enum[2]), SOC_ENUM("Output Width", fsl_audmix_enum[2]),
SOC_ENUM("Frame Rate Diff Error", fsl_audmix_enum[3]), SOC_ENUM("Frame Rate Diff Error", fsl_audmix_enum[3]),
SOC_ENUM("Clock Freq Diff Error", fsl_audmix_enum[4]), SOC_ENUM("Clock Freq Diff Error", fsl_audmix_enum[4]),
......
...@@ -333,6 +333,17 @@ static int sst_media_open(struct snd_pcm_substream *substream, ...@@ -333,6 +333,17 @@ static int sst_media_open(struct snd_pcm_substream *substream,
if (ret_val < 0) if (ret_val < 0)
goto out_power_up; goto out_power_up;
/*
* Make sure the period to be multiple of 1ms to align the
* design of firmware. Apply same rule to buffer size to make
* sure alsa could always find a value for period size
* regardless the buffer size given by user space.
*/
snd_pcm_hw_constraint_step(substream->runtime, 0,
SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 48);
snd_pcm_hw_constraint_step(substream->runtime, 0,
SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 48);
/* Make sure, that the period size is always even */ /* Make sure, that the period size is always even */
snd_pcm_hw_constraint_step(substream->runtime, 0, snd_pcm_hw_constraint_step(substream->runtime, 0,
SNDRV_PCM_HW_PARAM_PERIODS, 2); SNDRV_PCM_HW_PARAM_PERIODS, 2);
......
...@@ -591,6 +591,16 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = { ...@@ -591,6 +591,16 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = {
BYT_RT5640_SSP0_AIF1 | BYT_RT5640_SSP0_AIF1 |
BYT_RT5640_MCLK_EN), BYT_RT5640_MCLK_EN),
}, },
{ /* MPMAN Converter 9, similar hw as the I.T.Works TW891 2-in-1 */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "MPMAN"),
DMI_MATCH(DMI_PRODUCT_NAME, "Converter9"),
},
.driver_data = (void *)(BYTCR_INPUT_DEFAULTS |
BYT_RT5640_MONO_SPEAKER |
BYT_RT5640_SSP0_AIF1 |
BYT_RT5640_MCLK_EN),
},
{ {
/* MPMAN MPWIN895CL */ /* MPMAN MPWIN895CL */
.matches = { .matches = {
......
...@@ -181,7 +181,7 @@ static void skl_set_hda_codec_autosuspend_delay(struct snd_soc_card *card) ...@@ -181,7 +181,7 @@ static void skl_set_hda_codec_autosuspend_delay(struct snd_soc_card *card)
struct snd_soc_dai *dai; struct snd_soc_dai *dai;
for_each_card_rtds(card, rtd) { for_each_card_rtds(card, rtd) {
if (!strstr(rtd->dai_link->codecs->name, "ehdaudio")) if (!strstr(rtd->dai_link->codecs->name, "ehdaudio0D0"))
continue; continue;
dai = asoc_rtd_to_codec(rtd, 0); dai = asoc_rtd_to_codec(rtd, 0);
hda_pvt = snd_soc_component_get_drvdata(dai->component); hda_pvt = snd_soc_component_get_drvdata(dai->component);
......
...@@ -243,92 +243,45 @@ static irqreturn_t hsw_irq(int irq, void *context) ...@@ -243,92 +243,45 @@ static irqreturn_t hsw_irq(int irq, void *context)
return ret; return ret;
} }
#define CSR_DEFAULT_VALUE 0x8480040E
#define ISC_DEFAULT_VALUE 0x0
#define ISD_DEFAULT_VALUE 0x0
#define IMC_DEFAULT_VALUE 0x7FFF0003
#define IMD_DEFAULT_VALUE 0x7FFF0003
#define IPCC_DEFAULT_VALUE 0x0
#define IPCD_DEFAULT_VALUE 0x0
#define CLKCTL_DEFAULT_VALUE 0x7FF
#define CSR2_DEFAULT_VALUE 0x0
#define LTR_CTRL_DEFAULT_VALUE 0x0
#define HMD_CTRL_DEFAULT_VALUE 0x0
static void hsw_set_shim_defaults(struct sst_dsp *sst)
{
sst_dsp_shim_write_unlocked(sst, SST_CSR, CSR_DEFAULT_VALUE);
sst_dsp_shim_write_unlocked(sst, SST_ISRX, ISC_DEFAULT_VALUE);
sst_dsp_shim_write_unlocked(sst, SST_ISRD, ISD_DEFAULT_VALUE);
sst_dsp_shim_write_unlocked(sst, SST_IMRX, IMC_DEFAULT_VALUE);
sst_dsp_shim_write_unlocked(sst, SST_IMRD, IMD_DEFAULT_VALUE);
sst_dsp_shim_write_unlocked(sst, SST_IPCX, IPCC_DEFAULT_VALUE);
sst_dsp_shim_write_unlocked(sst, SST_IPCD, IPCD_DEFAULT_VALUE);
sst_dsp_shim_write_unlocked(sst, SST_CLKCTL, CLKCTL_DEFAULT_VALUE);
sst_dsp_shim_write_unlocked(sst, SST_CSR2, CSR2_DEFAULT_VALUE);
sst_dsp_shim_write_unlocked(sst, SST_LTRC, LTR_CTRL_DEFAULT_VALUE);
sst_dsp_shim_write_unlocked(sst, SST_HMDC, HMD_CTRL_DEFAULT_VALUE);
}
/* all clock-gating minus DCLCGE and DTCGE */
#define SST_VDRTCL2_CG_OTHER 0xB7D
static void hsw_set_dsp_D3(struct sst_dsp *sst) static void hsw_set_dsp_D3(struct sst_dsp *sst)
{ {
u32 val;
u32 reg; u32 reg;
/* disable clock core gating */ /* Disable core clock gating (VDRTCTL2.DCLCGE = 0) */
reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2); reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2);
reg &= ~(SST_VDRTCL2_DCLCGE); reg &= ~(SST_VDRTCL2_DCLCGE | SST_VDRTCL2_DTCGE);
writel(reg, sst->addr.pci_cfg + SST_VDRTCTL2); writel(reg, sst->addr.pci_cfg + SST_VDRTCTL2);
/* stall, reset and set 24MHz XOSC */ /* enable power gating and switch off DRAM & IRAM blocks */
sst_dsp_shim_update_bits_unlocked(sst, SST_CSR, val = readl(sst->addr.pci_cfg + SST_VDRTCTL0);
SST_CSR_24MHZ_LPCS | SST_CSR_STALL | SST_CSR_RST, val |= SST_VDRTCL0_DSRAMPGE_MASK |
SST_CSR_24MHZ_LPCS | SST_CSR_STALL | SST_CSR_RST); SST_VDRTCL0_ISRAMPGE_MASK;
val &= ~(SST_VDRTCL0_D3PGD | SST_VDRTCL0_D3SRAMPGD);
/* DRAM power gating all */ writel(val, sst->addr.pci_cfg + SST_VDRTCTL0);
reg = readl(sst->addr.pci_cfg + SST_VDRTCTL0);
reg |= SST_VDRTCL0_ISRAMPGE_MASK |
SST_VDRTCL0_DSRAMPGE_MASK;
reg &= ~(SST_VDRTCL0_D3SRAMPGD);
reg |= SST_VDRTCL0_D3PGD;
writel(reg, sst->addr.pci_cfg + SST_VDRTCTL0);
udelay(50);
/* PLL shutdown enable */ /* switch off audio PLL */
reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2); val = readl(sst->addr.pci_cfg + SST_VDRTCTL2);
reg |= SST_VDRTCL2_APLLSE_MASK; val |= SST_VDRTCL2_APLLSE_MASK;
writel(reg, sst->addr.pci_cfg + SST_VDRTCTL2); writel(val, sst->addr.pci_cfg + SST_VDRTCTL2);
/* disable MCLK */ /* disable MCLK(clkctl.smos = 0) */
sst_dsp_shim_update_bits_unlocked(sst, SST_CLKCTL, sst_dsp_shim_update_bits_unlocked(sst, SST_CLKCTL,
SST_CLKCTL_MASK, 0); SST_CLKCTL_MASK, 0);
/* switch clock gating */ /* Set D3 state, delay 50 us */
reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2); val = readl(sst->addr.pci_cfg + SST_PMCS);
reg |= SST_VDRTCL2_CG_OTHER; val |= SST_PMCS_PS_MASK;
reg &= ~(SST_VDRTCL2_DTCGE); writel(val, sst->addr.pci_cfg + SST_PMCS);
writel(reg, sst->addr.pci_cfg + SST_VDRTCTL2);
/* enable DTCGE separatelly */
reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2);
reg |= SST_VDRTCL2_DTCGE;
writel(reg, sst->addr.pci_cfg + SST_VDRTCTL2);
/* set shim defaults */
hsw_set_shim_defaults(sst);
/* set D3 */
reg = readl(sst->addr.pci_cfg + SST_PMCS);
reg |= SST_PMCS_PS_MASK;
writel(reg, sst->addr.pci_cfg + SST_PMCS);
udelay(50); udelay(50);
/* enable clock core gating */ /* Enable core clock gating (VDRTCTL2.DCLCGE = 1), delay 50 us */
reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2); reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2);
reg |= SST_VDRTCL2_DCLCGE; reg |= SST_VDRTCL2_DCLCGE | SST_VDRTCL2_DTCGE;
writel(reg, sst->addr.pci_cfg + SST_VDRTCTL2); writel(reg, sst->addr.pci_cfg + SST_VDRTCTL2);
udelay(50); udelay(50);
} }
static void hsw_reset(struct sst_dsp *sst) static void hsw_reset(struct sst_dsp *sst)
...@@ -346,62 +299,75 @@ static void hsw_reset(struct sst_dsp *sst) ...@@ -346,62 +299,75 @@ static void hsw_reset(struct sst_dsp *sst)
SST_CSR_RST | SST_CSR_STALL, SST_CSR_STALL); SST_CSR_RST | SST_CSR_STALL, SST_CSR_STALL);
} }
/* recommended CSR state for power-up */
#define SST_CSR_D0_MASK (0x18A09C0C | SST_CSR_DCS_MASK)
static int hsw_set_dsp_D0(struct sst_dsp *sst) static int hsw_set_dsp_D0(struct sst_dsp *sst)
{ {
u32 reg; int tries = 10;
u32 reg, fw_dump_bit;
/* disable clock core gating */ /* Disable core clock gating (VDRTCTL2.DCLCGE = 0) */
reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2); reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2);
reg &= ~(SST_VDRTCL2_DCLCGE); reg &= ~(SST_VDRTCL2_DCLCGE | SST_VDRTCL2_DTCGE);
writel(reg, sst->addr.pci_cfg + SST_VDRTCTL2); writel(reg, sst->addr.pci_cfg + SST_VDRTCTL2);
/* switch clock gating */ /* Disable D3PG (VDRTCTL0.D3PGD = 1) */
reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2); reg = readl(sst->addr.pci_cfg + SST_VDRTCTL0);
reg |= SST_VDRTCL2_CG_OTHER; reg |= SST_VDRTCL0_D3PGD;
reg &= ~(SST_VDRTCL2_DTCGE); writel(reg, sst->addr.pci_cfg + SST_VDRTCTL0);
writel(reg, sst->addr.pci_cfg + SST_VDRTCTL2);
/* set D0 */ /* Set D0 state */
reg = readl(sst->addr.pci_cfg + SST_PMCS); reg = readl(sst->addr.pci_cfg + SST_PMCS);
reg &= ~(SST_PMCS_PS_MASK); reg &= ~SST_PMCS_PS_MASK;
writel(reg, sst->addr.pci_cfg + SST_PMCS); writel(reg, sst->addr.pci_cfg + SST_PMCS);
/* DRAM power gating none */ /* check that ADSP shim is enabled */
reg = readl(sst->addr.pci_cfg + SST_VDRTCTL0); while (tries--) {
reg &= ~(SST_VDRTCL0_ISRAMPGE_MASK | reg = readl(sst->addr.pci_cfg + SST_PMCS) & SST_PMCS_PS_MASK;
SST_VDRTCL0_DSRAMPGE_MASK); if (reg == 0)
reg |= SST_VDRTCL0_D3SRAMPGD; goto finish;
reg |= SST_VDRTCL0_D3PGD;
writel(reg, sst->addr.pci_cfg + SST_VDRTCTL0); msleep(1);
mdelay(10); }
/* set shim defaults */ return -ENODEV;
hsw_set_shim_defaults(sst);
/* restore MCLK */ finish:
/* select SSP1 19.2MHz base clock, SSP clock 0, turn off Low Power Clock */
sst_dsp_shim_update_bits_unlocked(sst, SST_CSR,
SST_CSR_S1IOCS | SST_CSR_SBCS1 | SST_CSR_LPCS, 0x0);
/* stall DSP core, set clk to 192/96Mhz */
sst_dsp_shim_update_bits_unlocked(sst,
SST_CSR, SST_CSR_STALL | SST_CSR_DCS_MASK,
SST_CSR_STALL | SST_CSR_DCS(4));
/* Set 24MHz MCLK, prevent local clock gating, enable SSP0 clock */
sst_dsp_shim_update_bits_unlocked(sst, SST_CLKCTL, sst_dsp_shim_update_bits_unlocked(sst, SST_CLKCTL,
SST_CLKCTL_MASK, SST_CLKCTL_MASK); SST_CLKCTL_MASK | SST_CLKCTL_DCPLCG | SST_CLKCTL_SCOE0,
SST_CLKCTL_MASK | SST_CLKCTL_DCPLCG | SST_CLKCTL_SCOE0);
/* Stall and reset core, set CSR */
hsw_reset(sst);
/* PLL shutdown disable */ /* Enable core clock gating (VDRTCTL2.DCLCGE = 1), delay 50 us */
reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2); reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2);
reg &= ~(SST_VDRTCL2_APLLSE_MASK); reg |= SST_VDRTCL2_DCLCGE | SST_VDRTCL2_DTCGE;
writel(reg, sst->addr.pci_cfg + SST_VDRTCTL2); writel(reg, sst->addr.pci_cfg + SST_VDRTCTL2);
sst_dsp_shim_update_bits_unlocked(sst, SST_CSR,
SST_CSR_D0_MASK, SST_CSR_SBCS0 | SST_CSR_SBCS1 |
SST_CSR_STALL | SST_CSR_DCS(4));
udelay(50); udelay(50);
/* enable clock core gating */ /* switch on audio PLL */
reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2); reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2);
reg |= SST_VDRTCL2_DCLCGE; reg &= ~SST_VDRTCL2_APLLSE_MASK;
writel(reg, sst->addr.pci_cfg + SST_VDRTCTL2); writel(reg, sst->addr.pci_cfg + SST_VDRTCTL2);
/* clear reset */ /* set default power gating control, enable power gating control for all blocks. that is,
sst_dsp_shim_update_bits_unlocked(sst, SST_CSR, SST_CSR_RST, 0); can't be accessed, please enable each block before accessing. */
reg = readl(sst->addr.pci_cfg + SST_VDRTCTL0);
reg |= SST_VDRTCL0_DSRAMPGE_MASK | SST_VDRTCL0_ISRAMPGE_MASK;
/* for D0, always enable the block(DSRAM[0]) used for FW dump */
fw_dump_bit = 1 << SST_VDRTCL0_DSRAMPGE_SHIFT;
writel(reg & ~fw_dump_bit, sst->addr.pci_cfg + SST_VDRTCTL0);
/* disable DMA finish function for SSP0 & SSP1 */ /* disable DMA finish function for SSP0 & SSP1 */
sst_dsp_shim_update_bits_unlocked(sst, SST_CSR2, SST_CSR2_SDFD_SSP1, sst_dsp_shim_update_bits_unlocked(sst, SST_CSR2, SST_CSR2_SDFD_SSP1,
...@@ -418,6 +384,12 @@ static int hsw_set_dsp_D0(struct sst_dsp *sst) ...@@ -418,6 +384,12 @@ static int hsw_set_dsp_D0(struct sst_dsp *sst)
sst_dsp_shim_update_bits(sst, SST_IMRD, (SST_IMRD_DONE | SST_IMRD_BUSY | sst_dsp_shim_update_bits(sst, SST_IMRD, (SST_IMRD_DONE | SST_IMRD_BUSY |
SST_IMRD_SSP0 | SST_IMRD_DMAC), 0x0); SST_IMRD_SSP0 | SST_IMRD_DMAC), 0x0);
/* clear IPC registers */
sst_dsp_shim_write(sst, SST_IPCX, 0x0);
sst_dsp_shim_write(sst, SST_IPCD, 0x0);
sst_dsp_shim_write(sst, 0x80, 0x6);
sst_dsp_shim_write(sst, 0xe0, 0x300a);
return 0; return 0;
} }
...@@ -443,6 +415,11 @@ static void hsw_sleep(struct sst_dsp *sst) ...@@ -443,6 +415,11 @@ static void hsw_sleep(struct sst_dsp *sst)
{ {
dev_dbg(sst->dev, "HSW_PM dsp runtime suspend\n"); dev_dbg(sst->dev, "HSW_PM dsp runtime suspend\n");
/* put DSP into reset and stall */
sst_dsp_shim_update_bits(sst, SST_CSR,
SST_CSR_24MHZ_LPCS | SST_CSR_RST | SST_CSR_STALL,
SST_CSR_RST | SST_CSR_STALL | SST_CSR_24MHZ_LPCS);
hsw_set_dsp_D3(sst); hsw_set_dsp_D3(sst);
dev_dbg(sst->dev, "HSW_PM dsp runtime suspend exit\n"); dev_dbg(sst->dev, "HSW_PM dsp runtime suspend exit\n");
} }
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#define CTRL0_TODDR_SEL_RESAMPLE BIT(30) #define CTRL0_TODDR_SEL_RESAMPLE BIT(30)
#define CTRL0_TODDR_EXT_SIGNED BIT(29) #define CTRL0_TODDR_EXT_SIGNED BIT(29)
#define CTRL0_TODDR_PP_MODE BIT(28) #define CTRL0_TODDR_PP_MODE BIT(28)
#define CTRL0_TODDR_SYNC_CH BIT(27)
#define CTRL0_TODDR_TYPE_MASK GENMASK(15, 13) #define CTRL0_TODDR_TYPE_MASK GENMASK(15, 13)
#define CTRL0_TODDR_TYPE(x) ((x) << 13) #define CTRL0_TODDR_TYPE(x) ((x) << 13)
#define CTRL0_TODDR_MSB_POS_MASK GENMASK(12, 8) #define CTRL0_TODDR_MSB_POS_MASK GENMASK(12, 8)
...@@ -189,10 +190,31 @@ static const struct axg_fifo_match_data axg_toddr_match_data = { ...@@ -189,10 +190,31 @@ static const struct axg_fifo_match_data axg_toddr_match_data = {
.dai_drv = &axg_toddr_dai_drv .dai_drv = &axg_toddr_dai_drv
}; };
static int g12a_toddr_dai_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct axg_fifo *fifo = snd_soc_dai_get_drvdata(dai);
int ret;
ret = axg_toddr_dai_startup(substream, dai);
if (ret)
return ret;
/*
* Make sure the first channel ends up in the at beginning of the output
* As weird as it looks, without this the first channel may be misplaced
* in memory, with a random shift of 2 channels.
*/
regmap_update_bits(fifo->map, FIFO_CTRL0, CTRL0_TODDR_SYNC_CH,
CTRL0_TODDR_SYNC_CH);
return 0;
}
static const struct snd_soc_dai_ops g12a_toddr_ops = { static const struct snd_soc_dai_ops g12a_toddr_ops = {
.prepare = g12a_toddr_dai_prepare, .prepare = g12a_toddr_dai_prepare,
.hw_params = axg_toddr_dai_hw_params, .hw_params = axg_toddr_dai_hw_params,
.startup = axg_toddr_dai_startup, .startup = g12a_toddr_dai_startup,
.shutdown = axg_toddr_dai_shutdown, .shutdown = axg_toddr_dai_shutdown,
}; };
......
...@@ -143,6 +143,7 @@ static int apq8016_sbc_platform_probe(struct platform_device *pdev) ...@@ -143,6 +143,7 @@ static int apq8016_sbc_platform_probe(struct platform_device *pdev)
card = &data->card; card = &data->card;
card->dev = dev; card->dev = dev;
card->owner = THIS_MODULE;
card->dapm_widgets = apq8016_sbc_dapm_widgets; card->dapm_widgets = apq8016_sbc_dapm_widgets;
card->num_dapm_widgets = ARRAY_SIZE(apq8016_sbc_dapm_widgets); card->num_dapm_widgets = ARRAY_SIZE(apq8016_sbc_dapm_widgets);
......
...@@ -114,6 +114,7 @@ static int apq8096_platform_probe(struct platform_device *pdev) ...@@ -114,6 +114,7 @@ static int apq8096_platform_probe(struct platform_device *pdev)
return -ENOMEM; return -ENOMEM;
card->dev = dev; card->dev = dev;
card->owner = THIS_MODULE;
dev_set_drvdata(dev, card); dev_set_drvdata(dev, card);
ret = qcom_snd_parse_of(card); ret = qcom_snd_parse_of(card);
if (ret) if (ret)
......
...@@ -56,8 +56,10 @@ int qcom_snd_parse_of(struct snd_soc_card *card) ...@@ -56,8 +56,10 @@ int qcom_snd_parse_of(struct snd_soc_card *card)
for_each_child_of_node(dev->of_node, np) { for_each_child_of_node(dev->of_node, np) {
dlc = devm_kzalloc(dev, 2 * sizeof(*dlc), GFP_KERNEL); dlc = devm_kzalloc(dev, 2 * sizeof(*dlc), GFP_KERNEL);
if (!dlc) if (!dlc) {
return -ENOMEM; ret = -ENOMEM;
goto err;
}
link->cpus = &dlc[0]; link->cpus = &dlc[0];
link->platforms = &dlc[1]; link->platforms = &dlc[1];
......
...@@ -555,6 +555,7 @@ static int sdm845_snd_platform_probe(struct platform_device *pdev) ...@@ -555,6 +555,7 @@ static int sdm845_snd_platform_probe(struct platform_device *pdev)
card->dapm_widgets = sdm845_snd_widgets; card->dapm_widgets = sdm845_snd_widgets;
card->num_dapm_widgets = ARRAY_SIZE(sdm845_snd_widgets); card->num_dapm_widgets = ARRAY_SIZE(sdm845_snd_widgets);
card->dev = dev; card->dev = dev;
card->owner = THIS_MODULE;
dev_set_drvdata(dev, card); dev_set_drvdata(dev, card);
ret = qcom_snd_parse_of(card); ret = qcom_snd_parse_of(card);
if (ret) if (ret)
......
...@@ -96,6 +96,7 @@ static int storm_platform_probe(struct platform_device *pdev) ...@@ -96,6 +96,7 @@ static int storm_platform_probe(struct platform_device *pdev)
return -ENOMEM; return -ENOMEM;
card->dev = &pdev->dev; card->dev = &pdev->dev;
card->owner = THIS_MODULE;
ret = snd_soc_of_parse_card_name(card, "qcom,model"); ret = snd_soc_of_parse_card_name(card, "qcom,model");
if (ret) { if (ret) {
......
...@@ -812,7 +812,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) ...@@ -812,7 +812,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
return 0; return 0;
config_err: config_err:
for_each_rtd_dais(rtd, i, dai) for_each_rtd_dais_rollback(rtd, i, dai)
snd_soc_dai_shutdown(dai, substream); snd_soc_dai_shutdown(dai, substream);
snd_soc_link_shutdown(substream); snd_soc_link_shutdown(substream);
......
...@@ -592,6 +592,17 @@ static int soc_tplg_kcontrol_bind_io(struct snd_soc_tplg_ctl_hdr *hdr, ...@@ -592,6 +592,17 @@ static int soc_tplg_kcontrol_bind_io(struct snd_soc_tplg_ctl_hdr *hdr,
k->info = snd_soc_bytes_info_ext; k->info = snd_soc_bytes_info_ext;
k->tlv.c = snd_soc_bytes_tlv_callback; k->tlv.c = snd_soc_bytes_tlv_callback;
/*
* When a topology-based implementation abuses the
* control interface and uses bytes_ext controls of
* more than 512 bytes, we need to disable the size
* checks, otherwise accesses to such controls will
* return an -EINVAL error and prevent the card from
* being configured.
*/
if (IS_ENABLED(CONFIG_SND_CTL_VALIDATION) && sbe->max > 512)
k->access |= SNDRV_CTL_ELEM_ACCESS_SKIP_CHECK;
ext_ops = tplg->bytes_ext_ops; ext_ops = tplg->bytes_ext_ops;
num_ops = tplg->bytes_ext_ops_count; num_ops = tplg->bytes_ext_ops_count;
for (i = 0; i < num_ops; i++) { for (i = 0; i < num_ops; i++) {
......
...@@ -446,12 +446,12 @@ static const struct snd_soc_dai_ops ams_delta_dai_ops = { ...@@ -446,12 +446,12 @@ static const struct snd_soc_dai_ops ams_delta_dai_ops = {
/* Will be used if the codec ever has its own digital_mute function */ /* Will be used if the codec ever has its own digital_mute function */
static int ams_delta_startup(struct snd_pcm_substream *substream) static int ams_delta_startup(struct snd_pcm_substream *substream)
{ {
return ams_delta_digital_mute(NULL, 0, substream->stream); return ams_delta_mute(NULL, 0, substream->stream);
} }
static void ams_delta_shutdown(struct snd_pcm_substream *substream) static void ams_delta_shutdown(struct snd_pcm_substream *substream)
{ {
ams_delta_digital_mute(NULL, 1, substream->stream); ams_delta_mute(NULL, 1, substream->stream);
} }
......
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