ASoC: Fixes for v6.2
A few more fixes for v6.2, all driver specific and small. It's larger than is ideal but we can't really control when people find problems. -----BEGIN PGP SIGNATURE----- iQEzBAABCgAdFiEEreZoqmdXGLWf4p/qJNaLcl1Uh9AFAmPifS4ACgkQJNaLcl1U h9AG5wf9EKiquRiuxSxtLrZdPO2xRBgcfZBbTqPeRvYGWeCzYaKFwcjI5UlJZ3Kz tdymQ9tihVkcdrEH6xin3QETUI+8vU9++Vh1XVNN01GaSrMq9SupYFR5UvN5QNuD SfjtDt7oWWzlFwOouDnLC5T/5U5iWqFVd/hHvZWHsCFJYIPzBvNTnXhQ8My/88Lf 2Fmn1/3HTDzNhTTrPdVK84ZIMVb7IbfMcFw4E9+Yk9jtGtfQXtK0l6VzJCwgS6Kl 85CZ51pPKCx4X18iDqyc0j5dcqAjI08FAa0i9Rfix3Sz0GXRsW7CemnFQSOR7Zw4 QQiBIMAIFEp4UzeBG9K79IPh/B9biA== =hxoQ -----END PGP SIGNATURE----- Merge tag 'asoc-fix-v6.2-rc7' of https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-linus ASoC: Fixes for v6.2 A few more fixes for v6.2, all driver specific and small. It's larger than is ideal but we can't really control when people find problems.
This commit is contained in:
commit
02f64ed066
@ -729,14 +729,16 @@ static int es8326_probe(struct snd_soc_component *component)
|
||||
}
|
||||
dev_dbg(component->dev, "jack-pol %x", es8326->jack_pol);
|
||||
|
||||
ret = device_property_read_u8(component->dev, "everest,interrupt-src", &es8326->jack_pol);
|
||||
ret = device_property_read_u8(component->dev, "everest,interrupt-src",
|
||||
&es8326->interrupt_src);
|
||||
if (ret != 0) {
|
||||
dev_dbg(component->dev, "interrupt-src return %d", ret);
|
||||
es8326->interrupt_src = ES8326_HP_DET_SRC_PIN9;
|
||||
}
|
||||
dev_dbg(component->dev, "interrupt-src %x", es8326->interrupt_src);
|
||||
|
||||
ret = device_property_read_u8(component->dev, "everest,interrupt-clk", &es8326->jack_pol);
|
||||
ret = device_property_read_u8(component->dev, "everest,interrupt-clk",
|
||||
&es8326->interrupt_clk);
|
||||
if (ret != 0) {
|
||||
dev_dbg(component->dev, "interrupt-clk return %d", ret);
|
||||
es8326->interrupt_clk = 0x45;
|
||||
|
@ -167,7 +167,7 @@ static int rt715_sdca_read_prop(struct sdw_slave *slave)
|
||||
}
|
||||
|
||||
/* set the timeout values */
|
||||
prop->clk_stop_timeout = 20;
|
||||
prop->clk_stop_timeout = 200;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -154,6 +154,7 @@ static const uint32_t tas5805m_volume[] = {
|
||||
#define TAS5805M_VOLUME_MIN 0
|
||||
|
||||
struct tas5805m_priv {
|
||||
struct i2c_client *i2c;
|
||||
struct regulator *pvdd;
|
||||
struct gpio_desc *gpio_pdn_n;
|
||||
|
||||
@ -165,6 +166,9 @@ struct tas5805m_priv {
|
||||
int vol[2];
|
||||
bool is_powered;
|
||||
bool is_muted;
|
||||
|
||||
struct work_struct work;
|
||||
struct mutex lock;
|
||||
};
|
||||
|
||||
static void set_dsp_scale(struct regmap *rm, int offset, int vol)
|
||||
@ -181,13 +185,11 @@ static void set_dsp_scale(struct regmap *rm, int offset, int vol)
|
||||
regmap_bulk_write(rm, offset, v, ARRAY_SIZE(v));
|
||||
}
|
||||
|
||||
static void tas5805m_refresh(struct snd_soc_component *component)
|
||||
static void tas5805m_refresh(struct tas5805m_priv *tas5805m)
|
||||
{
|
||||
struct tas5805m_priv *tas5805m =
|
||||
snd_soc_component_get_drvdata(component);
|
||||
struct regmap *rm = tas5805m->regmap;
|
||||
|
||||
dev_dbg(component->dev, "refresh: is_muted=%d, vol=%d/%d\n",
|
||||
dev_dbg(&tas5805m->i2c->dev, "refresh: is_muted=%d, vol=%d/%d\n",
|
||||
tas5805m->is_muted, tas5805m->vol[0], tas5805m->vol[1]);
|
||||
|
||||
regmap_write(rm, REG_PAGE, 0x00);
|
||||
@ -201,6 +203,9 @@ static void tas5805m_refresh(struct snd_soc_component *component)
|
||||
set_dsp_scale(rm, 0x24, tas5805m->vol[0]);
|
||||
set_dsp_scale(rm, 0x28, tas5805m->vol[1]);
|
||||
|
||||
regmap_write(rm, REG_PAGE, 0x00);
|
||||
regmap_write(rm, REG_BOOK, 0x00);
|
||||
|
||||
/* Set/clear digital soft-mute */
|
||||
regmap_write(rm, REG_DEVICE_CTRL_2,
|
||||
(tas5805m->is_muted ? DCTRL2_MUTE : 0) |
|
||||
@ -226,8 +231,11 @@ static int tas5805m_vol_get(struct snd_kcontrol *kcontrol,
|
||||
struct tas5805m_priv *tas5805m =
|
||||
snd_soc_component_get_drvdata(component);
|
||||
|
||||
mutex_lock(&tas5805m->lock);
|
||||
ucontrol->value.integer.value[0] = tas5805m->vol[0];
|
||||
ucontrol->value.integer.value[1] = tas5805m->vol[1];
|
||||
mutex_unlock(&tas5805m->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -243,11 +251,13 @@ static int tas5805m_vol_put(struct snd_kcontrol *kcontrol,
|
||||
snd_soc_kcontrol_component(kcontrol);
|
||||
struct tas5805m_priv *tas5805m =
|
||||
snd_soc_component_get_drvdata(component);
|
||||
int ret = 0;
|
||||
|
||||
if (!(volume_is_valid(ucontrol->value.integer.value[0]) &&
|
||||
volume_is_valid(ucontrol->value.integer.value[1])))
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&tas5805m->lock);
|
||||
if (tas5805m->vol[0] != ucontrol->value.integer.value[0] ||
|
||||
tas5805m->vol[1] != ucontrol->value.integer.value[1]) {
|
||||
tas5805m->vol[0] = ucontrol->value.integer.value[0];
|
||||
@ -256,11 +266,12 @@ static int tas5805m_vol_put(struct snd_kcontrol *kcontrol,
|
||||
tas5805m->vol[0], tas5805m->vol[1],
|
||||
tas5805m->is_powered);
|
||||
if (tas5805m->is_powered)
|
||||
tas5805m_refresh(component);
|
||||
return 1;
|
||||
tas5805m_refresh(tas5805m);
|
||||
ret = 1;
|
||||
}
|
||||
mutex_unlock(&tas5805m->lock);
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct snd_kcontrol_new tas5805m_snd_controls[] = {
|
||||
@ -294,50 +305,18 @@ static int tas5805m_trigger(struct snd_pcm_substream *substream, int cmd,
|
||||
struct snd_soc_component *component = dai->component;
|
||||
struct tas5805m_priv *tas5805m =
|
||||
snd_soc_component_get_drvdata(component);
|
||||
struct regmap *rm = tas5805m->regmap;
|
||||
unsigned int chan, global1, global2;
|
||||
|
||||
switch (cmd) {
|
||||
case SNDRV_PCM_TRIGGER_START:
|
||||
case SNDRV_PCM_TRIGGER_RESUME:
|
||||
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
|
||||
dev_dbg(component->dev, "DSP startup\n");
|
||||
|
||||
/* We mustn't issue any I2C transactions until the I2S
|
||||
* clock is stable. Furthermore, we must allow a 5ms
|
||||
* delay after the first set of register writes to
|
||||
* allow the DSP to boot before configuring it.
|
||||
*/
|
||||
usleep_range(5000, 10000);
|
||||
send_cfg(rm, dsp_cfg_preboot,
|
||||
ARRAY_SIZE(dsp_cfg_preboot));
|
||||
usleep_range(5000, 15000);
|
||||
send_cfg(rm, tas5805m->dsp_cfg_data,
|
||||
tas5805m->dsp_cfg_len);
|
||||
|
||||
tas5805m->is_powered = true;
|
||||
tas5805m_refresh(component);
|
||||
dev_dbg(component->dev, "clock start\n");
|
||||
schedule_work(&tas5805m->work);
|
||||
break;
|
||||
|
||||
case SNDRV_PCM_TRIGGER_STOP:
|
||||
case SNDRV_PCM_TRIGGER_SUSPEND:
|
||||
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
|
||||
dev_dbg(component->dev, "DSP shutdown\n");
|
||||
|
||||
tas5805m->is_powered = false;
|
||||
|
||||
regmap_write(rm, REG_PAGE, 0x00);
|
||||
regmap_write(rm, REG_BOOK, 0x00);
|
||||
|
||||
regmap_read(rm, REG_CHAN_FAULT, &chan);
|
||||
regmap_read(rm, REG_GLOBAL_FAULT1, &global1);
|
||||
regmap_read(rm, REG_GLOBAL_FAULT2, &global2);
|
||||
|
||||
dev_dbg(component->dev,
|
||||
"fault regs: CHAN=%02x, GLOBAL1=%02x, GLOBAL2=%02x\n",
|
||||
chan, global1, global2);
|
||||
|
||||
regmap_write(rm, REG_DEVICE_CTRL_2, DCTRL2_MODE_HIZ);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -347,6 +326,67 @@ static int tas5805m_trigger(struct snd_pcm_substream *substream, int cmd,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void do_work(struct work_struct *work)
|
||||
{
|
||||
struct tas5805m_priv *tas5805m =
|
||||
container_of(work, struct tas5805m_priv, work);
|
||||
struct regmap *rm = tas5805m->regmap;
|
||||
|
||||
dev_dbg(&tas5805m->i2c->dev, "DSP startup\n");
|
||||
|
||||
mutex_lock(&tas5805m->lock);
|
||||
/* We mustn't issue any I2C transactions until the I2S
|
||||
* clock is stable. Furthermore, we must allow a 5ms
|
||||
* delay after the first set of register writes to
|
||||
* allow the DSP to boot before configuring it.
|
||||
*/
|
||||
usleep_range(5000, 10000);
|
||||
send_cfg(rm, dsp_cfg_preboot, ARRAY_SIZE(dsp_cfg_preboot));
|
||||
usleep_range(5000, 15000);
|
||||
send_cfg(rm, tas5805m->dsp_cfg_data, tas5805m->dsp_cfg_len);
|
||||
|
||||
tas5805m->is_powered = true;
|
||||
tas5805m_refresh(tas5805m);
|
||||
mutex_unlock(&tas5805m->lock);
|
||||
}
|
||||
|
||||
static int tas5805m_dac_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 tas5805m_priv *tas5805m =
|
||||
snd_soc_component_get_drvdata(component);
|
||||
struct regmap *rm = tas5805m->regmap;
|
||||
|
||||
if (event & SND_SOC_DAPM_PRE_PMD) {
|
||||
unsigned int chan, global1, global2;
|
||||
|
||||
dev_dbg(component->dev, "DSP shutdown\n");
|
||||
cancel_work_sync(&tas5805m->work);
|
||||
|
||||
mutex_lock(&tas5805m->lock);
|
||||
if (tas5805m->is_powered) {
|
||||
tas5805m->is_powered = false;
|
||||
|
||||
regmap_write(rm, REG_PAGE, 0x00);
|
||||
regmap_write(rm, REG_BOOK, 0x00);
|
||||
|
||||
regmap_read(rm, REG_CHAN_FAULT, &chan);
|
||||
regmap_read(rm, REG_GLOBAL_FAULT1, &global1);
|
||||
regmap_read(rm, REG_GLOBAL_FAULT2, &global2);
|
||||
|
||||
dev_dbg(component->dev, "fault regs: CHAN=%02x, "
|
||||
"GLOBAL1=%02x, GLOBAL2=%02x\n",
|
||||
chan, global1, global2);
|
||||
|
||||
regmap_write(rm, REG_DEVICE_CTRL_2, DCTRL2_MODE_HIZ);
|
||||
}
|
||||
mutex_unlock(&tas5805m->lock);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct snd_soc_dapm_route tas5805m_audio_map[] = {
|
||||
{ "DAC", NULL, "DAC IN" },
|
||||
{ "OUT", NULL, "DAC" },
|
||||
@ -354,7 +394,8 @@ static const struct snd_soc_dapm_route tas5805m_audio_map[] = {
|
||||
|
||||
static const struct snd_soc_dapm_widget tas5805m_dapm_widgets[] = {
|
||||
SND_SOC_DAPM_AIF_IN("DAC IN", "Playback", 0, SND_SOC_NOPM, 0, 0),
|
||||
SND_SOC_DAPM_DAC("DAC", NULL, SND_SOC_NOPM, 0, 0),
|
||||
SND_SOC_DAPM_DAC_E("DAC", NULL, SND_SOC_NOPM, 0, 0,
|
||||
tas5805m_dac_event, SND_SOC_DAPM_PRE_PMD),
|
||||
SND_SOC_DAPM_OUTPUT("OUT")
|
||||
};
|
||||
|
||||
@ -375,11 +416,14 @@ static int tas5805m_mute(struct snd_soc_dai *dai, int mute, int direction)
|
||||
struct tas5805m_priv *tas5805m =
|
||||
snd_soc_component_get_drvdata(component);
|
||||
|
||||
mutex_lock(&tas5805m->lock);
|
||||
dev_dbg(component->dev, "set mute=%d (is_powered=%d)\n",
|
||||
mute, tas5805m->is_powered);
|
||||
|
||||
tas5805m->is_muted = mute;
|
||||
if (tas5805m->is_powered)
|
||||
tas5805m_refresh(component);
|
||||
tas5805m_refresh(tas5805m);
|
||||
mutex_unlock(&tas5805m->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -434,6 +478,7 @@ static int tas5805m_i2c_probe(struct i2c_client *i2c)
|
||||
if (!tas5805m)
|
||||
return -ENOMEM;
|
||||
|
||||
tas5805m->i2c = i2c;
|
||||
tas5805m->pvdd = devm_regulator_get(dev, "pvdd");
|
||||
if (IS_ERR(tas5805m->pvdd)) {
|
||||
dev_err(dev, "failed to get pvdd supply: %ld\n",
|
||||
@ -507,6 +552,9 @@ static int tas5805m_i2c_probe(struct i2c_client *i2c)
|
||||
gpiod_set_value(tas5805m->gpio_pdn_n, 1);
|
||||
usleep_range(10000, 15000);
|
||||
|
||||
INIT_WORK(&tas5805m->work, do_work);
|
||||
mutex_init(&tas5805m->lock);
|
||||
|
||||
/* Don't register through devm. We need to be able to unregister
|
||||
* the component prior to deasserting PDN#
|
||||
*/
|
||||
@ -527,6 +575,7 @@ static void tas5805m_i2c_remove(struct i2c_client *i2c)
|
||||
struct device *dev = &i2c->dev;
|
||||
struct tas5805m_priv *tas5805m = dev_get_drvdata(dev);
|
||||
|
||||
cancel_work_sync(&tas5805m->work);
|
||||
snd_soc_unregister_component(dev);
|
||||
gpiod_set_value(tas5805m->gpio_pdn_n, 0);
|
||||
usleep_range(10000, 15000);
|
||||
|
@ -1141,6 +1141,7 @@ static int fsl_sai_check_version(struct device *dev)
|
||||
|
||||
sai->verid.version = val &
|
||||
(FSL_SAI_VERID_MAJOR_MASK | FSL_SAI_VERID_MINOR_MASK);
|
||||
sai->verid.version >>= FSL_SAI_VERID_MINOR_SHIFT;
|
||||
sai->verid.feature = val & FSL_SAI_VERID_FEATURE_MASK;
|
||||
|
||||
ret = regmap_read(sai->regmap, FSL_SAI_PARAM, &val);
|
||||
|
@ -1401,13 +1401,17 @@ static int soc_tplg_dapm_widget_create(struct soc_tplg *tplg,
|
||||
|
||||
template.num_kcontrols = le32_to_cpu(w->num_kcontrols);
|
||||
kc = devm_kcalloc(tplg->dev, le32_to_cpu(w->num_kcontrols), sizeof(*kc), GFP_KERNEL);
|
||||
if (!kc)
|
||||
if (!kc) {
|
||||
ret = -ENOMEM;
|
||||
goto hdr_err;
|
||||
}
|
||||
|
||||
kcontrol_type = devm_kcalloc(tplg->dev, le32_to_cpu(w->num_kcontrols), sizeof(unsigned int),
|
||||
GFP_KERNEL);
|
||||
if (!kcontrol_type)
|
||||
if (!kcontrol_type) {
|
||||
ret = -ENOMEM;
|
||||
goto hdr_err;
|
||||
}
|
||||
|
||||
for (i = 0; i < le32_to_cpu(w->num_kcontrols); i++) {
|
||||
control_hdr = (struct snd_soc_tplg_ctl_hdr *)tplg->pos;
|
||||
|
@ -318,7 +318,6 @@ static irqreturn_t acp_irq_thread(int irq, void *context)
|
||||
{
|
||||
struct snd_sof_dev *sdev = context;
|
||||
const struct sof_amd_acp_desc *desc = get_chip_info(sdev->pdata);
|
||||
unsigned int base = desc->dsp_intr_base;
|
||||
unsigned int val, count = ACP_HW_SEM_RETRY_COUNT;
|
||||
|
||||
val = snd_sof_dsp_read(sdev, ACP_DSP_BAR, desc->ext_intr_stat);
|
||||
@ -328,28 +327,20 @@ static irqreturn_t acp_irq_thread(int irq, void *context)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
val = snd_sof_dsp_read(sdev, ACP_DSP_BAR, base + DSP_SW_INTR_STAT_OFFSET);
|
||||
if (val & ACP_DSP_TO_HOST_IRQ) {
|
||||
while (snd_sof_dsp_read(sdev, ACP_DSP_BAR, desc->hw_semaphore_offset)) {
|
||||
/* Wait until acquired HW Semaphore lock or timeout */
|
||||
count--;
|
||||
if (!count) {
|
||||
dev_err(sdev->dev, "%s: Failed to acquire HW lock\n", __func__);
|
||||
return IRQ_NONE;
|
||||
}
|
||||
while (snd_sof_dsp_read(sdev, ACP_DSP_BAR, desc->hw_semaphore_offset)) {
|
||||
/* Wait until acquired HW Semaphore lock or timeout */
|
||||
count--;
|
||||
if (!count) {
|
||||
dev_err(sdev->dev, "%s: Failed to acquire HW lock\n", __func__);
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
sof_ops(sdev)->irq_thread(irq, sdev);
|
||||
val |= ACP_DSP_TO_HOST_IRQ;
|
||||
snd_sof_dsp_write(sdev, ACP_DSP_BAR, base + DSP_SW_INTR_STAT_OFFSET, val);
|
||||
|
||||
/* Unlock or Release HW Semaphore */
|
||||
snd_sof_dsp_write(sdev, ACP_DSP_BAR, desc->hw_semaphore_offset, 0x0);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
return IRQ_NONE;
|
||||
sof_ops(sdev)->irq_thread(irq, sdev);
|
||||
/* Unlock or Release HW Semaphore */
|
||||
snd_sof_dsp_write(sdev, ACP_DSP_BAR, desc->hw_semaphore_offset, 0x0);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
};
|
||||
|
||||
static irqreturn_t acp_irq_handler(int irq, void *dev_id)
|
||||
@ -360,8 +351,11 @@ static irqreturn_t acp_irq_handler(int irq, void *dev_id)
|
||||
unsigned int val;
|
||||
|
||||
val = snd_sof_dsp_read(sdev, ACP_DSP_BAR, base + DSP_SW_INTR_STAT_OFFSET);
|
||||
if (val)
|
||||
if (val) {
|
||||
val |= ACP_DSP_TO_HOST_IRQ;
|
||||
snd_sof_dsp_write(sdev, ACP_DSP_BAR, base + DSP_SW_INTR_STAT_OFFSET, val);
|
||||
return IRQ_WAKE_THREAD;
|
||||
}
|
||||
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user