Commit 029c77f8 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'sound-6.4-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound

Pull sound fixes from Takashi Iwai:
 "A collection of small fixes:

   - HD-audio runtime PM bug fix

   - A couple of HD-audio quirks

   - Fix series of ASoC Intel AVS drivers

   - ASoC DPCM fix for a bug found on new Intel systems

   - A few other ASoC device-specific small fixes"

* tag 'sound-6.4-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound:
  ALSA: hda/realtek: Enable headset onLenovo M70/M90
  ASoC: dwc: move DMA init to snd_soc_dai_driver probe()
  ASoC: cs35l41: Fix default regmap values for some registers
  ALSA: hda: Fix unhandled register update during auto-suspend period
  ASoC: dt-bindings: tlv320aic32x4: Fix supply names
  ASoC: Intel: avs: Add missing checks on FE startup
  ASoC: Intel: avs: Fix avs_path_module::instance_id size
  ASoC: Intel: avs: Account for UID of ACPI device
  ASoC: Intel: avs: Fix declaration of enum avs_channel_config
  ASoC: Intel: Skylake: Fix declaration of enum skl_ch_cfg
  ASoC: Intel: avs: Access path components under lock
  ASoC: Intel: avs: Fix module lookup
  ALSA: hda/ca0132: add quirk for EVGA X299 DARK
  ASoC: soc-pcm: test if a BE can be prepared
  ASoC: rt5682: Disable jack detection interrupt during suspend
  ASoC: lpass: Fix for KASAN use_after_free out of bounds
parents ecea3ba2 4ca110ca
...@@ -8,7 +8,7 @@ Required properties: ...@@ -8,7 +8,7 @@ Required properties:
"ti,tlv320aic32x6" TLV320AIC3206, TLV320AIC3256 "ti,tlv320aic32x6" TLV320AIC3206, TLV320AIC3256
"ti,tas2505" TAS2505, TAS2521 "ti,tas2505" TAS2505, TAS2521
- reg: I2C slave address - reg: I2C slave address
- supply-*: Required supply regulators are: - *-supply: Required supply regulators are:
"iov" - digital IO power supply "iov" - digital IO power supply
"ldoin" - LDO power supply "ldoin" - LDO power supply
"dv" - Digital core power supply "dv" - Digital core power supply
......
...@@ -170,6 +170,7 @@ struct snd_soc_acpi_link_adr { ...@@ -170,6 +170,7 @@ struct snd_soc_acpi_link_adr {
/* Descriptor for SST ASoC machine driver */ /* Descriptor for SST ASoC machine driver */
struct snd_soc_acpi_mach { struct snd_soc_acpi_mach {
u8 id[ACPI_ID_LEN]; u8 id[ACPI_ID_LEN];
const char *uid;
const struct snd_soc_acpi_codecs *comp_ids; const struct snd_soc_acpi_codecs *comp_ids;
const u32 link_mask; const u32 link_mask;
const struct snd_soc_acpi_link_adr *links; 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, ...@@ -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, int snd_soc_dpcm_can_be_params(struct snd_soc_pcm_runtime *fe,
struct snd_soc_pcm_runtime *be, int stream); 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 ? */ /* is the current PCM operation for this FE ? */
int snd_soc_dpcm_fe_can_update(struct snd_soc_pcm_runtime *fe, int stream); int snd_soc_dpcm_fe_can_update(struct snd_soc_pcm_runtime *fe, int stream);
......
...@@ -66,7 +66,8 @@ enum skl_ch_cfg { ...@@ -66,7 +66,8 @@ enum skl_ch_cfg {
SKL_CH_CFG_DUAL_MONO = 9, SKL_CH_CFG_DUAL_MONO = 9,
SKL_CH_CFG_I2S_DUAL_STEREO_0 = 10, SKL_CH_CFG_I2S_DUAL_STEREO_0 = 10,
SKL_CH_CFG_I2S_DUAL_STEREO_1 = 11, 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 SKL_CH_CFG_INVALID
}; };
......
...@@ -611,7 +611,7 @@ EXPORT_SYMBOL_GPL(snd_hdac_power_up_pm); ...@@ -611,7 +611,7 @@ EXPORT_SYMBOL_GPL(snd_hdac_power_up_pm);
int snd_hdac_keep_power_up(struct hdac_device *codec) int snd_hdac_keep_power_up(struct hdac_device *codec)
{ {
if (!atomic_inc_not_zero(&codec->in_pm)) { if (!atomic_inc_not_zero(&codec->in_pm)) {
int ret = pm_runtime_get_if_in_use(&codec->dev); int ret = pm_runtime_get_if_active(&codec->dev, true);
if (!ret) if (!ret)
return -1; return -1;
if (ret < 0) if (ret < 0)
......
...@@ -1306,6 +1306,7 @@ static const struct snd_pci_quirk ca0132_quirks[] = { ...@@ -1306,6 +1306,7 @@ static const struct snd_pci_quirk ca0132_quirks[] = {
SND_PCI_QUIRK(0x1458, 0xA026, "Gigabyte G1.Sniper Z97", QUIRK_R3DI), SND_PCI_QUIRK(0x1458, 0xA026, "Gigabyte G1.Sniper Z97", QUIRK_R3DI),
SND_PCI_QUIRK(0x1458, 0xA036, "Gigabyte GA-Z170X-Gaming 7", QUIRK_R3DI), SND_PCI_QUIRK(0x1458, 0xA036, "Gigabyte GA-Z170X-Gaming 7", QUIRK_R3DI),
SND_PCI_QUIRK(0x3842, 0x1038, "EVGA X99 Classified", QUIRK_R3DI), SND_PCI_QUIRK(0x3842, 0x1038, "EVGA X99 Classified", QUIRK_R3DI),
SND_PCI_QUIRK(0x3842, 0x104b, "EVGA X299 Dark", QUIRK_R3DI),
SND_PCI_QUIRK(0x3842, 0x1055, "EVGA Z390 DARK", QUIRK_R3DI), SND_PCI_QUIRK(0x3842, 0x1055, "EVGA Z390 DARK", QUIRK_R3DI),
SND_PCI_QUIRK(0x1102, 0x0013, "Recon3D", QUIRK_R3D), SND_PCI_QUIRK(0x1102, 0x0013, "Recon3D", QUIRK_R3D),
SND_PCI_QUIRK(0x1102, 0x0018, "Recon3D", QUIRK_R3D), SND_PCI_QUIRK(0x1102, 0x0018, "Recon3D", QUIRK_R3D),
......
...@@ -11719,6 +11719,8 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = { ...@@ -11719,6 +11719,8 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = {
SND_PCI_QUIRK(0x17aa, 0x32cb, "Lenovo ThinkCentre M70", ALC897_FIXUP_HEADSET_MIC_PIN), SND_PCI_QUIRK(0x17aa, 0x32cb, "Lenovo ThinkCentre M70", ALC897_FIXUP_HEADSET_MIC_PIN),
SND_PCI_QUIRK(0x17aa, 0x32cf, "Lenovo ThinkCentre M950", ALC897_FIXUP_HEADSET_MIC_PIN), SND_PCI_QUIRK(0x17aa, 0x32cf, "Lenovo ThinkCentre M950", ALC897_FIXUP_HEADSET_MIC_PIN),
SND_PCI_QUIRK(0x17aa, 0x32f7, "Lenovo ThinkCentre M90", ALC897_FIXUP_HEADSET_MIC_PIN), SND_PCI_QUIRK(0x17aa, 0x32f7, "Lenovo ThinkCentre M90", ALC897_FIXUP_HEADSET_MIC_PIN),
SND_PCI_QUIRK(0x17aa, 0x3321, "Lenovo ThinkCentre M70 Gen4", ALC897_FIXUP_HEADSET_MIC_PIN),
SND_PCI_QUIRK(0x17aa, 0x331b, "Lenovo ThinkCentre M90 Gen4", ALC897_FIXUP_HEADSET_MIC_PIN),
SND_PCI_QUIRK(0x17aa, 0x3742, "Lenovo TianYi510Pro-14IOB", ALC897_FIXUP_HEADSET_MIC_PIN2), SND_PCI_QUIRK(0x17aa, 0x3742, "Lenovo TianYi510Pro-14IOB", ALC897_FIXUP_HEADSET_MIC_PIN2),
SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo Ideapad Y550P", ALC662_FIXUP_IDEAPAD), SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo Ideapad Y550P", ALC662_FIXUP_IDEAPAD),
SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Ideapad Y550", ALC662_FIXUP_IDEAPAD), SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Ideapad Y550", ALC662_FIXUP_IDEAPAD),
......
...@@ -46,7 +46,7 @@ static const struct reg_default cs35l41_reg[] = { ...@@ -46,7 +46,7 @@ static const struct reg_default cs35l41_reg[] = {
{ CS35L41_DSP1_RX5_SRC, 0x00000020 }, { CS35L41_DSP1_RX5_SRC, 0x00000020 },
{ CS35L41_DSP1_RX6_SRC, 0x00000021 }, { CS35L41_DSP1_RX6_SRC, 0x00000021 },
{ CS35L41_DSP1_RX7_SRC, 0x0000003A }, { CS35L41_DSP1_RX7_SRC, 0x0000003A },
{ CS35L41_DSP1_RX8_SRC, 0x00000001 }, { CS35L41_DSP1_RX8_SRC, 0x0000003B },
{ CS35L41_NGATE1_SRC, 0x00000008 }, { CS35L41_NGATE1_SRC, 0x00000008 },
{ CS35L41_NGATE2_SRC, 0x00000009 }, { CS35L41_NGATE2_SRC, 0x00000009 },
{ CS35L41_AMP_DIG_VOL_CTRL, 0x00008000 }, { CS35L41_AMP_DIG_VOL_CTRL, 0x00008000 },
...@@ -58,8 +58,8 @@ static const struct reg_default cs35l41_reg[] = { ...@@ -58,8 +58,8 @@ static const struct reg_default cs35l41_reg[] = {
{ CS35L41_IRQ1_MASK2, 0xFFFFFFFF }, { CS35L41_IRQ1_MASK2, 0xFFFFFFFF },
{ CS35L41_IRQ1_MASK3, 0xFFFF87FF }, { CS35L41_IRQ1_MASK3, 0xFFFF87FF },
{ CS35L41_IRQ1_MASK4, 0xFEFFFFFF }, { CS35L41_IRQ1_MASK4, 0xFEFFFFFF },
{ CS35L41_GPIO1_CTRL1, 0xE1000001 }, { CS35L41_GPIO1_CTRL1, 0x81000001 },
{ CS35L41_GPIO2_CTRL1, 0xE1000001 }, { CS35L41_GPIO2_CTRL1, 0x81000001 },
{ CS35L41_MIXER_NGATE_CFG, 0x00000000 }, { CS35L41_MIXER_NGATE_CFG, 0x00000000 },
{ CS35L41_MIXER_NGATE_CH1_CFG, 0x00000303 }, { CS35L41_MIXER_NGATE_CH1_CFG, 0x00000303 },
{ CS35L41_MIXER_NGATE_CH2_CFG, 0x00000303 }, { CS35L41_MIXER_NGATE_CH2_CFG, 0x00000303 },
......
...@@ -746,6 +746,8 @@ static int tx_macro_put_dec_enum(struct snd_kcontrol *kcontrol, ...@@ -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); struct tx_macro *tx = snd_soc_component_get_drvdata(component);
val = ucontrol->value.enumerated.item[0]; val = ucontrol->value.enumerated.item[0];
if (val >= e->items)
return -EINVAL;
switch (e->reg) { switch (e->reg) {
case CDC_TX_INP_MUX_ADC_MUX0_CFG0: case CDC_TX_INP_MUX_ADC_MUX0_CFG0:
...@@ -772,6 +774,9 @@ static int tx_macro_put_dec_enum(struct snd_kcontrol *kcontrol, ...@@ -772,6 +774,9 @@ static int tx_macro_put_dec_enum(struct snd_kcontrol *kcontrol,
case CDC_TX_INP_MUX_ADC_MUX7_CFG0: case CDC_TX_INP_MUX_ADC_MUX7_CFG0:
mic_sel_reg = CDC_TX7_TX_PATH_CFG0; mic_sel_reg = CDC_TX7_TX_PATH_CFG0;
break; break;
default:
dev_err(component->dev, "Error in configuration!!\n");
return -EINVAL;
} }
if (val != 0) { if (val != 0) {
......
...@@ -267,7 +267,9 @@ static int rt5682_i2c_probe(struct i2c_client *i2c) ...@@ -267,7 +267,9 @@ static int rt5682_i2c_probe(struct i2c_client *i2c)
ret = devm_request_threaded_irq(&i2c->dev, i2c->irq, NULL, ret = devm_request_threaded_irq(&i2c->dev, i2c->irq, NULL,
rt5682_irq, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING rt5682_irq, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING
| IRQF_ONESHOT, "rt5682", rt5682); | IRQF_ONESHOT, "rt5682", rt5682);
if (ret) if (!ret)
rt5682->irq = i2c->irq;
else
dev_err(&i2c->dev, "Failed to reguest IRQ: %d\n", ret); dev_err(&i2c->dev, "Failed to reguest IRQ: %d\n", ret);
} }
......
...@@ -2959,6 +2959,9 @@ static int rt5682_suspend(struct snd_soc_component *component) ...@@ -2959,6 +2959,9 @@ static int rt5682_suspend(struct snd_soc_component *component)
if (rt5682->is_sdw) if (rt5682->is_sdw)
return 0; return 0;
if (rt5682->irq)
disable_irq(rt5682->irq);
cancel_delayed_work_sync(&rt5682->jack_detect_work); cancel_delayed_work_sync(&rt5682->jack_detect_work);
cancel_delayed_work_sync(&rt5682->jd_check_work); cancel_delayed_work_sync(&rt5682->jd_check_work);
if (rt5682->hs_jack && (rt5682->jack_type & SND_JACK_HEADSET) == SND_JACK_HEADSET) { 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) ...@@ -3027,6 +3030,9 @@ static int rt5682_resume(struct snd_soc_component *component)
mod_delayed_work(system_power_efficient_wq, mod_delayed_work(system_power_efficient_wq,
&rt5682->jack_detect_work, msecs_to_jiffies(0)); &rt5682->jack_detect_work, msecs_to_jiffies(0));
if (rt5682->irq)
enable_irq(rt5682->irq);
return 0; return 0;
} }
#else #else
......
...@@ -1462,6 +1462,7 @@ struct rt5682_priv { ...@@ -1462,6 +1462,7 @@ struct rt5682_priv {
int pll_out[RT5682_PLLS]; int pll_out[RT5682_PLLS];
int jack_type; int jack_type;
int irq;
int irq_work_delay_time; int irq_work_delay_time;
}; };
......
...@@ -183,30 +183,6 @@ static void i2s_stop(struct dw_i2s_dev *dev, ...@@ -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) static void dw_i2s_config(struct dw_i2s_dev *dev, int stream)
{ {
u32 ch_reg; u32 ch_reg;
...@@ -305,12 +281,6 @@ static int dw_i2s_hw_params(struct snd_pcm_substream *substream, ...@@ -305,12 +281,6 @@ static int dw_i2s_hw_params(struct snd_pcm_substream *substream,
return 0; 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, static int dw_i2s_prepare(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai) struct snd_soc_dai *dai)
{ {
...@@ -382,8 +352,6 @@ static int dw_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) ...@@ -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 = { 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, .hw_params = dw_i2s_hw_params,
.prepare = dw_i2s_prepare, .prepare = dw_i2s_prepare,
.trigger = dw_i2s_trigger, .trigger = dw_i2s_trigger,
...@@ -625,6 +593,14 @@ static int dw_configure_dai_by_dt(struct dw_i2s_dev *dev, ...@@ -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) static int dw_i2s_probe(struct platform_device *pdev)
{ {
const struct i2s_platform_data *pdata = pdev->dev.platform_data; const struct i2s_platform_data *pdata = pdev->dev.platform_data;
...@@ -643,6 +619,7 @@ static int dw_i2s_probe(struct platform_device *pdev) ...@@ -643,6 +619,7 @@ static int dw_i2s_probe(struct platform_device *pdev)
return -ENOMEM; return -ENOMEM;
dw_i2s_dai->ops = &dw_i2s_dai_ops; 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); dev->i2s_base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
if (IS_ERR(dev->i2s_base)) if (IS_ERR(dev->i2s_base))
......
...@@ -169,6 +169,7 @@ static bool apl_lp_streaming(struct avs_dev *adev) ...@@ -169,6 +169,7 @@ static bool apl_lp_streaming(struct avs_dev *adev)
{ {
struct avs_path *path; struct avs_path *path;
spin_lock(&adev->path_list_lock);
/* Any gateway without buffer allocated in LP area disqualifies D0IX. */ /* Any gateway without buffer allocated in LP area disqualifies D0IX. */
list_for_each_entry(path, &adev->path_list, node) { list_for_each_entry(path, &adev->path_list, node) {
struct avs_path_pipeline *ppl; struct avs_path_pipeline *ppl;
...@@ -188,11 +189,14 @@ static bool apl_lp_streaming(struct avs_dev *adev) ...@@ -188,11 +189,14 @@ static bool apl_lp_streaming(struct avs_dev *adev)
if (cfg->copier.dma_type == INVALID_OBJECT_ID) if (cfg->copier.dma_type == INVALID_OBJECT_ID)
continue; continue;
if (!mod->gtw_attrs.lp_buffer_alloc) if (!mod->gtw_attrs.lp_buffer_alloc) {
spin_unlock(&adev->path_list_lock);
return false; return false;
}
} }
} }
} }
spin_unlock(&adev->path_list_lock);
return true; return true;
} }
......
...@@ -283,8 +283,8 @@ void avs_release_firmwares(struct avs_dev *adev); ...@@ -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, 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, u8 core_id, u8 domain, void *param, u32 param_size,
u16 *instance_id); u8 *instance_id);
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); u8 ppl_instance_id, u8 core_id);
int avs_dsp_create_pipeline(struct avs_dev *adev, u16 req_size, u8 priority, int avs_dsp_create_pipeline(struct avs_dev *adev, u16 req_size, u8 priority,
bool lp, u16 attributes, u8 *instance_id); bool lp, u16 attributes, u8 *instance_id);
......
...@@ -443,7 +443,7 @@ static int avs_register_i2s_boards(struct avs_dev *adev) ...@@ -443,7 +443,7 @@ static int avs_register_i2s_boards(struct avs_dev *adev)
} }
for (mach = boards->machs; mach->id[0]; mach++) { 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; continue;
if (mach->machine_quirk) if (mach->machine_quirk)
......
...@@ -21,17 +21,25 @@ static struct avs_dev *avs_get_kcontrol_adev(struct snd_kcontrol *kcontrol) ...@@ -21,17 +21,25 @@ static struct avs_dev *avs_get_kcontrol_adev(struct snd_kcontrol *kcontrol)
return to_avs_dev(w->dapm->component->dev); 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 *path;
struct avs_path_pipeline *ppl; struct avs_path_pipeline *ppl;
struct avs_path_module *mod; struct avs_path_module *mod;
list_for_each_entry(path, &adev->path_list, node) spin_lock(&adev->path_list_lock);
list_for_each_entry(ppl, &path->ppl_list, node) list_for_each_entry(path, &adev->path_list, node) {
list_for_each_entry(mod, &ppl->mod_list, node) list_for_each_entry(ppl, &path->ppl_list, node) {
if (mod->template->ctl_id && mod->template->ctl_id == id) 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; return mod;
}
}
}
}
spin_unlock(&adev->path_list_lock);
return NULL; return NULL;
} }
...@@ -49,7 +57,7 @@ int avs_control_volume_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_va ...@@ -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 */ /* prevent access to modules while path is being constructed */
mutex_lock(&adev->path_mutex); 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) { if (active_module) {
ret = avs_ipc_peakvol_get_volume(adev, active_module->module_id, ret = avs_ipc_peakvol_get_volume(adev, active_module->module_id,
active_module->instance_id, &dspvols, active_module->instance_id, &dspvols,
...@@ -89,7 +97,7 @@ int avs_control_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_va ...@@ -89,7 +97,7 @@ int avs_control_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_va
changed = 1; 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) { if (active_module) {
dspvol.channel_id = AVS_ALL_CHANNELS_MASK; dspvol.channel_id = AVS_ALL_CHANNELS_MASK;
dspvol.target_volume = *volume; dspvol.target_volume = *volume;
......
...@@ -225,7 +225,7 @@ static int avs_dsp_put_core(struct avs_dev *adev, u32 core_id) ...@@ -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, 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, u8 core_id, u8 domain, void *param, u32 param_size,
u16 *instance_id) u8 *instance_id)
{ {
struct avs_module_entry mentry; struct avs_module_entry mentry;
bool was_loaded = false; bool was_loaded = false;
...@@ -272,7 +272,7 @@ int avs_dsp_init_module(struct avs_dev *adev, u16 module_id, u8 ppl_instance_id, ...@@ -272,7 +272,7 @@ int avs_dsp_init_module(struct avs_dev *adev, u16 module_id, u8 ppl_instance_id,
return ret; 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) u8 ppl_instance_id, u8 core_id)
{ {
struct avs_module_entry mentry; struct avs_module_entry mentry;
......
...@@ -619,7 +619,7 @@ enum avs_channel_config { ...@@ -619,7 +619,7 @@ enum avs_channel_config {
AVS_CHANNEL_CONFIG_DUAL_MONO = 9, AVS_CHANNEL_CONFIG_DUAL_MONO = 9,
AVS_CHANNEL_CONFIG_I2S_DUAL_STEREO_0 = 10, AVS_CHANNEL_CONFIG_I2S_DUAL_STEREO_0 = 10,
AVS_CHANNEL_CONFIG_I2S_DUAL_STEREO_1 = 11, AVS_CHANNEL_CONFIG_I2S_DUAL_STEREO_1 = 11,
AVS_CHANNEL_CONFIG_4_CHANNEL = 12, AVS_CHANNEL_CONFIG_7_1 = 12,
AVS_CHANNEL_CONFIG_INVALID AVS_CHANNEL_CONFIG_INVALID
}; };
......
...@@ -37,7 +37,7 @@ struct avs_path_pipeline { ...@@ -37,7 +37,7 @@ struct avs_path_pipeline {
struct avs_path_module { struct avs_path_module {
u16 module_id; u16 module_id;
u16 instance_id; u8 instance_id;
union avs_gtw_attributes gtw_attrs; union avs_gtw_attributes gtw_attrs;
struct avs_tplg_module *template; struct avs_tplg_module *template;
......
...@@ -468,21 +468,34 @@ static int avs_dai_fe_startup(struct snd_pcm_substream *substream, struct snd_so ...@@ -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); host_stream = snd_hdac_ext_stream_assign(bus, substream, HDAC_EXT_STREAM_TYPE_HOST);
if (!host_stream) { if (!host_stream) {
kfree(data); ret = -EBUSY;
return -EBUSY; goto err;
} }
data->host_stream = host_stream; 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 */ /* avoid wrap-around with wall-clock */
snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_TIME, 20, 178000000); ret = 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); 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); snd_pcm_set_sync(substream);
dev_dbg(dai->dev, "%s fe STARTUP tag %d str %p", dev_dbg(dai->dev, "%s fe STARTUP tag %d str %p",
__func__, hdac_stream(host_stream)->stream_tag, substream); __func__, hdac_stream(host_stream)->stream_tag, substream);
return 0; return 0;
err:
kfree(data);
return ret;
} }
static void avs_dai_fe_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) 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 ...@@ -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_probe_cfg cfg = {{0}};
struct avs_module_entry mentry; struct avs_module_entry mentry;
u16 dummy; u8 dummy;
avs_get_module_entry(adev, &AVS_PROBE_MOD_UUID, &mentry); 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) ...@@ -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)) if (!snd_soc_dpcm_be_can_update(fe, be, stream))
continue; continue;
if (!snd_soc_dpcm_can_be_prepared(fe, be, stream))
continue;
if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_PARAMS) && 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_STOP) &&
(be->dpcm[stream].state != SND_SOC_DPCM_STATE_SUSPEND) && (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, ...@@ -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)); return snd_soc_dpcm_check_state(fe, be, stream, state, ARRAY_SIZE(state));
} }
EXPORT_SYMBOL_GPL(snd_soc_dpcm_can_be_params); 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