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. -----BEGIN PGP SIGNATURE----- iQEzBAABCgAdFiEEreZoqmdXGLWf4p/qJNaLcl1Uh9AFAmUK6tUACgkQJNaLcl1U h9CF5Af+IhyN4/WaqDOl6hgKJr206SDHkiW5SAq+cRMsTGWLzM32MXDYxHg21Lke hD6weld3cjvN/yqPOxLGS6+Sf5S6BXIdSmTrjVKyrRag6qn+ArzzO2sQpOWdeYs3 SJAa36Ias/Mz8IPNOZpoQLdF8p7ncXYqUyqnx579pPMO5P2IeLSf0MbBdAxxrw8V Q0OOulaLxwKaDx2ss0mL4KAnfbgYe8e9c0xYhyBCNElAU/m+FCWazslXF5tOWkjI vZFmqJ1jBsCXLctWnCceER4A/nTK2m8WIJ6ep97cuD2dhVuzJxY3BmhN+aL2zgDQ dvl5f8gv8PhYX2aM8gCXP5SE+Lczvg== =MePv -----END PGP SIGNATURE----- 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.
This commit is contained in:
Коммит
0eb0e272e4
|
@ -1863,15 +1863,15 @@ static int cs_dsp_adsp2_setup_algs(struct cs_dsp *dsp)
|
|||
return PTR_ERR(adsp2_alg);
|
||||
|
||||
for (i = 0; i < n_algs; i++) {
|
||||
cs_dsp_info(dsp,
|
||||
"%d: ID %x v%d.%d.%d XM@%x YM@%x ZM@%x\n",
|
||||
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) & 0xff00) >> 8,
|
||||
be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff,
|
||||
be32_to_cpu(adsp2_alg[i].xm),
|
||||
be32_to_cpu(adsp2_alg[i].ym),
|
||||
be32_to_cpu(adsp2_alg[i].zm));
|
||||
cs_dsp_dbg(dsp,
|
||||
"%d: ID %x v%d.%d.%d XM@%x YM@%x ZM@%x\n",
|
||||
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) & 0xff00) >> 8,
|
||||
be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff,
|
||||
be32_to_cpu(adsp2_alg[i].xm),
|
||||
be32_to_cpu(adsp2_alg[i].ym),
|
||||
be32_to_cpu(adsp2_alg[i].zm));
|
||||
|
||||
alg_region = cs_dsp_create_region(dsp, WMFW_ADSP2_XM,
|
||||
adsp2_alg[i].alg.id,
|
||||
|
@ -1996,14 +1996,14 @@ static int cs_dsp_halo_setup_algs(struct cs_dsp *dsp)
|
|||
return PTR_ERR(halo_alg);
|
||||
|
||||
for (i = 0; i < n_algs; i++) {
|
||||
cs_dsp_info(dsp,
|
||||
"%d: ID %x v%d.%d.%d XM@%x YM@%x\n",
|
||||
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) & 0xff00) >> 8,
|
||||
be32_to_cpu(halo_alg[i].alg.ver) & 0xff,
|
||||
be32_to_cpu(halo_alg[i].xm_base),
|
||||
be32_to_cpu(halo_alg[i].ym_base));
|
||||
cs_dsp_dbg(dsp,
|
||||
"%d: ID %x v%d.%d.%d XM@%x YM@%x\n",
|
||||
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) & 0xff00) >> 8,
|
||||
be32_to_cpu(halo_alg[i].alg.ver) & 0xff,
|
||||
be32_to_cpu(halo_alg[i].xm_base),
|
||||
be32_to_cpu(halo_alg[i].ym_base));
|
||||
|
||||
ret = cs_dsp_halo_create_regions(dsp, halo_alg[i].alg.id,
|
||||
halo_alg[i].alg.ver,
|
||||
|
|
|
@ -213,6 +213,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
|
|||
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,
|
||||
.matches = {
|
||||
|
@ -220,6 +227,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
|
|||
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,
|
||||
.matches = {
|
||||
|
@ -262,6 +276,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
|
|||
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,
|
||||
.matches = {
|
||||
|
|
|
@ -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) ||
|
||||
(aw_bin->header_info[0].bin_data_type != DATA_TYPE_REGISTER)) {
|
||||
dev_err(aw_dev->dev, "bin num or type error");
|
||||
ret = -EINVAL;
|
||||
goto parse_bin_failed;
|
||||
}
|
||||
|
||||
if (aw_bin->header_info[0].valid_data_len % 4) {
|
||||
dev_err(aw_dev->dev, "bin data len get error!");
|
||||
ret = -EINVAL;
|
||||
goto parse_bin_failed;
|
||||
}
|
||||
|
||||
|
|
|
@ -27,7 +27,6 @@ static int cs35l56_i2c_probe(struct i2c_client *client)
|
|||
return -ENOMEM;
|
||||
|
||||
cs35l56->base.dev = dev;
|
||||
cs35l56->base.can_hibernate = true;
|
||||
|
||||
i2c_set_clientdata(client, cs35l56);
|
||||
cs35l56->base.regmap = devm_regmap_init_i2c(client, regmap_config);
|
||||
|
|
|
@ -1207,6 +1207,7 @@ void cs35l56_remove(struct cs35l56_private *cs35l56)
|
|||
flush_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_disable(cs35l56->base.dev);
|
||||
|
||||
|
|
|
@ -344,6 +344,16 @@ static int cs42l42_sdw_update_status(struct sdw_slave *peripheral,
|
|||
switch (status) {
|
||||
case SDW_SLAVE_ATTACHED:
|
||||
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.
|
||||
* 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,
|
|||
break;
|
||||
case SDW_SLAVE_UNATTACHED:
|
||||
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;
|
||||
default:
|
||||
break;
|
||||
|
|
|
@ -2320,7 +2320,26 @@ int cs42l42_common_probe(struct cs42l42_private *cs42l42,
|
|||
|
||||
if (cs42l42->reset_gpio) {
|
||||
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);
|
||||
|
||||
|
|
|
@ -53,6 +53,7 @@ struct cs42l42_private {
|
|||
u8 stream_use;
|
||||
bool hp_adc_up_pending;
|
||||
bool suspended;
|
||||
bool sdw_waiting_first_unattach;
|
||||
bool init_done;
|
||||
};
|
||||
|
||||
|
|
|
@ -2077,7 +2077,8 @@ static const struct cs42l43_irq cs42l43_irqs[] = {
|
|||
|
||||
static int cs42l43_request_irq(struct cs42l43_codec *priv,
|
||||
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;
|
||||
|
||||
|
@ -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);
|
||||
|
||||
ret = devm_request_threaded_irq(priv->dev, ret, NULL, handler, IRQF_ONESHOT,
|
||||
name, priv);
|
||||
ret = devm_request_threaded_irq(priv->dev, ret, NULL, handler,
|
||||
IRQF_ONESHOT | flags, name, priv);
|
||||
if (ret)
|
||||
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,
|
|||
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)
|
||||
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)
|
||||
|
@ -2178,7 +2179,8 @@ static int cs42l43_codec_probe(struct platform_device *pdev)
|
|||
|
||||
for (i = 0; i < ARRAY_SIZE(cs42l43_irqs); i++) {
|
||||
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)
|
||||
goto err_pm;
|
||||
}
|
||||
|
|
|
@ -2403,13 +2403,11 @@ static irqreturn_t rt5640_irq(int irq, void *data)
|
|||
struct rt5640_priv *rt5640 = data;
|
||||
int delay = 0;
|
||||
|
||||
if (rt5640->jd_src == RT5640_JD_SRC_HDA_HEADER) {
|
||||
cancel_delayed_work_sync(&rt5640->jack_work);
|
||||
if (rt5640->jd_src == RT5640_JD_SRC_HDA_HEADER)
|
||||
delay = 100;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -2565,10 +2563,9 @@ static void rt5640_enable_jack_detect(struct snd_soc_component *component,
|
|||
if (jack_data && jack_data->use_platform_clock)
|
||||
rt5640->use_platform_clock = jack_data->use_platform_clock;
|
||||
|
||||
ret = devm_request_threaded_irq(component->dev, rt5640->irq,
|
||||
NULL, rt5640_irq,
|
||||
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
|
||||
"rt5640", rt5640);
|
||||
ret = request_irq(rt5640->irq, rt5640_irq,
|
||||
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
|
||||
"rt5640", rt5640);
|
||||
if (ret) {
|
||||
dev_warn(component->dev, "Failed to request IRQ %d: %d\n", rt5640->irq, ret);
|
||||
rt5640_disable_jack_detect(component);
|
||||
|
@ -2621,14 +2618,14 @@ static void rt5640_enable_hda_jack_detect(
|
|||
|
||||
rt5640->jack = jack;
|
||||
|
||||
ret = devm_request_threaded_irq(component->dev, rt5640->irq,
|
||||
NULL, rt5640_irq, IRQF_TRIGGER_RISING | IRQF_ONESHOT,
|
||||
"rt5640", rt5640);
|
||||
ret = request_irq(rt5640->irq, rt5640_irq,
|
||||
IRQF_TRIGGER_RISING | IRQF_ONESHOT, "rt5640", rt5640);
|
||||
if (ret) {
|
||||
dev_warn(component->dev, "Failed to request IRQ %d: %d\n", rt5640->irq, ret);
|
||||
rt5640->irq = -ENXIO;
|
||||
rt5640->jack = NULL;
|
||||
return;
|
||||
}
|
||||
rt5640->irq_requested = true;
|
||||
|
||||
/* sync initial jack state */
|
||||
queue_delayed_work(system_long_wq, &rt5640->jack_work, 0);
|
||||
|
@ -2801,12 +2798,12 @@ static int rt5640_suspend(struct snd_soc_component *component)
|
|||
{
|
||||
struct rt5640_priv *rt5640 = snd_soc_component_get_drvdata(component);
|
||||
|
||||
if (rt5640->irq) {
|
||||
if (rt5640->jack) {
|
||||
/* disable jack interrupts during system suspend */
|
||||
disable_irq(rt5640->irq);
|
||||
rt5640_cancel_work(rt5640);
|
||||
}
|
||||
|
||||
rt5640_cancel_work(rt5640);
|
||||
snd_soc_component_force_bias_level(component, SND_SOC_BIAS_OFF);
|
||||
rt5640_reset(component);
|
||||
regcache_cache_only(rt5640->regmap, true);
|
||||
|
@ -2829,9 +2826,6 @@ static int rt5640_resume(struct snd_soc_component *component)
|
|||
regcache_cache_only(rt5640->regmap, false);
|
||||
regcache_sync(rt5640->regmap);
|
||||
|
||||
if (rt5640->irq)
|
||||
enable_irq(rt5640->irq);
|
||||
|
||||
if (rt5640->jack) {
|
||||
if (rt5640->jd_src == RT5640_JD_SRC_HDA_HEADER) {
|
||||
snd_soc_component_update_bits(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);
|
||||
}
|
||||
|
||||
|
|
|
@ -1468,8 +1468,10 @@ static int wm8960_i2c_probe(struct i2c_client *i2c)
|
|||
}
|
||||
|
||||
wm8960->regmap = devm_regmap_init_i2c(i2c, &wm8960_regmap);
|
||||
if (IS_ERR(wm8960->regmap))
|
||||
return PTR_ERR(wm8960->regmap);
|
||||
if (IS_ERR(wm8960->regmap)) {
|
||||
ret = PTR_ERR(wm8960->regmap);
|
||||
goto bulk_disable;
|
||||
}
|
||||
|
||||
if (pdata)
|
||||
memcpy(&wm8960->pdata, pdata, sizeof(struct wm8960_data));
|
||||
|
@ -1479,13 +1481,14 @@ static int wm8960_i2c_probe(struct i2c_client *i2c)
|
|||
ret = i2c_master_recv(i2c, &val, sizeof(val));
|
||||
if (ret >= 0) {
|
||||
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);
|
||||
if (ret != 0) {
|
||||
dev_err(&i2c->dev, "Failed to issue reset\n");
|
||||
return ret;
|
||||
goto bulk_disable;
|
||||
}
|
||||
|
||||
if (wm8960->pdata.shared_lrclk) {
|
||||
|
@ -1494,7 +1497,7 @@ static int wm8960_i2c_probe(struct i2c_client *i2c)
|
|||
if (ret != 0) {
|
||||
dev_err(&i2c->dev, "Failed to enable LRCM: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
goto bulk_disable;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1528,7 +1531,13 @@ static int wm8960_i2c_probe(struct i2c_client *i2c)
|
|||
|
||||
ret = devm_snd_soc_register_component(&i2c->dev,
|
||||
&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;
|
||||
}
|
||||
|
||||
|
|
|
@ -687,7 +687,10 @@ int wm_adsp_write_ctl(struct wm_adsp *dsp, const char *name, int type,
|
|||
struct wm_coeff_ctl *ctl;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&dsp->cs_dsp.pwr_lock);
|
||||
ret = cs_dsp_coeff_write_ctrl(cs_ctl, 0, buf, len);
|
||||
mutex_unlock(&dsp->cs_dsp.pwr_lock);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
@ -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,
|
||||
unsigned int alg, void *buf, size_t len)
|
||||
{
|
||||
return cs_dsp_coeff_read_ctrl(cs_dsp_get_ctl(&dsp->cs_dsp, name, type, alg),
|
||||
0, buf, len);
|
||||
int ret;
|
||||
|
||||
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);
|
||||
|
||||
|
|
|
@ -315,7 +315,7 @@ static int imx_audmix_probe(struct platform_device *pdev)
|
|||
if (IS_ERR(priv->cpu_mclk)) {
|
||||
ret = PTR_ERR(priv->cpu_mclk);
|
||||
dev_err(&cpu_pdev->dev, "failed to get DAI mclk1: %d\n", ret);
|
||||
return -EINVAL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
priv->audmix_pdev = audmix_pdev;
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
static struct snd_pcm_hardware imx_rpmsg_pcm_hardware = {
|
||||
.info = SNDRV_PCM_INFO_INTERLEAVED |
|
||||
SNDRV_PCM_INFO_BLOCK_TRANSFER |
|
||||
SNDRV_PCM_INFO_BATCH |
|
||||
SNDRV_PCM_INFO_MMAP |
|
||||
SNDRV_PCM_INFO_MMAP_VALID |
|
||||
SNDRV_PCM_INFO_NO_PERIOD_WAKEUP |
|
||||
|
|
|
@ -89,6 +89,14 @@ static int imx_rpmsg_probe(struct platform_device *pdev)
|
|||
SND_SOC_DAIFMT_NB_NF |
|
||||
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 */
|
||||
ret = of_parse_phandle_with_fixed_args(np, "audio-codec", 0, 0, &args);
|
||||
if (ret) {
|
||||
|
|
|
@ -55,6 +55,9 @@ static int avs_create_dai_links(struct device *dev, struct hda_codec *codec, int
|
|||
return -ENOMEM;
|
||||
|
||||
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].num_codecs = 1;
|
||||
dl[i].num_cpus = 1;
|
||||
|
|
|
@ -112,34 +112,6 @@ static int axg_spdifin_prepare(struct snd_pcm_substream *substream,
|
|||
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,
|
||||
unsigned int val,
|
||||
unsigned int num_per_reg,
|
||||
|
@ -251,17 +223,32 @@ static int axg_spdifin_dai_probe(struct snd_soc_dai *dai)
|
|||
ret = axg_spdifin_sample_mode_config(dai, priv);
|
||||
if (ret) {
|
||||
dev_err(dai->dev, "mode configuration failed\n");
|
||||
clk_disable_unprepare(priv->pclk);
|
||||
return ret;
|
||||
goto pclk_err;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
pclk_err:
|
||||
clk_disable_unprepare(priv->pclk);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int axg_spdifin_dai_remove(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);
|
||||
clk_disable_unprepare(priv->pclk);
|
||||
return 0;
|
||||
}
|
||||
|
@ -270,8 +257,6 @@ static const struct snd_soc_dai_ops axg_spdifin_ops = {
|
|||
.probe = axg_spdifin_dai_probe,
|
||||
.remove = axg_spdifin_dai_remove,
|
||||
.prepare = axg_spdifin_prepare,
|
||||
.startup = axg_spdifin_startup,
|
||||
.shutdown = axg_spdifin_shutdown,
|
||||
};
|
||||
|
||||
static int axg_spdifin_iec958_info(struct snd_kcontrol *kcontrol,
|
||||
|
|
|
@ -1303,6 +1303,7 @@ audio_graph:
|
|||
if (i >= RSND_MAX_COMPONENT) {
|
||||
dev_info(dev, "reach to max component\n");
|
||||
of_node_put(node);
|
||||
of_node_put(ports);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 *codec_dai;
|
||||
struct snd_pcm_hw_params tmp_params;
|
||||
int i, ret = 0;
|
||||
|
||||
snd_soc_dpcm_mutex_assert_held(rtd);
|
||||
|
@ -998,7 +999,6 @@ static int __soc_pcm_hw_params(struct snd_soc_pcm_runtime *rtd,
|
|||
goto out;
|
||||
|
||||
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);
|
||||
|
||||
/*
|
||||
|
@ -1019,23 +1019,22 @@ static int __soc_pcm_hw_params(struct snd_soc_pcm_runtime *rtd,
|
|||
continue;
|
||||
|
||||
/* copy params for each codec */
|
||||
codec_params = *params;
|
||||
tmp_params = *params;
|
||||
|
||||
/* fixup params based on TDM slot masks */
|
||||
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,
|
||||
&codec_params);
|
||||
&tmp_params);
|
||||
if(ret < 0)
|
||||
goto out;
|
||||
|
||||
soc_pcm_set_dai_params(codec_dai, &codec_params);
|
||||
snd_soc_dapm_update_dai(substream, &codec_params, codec_dai);
|
||||
soc_pcm_set_dai_params(codec_dai, &tmp_params);
|
||||
snd_soc_dapm_update_dai(substream, &tmp_params, codec_dai);
|
||||
}
|
||||
|
||||
for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
|
||||
struct snd_pcm_hw_params cpu_params;
|
||||
unsigned int ch_mask = 0;
|
||||
int j;
|
||||
|
||||
|
@ -1047,7 +1046,7 @@ static int __soc_pcm_hw_params(struct snd_soc_pcm_runtime *rtd,
|
|||
continue;
|
||||
|
||||
/* copy params for each cpu */
|
||||
cpu_params = *params;
|
||||
tmp_params = *params;
|
||||
|
||||
if (!rtd->dai_link->codec_ch_maps)
|
||||
goto hw_params;
|
||||
|
@ -1062,16 +1061,16 @@ static int __soc_pcm_hw_params(struct snd_soc_pcm_runtime *rtd,
|
|||
|
||||
/* fixup cpu channel number */
|
||||
if (ch_mask)
|
||||
soc_pcm_codec_params_fixup(&cpu_params, ch_mask);
|
||||
soc_pcm_codec_params_fixup(&tmp_params, ch_mask);
|
||||
|
||||
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)
|
||||
goto out;
|
||||
|
||||
/* store the parameters for each DAI */
|
||||
soc_pcm_set_dai_params(cpu_dai, &cpu_params);
|
||||
snd_soc_dapm_update_dai(substream, &cpu_params, cpu_dai);
|
||||
soc_pcm_set_dai_params(cpu_dai, &tmp_params);
|
||||
snd_soc_dapm_update_dai(substream, &tmp_params, cpu_dai);
|
||||
}
|
||||
|
||||
ret = snd_soc_pcm_component_hw_params(substream, params);
|
||||
|
|
|
@ -217,6 +217,7 @@ int snd_soc_dai_is_dummy(struct snd_soc_dai *dai)
|
|||
return 1;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_soc_dai_is_dummy);
|
||||
|
||||
int snd_soc_component_is_dummy(struct snd_soc_component *component)
|
||||
{
|
||||
|
|
|
@ -486,10 +486,9 @@ int snd_sof_device_remove(struct device *dev)
|
|||
snd_sof_ipc_free(sdev);
|
||||
snd_sof_free_debug(sdev);
|
||||
snd_sof_remove(sdev);
|
||||
sof_ops_free(sdev);
|
||||
}
|
||||
|
||||
sof_ops_free(sdev);
|
||||
|
||||
/* release firmware */
|
||||
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)
|
|||
/* step 3: wait for IPC DONE bit from ROM */
|
||||
ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, chip->ipc_ack, status,
|
||||
((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 (hda->boot_iteration == HDA_FW_BOOT_ATTEMPTS)
|
||||
dev_err(sdev->dev, "timeout waiting for purge IPC done\n");
|
||||
|
|
|
@ -62,7 +62,6 @@
|
|||
#define MTL_DSP_IRQSTS_IPC BIT(0)
|
||||
#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 */
|
||||
|
||||
/* Memory windows */
|
||||
|
|
|
@ -231,7 +231,7 @@ static int sof_ipc4_get_audio_fmt(struct snd_soc_component *scomp,
|
|||
|
||||
ret = sof_update_ipc_object(scomp, available_fmt,
|
||||
SOF_AUDIO_FMT_NUM_TOKENS, swidget->tuples,
|
||||
swidget->num_tuples, sizeof(available_fmt), 1);
|
||||
swidget->num_tuples, sizeof(*available_fmt), 1);
|
||||
if (ret) {
|
||||
dev_err(scomp->dev, "Failed to parse audio format token count\n");
|
||||
return ret;
|
||||
|
|
|
@ -212,7 +212,8 @@ widget_free:
|
|||
sof_widget_free_unlocked(sdev, swidget);
|
||||
use_count_decremented = true;
|
||||
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:
|
||||
if (swidget->id != snd_soc_dapm_scheduler)
|
||||
sof_widget_free_unlocked(sdev, swidget->spipe->pipe_widget);
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include <linux/platform_device.h>
|
||||
#include <sound/graph_card.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/soc-dai.h>
|
||||
|
||||
#define MAX_PLLA_OUT0_DIV 128
|
||||
|
||||
|
@ -44,6 +45,21 @@ struct tegra_audio_cdata {
|
|||
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 */
|
||||
static int tegra_audio_graph_update_pll(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params)
|
||||
|
@ -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);
|
||||
int err;
|
||||
|
||||
/*
|
||||
* 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) {
|
||||
if (need_clk_update(cpu_dai)) {
|
||||
err = tegra_audio_graph_update_pll(substream, params);
|
||||
if (err)
|
||||
return err;
|
||||
|
|
Загрузка…
Ссылка в новой задаче