mirror of
https://kernel.googlesource.com/pub/scm/linux/kernel/git/torvalds/linux
synced 2025-09-15 09:07:11 +10:00
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:
commit
0eb0e272e4
@ -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)
|
|||||||
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[] = {
|
|||||||
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[] = {
|
|||||||
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[] = {
|
|||||||
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,
|
|||||||
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)
|
|||||||
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)
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
|
|
||||||
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 {
|
|||||||
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[] = {
|
|||||||
|
|
||||||
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,
|
|||||||
|
|
||||||
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,
|
|||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
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,
|
|||||||
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(
|
|||||||
|
|
||||||
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)
|
|||||||
{
|
{
|
||||||
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)
|
|||||||
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)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
|||||||
}
|
}
|
||||||
|
|
||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
|
|
||||||
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,
|
|||||||
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);
|
|||||||
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)
|
|||||||
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 @@
|
|||||||
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)
|
|||||||
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
|
|||||||
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,
|
|||||||
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)
|
|||||||
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 = {
|
|||||||
.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 @@ audio_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,
|
|||||||
{
|
{
|
||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
|
|
||||||
/* 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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
/* 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 @@
|
|||||||
#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,
|
|||||||
|
|
||||||
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 @@ widget_free:
|
|||||||
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 @@
|
|||||||
#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 {
|
|||||||
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,
|
|||||||
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;
|
||||||
|
Loading…
Reference in New Issue
Block a user