Commit 6bf5f9a8 authored by Takashi Iwai's avatar Takashi Iwai

Merge tag 'asoc-v6.2-3' of...

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

ASoC: Updates for v6.2

Some more small fixes and board quirks that came in since my last
update, the main one being the fixes from Kai for issues around the
attempts to get kexec working well on SOF based systems.
parents fd28941c a12a383e
...@@ -253,7 +253,7 @@ MODULE_DEVICE_TABLE(of, lochnagar_of_match); ...@@ -253,7 +253,7 @@ MODULE_DEVICE_TABLE(of, lochnagar_of_match);
static struct platform_driver lochnagar_sc_codec_driver = { static struct platform_driver lochnagar_sc_codec_driver = {
.driver = { .driver = {
.name = "lochnagar-soundcard", .name = "lochnagar-soundcard",
.of_match_table = of_match_ptr(lochnagar_of_match), .of_match_table = lochnagar_of_match,
}, },
.probe = lochnagar_sc_probe, .probe = lochnagar_sc_probe,
......
...@@ -3311,8 +3311,6 @@ static int rt5670_i2c_probe(struct i2c_client *i2c) ...@@ -3311,8 +3311,6 @@ static int rt5670_i2c_probe(struct i2c_client *i2c)
if (ret < 0) if (ret < 0)
goto err; goto err;
pm_runtime_put(&i2c->dev);
return 0; return 0;
err: err:
pm_runtime_disable(&i2c->dev); pm_runtime_disable(&i2c->dev);
......
...@@ -3853,7 +3853,12 @@ static irqreturn_t wm1811_jackdet_irq(int irq, void *data) ...@@ -3853,7 +3853,12 @@ static irqreturn_t wm1811_jackdet_irq(int irq, void *data)
} else { } else {
dev_dbg(component->dev, "Jack not detected\n"); dev_dbg(component->dev, "Jack not detected\n");
/* Release wm8994->accdet_lock to avoid deadlock:
* cancel_delayed_work_sync() takes wm8994->mic_work internal
* lock and wm1811_mic_work takes wm8994->accdet_lock */
mutex_unlock(&wm8994->accdet_lock);
cancel_delayed_work_sync(&wm8994->mic_work); cancel_delayed_work_sync(&wm8994->mic_work);
mutex_lock(&wm8994->accdet_lock);
snd_soc_component_update_bits(component, WM8958_MICBIAS2, snd_soc_component_update_bits(component, WM8958_MICBIAS2,
WM8958_MICB2_DISCH, WM8958_MICB2_DISCH); WM8958_MICB2_DISCH, WM8958_MICB2_DISCH);
......
...@@ -570,6 +570,21 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = { ...@@ -570,6 +570,21 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = {
BYT_RT5640_SSP0_AIF1 | BYT_RT5640_SSP0_AIF1 |
BYT_RT5640_MCLK_EN), BYT_RT5640_MCLK_EN),
}, },
{
/* Advantech MICA-071 */
.matches = {
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Advantech"),
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "MICA-071"),
},
/* OVCD Th = 1500uA to reliable detect head-phones vs -set */
.driver_data = (void *)(BYT_RT5640_IN3_MAP |
BYT_RT5640_JD_SRC_JD2_IN4N |
BYT_RT5640_OVCD_TH_1500UA |
BYT_RT5640_OVCD_SF_0P75 |
BYT_RT5640_MONO_SPEAKER |
BYT_RT5640_DIFF_MIC |
BYT_RT5640_MCLK_EN),
},
{ {
.matches = { .matches = {
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ARCHOS"), DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ARCHOS"),
...@@ -796,6 +811,16 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = { ...@@ -796,6 +811,16 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = {
BYT_RT5640_SSP0_AIF1 | BYT_RT5640_SSP0_AIF1 |
BYT_RT5640_MCLK_EN), BYT_RT5640_MCLK_EN),
}, },
{ /* HP Stream 8 */
.matches = {
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "HP Stream 8 Tablet"),
},
.driver_data = (void *)(BYTCR_INPUT_DEFAULTS |
BYT_RT5640_JD_NOT_INV |
BYT_RT5640_SSP0_AIF1 |
BYT_RT5640_MCLK_EN),
},
{ /* I.T.Works TW891 */ { /* I.T.Works TW891 */
.matches = { .matches = {
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "To be filled by O.E.M."), DMI_EXACT_MATCH(DMI_SYS_VENDOR, "To be filled by O.E.M."),
......
...@@ -112,7 +112,7 @@ static const struct snd_soc_acpi_adr_device rt1316_1_group2_adr[] = { ...@@ -112,7 +112,7 @@ static const struct snd_soc_acpi_adr_device rt1316_1_group2_adr[] = {
static const struct snd_soc_acpi_adr_device rt1318_1_group1_adr[] = { static const struct snd_soc_acpi_adr_device rt1318_1_group1_adr[] = {
{ {
.adr = 0x000131025D131801ull, .adr = 0x000132025D131801ull,
.num_endpoints = 1, .num_endpoints = 1,
.endpoints = &spk_l_endpoint, .endpoints = &spk_l_endpoint,
.name_prefix = "rt1318-1" .name_prefix = "rt1318-1"
......
...@@ -633,6 +633,32 @@ static const struct snd_soc_ops mt8195_rt1011_etdm_ops = { ...@@ -633,6 +633,32 @@ static const struct snd_soc_ops mt8195_rt1011_etdm_ops = {
.hw_params = mt8195_rt1011_etdm_hw_params, .hw_params = mt8195_rt1011_etdm_hw_params,
}; };
static int mt8195_sof_be_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
struct snd_soc_component *cmpnt_afe = NULL;
struct snd_soc_pcm_runtime *runtime;
/* find afe component */
for_each_card_rtds(rtd->card, runtime) {
cmpnt_afe = snd_soc_rtdcom_lookup(runtime, AFE_PCM_NAME);
if (cmpnt_afe)
break;
}
if (cmpnt_afe && !pm_runtime_active(cmpnt_afe->dev)) {
dev_err(rtd->dev, "afe pm runtime is not active!!\n");
return -EINVAL;
}
return 0;
}
static const struct snd_soc_ops mt8195_sof_be_ops = {
.hw_params = mt8195_sof_be_hw_params,
};
static int mt8195_rt1011_init(struct snd_soc_pcm_runtime *rtd) static int mt8195_rt1011_init(struct snd_soc_pcm_runtime *rtd)
{ {
struct snd_soc_card *card = rtd->card; struct snd_soc_card *card = rtd->card;
...@@ -1272,24 +1298,28 @@ static struct snd_soc_dai_link mt8195_mt6359_dai_links[] = { ...@@ -1272,24 +1298,28 @@ static struct snd_soc_dai_link mt8195_mt6359_dai_links[] = {
.name = "AFE_SOF_DL2", .name = "AFE_SOF_DL2",
.no_pcm = 1, .no_pcm = 1,
.dpcm_playback = 1, .dpcm_playback = 1,
.ops = &mt8195_sof_be_ops,
SND_SOC_DAILINK_REG(AFE_SOF_DL2), SND_SOC_DAILINK_REG(AFE_SOF_DL2),
}, },
[DAI_LINK_SOF_DL3_BE] = { [DAI_LINK_SOF_DL3_BE] = {
.name = "AFE_SOF_DL3", .name = "AFE_SOF_DL3",
.no_pcm = 1, .no_pcm = 1,
.dpcm_playback = 1, .dpcm_playback = 1,
.ops = &mt8195_sof_be_ops,
SND_SOC_DAILINK_REG(AFE_SOF_DL3), SND_SOC_DAILINK_REG(AFE_SOF_DL3),
}, },
[DAI_LINK_SOF_UL4_BE] = { [DAI_LINK_SOF_UL4_BE] = {
.name = "AFE_SOF_UL4", .name = "AFE_SOF_UL4",
.no_pcm = 1, .no_pcm = 1,
.dpcm_capture = 1, .dpcm_capture = 1,
.ops = &mt8195_sof_be_ops,
SND_SOC_DAILINK_REG(AFE_SOF_UL4), SND_SOC_DAILINK_REG(AFE_SOF_UL4),
}, },
[DAI_LINK_SOF_UL5_BE] = { [DAI_LINK_SOF_UL5_BE] = {
.name = "AFE_SOF_UL5", .name = "AFE_SOF_UL5",
.no_pcm = 1, .no_pcm = 1,
.dpcm_capture = 1, .dpcm_capture = 1,
.ops = &mt8195_sof_be_ops,
SND_SOC_DAILINK_REG(AFE_SOF_UL5), SND_SOC_DAILINK_REG(AFE_SOF_UL5),
}, },
}; };
......
...@@ -88,6 +88,7 @@ static int __maybe_unused rk_spdif_runtime_resume(struct device *dev) ...@@ -88,6 +88,7 @@ static int __maybe_unused rk_spdif_runtime_resume(struct device *dev)
ret = clk_prepare_enable(spdif->hclk); ret = clk_prepare_enable(spdif->hclk);
if (ret) { if (ret) {
clk_disable_unprepare(spdif->mclk);
dev_err(spdif->dev, "hclk clock enable failed %d\n", ret); dev_err(spdif->dev, "hclk clock enable failed %d\n", ret);
return ret; return ret;
} }
......
...@@ -475,19 +475,10 @@ EXPORT_SYMBOL(snd_sof_device_remove); ...@@ -475,19 +475,10 @@ EXPORT_SYMBOL(snd_sof_device_remove);
int snd_sof_device_shutdown(struct device *dev) int snd_sof_device_shutdown(struct device *dev)
{ {
struct snd_sof_dev *sdev = dev_get_drvdata(dev); struct snd_sof_dev *sdev = dev_get_drvdata(dev);
struct snd_sof_pdata *pdata = sdev->pdata;
if (IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE)) if (IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE))
cancel_work_sync(&sdev->probe_work); cancel_work_sync(&sdev->probe_work);
/*
* make sure clients and machine driver(s) are unregistered to force
* all userspace devices to be closed prior to the DSP shutdown sequence
*/
sof_unregister_clients(sdev);
snd_sof_machine_unregister(sdev, pdata);
if (sdev->fw_state == SOF_FW_BOOT_COMPLETE) if (sdev->fw_state == SOF_FW_BOOT_COMPLETE)
return snd_sof_shutdown(sdev); return snd_sof_shutdown(sdev);
......
...@@ -878,6 +878,78 @@ int hda_dsp_suspend(struct snd_sof_dev *sdev, u32 target_state) ...@@ -878,6 +878,78 @@ int hda_dsp_suspend(struct snd_sof_dev *sdev, u32 target_state)
return snd_sof_dsp_set_power_state(sdev, &target_dsp_state); return snd_sof_dsp_set_power_state(sdev, &target_dsp_state);
} }
static unsigned int hda_dsp_check_for_dma_streams(struct snd_sof_dev *sdev)
{
struct hdac_bus *bus = sof_to_bus(sdev);
struct hdac_stream *s;
unsigned int active_streams = 0;
int sd_offset;
u32 val;
list_for_each_entry(s, &bus->stream_list, list) {
sd_offset = SOF_STREAM_SD_OFFSET(s);
val = snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR,
sd_offset);
if (val & SOF_HDA_SD_CTL_DMA_START)
active_streams |= BIT(s->index);
}
return active_streams;
}
static int hda_dsp_s5_quirk(struct snd_sof_dev *sdev)
{
int ret;
/*
* Do not assume a certain timing between the prior
* suspend flow, and running of this quirk function.
* This is needed if the controller was just put
* to reset before calling this function.
*/
usleep_range(500, 1000);
/*
* Take controller out of reset to flush DMA
* transactions.
*/
ret = hda_dsp_ctrl_link_reset(sdev, false);
if (ret < 0)
return ret;
usleep_range(500, 1000);
/* Restore state for shutdown, back to reset */
ret = hda_dsp_ctrl_link_reset(sdev, true);
if (ret < 0)
return ret;
return ret;
}
int hda_dsp_shutdown_dma_flush(struct snd_sof_dev *sdev)
{
unsigned int active_streams;
int ret, ret2;
/* check if DMA cleanup has been successful */
active_streams = hda_dsp_check_for_dma_streams(sdev);
sdev->system_suspend_target = SOF_SUSPEND_S3;
ret = snd_sof_suspend(sdev->dev);
if (active_streams) {
dev_warn(sdev->dev,
"There were active DSP streams (%#x) at shutdown, trying to recover\n",
active_streams);
ret2 = hda_dsp_s5_quirk(sdev);
if (ret2 < 0)
dev_err(sdev->dev, "shutdown recovery failed (%d)\n", ret2);
}
return ret;
}
int hda_dsp_shutdown(struct snd_sof_dev *sdev) int hda_dsp_shutdown(struct snd_sof_dev *sdev)
{ {
sdev->system_suspend_target = SOF_SUSPEND_S3; sdev->system_suspend_target = SOF_SUSPEND_S3;
......
...@@ -592,6 +592,7 @@ int hda_dsp_resume(struct snd_sof_dev *sdev); ...@@ -592,6 +592,7 @@ int hda_dsp_resume(struct snd_sof_dev *sdev);
int hda_dsp_runtime_suspend(struct snd_sof_dev *sdev); int hda_dsp_runtime_suspend(struct snd_sof_dev *sdev);
int hda_dsp_runtime_resume(struct snd_sof_dev *sdev); int hda_dsp_runtime_resume(struct snd_sof_dev *sdev);
int hda_dsp_runtime_idle(struct snd_sof_dev *sdev); int hda_dsp_runtime_idle(struct snd_sof_dev *sdev);
int hda_dsp_shutdown_dma_flush(struct snd_sof_dev *sdev);
int hda_dsp_shutdown(struct snd_sof_dev *sdev); int hda_dsp_shutdown(struct snd_sof_dev *sdev);
int hda_dsp_set_hw_params_upon_resume(struct snd_sof_dev *sdev); int hda_dsp_set_hw_params_upon_resume(struct snd_sof_dev *sdev);
void hda_dsp_dump(struct snd_sof_dev *sdev, u32 flags); void hda_dsp_dump(struct snd_sof_dev *sdev, u32 flags);
......
...@@ -60,7 +60,7 @@ int sof_tgl_ops_init(struct snd_sof_dev *sdev) ...@@ -60,7 +60,7 @@ int sof_tgl_ops_init(struct snd_sof_dev *sdev)
memcpy(&sof_tgl_ops, &sof_hda_common_ops, sizeof(struct snd_sof_dsp_ops)); memcpy(&sof_tgl_ops, &sof_hda_common_ops, sizeof(struct snd_sof_dsp_ops));
/* probe/remove/shutdown */ /* probe/remove/shutdown */
sof_tgl_ops.shutdown = hda_dsp_shutdown; sof_tgl_ops.shutdown = hda_dsp_shutdown_dma_flush;
if (sdev->pdata->ipc_type == SOF_IPC) { if (sdev->pdata->ipc_type == SOF_IPC) {
/* doorbell */ /* doorbell */
......
...@@ -60,7 +60,7 @@ void mtk_adsp_dump(struct snd_sof_dev *sdev, u32 flags) ...@@ -60,7 +60,7 @@ void mtk_adsp_dump(struct snd_sof_dev *sdev, u32 flags)
{ {
char *level = (flags & SOF_DBG_DUMP_OPTIONAL) ? KERN_DEBUG : KERN_ERR; char *level = (flags & SOF_DBG_DUMP_OPTIONAL) ? KERN_DEBUG : KERN_ERR;
struct sof_ipc_dsp_oops_xtensa xoops; struct sof_ipc_dsp_oops_xtensa xoops;
struct sof_ipc_panic_info panic_info; struct sof_ipc_panic_info panic_info = {};
u32 stack[MTK_ADSP_STACK_DUMP_SIZE]; u32 stack[MTK_ADSP_STACK_DUMP_SIZE];
u32 status; u32 status;
......
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