Commit bac4d822 authored by Takashi Iwai's avatar Takashi Iwai

Merge tag 'asoc-fix-v6.4-rc3' of...

Merge tag 'asoc-fix-v6.4-rc3' of https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-linus

ASoC: Fixes for v6.4

A collection of fixes for v6.4, mostly driver specific but there's also
one fix for DPCM to avoid incorrectly repeated calls to prepare() which
can trigger issues on some systems.
parents 81302b1c 011a8719
......@@ -8,7 +8,7 @@ Required properties:
"ti,tlv320aic32x6" TLV320AIC3206, TLV320AIC3256
"ti,tas2505" TAS2505, TAS2521
- reg: I2C slave address
- supply-*: Required supply regulators are:
- *-supply: Required supply regulators are:
"iov" - digital IO power supply
"ldoin" - LDO power supply
"dv" - Digital core power supply
......
......@@ -170,6 +170,7 @@ struct snd_soc_acpi_link_adr {
/* Descriptor for SST ASoC machine driver */
struct snd_soc_acpi_mach {
u8 id[ACPI_ID_LEN];
const char *uid;
const struct snd_soc_acpi_codecs *comp_ids;
const u32 link_mask;
const struct snd_soc_acpi_link_adr *links;
......
......@@ -122,6 +122,10 @@ int snd_soc_dpcm_can_be_free_stop(struct snd_soc_pcm_runtime *fe,
int snd_soc_dpcm_can_be_params(struct snd_soc_pcm_runtime *fe,
struct snd_soc_pcm_runtime *be, int stream);
/* can this BE perform prepare */
int snd_soc_dpcm_can_be_prepared(struct snd_soc_pcm_runtime *fe,
struct snd_soc_pcm_runtime *be, int stream);
/* is the current PCM operation for this FE ? */
int snd_soc_dpcm_fe_can_update(struct snd_soc_pcm_runtime *fe, int stream);
......
......@@ -66,7 +66,8 @@ enum skl_ch_cfg {
SKL_CH_CFG_DUAL_MONO = 9,
SKL_CH_CFG_I2S_DUAL_STEREO_0 = 10,
SKL_CH_CFG_I2S_DUAL_STEREO_1 = 11,
SKL_CH_CFG_4_CHANNEL = 12,
SKL_CH_CFG_7_1 = 12,
SKL_CH_CFG_4_CHANNEL = SKL_CH_CFG_7_1,
SKL_CH_CFG_INVALID
};
......
......@@ -46,7 +46,7 @@ static const struct reg_default cs35l41_reg[] = {
{ CS35L41_DSP1_RX5_SRC, 0x00000020 },
{ CS35L41_DSP1_RX6_SRC, 0x00000021 },
{ CS35L41_DSP1_RX7_SRC, 0x0000003A },
{ CS35L41_DSP1_RX8_SRC, 0x00000001 },
{ CS35L41_DSP1_RX8_SRC, 0x0000003B },
{ CS35L41_NGATE1_SRC, 0x00000008 },
{ CS35L41_NGATE2_SRC, 0x00000009 },
{ CS35L41_AMP_DIG_VOL_CTRL, 0x00008000 },
......@@ -58,8 +58,8 @@ static const struct reg_default cs35l41_reg[] = {
{ CS35L41_IRQ1_MASK2, 0xFFFFFFFF },
{ CS35L41_IRQ1_MASK3, 0xFFFF87FF },
{ CS35L41_IRQ1_MASK4, 0xFEFFFFFF },
{ CS35L41_GPIO1_CTRL1, 0xE1000001 },
{ CS35L41_GPIO2_CTRL1, 0xE1000001 },
{ CS35L41_GPIO1_CTRL1, 0x81000001 },
{ CS35L41_GPIO2_CTRL1, 0x81000001 },
{ CS35L41_MIXER_NGATE_CFG, 0x00000000 },
{ CS35L41_MIXER_NGATE_CH1_CFG, 0x00000303 },
{ CS35L41_MIXER_NGATE_CH2_CFG, 0x00000303 },
......
......@@ -746,6 +746,8 @@ static int tx_macro_put_dec_enum(struct snd_kcontrol *kcontrol,
struct tx_macro *tx = snd_soc_component_get_drvdata(component);
val = ucontrol->value.enumerated.item[0];
if (val >= e->items)
return -EINVAL;
switch (e->reg) {
case CDC_TX_INP_MUX_ADC_MUX0_CFG0:
......@@ -772,6 +774,9 @@ static int tx_macro_put_dec_enum(struct snd_kcontrol *kcontrol,
case CDC_TX_INP_MUX_ADC_MUX7_CFG0:
mic_sel_reg = CDC_TX7_TX_PATH_CFG0;
break;
default:
dev_err(component->dev, "Error in configuration!!\n");
return -EINVAL;
}
if (val != 0) {
......
......@@ -267,7 +267,9 @@ static int rt5682_i2c_probe(struct i2c_client *i2c)
ret = devm_request_threaded_irq(&i2c->dev, i2c->irq, NULL,
rt5682_irq, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING
| IRQF_ONESHOT, "rt5682", rt5682);
if (ret)
if (!ret)
rt5682->irq = i2c->irq;
else
dev_err(&i2c->dev, "Failed to reguest IRQ: %d\n", ret);
}
......
......@@ -2959,6 +2959,9 @@ static int rt5682_suspend(struct snd_soc_component *component)
if (rt5682->is_sdw)
return 0;
if (rt5682->irq)
disable_irq(rt5682->irq);
cancel_delayed_work_sync(&rt5682->jack_detect_work);
cancel_delayed_work_sync(&rt5682->jd_check_work);
if (rt5682->hs_jack && (rt5682->jack_type & SND_JACK_HEADSET) == SND_JACK_HEADSET) {
......@@ -3027,6 +3030,9 @@ static int rt5682_resume(struct snd_soc_component *component)
mod_delayed_work(system_power_efficient_wq,
&rt5682->jack_detect_work, msecs_to_jiffies(0));
if (rt5682->irq)
enable_irq(rt5682->irq);
return 0;
}
#else
......
......@@ -1462,6 +1462,7 @@ struct rt5682_priv {
int pll_out[RT5682_PLLS];
int jack_type;
int irq;
int irq_work_delay_time;
};
......
......@@ -183,30 +183,6 @@ static void i2s_stop(struct dw_i2s_dev *dev,
}
}
static int dw_i2s_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *cpu_dai)
{
struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(cpu_dai);
union dw_i2s_snd_dma_data *dma_data = NULL;
if (!(dev->capability & DWC_I2S_RECORD) &&
(substream->stream == SNDRV_PCM_STREAM_CAPTURE))
return -EINVAL;
if (!(dev->capability & DWC_I2S_PLAY) &&
(substream->stream == SNDRV_PCM_STREAM_PLAYBACK))
return -EINVAL;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
dma_data = &dev->play_dma_data;
else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
dma_data = &dev->capture_dma_data;
snd_soc_dai_set_dma_data(cpu_dai, substream, (void *)dma_data);
return 0;
}
static void dw_i2s_config(struct dw_i2s_dev *dev, int stream)
{
u32 ch_reg;
......@@ -305,12 +281,6 @@ static int dw_i2s_hw_params(struct snd_pcm_substream *substream,
return 0;
}
static void dw_i2s_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
snd_soc_dai_set_dma_data(dai, substream, NULL);
}
static int dw_i2s_prepare(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
......@@ -382,8 +352,6 @@ static int dw_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
}
static const struct snd_soc_dai_ops dw_i2s_dai_ops = {
.startup = dw_i2s_startup,
.shutdown = dw_i2s_shutdown,
.hw_params = dw_i2s_hw_params,
.prepare = dw_i2s_prepare,
.trigger = dw_i2s_trigger,
......@@ -625,6 +593,14 @@ static int dw_configure_dai_by_dt(struct dw_i2s_dev *dev,
}
static int dw_i2s_dai_probe(struct snd_soc_dai *dai)
{
struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
snd_soc_dai_init_dma_data(dai, &dev->play_dma_data, &dev->capture_dma_data);
return 0;
}
static int dw_i2s_probe(struct platform_device *pdev)
{
const struct i2s_platform_data *pdata = pdev->dev.platform_data;
......@@ -643,6 +619,7 @@ static int dw_i2s_probe(struct platform_device *pdev)
return -ENOMEM;
dw_i2s_dai->ops = &dw_i2s_dai_ops;
dw_i2s_dai->probe = dw_i2s_dai_probe;
dev->i2s_base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
if (IS_ERR(dev->i2s_base))
......
......@@ -169,6 +169,7 @@ static bool apl_lp_streaming(struct avs_dev *adev)
{
struct avs_path *path;
spin_lock(&adev->path_list_lock);
/* Any gateway without buffer allocated in LP area disqualifies D0IX. */
list_for_each_entry(path, &adev->path_list, node) {
struct avs_path_pipeline *ppl;
......@@ -188,11 +189,14 @@ static bool apl_lp_streaming(struct avs_dev *adev)
if (cfg->copier.dma_type == INVALID_OBJECT_ID)
continue;
if (!mod->gtw_attrs.lp_buffer_alloc)
if (!mod->gtw_attrs.lp_buffer_alloc) {
spin_unlock(&adev->path_list_lock);
return false;
}
}
}
}
spin_unlock(&adev->path_list_lock);
return true;
}
......
......@@ -283,8 +283,8 @@ void avs_release_firmwares(struct avs_dev *adev);
int avs_dsp_init_module(struct avs_dev *adev, u16 module_id, u8 ppl_instance_id,
u8 core_id, u8 domain, void *param, u32 param_size,
u16 *instance_id);
void avs_dsp_delete_module(struct avs_dev *adev, u16 module_id, u16 instance_id,
u8 *instance_id);
void avs_dsp_delete_module(struct avs_dev *adev, u16 module_id, u8 instance_id,
u8 ppl_instance_id, u8 core_id);
int avs_dsp_create_pipeline(struct avs_dev *adev, u16 req_size, u8 priority,
bool lp, u16 attributes, u8 *instance_id);
......
......@@ -443,7 +443,7 @@ static int avs_register_i2s_boards(struct avs_dev *adev)
}
for (mach = boards->machs; mach->id[0]; mach++) {
if (!acpi_dev_present(mach->id, NULL, -1))
if (!acpi_dev_present(mach->id, mach->uid, -1))
continue;
if (mach->machine_quirk)
......
......@@ -21,17 +21,25 @@ static struct avs_dev *avs_get_kcontrol_adev(struct snd_kcontrol *kcontrol)
return to_avs_dev(w->dapm->component->dev);
}
static struct avs_path_module *avs_get_kcontrol_module(struct avs_dev *adev, u32 id)
static struct avs_path_module *avs_get_volume_module(struct avs_dev *adev, u32 id)
{
struct avs_path *path;
struct avs_path_pipeline *ppl;
struct avs_path_module *mod;
list_for_each_entry(path, &adev->path_list, node)
list_for_each_entry(ppl, &path->ppl_list, node)
list_for_each_entry(mod, &ppl->mod_list, node)
if (mod->template->ctl_id && mod->template->ctl_id == id)
spin_lock(&adev->path_list_lock);
list_for_each_entry(path, &adev->path_list, node) {
list_for_each_entry(ppl, &path->ppl_list, node) {
list_for_each_entry(mod, &ppl->mod_list, node) {
if (guid_equal(&mod->template->cfg_ext->type, &AVS_PEAKVOL_MOD_UUID)
&& mod->template->ctl_id == id) {
spin_unlock(&adev->path_list_lock);
return mod;
}
}
}
}
spin_unlock(&adev->path_list_lock);
return NULL;
}
......@@ -49,7 +57,7 @@ int avs_control_volume_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_va
/* prevent access to modules while path is being constructed */
mutex_lock(&adev->path_mutex);
active_module = avs_get_kcontrol_module(adev, ctl_data->id);
active_module = avs_get_volume_module(adev, ctl_data->id);
if (active_module) {
ret = avs_ipc_peakvol_get_volume(adev, active_module->module_id,
active_module->instance_id, &dspvols,
......@@ -89,7 +97,7 @@ int avs_control_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_va
changed = 1;
}
active_module = avs_get_kcontrol_module(adev, ctl_data->id);
active_module = avs_get_volume_module(adev, ctl_data->id);
if (active_module) {
dspvol.channel_id = AVS_ALL_CHANNELS_MASK;
dspvol.target_volume = *volume;
......
......@@ -225,7 +225,7 @@ static int avs_dsp_put_core(struct avs_dev *adev, u32 core_id)
int avs_dsp_init_module(struct avs_dev *adev, u16 module_id, u8 ppl_instance_id,
u8 core_id, u8 domain, void *param, u32 param_size,
u16 *instance_id)
u8 *instance_id)
{
struct avs_module_entry mentry;
bool was_loaded = false;
......@@ -272,7 +272,7 @@ int avs_dsp_init_module(struct avs_dev *adev, u16 module_id, u8 ppl_instance_id,
return ret;
}
void avs_dsp_delete_module(struct avs_dev *adev, u16 module_id, u16 instance_id,
void avs_dsp_delete_module(struct avs_dev *adev, u16 module_id, u8 instance_id,
u8 ppl_instance_id, u8 core_id)
{
struct avs_module_entry mentry;
......
......@@ -619,7 +619,7 @@ enum avs_channel_config {
AVS_CHANNEL_CONFIG_DUAL_MONO = 9,
AVS_CHANNEL_CONFIG_I2S_DUAL_STEREO_0 = 10,
AVS_CHANNEL_CONFIG_I2S_DUAL_STEREO_1 = 11,
AVS_CHANNEL_CONFIG_4_CHANNEL = 12,
AVS_CHANNEL_CONFIG_7_1 = 12,
AVS_CHANNEL_CONFIG_INVALID
};
......
......@@ -37,7 +37,7 @@ struct avs_path_pipeline {
struct avs_path_module {
u16 module_id;
u16 instance_id;
u8 instance_id;
union avs_gtw_attributes gtw_attrs;
struct avs_tplg_module *template;
......
......@@ -468,21 +468,34 @@ static int avs_dai_fe_startup(struct snd_pcm_substream *substream, struct snd_so
host_stream = snd_hdac_ext_stream_assign(bus, substream, HDAC_EXT_STREAM_TYPE_HOST);
if (!host_stream) {
kfree(data);
return -EBUSY;
ret = -EBUSY;
goto err;
}
data->host_stream = host_stream;
snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
if (ret < 0)
goto err;
/* avoid wrap-around with wall-clock */
snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_TIME, 20, 178000000);
snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_rates);
ret = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_TIME, 20, 178000000);
if (ret < 0)
goto err;
ret = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_rates);
if (ret < 0)
goto err;
snd_pcm_set_sync(substream);
dev_dbg(dai->dev, "%s fe STARTUP tag %d str %p",
__func__, hdac_stream(host_stream)->stream_tag, substream);
return 0;
err:
kfree(data);
return ret;
}
static void avs_dai_fe_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
......
......@@ -18,7 +18,7 @@ static int avs_dsp_init_probe(struct avs_dev *adev, union avs_connector_node_id
{
struct avs_probe_cfg cfg = {{0}};
struct avs_module_entry mentry;
u16 dummy;
u8 dummy;
avs_get_module_entry(adev, &AVS_PROBE_MOD_UUID, &mentry);
......
......@@ -2405,6 +2405,9 @@ int dpcm_be_dai_prepare(struct snd_soc_pcm_runtime *fe, int stream)
if (!snd_soc_dpcm_be_can_update(fe, be, stream))
continue;
if (!snd_soc_dpcm_can_be_prepared(fe, be, stream))
continue;
if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_PARAMS) &&
(be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP) &&
(be->dpcm[stream].state != SND_SOC_DPCM_STATE_SUSPEND) &&
......@@ -3042,3 +3045,20 @@ int snd_soc_dpcm_can_be_params(struct snd_soc_pcm_runtime *fe,
return snd_soc_dpcm_check_state(fe, be, stream, state, ARRAY_SIZE(state));
}
EXPORT_SYMBOL_GPL(snd_soc_dpcm_can_be_params);
/*
* We can only prepare a BE DAI if any of it's FE are not prepared,
* running or paused for the specified stream direction.
*/
int snd_soc_dpcm_can_be_prepared(struct snd_soc_pcm_runtime *fe,
struct snd_soc_pcm_runtime *be, int stream)
{
const enum snd_soc_dpcm_state state[] = {
SND_SOC_DPCM_STATE_START,
SND_SOC_DPCM_STATE_PAUSED,
SND_SOC_DPCM_STATE_PREPARE,
};
return snd_soc_dpcm_check_state(fe, be, stream, state, ARRAY_SIZE(state));
}
EXPORT_SYMBOL_GPL(snd_soc_dpcm_can_be_prepared);
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