mirror of
https://github.com/torvalds/linux.git
synced 2024-11-23 20:51:44 +00:00
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. -----BEGIN PGP SIGNATURE----- iQEzBAABCgAdFiEEreZoqmdXGLWf4p/qJNaLcl1Uh9AFAmRt4skACgkQJNaLcl1U h9Cl2gf8CnINVsSuzSgRqvpaxSpsEufghFJrlVtNPJxJz6z+1X+sz/bsq3ceuIWl 56kJ9V0FgdcFJn8PtzJWSMvY/iwyMjAVrCl7cPqPlEIRrelQUihEteDQiL+lGrPn m0zkFWywW+r+KuzgoEosqL6/cDx7iR2NsELm/z/6aobsJRwVii7DigGAym9TNvwf dKvxy3uSX+XbCR7BTadO4wn4iHZ0/BkgYxUu4KckTgFDqHQHwrnbZNLhr0w214el bQuQOD0o6n8ZhBabOYv6j+TpwMO9qI/PjqJtn+fOZRi4pSmF1HlHL+8HLbukzblA FcsQJdXyKNzEbgHKTamOul9hgx4q4w== =H2J9 -----END PGP SIGNATURE----- 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.
This commit is contained in:
commit
bac4d8220b
@ -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 @@ err:
|
||||
|
||||
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 @@ err_mod_entry:
|
||||
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);
|
||||
|
Loading…
Reference in New Issue
Block a user