Commit 0eb0e272 authored by Takashi Iwai's avatar Takashi Iwai

Merge tag 'asoc-fix-v6.6-rc2' of...

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

ASoC: Fixes for v6.6

Quite a large collection of fixes, with numbers boosted by multiple
vendors sending multi-patch serieses.  Nothing super major, and also one
device quirk.
parents 41b07476 31bb7bd9
...@@ -1863,15 +1863,15 @@ static int cs_dsp_adsp2_setup_algs(struct cs_dsp *dsp) ...@@ -1863,15 +1863,15 @@ static int cs_dsp_adsp2_setup_algs(struct cs_dsp *dsp)
return PTR_ERR(adsp2_alg); return PTR_ERR(adsp2_alg);
for (i = 0; i < n_algs; i++) { for (i = 0; i < n_algs; i++) {
cs_dsp_info(dsp, cs_dsp_dbg(dsp,
"%d: ID %x v%d.%d.%d XM@%x YM@%x ZM@%x\n", "%d: ID %x v%d.%d.%d XM@%x YM@%x ZM@%x\n",
i, be32_to_cpu(adsp2_alg[i].alg.id), i, be32_to_cpu(adsp2_alg[i].alg.id),
(be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff0000) >> 16, (be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff0000) >> 16,
(be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff00) >> 8, (be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff00) >> 8,
be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff, be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff,
be32_to_cpu(adsp2_alg[i].xm), be32_to_cpu(adsp2_alg[i].xm),
be32_to_cpu(adsp2_alg[i].ym), be32_to_cpu(adsp2_alg[i].ym),
be32_to_cpu(adsp2_alg[i].zm)); be32_to_cpu(adsp2_alg[i].zm));
alg_region = cs_dsp_create_region(dsp, WMFW_ADSP2_XM, alg_region = cs_dsp_create_region(dsp, WMFW_ADSP2_XM,
adsp2_alg[i].alg.id, adsp2_alg[i].alg.id,
...@@ -1996,14 +1996,14 @@ static int cs_dsp_halo_setup_algs(struct cs_dsp *dsp) ...@@ -1996,14 +1996,14 @@ static int cs_dsp_halo_setup_algs(struct cs_dsp *dsp)
return PTR_ERR(halo_alg); return PTR_ERR(halo_alg);
for (i = 0; i < n_algs; i++) { for (i = 0; i < n_algs; i++) {
cs_dsp_info(dsp, cs_dsp_dbg(dsp,
"%d: ID %x v%d.%d.%d XM@%x YM@%x\n", "%d: ID %x v%d.%d.%d XM@%x YM@%x\n",
i, be32_to_cpu(halo_alg[i].alg.id), i, be32_to_cpu(halo_alg[i].alg.id),
(be32_to_cpu(halo_alg[i].alg.ver) & 0xff0000) >> 16, (be32_to_cpu(halo_alg[i].alg.ver) & 0xff0000) >> 16,
(be32_to_cpu(halo_alg[i].alg.ver) & 0xff00) >> 8, (be32_to_cpu(halo_alg[i].alg.ver) & 0xff00) >> 8,
be32_to_cpu(halo_alg[i].alg.ver) & 0xff, be32_to_cpu(halo_alg[i].alg.ver) & 0xff,
be32_to_cpu(halo_alg[i].xm_base), be32_to_cpu(halo_alg[i].xm_base),
be32_to_cpu(halo_alg[i].ym_base)); be32_to_cpu(halo_alg[i].ym_base));
ret = cs_dsp_halo_create_regions(dsp, halo_alg[i].alg.id, ret = cs_dsp_halo_create_regions(dsp, halo_alg[i].alg.id,
halo_alg[i].alg.ver, halo_alg[i].alg.ver,
......
...@@ -213,6 +213,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = { ...@@ -213,6 +213,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "21J6"), DMI_MATCH(DMI_PRODUCT_NAME, "21J6"),
} }
}, },
{
.driver_data = &acp6x_card,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_NAME, "82QF"),
}
},
{ {
.driver_data = &acp6x_card, .driver_data = &acp6x_card,
.matches = { .matches = {
...@@ -220,6 +227,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = { ...@@ -220,6 +227,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "82TL"), DMI_MATCH(DMI_PRODUCT_NAME, "82TL"),
} }
}, },
{
.driver_data = &acp6x_card,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_NAME, "82UG"),
}
},
{ {
.driver_data = &acp6x_card, .driver_data = &acp6x_card,
.matches = { .matches = {
...@@ -262,6 +276,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = { ...@@ -262,6 +276,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "M6500RC"), DMI_MATCH(DMI_PRODUCT_NAME, "M6500RC"),
} }
}, },
{
.driver_data = &acp6x_card,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Micro-Star International Co., Ltd."),
DMI_MATCH(DMI_PRODUCT_NAME, "Bravo 15 B7ED"),
}
},
{ {
.driver_data = &acp6x_card, .driver_data = &acp6x_card,
.matches = { .matches = {
......
...@@ -452,11 +452,13 @@ static int aw_dev_parse_reg_bin_with_hdr(struct aw_device *aw_dev, ...@@ -452,11 +452,13 @@ static int aw_dev_parse_reg_bin_with_hdr(struct aw_device *aw_dev,
if ((aw_bin->all_bin_parse_num != 1) || if ((aw_bin->all_bin_parse_num != 1) ||
(aw_bin->header_info[0].bin_data_type != DATA_TYPE_REGISTER)) { (aw_bin->header_info[0].bin_data_type != DATA_TYPE_REGISTER)) {
dev_err(aw_dev->dev, "bin num or type error"); dev_err(aw_dev->dev, "bin num or type error");
ret = -EINVAL;
goto parse_bin_failed; goto parse_bin_failed;
} }
if (aw_bin->header_info[0].valid_data_len % 4) { if (aw_bin->header_info[0].valid_data_len % 4) {
dev_err(aw_dev->dev, "bin data len get error!"); dev_err(aw_dev->dev, "bin data len get error!");
ret = -EINVAL;
goto parse_bin_failed; goto parse_bin_failed;
} }
......
...@@ -27,7 +27,6 @@ static int cs35l56_i2c_probe(struct i2c_client *client) ...@@ -27,7 +27,6 @@ static int cs35l56_i2c_probe(struct i2c_client *client)
return -ENOMEM; return -ENOMEM;
cs35l56->base.dev = dev; cs35l56->base.dev = dev;
cs35l56->base.can_hibernate = true;
i2c_set_clientdata(client, cs35l56); i2c_set_clientdata(client, cs35l56);
cs35l56->base.regmap = devm_regmap_init_i2c(client, regmap_config); cs35l56->base.regmap = devm_regmap_init_i2c(client, regmap_config);
......
...@@ -1207,6 +1207,7 @@ void cs35l56_remove(struct cs35l56_private *cs35l56) ...@@ -1207,6 +1207,7 @@ void cs35l56_remove(struct cs35l56_private *cs35l56)
flush_workqueue(cs35l56->dsp_wq); flush_workqueue(cs35l56->dsp_wq);
destroy_workqueue(cs35l56->dsp_wq); destroy_workqueue(cs35l56->dsp_wq);
pm_runtime_dont_use_autosuspend(cs35l56->base.dev);
pm_runtime_suspend(cs35l56->base.dev); pm_runtime_suspend(cs35l56->base.dev);
pm_runtime_disable(cs35l56->base.dev); pm_runtime_disable(cs35l56->base.dev);
......
...@@ -344,6 +344,16 @@ static int cs42l42_sdw_update_status(struct sdw_slave *peripheral, ...@@ -344,6 +344,16 @@ static int cs42l42_sdw_update_status(struct sdw_slave *peripheral,
switch (status) { switch (status) {
case SDW_SLAVE_ATTACHED: case SDW_SLAVE_ATTACHED:
dev_dbg(cs42l42->dev, "ATTACHED\n"); dev_dbg(cs42l42->dev, "ATTACHED\n");
/*
* The SoundWire core can report stale ATTACH notifications
* if we hard-reset CS42L42 in probe() but it had already been
* enumerated. Reject the ATTACH if we haven't yet seen an
* UNATTACH report for the device being in reset.
*/
if (cs42l42->sdw_waiting_first_unattach)
break;
/* /*
* Initialise codec, this only needs to be done once. * Initialise codec, this only needs to be done once.
* When resuming from suspend, resume callback will handle re-init of codec, * When resuming from suspend, resume callback will handle re-init of codec,
...@@ -354,6 +364,16 @@ static int cs42l42_sdw_update_status(struct sdw_slave *peripheral, ...@@ -354,6 +364,16 @@ static int cs42l42_sdw_update_status(struct sdw_slave *peripheral,
break; break;
case SDW_SLAVE_UNATTACHED: case SDW_SLAVE_UNATTACHED:
dev_dbg(cs42l42->dev, "UNATTACHED\n"); dev_dbg(cs42l42->dev, "UNATTACHED\n");
if (cs42l42->sdw_waiting_first_unattach) {
/*
* SoundWire core has seen that CS42L42 is not on
* the bus so release RESET and wait for ATTACH.
*/
cs42l42->sdw_waiting_first_unattach = false;
gpiod_set_value_cansleep(cs42l42->reset_gpio, 1);
}
break; break;
default: default:
break; break;
......
...@@ -2320,7 +2320,26 @@ int cs42l42_common_probe(struct cs42l42_private *cs42l42, ...@@ -2320,7 +2320,26 @@ int cs42l42_common_probe(struct cs42l42_private *cs42l42,
if (cs42l42->reset_gpio) { if (cs42l42->reset_gpio) {
dev_dbg(cs42l42->dev, "Found reset GPIO\n"); dev_dbg(cs42l42->dev, "Found reset GPIO\n");
gpiod_set_value_cansleep(cs42l42->reset_gpio, 1);
/*
* ACPI can override the default GPIO state we requested
* so ensure that we start with RESET low.
*/
gpiod_set_value_cansleep(cs42l42->reset_gpio, 0);
/* Ensure minimum reset pulse width */
usleep_range(10, 500);
/*
* On SoundWire keep the chip in reset until we get an UNATTACH
* notification from the SoundWire core. This acts as a
* synchronization point to reject stale ATTACH notifications
* if the chip was already enumerated before we reset it.
*/
if (cs42l42->sdw_peripheral)
cs42l42->sdw_waiting_first_unattach = true;
else
gpiod_set_value_cansleep(cs42l42->reset_gpio, 1);
} }
usleep_range(CS42L42_BOOT_TIME_US, CS42L42_BOOT_TIME_US * 2); usleep_range(CS42L42_BOOT_TIME_US, CS42L42_BOOT_TIME_US * 2);
......
...@@ -53,6 +53,7 @@ struct cs42l42_private { ...@@ -53,6 +53,7 @@ struct cs42l42_private {
u8 stream_use; u8 stream_use;
bool hp_adc_up_pending; bool hp_adc_up_pending;
bool suspended; bool suspended;
bool sdw_waiting_first_unattach;
bool init_done; bool init_done;
}; };
......
...@@ -2077,7 +2077,8 @@ static const struct cs42l43_irq cs42l43_irqs[] = { ...@@ -2077,7 +2077,8 @@ static const struct cs42l43_irq cs42l43_irqs[] = {
static int cs42l43_request_irq(struct cs42l43_codec *priv, static int cs42l43_request_irq(struct cs42l43_codec *priv,
struct irq_domain *dom, const char * const name, struct irq_domain *dom, const char * const name,
unsigned int irq, irq_handler_t handler) unsigned int irq, irq_handler_t handler,
unsigned long flags)
{ {
int ret; int ret;
...@@ -2087,8 +2088,8 @@ static int cs42l43_request_irq(struct cs42l43_codec *priv, ...@@ -2087,8 +2088,8 @@ static int cs42l43_request_irq(struct cs42l43_codec *priv,
dev_dbg(priv->dev, "Request IRQ %d for %s\n", ret, name); dev_dbg(priv->dev, "Request IRQ %d for %s\n", ret, name);
ret = devm_request_threaded_irq(priv->dev, ret, NULL, handler, IRQF_ONESHOT, ret = devm_request_threaded_irq(priv->dev, ret, NULL, handler,
name, priv); IRQF_ONESHOT | flags, name, priv);
if (ret) if (ret)
return dev_err_probe(priv->dev, ret, "Failed to request IRQ %s\n", name); return dev_err_probe(priv->dev, ret, "Failed to request IRQ %s\n", name);
...@@ -2124,11 +2125,11 @@ static int cs42l43_shutter_irq(struct cs42l43_codec *priv, ...@@ -2124,11 +2125,11 @@ static int cs42l43_shutter_irq(struct cs42l43_codec *priv,
return 0; return 0;
} }
ret = cs42l43_request_irq(priv, dom, close_name, close_irq, handler); ret = cs42l43_request_irq(priv, dom, close_name, close_irq, handler, IRQF_SHARED);
if (ret) if (ret)
return ret; return ret;
return cs42l43_request_irq(priv, dom, open_name, open_irq, handler); return cs42l43_request_irq(priv, dom, open_name, open_irq, handler, IRQF_SHARED);
} }
static int cs42l43_codec_probe(struct platform_device *pdev) static int cs42l43_codec_probe(struct platform_device *pdev)
...@@ -2178,7 +2179,8 @@ static int cs42l43_codec_probe(struct platform_device *pdev) ...@@ -2178,7 +2179,8 @@ static int cs42l43_codec_probe(struct platform_device *pdev)
for (i = 0; i < ARRAY_SIZE(cs42l43_irqs); i++) { for (i = 0; i < ARRAY_SIZE(cs42l43_irqs); i++) {
ret = cs42l43_request_irq(priv, dom, cs42l43_irqs[i].name, ret = cs42l43_request_irq(priv, dom, cs42l43_irqs[i].name,
cs42l43_irqs[i].irq, cs42l43_irqs[i].handler); cs42l43_irqs[i].irq,
cs42l43_irqs[i].handler, 0);
if (ret) if (ret)
goto err_pm; goto err_pm;
} }
......
...@@ -2403,13 +2403,11 @@ static irqreturn_t rt5640_irq(int irq, void *data) ...@@ -2403,13 +2403,11 @@ static irqreturn_t rt5640_irq(int irq, void *data)
struct rt5640_priv *rt5640 = data; struct rt5640_priv *rt5640 = data;
int delay = 0; int delay = 0;
if (rt5640->jd_src == RT5640_JD_SRC_HDA_HEADER) { if (rt5640->jd_src == RT5640_JD_SRC_HDA_HEADER)
cancel_delayed_work_sync(&rt5640->jack_work);
delay = 100; delay = 100;
}
if (rt5640->jack) if (rt5640->jack)
queue_delayed_work(system_long_wq, &rt5640->jack_work, delay); mod_delayed_work(system_long_wq, &rt5640->jack_work, delay);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -2565,10 +2563,9 @@ static void rt5640_enable_jack_detect(struct snd_soc_component *component, ...@@ -2565,10 +2563,9 @@ static void rt5640_enable_jack_detect(struct snd_soc_component *component,
if (jack_data && jack_data->use_platform_clock) if (jack_data && jack_data->use_platform_clock)
rt5640->use_platform_clock = jack_data->use_platform_clock; rt5640->use_platform_clock = jack_data->use_platform_clock;
ret = devm_request_threaded_irq(component->dev, rt5640->irq, ret = request_irq(rt5640->irq, rt5640_irq,
NULL, rt5640_irq, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, "rt5640", rt5640);
"rt5640", rt5640);
if (ret) { if (ret) {
dev_warn(component->dev, "Failed to request IRQ %d: %d\n", rt5640->irq, ret); dev_warn(component->dev, "Failed to request IRQ %d: %d\n", rt5640->irq, ret);
rt5640_disable_jack_detect(component); rt5640_disable_jack_detect(component);
...@@ -2621,14 +2618,14 @@ static void rt5640_enable_hda_jack_detect( ...@@ -2621,14 +2618,14 @@ static void rt5640_enable_hda_jack_detect(
rt5640->jack = jack; rt5640->jack = jack;
ret = devm_request_threaded_irq(component->dev, rt5640->irq, ret = request_irq(rt5640->irq, rt5640_irq,
NULL, rt5640_irq, IRQF_TRIGGER_RISING | IRQF_ONESHOT, IRQF_TRIGGER_RISING | IRQF_ONESHOT, "rt5640", rt5640);
"rt5640", rt5640);
if (ret) { if (ret) {
dev_warn(component->dev, "Failed to request IRQ %d: %d\n", rt5640->irq, ret); dev_warn(component->dev, "Failed to request IRQ %d: %d\n", rt5640->irq, ret);
rt5640->irq = -ENXIO; rt5640->jack = NULL;
return; return;
} }
rt5640->irq_requested = true;
/* sync initial jack state */ /* sync initial jack state */
queue_delayed_work(system_long_wq, &rt5640->jack_work, 0); queue_delayed_work(system_long_wq, &rt5640->jack_work, 0);
...@@ -2801,12 +2798,12 @@ static int rt5640_suspend(struct snd_soc_component *component) ...@@ -2801,12 +2798,12 @@ static int rt5640_suspend(struct snd_soc_component *component)
{ {
struct rt5640_priv *rt5640 = snd_soc_component_get_drvdata(component); struct rt5640_priv *rt5640 = snd_soc_component_get_drvdata(component);
if (rt5640->irq) { if (rt5640->jack) {
/* disable jack interrupts during system suspend */ /* disable jack interrupts during system suspend */
disable_irq(rt5640->irq); disable_irq(rt5640->irq);
rt5640_cancel_work(rt5640);
} }
rt5640_cancel_work(rt5640);
snd_soc_component_force_bias_level(component, SND_SOC_BIAS_OFF); snd_soc_component_force_bias_level(component, SND_SOC_BIAS_OFF);
rt5640_reset(component); rt5640_reset(component);
regcache_cache_only(rt5640->regmap, true); regcache_cache_only(rt5640->regmap, true);
...@@ -2829,9 +2826,6 @@ static int rt5640_resume(struct snd_soc_component *component) ...@@ -2829,9 +2826,6 @@ static int rt5640_resume(struct snd_soc_component *component)
regcache_cache_only(rt5640->regmap, false); regcache_cache_only(rt5640->regmap, false);
regcache_sync(rt5640->regmap); regcache_sync(rt5640->regmap);
if (rt5640->irq)
enable_irq(rt5640->irq);
if (rt5640->jack) { if (rt5640->jack) {
if (rt5640->jd_src == RT5640_JD_SRC_HDA_HEADER) { if (rt5640->jd_src == RT5640_JD_SRC_HDA_HEADER) {
snd_soc_component_update_bits(component, snd_soc_component_update_bits(component,
...@@ -2859,6 +2853,7 @@ static int rt5640_resume(struct snd_soc_component *component) ...@@ -2859,6 +2853,7 @@ static int rt5640_resume(struct snd_soc_component *component)
} }
} }
enable_irq(rt5640->irq);
queue_delayed_work(system_long_wq, &rt5640->jack_work, 0); queue_delayed_work(system_long_wq, &rt5640->jack_work, 0);
} }
......
...@@ -1468,8 +1468,10 @@ static int wm8960_i2c_probe(struct i2c_client *i2c) ...@@ -1468,8 +1468,10 @@ static int wm8960_i2c_probe(struct i2c_client *i2c)
} }
wm8960->regmap = devm_regmap_init_i2c(i2c, &wm8960_regmap); wm8960->regmap = devm_regmap_init_i2c(i2c, &wm8960_regmap);
if (IS_ERR(wm8960->regmap)) if (IS_ERR(wm8960->regmap)) {
return PTR_ERR(wm8960->regmap); ret = PTR_ERR(wm8960->regmap);
goto bulk_disable;
}
if (pdata) if (pdata)
memcpy(&wm8960->pdata, pdata, sizeof(struct wm8960_data)); memcpy(&wm8960->pdata, pdata, sizeof(struct wm8960_data));
...@@ -1479,13 +1481,14 @@ static int wm8960_i2c_probe(struct i2c_client *i2c) ...@@ -1479,13 +1481,14 @@ static int wm8960_i2c_probe(struct i2c_client *i2c)
ret = i2c_master_recv(i2c, &val, sizeof(val)); ret = i2c_master_recv(i2c, &val, sizeof(val));
if (ret >= 0) { if (ret >= 0) {
dev_err(&i2c->dev, "Not wm8960, wm8960 reg can not read by i2c\n"); dev_err(&i2c->dev, "Not wm8960, wm8960 reg can not read by i2c\n");
return -EINVAL; ret = -EINVAL;
goto bulk_disable;
} }
ret = wm8960_reset(wm8960->regmap); ret = wm8960_reset(wm8960->regmap);
if (ret != 0) { if (ret != 0) {
dev_err(&i2c->dev, "Failed to issue reset\n"); dev_err(&i2c->dev, "Failed to issue reset\n");
return ret; goto bulk_disable;
} }
if (wm8960->pdata.shared_lrclk) { if (wm8960->pdata.shared_lrclk) {
...@@ -1494,7 +1497,7 @@ static int wm8960_i2c_probe(struct i2c_client *i2c) ...@@ -1494,7 +1497,7 @@ static int wm8960_i2c_probe(struct i2c_client *i2c)
if (ret != 0) { if (ret != 0) {
dev_err(&i2c->dev, "Failed to enable LRCM: %d\n", dev_err(&i2c->dev, "Failed to enable LRCM: %d\n",
ret); ret);
return ret; goto bulk_disable;
} }
} }
...@@ -1528,7 +1531,13 @@ static int wm8960_i2c_probe(struct i2c_client *i2c) ...@@ -1528,7 +1531,13 @@ static int wm8960_i2c_probe(struct i2c_client *i2c)
ret = devm_snd_soc_register_component(&i2c->dev, ret = devm_snd_soc_register_component(&i2c->dev,
&soc_component_dev_wm8960, &wm8960_dai, 1); &soc_component_dev_wm8960, &wm8960_dai, 1);
if (ret)
goto bulk_disable;
return 0;
bulk_disable:
regulator_bulk_disable(ARRAY_SIZE(wm8960->supplies), wm8960->supplies);
return ret; return ret;
} }
......
...@@ -687,7 +687,10 @@ int wm_adsp_write_ctl(struct wm_adsp *dsp, const char *name, int type, ...@@ -687,7 +687,10 @@ int wm_adsp_write_ctl(struct wm_adsp *dsp, const char *name, int type,
struct wm_coeff_ctl *ctl; struct wm_coeff_ctl *ctl;
int ret; int ret;
mutex_lock(&dsp->cs_dsp.pwr_lock);
ret = cs_dsp_coeff_write_ctrl(cs_ctl, 0, buf, len); ret = cs_dsp_coeff_write_ctrl(cs_ctl, 0, buf, len);
mutex_unlock(&dsp->cs_dsp.pwr_lock);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -703,8 +706,14 @@ EXPORT_SYMBOL_GPL(wm_adsp_write_ctl); ...@@ -703,8 +706,14 @@ EXPORT_SYMBOL_GPL(wm_adsp_write_ctl);
int wm_adsp_read_ctl(struct wm_adsp *dsp, const char *name, int type, int wm_adsp_read_ctl(struct wm_adsp *dsp, const char *name, int type,
unsigned int alg, void *buf, size_t len) unsigned int alg, void *buf, size_t len)
{ {
return cs_dsp_coeff_read_ctrl(cs_dsp_get_ctl(&dsp->cs_dsp, name, type, alg), int ret;
0, buf, len);
mutex_lock(&dsp->cs_dsp.pwr_lock);
ret = cs_dsp_coeff_read_ctrl(cs_dsp_get_ctl(&dsp->cs_dsp, name, type, alg),
0, buf, len);
mutex_unlock(&dsp->cs_dsp.pwr_lock);
return ret;
} }
EXPORT_SYMBOL_GPL(wm_adsp_read_ctl); EXPORT_SYMBOL_GPL(wm_adsp_read_ctl);
......
...@@ -315,7 +315,7 @@ static int imx_audmix_probe(struct platform_device *pdev) ...@@ -315,7 +315,7 @@ static int imx_audmix_probe(struct platform_device *pdev)
if (IS_ERR(priv->cpu_mclk)) { if (IS_ERR(priv->cpu_mclk)) {
ret = PTR_ERR(priv->cpu_mclk); ret = PTR_ERR(priv->cpu_mclk);
dev_err(&cpu_pdev->dev, "failed to get DAI mclk1: %d\n", ret); dev_err(&cpu_pdev->dev, "failed to get DAI mclk1: %d\n", ret);
return -EINVAL; return ret;
} }
priv->audmix_pdev = audmix_pdev; priv->audmix_pdev = audmix_pdev;
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
static struct snd_pcm_hardware imx_rpmsg_pcm_hardware = { static struct snd_pcm_hardware imx_rpmsg_pcm_hardware = {
.info = SNDRV_PCM_INFO_INTERLEAVED | .info = SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_BLOCK_TRANSFER |
SNDRV_PCM_INFO_BATCH |
SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_MMAP_VALID |
SNDRV_PCM_INFO_NO_PERIOD_WAKEUP | SNDRV_PCM_INFO_NO_PERIOD_WAKEUP |
......
...@@ -89,6 +89,14 @@ static int imx_rpmsg_probe(struct platform_device *pdev) ...@@ -89,6 +89,14 @@ static int imx_rpmsg_probe(struct platform_device *pdev)
SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBC_CFC; SND_SOC_DAIFMT_CBC_CFC;
/*
* i.MX rpmsg sound cards work on codec slave mode. MCLK will be
* disabled by CPU DAI driver in hw_free(). Some codec requires MCLK
* present at power up/down sequence. So need to set ignore_pmdown_time
* to power down codec immediately before MCLK is turned off.
*/
data->dai.ignore_pmdown_time = 1;
/* Optional codec node */ /* Optional codec node */
ret = of_parse_phandle_with_fixed_args(np, "audio-codec", 0, 0, &args); ret = of_parse_phandle_with_fixed_args(np, "audio-codec", 0, 0, &args);
if (ret) { if (ret) {
......
...@@ -55,6 +55,9 @@ static int avs_create_dai_links(struct device *dev, struct hda_codec *codec, int ...@@ -55,6 +55,9 @@ static int avs_create_dai_links(struct device *dev, struct hda_codec *codec, int
return -ENOMEM; return -ENOMEM;
dl[i].codecs->name = devm_kstrdup(dev, cname, GFP_KERNEL); dl[i].codecs->name = devm_kstrdup(dev, cname, GFP_KERNEL);
if (!dl[i].codecs->name)
return -ENOMEM;
dl[i].codecs->dai_name = pcm->name; dl[i].codecs->dai_name = pcm->name;
dl[i].num_codecs = 1; dl[i].num_codecs = 1;
dl[i].num_cpus = 1; dl[i].num_cpus = 1;
......
...@@ -112,34 +112,6 @@ static int axg_spdifin_prepare(struct snd_pcm_substream *substream, ...@@ -112,34 +112,6 @@ static int axg_spdifin_prepare(struct snd_pcm_substream *substream,
return 0; return 0;
} }
static int axg_spdifin_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct axg_spdifin *priv = snd_soc_dai_get_drvdata(dai);
int ret;
ret = clk_prepare_enable(priv->refclk);
if (ret) {
dev_err(dai->dev,
"failed to enable spdifin reference clock\n");
return ret;
}
regmap_update_bits(priv->map, SPDIFIN_CTRL0, SPDIFIN_CTRL0_EN,
SPDIFIN_CTRL0_EN);
return 0;
}
static void axg_spdifin_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct axg_spdifin *priv = snd_soc_dai_get_drvdata(dai);
regmap_update_bits(priv->map, SPDIFIN_CTRL0, SPDIFIN_CTRL0_EN, 0);
clk_disable_unprepare(priv->refclk);
}
static void axg_spdifin_write_mode_param(struct regmap *map, int mode, static void axg_spdifin_write_mode_param(struct regmap *map, int mode,
unsigned int val, unsigned int val,
unsigned int num_per_reg, unsigned int num_per_reg,
...@@ -251,17 +223,32 @@ static int axg_spdifin_dai_probe(struct snd_soc_dai *dai) ...@@ -251,17 +223,32 @@ static int axg_spdifin_dai_probe(struct snd_soc_dai *dai)
ret = axg_spdifin_sample_mode_config(dai, priv); ret = axg_spdifin_sample_mode_config(dai, priv);
if (ret) { if (ret) {
dev_err(dai->dev, "mode configuration failed\n"); dev_err(dai->dev, "mode configuration failed\n");
clk_disable_unprepare(priv->pclk); goto pclk_err;
return ret;
} }
ret = clk_prepare_enable(priv->refclk);
if (ret) {
dev_err(dai->dev,
"failed to enable spdifin reference clock\n");
goto pclk_err;
}
regmap_update_bits(priv->map, SPDIFIN_CTRL0, SPDIFIN_CTRL0_EN,
SPDIFIN_CTRL0_EN);
return 0; return 0;
pclk_err:
clk_disable_unprepare(priv->pclk);
return ret;
} }
static int axg_spdifin_dai_remove(struct snd_soc_dai *dai) static int axg_spdifin_dai_remove(struct snd_soc_dai *dai)
{ {
struct axg_spdifin *priv = snd_soc_dai_get_drvdata(dai); struct axg_spdifin *priv = snd_soc_dai_get_drvdata(dai);
regmap_update_bits(priv->map, SPDIFIN_CTRL0, SPDIFIN_CTRL0_EN, 0);
clk_disable_unprepare(priv->refclk);
clk_disable_unprepare(priv->pclk); clk_disable_unprepare(priv->pclk);
return 0; return 0;
} }
...@@ -270,8 +257,6 @@ static const struct snd_soc_dai_ops axg_spdifin_ops = { ...@@ -270,8 +257,6 @@ static const struct snd_soc_dai_ops axg_spdifin_ops = {
.probe = axg_spdifin_dai_probe, .probe = axg_spdifin_dai_probe,
.remove = axg_spdifin_dai_remove, .remove = axg_spdifin_dai_remove,
.prepare = axg_spdifin_prepare, .prepare = axg_spdifin_prepare,
.startup = axg_spdifin_startup,
.shutdown = axg_spdifin_shutdown,
}; };
static int axg_spdifin_iec958_info(struct snd_kcontrol *kcontrol, static int axg_spdifin_iec958_info(struct snd_kcontrol *kcontrol,
......
...@@ -1303,6 +1303,7 @@ static int rsnd_dai_of_node(struct rsnd_priv *priv, int *is_graph) ...@@ -1303,6 +1303,7 @@ static int rsnd_dai_of_node(struct rsnd_priv *priv, int *is_graph)
if (i >= RSND_MAX_COMPONENT) { if (i >= RSND_MAX_COMPONENT) {
dev_info(dev, "reach to max component\n"); dev_info(dev, "reach to max component\n");
of_node_put(node); of_node_put(node);
of_node_put(ports);
break; break;
} }
} }
......
...@@ -985,6 +985,7 @@ static int __soc_pcm_hw_params(struct snd_soc_pcm_runtime *rtd, ...@@ -985,6 +985,7 @@ static int __soc_pcm_hw_params(struct snd_soc_pcm_runtime *rtd,
{ {
struct snd_soc_dai *cpu_dai; struct snd_soc_dai *cpu_dai;
struct snd_soc_dai *codec_dai; struct snd_soc_dai *codec_dai;
struct snd_pcm_hw_params tmp_params;
int i, ret = 0; int i, ret = 0;
snd_soc_dpcm_mutex_assert_held(rtd); snd_soc_dpcm_mutex_assert_held(rtd);
...@@ -998,7 +999,6 @@ static int __soc_pcm_hw_params(struct snd_soc_pcm_runtime *rtd, ...@@ -998,7 +999,6 @@ static int __soc_pcm_hw_params(struct snd_soc_pcm_runtime *rtd,
goto out; goto out;
for_each_rtd_codec_dais(rtd, i, codec_dai) { for_each_rtd_codec_dais(rtd, i, codec_dai) {
struct snd_pcm_hw_params codec_params;
unsigned int tdm_mask = snd_soc_dai_tdm_mask_get(codec_dai, substream->stream); unsigned int tdm_mask = snd_soc_dai_tdm_mask_get(codec_dai, substream->stream);
/* /*
...@@ -1019,23 +1019,22 @@ static int __soc_pcm_hw_params(struct snd_soc_pcm_runtime *rtd, ...@@ -1019,23 +1019,22 @@ static int __soc_pcm_hw_params(struct snd_soc_pcm_runtime *rtd,
continue; continue;
/* copy params for each codec */ /* copy params for each codec */
codec_params = *params; tmp_params = *params;
/* fixup params based on TDM slot masks */ /* fixup params based on TDM slot masks */
if (tdm_mask) if (tdm_mask)
soc_pcm_codec_params_fixup(&codec_params, tdm_mask); soc_pcm_codec_params_fixup(&tmp_params, tdm_mask);
ret = snd_soc_dai_hw_params(codec_dai, substream, ret = snd_soc_dai_hw_params(codec_dai, substream,
&codec_params); &tmp_params);
if(ret < 0) if(ret < 0)
goto out; goto out;
soc_pcm_set_dai_params(codec_dai, &codec_params); soc_pcm_set_dai_params(codec_dai, &tmp_params);
snd_soc_dapm_update_dai(substream, &codec_params, codec_dai); snd_soc_dapm_update_dai(substream, &tmp_params, codec_dai);
} }
for_each_rtd_cpu_dais(rtd, i, cpu_dai) { for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
struct snd_pcm_hw_params cpu_params;
unsigned int ch_mask = 0; unsigned int ch_mask = 0;
int j; int j;
...@@ -1047,7 +1046,7 @@ static int __soc_pcm_hw_params(struct snd_soc_pcm_runtime *rtd, ...@@ -1047,7 +1046,7 @@ static int __soc_pcm_hw_params(struct snd_soc_pcm_runtime *rtd,
continue; continue;
/* copy params for each cpu */ /* copy params for each cpu */
cpu_params = *params; tmp_params = *params;
if (!rtd->dai_link->codec_ch_maps) if (!rtd->dai_link->codec_ch_maps)
goto hw_params; goto hw_params;
...@@ -1062,16 +1061,16 @@ static int __soc_pcm_hw_params(struct snd_soc_pcm_runtime *rtd, ...@@ -1062,16 +1061,16 @@ static int __soc_pcm_hw_params(struct snd_soc_pcm_runtime *rtd,
/* fixup cpu channel number */ /* fixup cpu channel number */
if (ch_mask) if (ch_mask)
soc_pcm_codec_params_fixup(&cpu_params, ch_mask); soc_pcm_codec_params_fixup(&tmp_params, ch_mask);
hw_params: hw_params:
ret = snd_soc_dai_hw_params(cpu_dai, substream, &cpu_params); ret = snd_soc_dai_hw_params(cpu_dai, substream, &tmp_params);
if (ret < 0) if (ret < 0)
goto out; goto out;
/* store the parameters for each DAI */ /* store the parameters for each DAI */
soc_pcm_set_dai_params(cpu_dai, &cpu_params); soc_pcm_set_dai_params(cpu_dai, &tmp_params);
snd_soc_dapm_update_dai(substream, &cpu_params, cpu_dai); snd_soc_dapm_update_dai(substream, &tmp_params, cpu_dai);
} }
ret = snd_soc_pcm_component_hw_params(substream, params); ret = snd_soc_pcm_component_hw_params(substream, params);
......
...@@ -217,6 +217,7 @@ int snd_soc_dai_is_dummy(struct snd_soc_dai *dai) ...@@ -217,6 +217,7 @@ int snd_soc_dai_is_dummy(struct snd_soc_dai *dai)
return 1; return 1;
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(snd_soc_dai_is_dummy);
int snd_soc_component_is_dummy(struct snd_soc_component *component) int snd_soc_component_is_dummy(struct snd_soc_component *component)
{ {
......
...@@ -486,10 +486,9 @@ int snd_sof_device_remove(struct device *dev) ...@@ -486,10 +486,9 @@ int snd_sof_device_remove(struct device *dev)
snd_sof_ipc_free(sdev); snd_sof_ipc_free(sdev);
snd_sof_free_debug(sdev); snd_sof_free_debug(sdev);
snd_sof_remove(sdev); snd_sof_remove(sdev);
sof_ops_free(sdev);
} }
sof_ops_free(sdev);
/* release firmware */ /* release firmware */
snd_sof_fw_unload(sdev); snd_sof_fw_unload(sdev);
......
...@@ -460,7 +460,7 @@ int mtl_dsp_cl_init(struct snd_sof_dev *sdev, int stream_tag, bool imr_boot) ...@@ -460,7 +460,7 @@ int mtl_dsp_cl_init(struct snd_sof_dev *sdev, int stream_tag, bool imr_boot)
/* step 3: wait for IPC DONE bit from ROM */ /* step 3: wait for IPC DONE bit from ROM */
ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, chip->ipc_ack, status, ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, chip->ipc_ack, status,
((status & chip->ipc_ack_mask) == chip->ipc_ack_mask), ((status & chip->ipc_ack_mask) == chip->ipc_ack_mask),
HDA_DSP_REG_POLL_INTERVAL_US, MTL_DSP_PURGE_TIMEOUT_US); HDA_DSP_REG_POLL_INTERVAL_US, HDA_DSP_INIT_TIMEOUT_US);
if (ret < 0) { if (ret < 0) {
if (hda->boot_iteration == HDA_FW_BOOT_ATTEMPTS) if (hda->boot_iteration == HDA_FW_BOOT_ATTEMPTS)
dev_err(sdev->dev, "timeout waiting for purge IPC done\n"); dev_err(sdev->dev, "timeout waiting for purge IPC done\n");
......
...@@ -62,7 +62,6 @@ ...@@ -62,7 +62,6 @@
#define MTL_DSP_IRQSTS_IPC BIT(0) #define MTL_DSP_IRQSTS_IPC BIT(0)
#define MTL_DSP_IRQSTS_SDW BIT(6) #define MTL_DSP_IRQSTS_SDW BIT(6)
#define MTL_DSP_PURGE_TIMEOUT_US 20000000 /* 20s */
#define MTL_DSP_REG_POLL_INTERVAL_US 10 /* 10 us */ #define MTL_DSP_REG_POLL_INTERVAL_US 10 /* 10 us */
/* Memory windows */ /* Memory windows */
......
...@@ -231,7 +231,7 @@ static int sof_ipc4_get_audio_fmt(struct snd_soc_component *scomp, ...@@ -231,7 +231,7 @@ static int sof_ipc4_get_audio_fmt(struct snd_soc_component *scomp,
ret = sof_update_ipc_object(scomp, available_fmt, ret = sof_update_ipc_object(scomp, available_fmt,
SOF_AUDIO_FMT_NUM_TOKENS, swidget->tuples, SOF_AUDIO_FMT_NUM_TOKENS, swidget->tuples,
swidget->num_tuples, sizeof(available_fmt), 1); swidget->num_tuples, sizeof(*available_fmt), 1);
if (ret) { if (ret) {
dev_err(scomp->dev, "Failed to parse audio format token count\n"); dev_err(scomp->dev, "Failed to parse audio format token count\n");
return ret; return ret;
......
...@@ -212,7 +212,8 @@ static int sof_widget_setup_unlocked(struct snd_sof_dev *sdev, ...@@ -212,7 +212,8 @@ static int sof_widget_setup_unlocked(struct snd_sof_dev *sdev,
sof_widget_free_unlocked(sdev, swidget); sof_widget_free_unlocked(sdev, swidget);
use_count_decremented = true; use_count_decremented = true;
core_put: core_put:
snd_sof_dsp_core_put(sdev, swidget->core); if (!use_count_decremented)
snd_sof_dsp_core_put(sdev, swidget->core);
pipe_widget_free: pipe_widget_free:
if (swidget->id != snd_soc_dapm_scheduler) if (swidget->id != snd_soc_dapm_scheduler)
sof_widget_free_unlocked(sdev, swidget->spipe->pipe_widget); sof_widget_free_unlocked(sdev, swidget->spipe->pipe_widget);
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <sound/graph_card.h> #include <sound/graph_card.h>
#include <sound/pcm_params.h> #include <sound/pcm_params.h>
#include <sound/soc-dai.h>
#define MAX_PLLA_OUT0_DIV 128 #define MAX_PLLA_OUT0_DIV 128
...@@ -44,6 +45,21 @@ struct tegra_audio_cdata { ...@@ -44,6 +45,21 @@ struct tegra_audio_cdata {
unsigned int plla_out0_rates[NUM_RATE_TYPE]; unsigned int plla_out0_rates[NUM_RATE_TYPE];
}; };
static bool need_clk_update(struct snd_soc_dai *dai)
{
if (snd_soc_dai_is_dummy(dai) ||
!dai->driver->ops ||
!dai->driver->name)
return false;
if (strstr(dai->driver->name, "I2S") ||
strstr(dai->driver->name, "DMIC") ||
strstr(dai->driver->name, "DSPK"))
return true;
return false;
}
/* Setup PLL clock as per the given sample rate */ /* Setup PLL clock as per the given sample rate */
static int tegra_audio_graph_update_pll(struct snd_pcm_substream *substream, static int tegra_audio_graph_update_pll(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params) struct snd_pcm_hw_params *params)
...@@ -140,19 +156,7 @@ static int tegra_audio_graph_hw_params(struct snd_pcm_substream *substream, ...@@ -140,19 +156,7 @@ static int tegra_audio_graph_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
int err; int err;
/* if (need_clk_update(cpu_dai)) {
* This gets called for each DAI link (FE or BE) when DPCM is used.
* We may not want to update PLLA rate for each call. So PLLA update
* must be restricted to external I/O links (I2S, DMIC or DSPK) since
* they actually depend on it. I/O modules update their clocks in
* hw_param() of their respective component driver and PLLA rate
* update here helps them to derive appropriate rates.
*
* TODO: When more HW accelerators get added (like sample rate
* converter, volume gain controller etc., which don't really
* depend on PLLA) we need a better way to filter here.
*/
if (cpu_dai->driver->ops && rtd->dai_link->no_pcm) {
err = tegra_audio_graph_update_pll(substream, params); err = tegra_audio_graph_update_pll(substream, params);
if (err) if (err)
return err; return err;
......
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