Commit 84396d14 authored by Takashi Iwai's avatar Takashi Iwai

Merge tag 'asoc-fix-v5.2-rc4' of...

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

ASoC: Fixes for v5.2

There's an awful lot of fixes here, almost all for the newly introduced
SoF DSP drivers (including a few things it turned up in shared code).
This is a large and complex piece of code so it's not surprising that
there have been quite a few issues here, fortunately things seem to have
mostly calmed down now.  Otherwise there's just a smattering of small fixes.
parents 352bcae9 3da428ff
...@@ -49,6 +49,7 @@ enum sof_ipc_dai_type { ...@@ -49,6 +49,7 @@ enum sof_ipc_dai_type {
SOF_DAI_INTEL_SSP, /**< Intel SSP */ SOF_DAI_INTEL_SSP, /**< Intel SSP */
SOF_DAI_INTEL_DMIC, /**< Intel DMIC */ SOF_DAI_INTEL_DMIC, /**< Intel DMIC */
SOF_DAI_INTEL_HDA, /**< Intel HD/A */ SOF_DAI_INTEL_HDA, /**< Intel HD/A */
SOF_DAI_INTEL_SOUNDWIRE, /**< Intel SoundWire */
}; };
/* general purpose DAI configuration */ /* general purpose DAI configuration */
......
...@@ -48,6 +48,7 @@ ...@@ -48,6 +48,7 @@
#define SOF_IPC_FW_READY SOF_GLB_TYPE(0x7U) #define SOF_IPC_FW_READY SOF_GLB_TYPE(0x7U)
#define SOF_IPC_GLB_DAI_MSG SOF_GLB_TYPE(0x8U) #define SOF_IPC_GLB_DAI_MSG SOF_GLB_TYPE(0x8U)
#define SOF_IPC_GLB_TRACE_MSG SOF_GLB_TYPE(0x9U) #define SOF_IPC_GLB_TRACE_MSG SOF_GLB_TYPE(0x9U)
#define SOF_IPC_GLB_GDB_DEBUG SOF_GLB_TYPE(0xAU)
/* /*
* DSP Command Message Types * DSP Command Message Types
...@@ -78,6 +79,7 @@ ...@@ -78,6 +79,7 @@
#define SOF_IPC_COMP_GET_VALUE SOF_CMD_TYPE(0x002) #define SOF_IPC_COMP_GET_VALUE SOF_CMD_TYPE(0x002)
#define SOF_IPC_COMP_SET_DATA SOF_CMD_TYPE(0x003) #define SOF_IPC_COMP_SET_DATA SOF_CMD_TYPE(0x003)
#define SOF_IPC_COMP_GET_DATA SOF_CMD_TYPE(0x004) #define SOF_IPC_COMP_GET_DATA SOF_CMD_TYPE(0x004)
#define SOF_IPC_COMP_NOTIFICATION SOF_CMD_TYPE(0x005)
/* DAI messages */ /* DAI messages */
#define SOF_IPC_DAI_CONFIG SOF_CMD_TYPE(0x001) #define SOF_IPC_DAI_CONFIG SOF_CMD_TYPE(0x001)
...@@ -153,6 +155,27 @@ struct sof_ipc_compound_hdr { ...@@ -153,6 +155,27 @@ struct sof_ipc_compound_hdr {
uint32_t count; /**< count of 0 means end of compound sequence */ uint32_t count; /**< count of 0 means end of compound sequence */
} __packed; } __packed;
/**
* OOPS header architecture specific data.
*/
struct sof_ipc_dsp_oops_arch_hdr {
uint32_t arch; /* Identifier of architecture */
uint32_t totalsize; /* Total size of oops message */
} __packed;
/**
* OOPS header platform specific data.
*/
struct sof_ipc_dsp_oops_plat_hdr {
uint32_t configidhi; /* ConfigID hi 32bits */
uint32_t configidlo; /* ConfigID lo 32bits */
uint32_t numaregs; /* Special regs num */
uint32_t stackoffset; /* Offset to stack pointer from beginning of
* oops message
*/
uint32_t stackptr; /* Stack ptr */
} __packed;
/** @}*/ /** @}*/
#endif #endif
...@@ -18,6 +18,14 @@ ...@@ -18,6 +18,14 @@
#define SOF_IPC_MAX_ELEMS 16 #define SOF_IPC_MAX_ELEMS 16
/*
* Firmware boot info flag bits (64-bit)
*/
#define SOF_IPC_INFO_BUILD BIT(0)
#define SOF_IPC_INFO_LOCKS BIT(1)
#define SOF_IPC_INFO_LOCKSV BIT(2)
#define SOF_IPC_INFO_GDB BIT(3)
/* extended data types that can be appended onto end of sof_ipc_fw_ready */ /* extended data types that can be appended onto end of sof_ipc_fw_ready */
enum sof_ipc_ext_data { enum sof_ipc_ext_data {
SOF_IPC_EXT_DMA_BUFFER = 0, SOF_IPC_EXT_DMA_BUFFER = 0,
...@@ -49,16 +57,8 @@ struct sof_ipc_fw_ready { ...@@ -49,16 +57,8 @@ struct sof_ipc_fw_ready {
uint32_t hostbox_size; uint32_t hostbox_size;
struct sof_ipc_fw_version version; struct sof_ipc_fw_version version;
/* Miscellaneous debug flags showing build/debug features enabled */ /* Miscellaneous flags */
union { uint64_t flags;
uint64_t reserved;
struct {
uint64_t build:1;
uint64_t locks:1;
uint64_t locks_verbose:1;
uint64_t gdb:1;
} bits;
} debug;
/* reserved for future use */ /* reserved for future use */
uint32_t reserved[4]; uint32_t reserved[4];
......
...@@ -17,7 +17,8 @@ ...@@ -17,7 +17,8 @@
/* Xtensa Firmware Oops data */ /* Xtensa Firmware Oops data */
struct sof_ipc_dsp_oops_xtensa { struct sof_ipc_dsp_oops_xtensa {
struct sof_ipc_hdr hdr; struct sof_ipc_dsp_oops_arch_hdr arch_hdr;
struct sof_ipc_dsp_oops_plat_hdr plat_hdr;
uint32_t exccause; uint32_t exccause;
uint32_t excvaddr; uint32_t excvaddr;
uint32_t ps; uint32_t ps;
...@@ -38,7 +39,11 @@ struct sof_ipc_dsp_oops_xtensa { ...@@ -38,7 +39,11 @@ struct sof_ipc_dsp_oops_xtensa {
uint32_t intenable; uint32_t intenable;
uint32_t interrupt; uint32_t interrupt;
uint32_t sar; uint32_t sar;
uint32_t stack; uint32_t debugcause;
uint32_t windowbase;
uint32_t windowstart;
uint32_t excsave1;
uint32_t ar[];
} __packed; } __packed;
#endif #endif
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
/* SOF ABI version major, minor and patch numbers */ /* SOF ABI version major, minor and patch numbers */
#define SOF_ABI_MAJOR 3 #define SOF_ABI_MAJOR 3
#define SOF_ABI_MINOR 4 #define SOF_ABI_MINOR 6
#define SOF_ABI_PATCH 0 #define SOF_ABI_PATCH 0
/* SOF ABI version number. Format within 32bit word is MMmmmppp */ /* SOF ABI version number. Format within 32bit word is MMmmmppp */
......
...@@ -170,7 +170,6 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_device_init); ...@@ -170,7 +170,6 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_device_init);
void snd_hdac_ext_bus_device_exit(struct hdac_device *hdev) void snd_hdac_ext_bus_device_exit(struct hdac_device *hdev)
{ {
snd_hdac_device_exit(hdev); snd_hdac_device_exit(hdev);
kfree(hdev);
} }
EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_device_exit); EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_device_exit);
......
...@@ -840,7 +840,14 @@ static int snd_hda_codec_dev_free(struct snd_device *device) ...@@ -840,7 +840,14 @@ static int snd_hda_codec_dev_free(struct snd_device *device)
if (codec->core.type == HDA_DEV_LEGACY) if (codec->core.type == HDA_DEV_LEGACY)
snd_hdac_device_unregister(&codec->core); snd_hdac_device_unregister(&codec->core);
codec_display_power(codec, false); codec_display_power(codec, false);
put_device(hda_codec_dev(codec));
/*
* In the case of ASoC HD-audio bus, the device refcount is released in
* snd_hdac_ext_bus_device_remove() explicitly.
*/
if (codec->core.type == HDA_DEV_LEGACY)
put_device(hda_codec_dev(codec));
return 0; return 0;
} }
......
...@@ -304,7 +304,10 @@ static int ak4458_rstn_control(struct snd_soc_component *component, int bit) ...@@ -304,7 +304,10 @@ static int ak4458_rstn_control(struct snd_soc_component *component, int bit)
AK4458_00_CONTROL1, AK4458_00_CONTROL1,
AK4458_RSTN_MASK, AK4458_RSTN_MASK,
0x0); 0x0);
return ret; if (ret < 0)
return ret;
return 0;
} }
static int ak4458_hw_params(struct snd_pcm_substream *substream, static int ak4458_hw_params(struct snd_pcm_substream *substream,
...@@ -536,9 +539,10 @@ static void ak4458_power_on(struct ak4458_priv *ak4458) ...@@ -536,9 +539,10 @@ static void ak4458_power_on(struct ak4458_priv *ak4458)
} }
} }
static void ak4458_init(struct snd_soc_component *component) static int ak4458_init(struct snd_soc_component *component)
{ {
struct ak4458_priv *ak4458 = snd_soc_component_get_drvdata(component); struct ak4458_priv *ak4458 = snd_soc_component_get_drvdata(component);
int ret;
/* External Mute ON */ /* External Mute ON */
if (ak4458->mute_gpiod) if (ak4458->mute_gpiod)
...@@ -546,21 +550,21 @@ static void ak4458_init(struct snd_soc_component *component) ...@@ -546,21 +550,21 @@ static void ak4458_init(struct snd_soc_component *component)
ak4458_power_on(ak4458); ak4458_power_on(ak4458);
snd_soc_component_update_bits(component, AK4458_00_CONTROL1, ret = snd_soc_component_update_bits(component, AK4458_00_CONTROL1,
0x80, 0x80); /* ACKS bit = 1; 10000000 */ 0x80, 0x80); /* ACKS bit = 1; 10000000 */
if (ret < 0)
return ret;
ak4458_rstn_control(component, 1); return ak4458_rstn_control(component, 1);
} }
static int ak4458_probe(struct snd_soc_component *component) static int ak4458_probe(struct snd_soc_component *component)
{ {
struct ak4458_priv *ak4458 = snd_soc_component_get_drvdata(component); struct ak4458_priv *ak4458 = snd_soc_component_get_drvdata(component);
ak4458_init(component);
ak4458->fs = 48000; ak4458->fs = 48000;
return 0; return ak4458_init(component);
} }
static void ak4458_remove(struct snd_soc_component *component) static void ak4458_remove(struct snd_soc_component *component)
......
...@@ -60,7 +60,7 @@ static const struct reg_default cs4265_reg_defaults[] = { ...@@ -60,7 +60,7 @@ static const struct reg_default cs4265_reg_defaults[] = {
static bool cs4265_readable_register(struct device *dev, unsigned int reg) static bool cs4265_readable_register(struct device *dev, unsigned int reg)
{ {
switch (reg) { switch (reg) {
case CS4265_CHIP_ID ... CS4265_SPDIF_CTL2: case CS4265_CHIP_ID ... CS4265_MAX_REGISTER:
return true; return true;
default: default:
return false; return false;
......
...@@ -558,6 +558,7 @@ static int cs42xx8_runtime_resume(struct device *dev) ...@@ -558,6 +558,7 @@ static int cs42xx8_runtime_resume(struct device *dev)
msleep(5); msleep(5);
regcache_cache_only(cs42xx8->regmap, false); regcache_cache_only(cs42xx8->regmap, false);
regcache_mark_dirty(cs42xx8->regmap);
ret = regcache_sync(cs42xx8->regmap); ret = regcache_sync(cs42xx8->regmap);
if (ret) { if (ret) {
......
...@@ -1909,6 +1909,21 @@ static int max98090_configure_dmic(struct max98090_priv *max98090, ...@@ -1909,6 +1909,21 @@ static int max98090_configure_dmic(struct max98090_priv *max98090,
return 0; return 0;
} }
static int max98090_dai_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_component *component = dai->component;
struct max98090_priv *max98090 = snd_soc_component_get_drvdata(component);
unsigned int fmt = max98090->dai_fmt;
/* Remove 24-bit format support if it is not in right justified mode. */
if ((fmt & SND_SOC_DAIFMT_FORMAT_MASK) != SND_SOC_DAIFMT_RIGHT_J) {
substream->runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE;
snd_pcm_hw_constraint_msbits(substream->runtime, 0, 16, 16);
}
return 0;
}
static int max98090_dai_hw_params(struct snd_pcm_substream *substream, static int max98090_dai_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params, struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai) struct snd_soc_dai *dai)
...@@ -2316,6 +2331,7 @@ EXPORT_SYMBOL_GPL(max98090_mic_detect); ...@@ -2316,6 +2331,7 @@ EXPORT_SYMBOL_GPL(max98090_mic_detect);
#define MAX98090_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE) #define MAX98090_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE)
static const struct snd_soc_dai_ops max98090_dai_ops = { static const struct snd_soc_dai_ops max98090_dai_ops = {
.startup = max98090_dai_startup,
.set_sysclk = max98090_dai_set_sysclk, .set_sysclk = max98090_dai_set_sysclk,
.set_fmt = max98090_dai_set_fmt, .set_fmt = max98090_dai_set_fmt,
.set_tdm_slot = max98090_set_tdm_slot, .set_tdm_slot = max98090_set_tdm_slot,
......
...@@ -405,6 +405,8 @@ static int rt274_mic_detect(struct snd_soc_component *component, ...@@ -405,6 +405,8 @@ static int rt274_mic_detect(struct snd_soc_component *component,
{ {
struct rt274_priv *rt274 = snd_soc_component_get_drvdata(component); struct rt274_priv *rt274 = snd_soc_component_get_drvdata(component);
rt274->jack = jack;
if (jack == NULL) { if (jack == NULL) {
/* Disable jack detection */ /* Disable jack detection */
regmap_update_bits(rt274->regmap, RT274_EAPD_GPIO_IRQ_CTRL, regmap_update_bits(rt274->regmap, RT274_EAPD_GPIO_IRQ_CTRL,
...@@ -412,7 +414,6 @@ static int rt274_mic_detect(struct snd_soc_component *component, ...@@ -412,7 +414,6 @@ static int rt274_mic_detect(struct snd_soc_component *component,
return 0; return 0;
} }
rt274->jack = jack;
regmap_update_bits(rt274->regmap, RT274_EAPD_GPIO_IRQ_CTRL, regmap_update_bits(rt274->regmap, RT274_EAPD_GPIO_IRQ_CTRL,
RT274_IRQ_EN, RT274_IRQ_EN); RT274_IRQ_EN, RT274_IRQ_EN);
......
...@@ -2882,6 +2882,18 @@ static const struct dmi_system_id dmi_platform_intel_quirks[] = { ...@@ -2882,6 +2882,18 @@ static const struct dmi_system_id dmi_platform_intel_quirks[] = {
RT5670_DEV_GPIO | RT5670_DEV_GPIO |
RT5670_JD_MODE3), RT5670_JD_MODE3),
}, },
{
.callback = rt5670_quirk_cb,
.ident = "Aegex 10 tablet (RU2)",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "AEGEX"),
DMI_MATCH(DMI_PRODUCT_VERSION, "RU2"),
},
.driver_data = (unsigned long *)(RT5670_DMIC_EN |
RT5670_DMIC2_INR |
RT5670_DEV_GPIO |
RT5670_JD_MODE3),
},
{} {}
}; };
......
...@@ -101,7 +101,7 @@ static void rt5677_spi_reverse(u8 *dst, u32 dstlen, const u8 *src, u32 srclen) ...@@ -101,7 +101,7 @@ static void rt5677_spi_reverse(u8 *dst, u32 dstlen, const u8 *src, u32 srclen)
u32 word_size = min_t(u32, dstlen, 8); u32 word_size = min_t(u32, dstlen, 8);
for (w = 0; w < dstlen; w += word_size) { for (w = 0; w < dstlen; w += word_size) {
for (i = 0; i < word_size; i++) { for (i = 0; i < word_size && i + w < dstlen; i++) {
si = w + word_size - i - 1; si = w + word_size - i - 1;
dst[w + i] = si < srclen ? src[si] : 0; dst[w + i] = si < srclen ? src[si] : 0;
} }
...@@ -152,8 +152,9 @@ int rt5677_spi_read(u32 addr, void *rxbuf, size_t len) ...@@ -152,8 +152,9 @@ int rt5677_spi_read(u32 addr, void *rxbuf, size_t len)
status |= spi_sync(g_spi, &m); status |= spi_sync(g_spi, &m);
mutex_unlock(&spi_mutex); mutex_unlock(&spi_mutex);
/* Copy data back to caller buffer */ /* Copy data back to caller buffer */
rt5677_spi_reverse(cb + offset, t[1].len, body, t[1].len); rt5677_spi_reverse(cb + offset, len - offset, body, t[1].len);
} }
return status; return status;
} }
......
...@@ -282,8 +282,8 @@ static int fsl_asrc_config_pair(struct fsl_asrc_pair *pair) ...@@ -282,8 +282,8 @@ static int fsl_asrc_config_pair(struct fsl_asrc_pair *pair)
return -EINVAL; return -EINVAL;
} }
if ((outrate > 8000 && outrate < 30000) && if ((outrate >= 8000 && outrate <= 30000) &&
(outrate/inrate > 24 || inrate/outrate > 8)) { (outrate > 24 * inrate || inrate > 8 * outrate)) {
pair_err("exceed supported ratio range [1/24, 8] for \ pair_err("exceed supported ratio range [1/24, 8] for \
inrate/outrate: %d/%d\n", inrate, outrate); inrate/outrate: %d/%d\n", inrate, outrate);
return -EINVAL; return -EINVAL;
......
...@@ -166,11 +166,11 @@ int sst_create_ipc_msg(struct ipc_post **arg, bool large) ...@@ -166,11 +166,11 @@ int sst_create_ipc_msg(struct ipc_post **arg, bool large)
{ {
struct ipc_post *msg; struct ipc_post *msg;
msg = kzalloc(sizeof(*msg), GFP_KERNEL); msg = kzalloc(sizeof(*msg), GFP_ATOMIC);
if (!msg) if (!msg)
return -ENOMEM; return -ENOMEM;
if (large) { if (large) {
msg->mailbox_data = kzalloc(SST_MAILBOX_SIZE, GFP_KERNEL); msg->mailbox_data = kzalloc(SST_MAILBOX_SIZE, GFP_ATOMIC);
if (!msg->mailbox_data) { if (!msg->mailbox_data) {
kfree(msg); kfree(msg);
return -ENOMEM; return -ENOMEM;
......
...@@ -495,6 +495,7 @@ static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev) ...@@ -495,6 +495,7 @@ static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev)
} }
/* override plaform name, if required */ /* override plaform name, if required */
byt_cht_es8316_card.dev = dev;
platform_name = mach->mach_params.platform; platform_name = mach->mach_params.platform;
ret = snd_soc_fixup_dai_links_platform_name(&byt_cht_es8316_card, ret = snd_soc_fixup_dai_links_platform_name(&byt_cht_es8316_card,
...@@ -575,7 +576,6 @@ static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev) ...@@ -575,7 +576,6 @@ static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev)
(quirk & BYT_CHT_ES8316_MONO_SPEAKER) ? "mono" : "stereo", (quirk & BYT_CHT_ES8316_MONO_SPEAKER) ? "mono" : "stereo",
mic_name[BYT_CHT_ES8316_MAP(quirk)]); mic_name[BYT_CHT_ES8316_MAP(quirk)]);
byt_cht_es8316_card.long_name = long_name; byt_cht_es8316_card.long_name = long_name;
byt_cht_es8316_card.dev = dev;
snd_soc_card_set_drvdata(&byt_cht_es8316_card, priv); snd_soc_card_set_drvdata(&byt_cht_es8316_card, priv);
ret = devm_snd_soc_register_card(dev, &byt_cht_es8316_card); ret = devm_snd_soc_register_card(dev, &byt_cht_es8316_card);
......
...@@ -454,6 +454,7 @@ static int snd_cht_mc_probe(struct platform_device *pdev) ...@@ -454,6 +454,7 @@ static int snd_cht_mc_probe(struct platform_device *pdev)
} }
/* override plaform name, if required */ /* override plaform name, if required */
snd_soc_card_cht.dev = &pdev->dev;
mach = (&pdev->dev)->platform_data; mach = (&pdev->dev)->platform_data;
platform_name = mach->mach_params.platform; platform_name = mach->mach_params.platform;
...@@ -463,7 +464,6 @@ static int snd_cht_mc_probe(struct platform_device *pdev) ...@@ -463,7 +464,6 @@ static int snd_cht_mc_probe(struct platform_device *pdev)
return ret_val; return ret_val;
/* register the soc card */ /* register the soc card */
snd_soc_card_cht.dev = &pdev->dev;
snd_soc_card_set_drvdata(&snd_soc_card_cht, drv); snd_soc_card_set_drvdata(&snd_soc_card_cht, drv);
if (drv->quirks & QUIRK_PMC_PLT_CLK_0) if (drv->quirks & QUIRK_PMC_PLT_CLK_0)
......
...@@ -257,6 +257,7 @@ static int snd_cht_mc_probe(struct platform_device *pdev) ...@@ -257,6 +257,7 @@ static int snd_cht_mc_probe(struct platform_device *pdev)
snd_soc_card_set_drvdata(&snd_soc_card_cht, drv); snd_soc_card_set_drvdata(&snd_soc_card_cht, drv);
/* override plaform name, if required */ /* override plaform name, if required */
snd_soc_card_cht.dev = &pdev->dev;
mach = (&pdev->dev)->platform_data; mach = (&pdev->dev)->platform_data;
platform_name = mach->mach_params.platform; platform_name = mach->mach_params.platform;
...@@ -266,7 +267,6 @@ static int snd_cht_mc_probe(struct platform_device *pdev) ...@@ -266,7 +267,6 @@ static int snd_cht_mc_probe(struct platform_device *pdev)
return ret_val; return ret_val;
/* register the soc card */ /* register the soc card */
snd_soc_card_cht.dev = &pdev->dev;
ret_val = devm_snd_soc_register_card(&pdev->dev, &snd_soc_card_cht); ret_val = devm_snd_soc_register_card(&pdev->dev, &snd_soc_card_cht);
if (ret_val) { if (ret_val) {
dev_err(&pdev->dev, dev_err(&pdev->dev,
......
...@@ -426,6 +426,7 @@ static int snd_cht_mc_probe(struct platform_device *pdev) ...@@ -426,6 +426,7 @@ static int snd_cht_mc_probe(struct platform_device *pdev)
} }
/* override plaform name, if required */ /* override plaform name, if required */
snd_soc_card_cht.dev = &pdev->dev;
platform_name = mach->mach_params.platform; platform_name = mach->mach_params.platform;
ret_val = snd_soc_fixup_dai_links_platform_name(&snd_soc_card_cht, ret_val = snd_soc_fixup_dai_links_platform_name(&snd_soc_card_cht,
...@@ -443,7 +444,6 @@ static int snd_cht_mc_probe(struct platform_device *pdev) ...@@ -443,7 +444,6 @@ static int snd_cht_mc_probe(struct platform_device *pdev)
snd_soc_card_set_drvdata(&snd_soc_card_cht, drv); snd_soc_card_set_drvdata(&snd_soc_card_cht, drv);
/* register the soc card */ /* register the soc card */
snd_soc_card_cht.dev = &pdev->dev;
ret_val = devm_snd_soc_register_card(&pdev->dev, &snd_soc_card_cht); ret_val = devm_snd_soc_register_card(&pdev->dev, &snd_soc_card_cht);
if (ret_val) { if (ret_val) {
dev_err(&pdev->dev, dev_err(&pdev->dev,
......
...@@ -29,9 +29,10 @@ ...@@ -29,9 +29,10 @@
#define SOF_RT5682_MCLK_EN BIT(3) #define SOF_RT5682_MCLK_EN BIT(3)
#define SOF_RT5682_MCLK_24MHZ BIT(4) #define SOF_RT5682_MCLK_24MHZ BIT(4)
#define SOF_SPEAKER_AMP_PRESENT BIT(5) #define SOF_SPEAKER_AMP_PRESENT BIT(5)
#define SOF_RT5682_SSP_AMP(quirk) ((quirk) & GENMASK(8, 6))
#define SOF_RT5682_SSP_AMP_MASK (GENMASK(8, 6))
#define SOF_RT5682_SSP_AMP_SHIFT 6 #define SOF_RT5682_SSP_AMP_SHIFT 6
#define SOF_RT5682_SSP_AMP_MASK (GENMASK(8, 6))
#define SOF_RT5682_SSP_AMP(quirk) \
(((quirk) << SOF_RT5682_SSP_AMP_SHIFT) & SOF_RT5682_SSP_AMP_MASK)
/* Default: MCLK on, MCLK 19.2M, SSP0 */ /* Default: MCLK on, MCLK 19.2M, SSP0 */
static unsigned long sof_rt5682_quirk = SOF_RT5682_MCLK_EN | static unsigned long sof_rt5682_quirk = SOF_RT5682_MCLK_EN |
...@@ -144,9 +145,9 @@ static int sof_rt5682_codec_init(struct snd_soc_pcm_runtime *rtd) ...@@ -144,9 +145,9 @@ static int sof_rt5682_codec_init(struct snd_soc_pcm_runtime *rtd)
jack = &ctx->sof_headset; jack = &ctx->sof_headset;
snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE); snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOLUMEUP); snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);
snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEDOWN); snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOICECOMMAND); snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);
ret = snd_soc_component_set_jack(component, jack, NULL); ret = snd_soc_component_set_jack(component, jack, NULL);
if (ret) { if (ret) {
......
...@@ -22,6 +22,7 @@ static unsigned long byt_machine_id; ...@@ -22,6 +22,7 @@ static unsigned long byt_machine_id;
#define BYT_THINKPAD_10 1 #define BYT_THINKPAD_10 1
#define BYT_POV_P1006W 2 #define BYT_POV_P1006W 2
#define BYT_AEGEX_10 3
static int byt_thinkpad10_quirk_cb(const struct dmi_system_id *id) static int byt_thinkpad10_quirk_cb(const struct dmi_system_id *id)
{ {
...@@ -35,6 +36,12 @@ static int byt_pov_p1006w_quirk_cb(const struct dmi_system_id *id) ...@@ -35,6 +36,12 @@ static int byt_pov_p1006w_quirk_cb(const struct dmi_system_id *id)
return 1; return 1;
} }
static int byt_aegex10_quirk_cb(const struct dmi_system_id *id)
{
byt_machine_id = BYT_AEGEX_10;
return 1;
}
static const struct dmi_system_id byt_table[] = { static const struct dmi_system_id byt_table[] = {
{ {
.callback = byt_thinkpad10_quirk_cb, .callback = byt_thinkpad10_quirk_cb,
...@@ -75,9 +82,18 @@ static const struct dmi_system_id byt_table[] = { ...@@ -75,9 +82,18 @@ static const struct dmi_system_id byt_table[] = {
DMI_EXACT_MATCH(DMI_BOARD_NAME, "0E57"), DMI_EXACT_MATCH(DMI_BOARD_NAME, "0E57"),
}, },
}, },
{
/* Aegex 10 tablet (RU2) */
.callback = byt_aegex10_quirk_cb,
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "AEGEX"),
DMI_MATCH(DMI_PRODUCT_VERSION, "RU2"),
},
},
{ } { }
}; };
/* The Thinkapd 10 and Aegex 10 tablets have the same ID problem */
static struct snd_soc_acpi_mach byt_thinkpad_10 = { static struct snd_soc_acpi_mach byt_thinkpad_10 = {
.id = "10EC5640", .id = "10EC5640",
.drv_name = "cht-bsw-rt5672", .drv_name = "cht-bsw-rt5672",
...@@ -104,6 +120,7 @@ static struct snd_soc_acpi_mach *byt_quirk(void *arg) ...@@ -104,6 +120,7 @@ static struct snd_soc_acpi_mach *byt_quirk(void *arg)
switch (byt_machine_id) { switch (byt_machine_id) {
case BYT_THINKPAD_10: case BYT_THINKPAD_10:
case BYT_AEGEX_10:
return &byt_thinkpad_10; return &byt_thinkpad_10;
case BYT_POV_P1006W: case BYT_POV_P1006W:
return &byt_pov_p1006w; return &byt_pov_p1006w;
......
...@@ -29,17 +29,17 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_cnl_machines[] = { ...@@ -29,17 +29,17 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_cnl_machines[] = {
.sof_tplg_filename = "sof-cnl-rt274.tplg", .sof_tplg_filename = "sof-cnl-rt274.tplg",
}, },
{ {
.id = "10EC5682", .id = "MX98357A",
.drv_name = "sof_rt5682", .drv_name = "sof_rt5682",
.quirk_data = &cml_codecs,
.sof_fw_filename = "sof-cnl.ri", .sof_fw_filename = "sof-cnl.ri",
.sof_tplg_filename = "sof-cml-rt5682.tplg", .sof_tplg_filename = "sof-cml-rt5682-max98357a.tplg",
}, },
{ {
.id = "MX98357A", .id = "10EC5682",
.drv_name = "sof_rt5682", .drv_name = "sof_rt5682",
.quirk_data = &cml_codecs,
.sof_fw_filename = "sof-cnl.ri", .sof_fw_filename = "sof-cnl.ri",
.sof_tplg_filename = "sof-cml-rt5682-max98357a.tplg", .sof_tplg_filename = "sof-cml-rt5682.tplg",
}, },
{}, {},
......
...@@ -132,7 +132,7 @@ config SND_SOC_MT8183_MT6358_TS3A227E_MAX98357A ...@@ -132,7 +132,7 @@ config SND_SOC_MT8183_MT6358_TS3A227E_MAX98357A
config SND_SOC_MT8183_DA7219_MAX98357A config SND_SOC_MT8183_DA7219_MAX98357A
tristate "ASoC Audio driver for MT8183 with DA7219 MAX98357A codec" tristate "ASoC Audio driver for MT8183 with DA7219 MAX98357A codec"
depends on SND_SOC_MT8183 depends on SND_SOC_MT8183 && I2C
select SND_SOC_MT6358 select SND_SOC_MT6358
select SND_SOC_MAX98357A select SND_SOC_MAX98357A
select SND_SOC_DA7219 select SND_SOC_DA7219
......
...@@ -228,7 +228,10 @@ static void soc_init_card_debugfs(struct snd_soc_card *card) ...@@ -228,7 +228,10 @@ static void soc_init_card_debugfs(struct snd_soc_card *card)
static void soc_cleanup_card_debugfs(struct snd_soc_card *card) static void soc_cleanup_card_debugfs(struct snd_soc_card *card)
{ {
if (!card->debugfs_card_root)
return;
debugfs_remove_recursive(card->debugfs_card_root); debugfs_remove_recursive(card->debugfs_card_root);
card->debugfs_card_root = NULL;
} }
static void snd_soc_debugfs_init(void) static void snd_soc_debugfs_init(void)
...@@ -2037,8 +2040,10 @@ static void soc_check_tplg_fes(struct snd_soc_card *card) ...@@ -2037,8 +2040,10 @@ static void soc_check_tplg_fes(struct snd_soc_card *card)
static int soc_cleanup_card_resources(struct snd_soc_card *card) static int soc_cleanup_card_resources(struct snd_soc_card *card)
{ {
/* free the ALSA card at first; this syncs with pending operations */ /* free the ALSA card at first; this syncs with pending operations */
if (card->snd_card) if (card->snd_card) {
snd_card_free(card->snd_card); snd_card_free(card->snd_card);
card->snd_card = NULL;
}
/* remove and free each DAI */ /* remove and free each DAI */
soc_remove_dai_links(card); soc_remove_dai_links(card);
...@@ -2065,6 +2070,16 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card) ...@@ -2065,6 +2070,16 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card)
int ret, i, order; int ret, i, order;
mutex_lock(&client_mutex); mutex_lock(&client_mutex);
for_each_card_prelinks(card, i, dai_link) {
ret = soc_init_dai_link(card, dai_link);
if (ret) {
soc_cleanup_platform(card);
dev_err(card->dev, "ASoC: failed to init link %s: %d\n",
dai_link->name, ret);
mutex_unlock(&client_mutex);
return ret;
}
}
mutex_lock_nested(&card->mutex, SND_SOC_CARD_CLASS_INIT); mutex_lock_nested(&card->mutex, SND_SOC_CARD_CLASS_INIT);
card->dapm.bias_level = SND_SOC_BIAS_OFF; card->dapm.bias_level = SND_SOC_BIAS_OFF;
...@@ -2789,26 +2804,9 @@ static int snd_soc_bind_card(struct snd_soc_card *card) ...@@ -2789,26 +2804,9 @@ static int snd_soc_bind_card(struct snd_soc_card *card)
*/ */
int snd_soc_register_card(struct snd_soc_card *card) int snd_soc_register_card(struct snd_soc_card *card)
{ {
int i, ret;
struct snd_soc_dai_link *link;
if (!card->name || !card->dev) if (!card->name || !card->dev)
return -EINVAL; return -EINVAL;
mutex_lock(&client_mutex);
for_each_card_prelinks(card, i, link) {
ret = soc_init_dai_link(card, link);
if (ret) {
soc_cleanup_platform(card);
dev_err(card->dev, "ASoC: failed to init link %s\n",
link->name);
mutex_unlock(&client_mutex);
return ret;
}
}
mutex_unlock(&client_mutex);
dev_set_drvdata(card->dev, card); dev_set_drvdata(card->dev, card);
snd_soc_initialize_card_lists(card); snd_soc_initialize_card_lists(card);
...@@ -2839,12 +2837,14 @@ static void snd_soc_unbind_card(struct snd_soc_card *card, bool unregister) ...@@ -2839,12 +2837,14 @@ static void snd_soc_unbind_card(struct snd_soc_card *card, bool unregister)
snd_soc_dapm_shutdown(card); snd_soc_dapm_shutdown(card);
snd_soc_flush_all_delayed_work(card); snd_soc_flush_all_delayed_work(card);
mutex_lock(&client_mutex);
/* remove all components used by DAI links on this card */ /* remove all components used by DAI links on this card */
for_each_comp_order(order) { for_each_comp_order(order) {
for_each_card_rtds(card, rtd) { for_each_card_rtds(card, rtd) {
soc_remove_link_components(card, rtd, order); soc_remove_link_components(card, rtd, order);
} }
} }
mutex_unlock(&client_mutex);
soc_cleanup_card_resources(card); soc_cleanup_card_resources(card);
if (!unregister) if (!unregister)
......
...@@ -2193,7 +2193,10 @@ static void dapm_debugfs_add_widget(struct snd_soc_dapm_widget *w) ...@@ -2193,7 +2193,10 @@ static void dapm_debugfs_add_widget(struct snd_soc_dapm_widget *w)
static void dapm_debugfs_cleanup(struct snd_soc_dapm_context *dapm) static void dapm_debugfs_cleanup(struct snd_soc_dapm_context *dapm)
{ {
if (!dapm->debugfs_dapm)
return;
debugfs_remove_recursive(dapm->debugfs_dapm); debugfs_remove_recursive(dapm->debugfs_dapm);
dapm->debugfs_dapm = NULL;
} }
#else #else
...@@ -3831,8 +3834,8 @@ static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w, ...@@ -3831,8 +3834,8 @@ static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w,
ret); ret);
goto out; goto out;
} }
source->active++;
} }
source->active++;
ret = soc_dai_hw_params(&substream, params, source); ret = soc_dai_hw_params(&substream, params, source);
if (ret < 0) if (ret < 0)
goto out; goto out;
...@@ -3853,8 +3856,8 @@ static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w, ...@@ -3853,8 +3856,8 @@ static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w,
ret); ret);
goto out; goto out;
} }
sink->active++;
} }
sink->active++;
ret = soc_dai_hw_params(&substream, params, sink); ret = soc_dai_hw_params(&substream, params, sink);
if (ret < 0) if (ret < 0)
goto out; goto out;
......
...@@ -2479,7 +2479,8 @@ int dpcm_be_dai_prepare(struct snd_soc_pcm_runtime *fe, int stream) ...@@ -2479,7 +2479,8 @@ int dpcm_be_dai_prepare(struct snd_soc_pcm_runtime *fe, int stream)
if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_PARAMS) && if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_PARAMS) &&
(be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP) && (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP) &&
(be->dpcm[stream].state != SND_SOC_DPCM_STATE_SUSPEND)) (be->dpcm[stream].state != SND_SOC_DPCM_STATE_SUSPEND) &&
(be->dpcm[stream].state != SND_SOC_DPCM_STATE_PAUSED))
continue; continue;
dev_dbg(be->dev, "ASoC: prepare BE %s\n", dev_dbg(be->dev, "ASoC: prepare BE %s\n",
......
...@@ -44,7 +44,10 @@ config SND_SOC_SOF_OPTIONS ...@@ -44,7 +44,10 @@ config SND_SOC_SOF_OPTIONS
if SND_SOC_SOF_OPTIONS if SND_SOC_SOF_OPTIONS
config SND_SOC_SOF_NOCODEC config SND_SOC_SOF_NOCODEC
tristate "SOF nocodec mode Support" tristate
config SND_SOC_SOF_NOCODEC_SUPPORT
bool "SOF nocodec mode support"
help help
This adds support for a dummy/nocodec machine driver fallback This adds support for a dummy/nocodec machine driver fallback
option if no known codec is detected. This is typically only option if no known codec is detected. This is typically only
...@@ -80,7 +83,7 @@ if SND_SOC_SOF_DEBUG ...@@ -80,7 +83,7 @@ if SND_SOC_SOF_DEBUG
config SND_SOC_SOF_FORCE_NOCODEC_MODE config SND_SOC_SOF_FORCE_NOCODEC_MODE
bool "SOF force nocodec Mode" bool "SOF force nocodec Mode"
depends on SND_SOC_SOF_NOCODEC depends on SND_SOC_SOF_NOCODEC_SUPPORT
help help
This forces SOF to use dummy/nocodec as machine driver, even This forces SOF to use dummy/nocodec as machine driver, even
though there is a codec detected on the real platform. This is though there is a codec detected on the real platform. This is
...@@ -135,6 +138,7 @@ endif ## SND_SOC_SOF_OPTIONS ...@@ -135,6 +138,7 @@ endif ## SND_SOC_SOF_OPTIONS
config SND_SOC_SOF config SND_SOC_SOF
tristate tristate
select SND_SOC_TOPOLOGY select SND_SOC_TOPOLOGY
select SND_SOC_SOF_NOCODEC if SND_SOC_SOF_NOCODEC_SUPPORT
help help
This option is not user-selectable but automagically handled by This option is not user-selectable but automagically handled by
'select' statements at a higher level 'select' statements at a higher level
......
...@@ -349,6 +349,7 @@ int snd_sof_bytes_put(struct snd_kcontrol *kcontrol, ...@@ -349,6 +349,7 @@ int snd_sof_bytes_put(struct snd_kcontrol *kcontrol,
struct snd_sof_dev *sdev = scontrol->sdev; struct snd_sof_dev *sdev = scontrol->sdev;
struct sof_ipc_ctrl_data *cdata = scontrol->control_data; struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
struct sof_abi_hdr *data = cdata->data; struct sof_abi_hdr *data = cdata->data;
size_t size = data->size + sizeof(*data);
int ret, err; int ret, err;
if (be->max > sizeof(ucontrol->value.bytes.data)) { if (be->max > sizeof(ucontrol->value.bytes.data)) {
...@@ -358,10 +359,10 @@ int snd_sof_bytes_put(struct snd_kcontrol *kcontrol, ...@@ -358,10 +359,10 @@ int snd_sof_bytes_put(struct snd_kcontrol *kcontrol,
return -EINVAL; return -EINVAL;
} }
if (data->size > be->max) { if (size > be->max) {
dev_err_ratelimited(sdev->dev, dev_err_ratelimited(sdev->dev,
"error: size too big %d bytes max is %d\n", "error: size too big %zu bytes max is %d\n",
data->size, be->max); size, be->max);
return -EINVAL; return -EINVAL;
} }
...@@ -375,7 +376,7 @@ int snd_sof_bytes_put(struct snd_kcontrol *kcontrol, ...@@ -375,7 +376,7 @@ int snd_sof_bytes_put(struct snd_kcontrol *kcontrol,
} }
/* copy from kcontrol */ /* copy from kcontrol */
memcpy(data, ucontrol->value.bytes.data, data->size); memcpy(data, ucontrol->value.bytes.data, size);
/* notify DSP of byte control updates */ /* notify DSP of byte control updates */
snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol, snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol,
......
...@@ -382,7 +382,7 @@ static int sof_probe_continue(struct snd_sof_dev *sdev) ...@@ -382,7 +382,7 @@ static int sof_probe_continue(struct snd_sof_dev *sdev)
if (IS_ERR(plat_data->pdev_mach)) { if (IS_ERR(plat_data->pdev_mach)) {
ret = PTR_ERR(plat_data->pdev_mach); ret = PTR_ERR(plat_data->pdev_mach);
goto comp_err; goto fw_run_err;
} }
dev_dbg(sdev->dev, "created machine %s\n", dev_dbg(sdev->dev, "created machine %s\n",
...@@ -393,8 +393,7 @@ static int sof_probe_continue(struct snd_sof_dev *sdev) ...@@ -393,8 +393,7 @@ static int sof_probe_continue(struct snd_sof_dev *sdev)
return 0; return 0;
comp_err: #if !IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE)
snd_soc_unregister_component(sdev->dev);
fw_run_err: fw_run_err:
snd_sof_fw_unload(sdev); snd_sof_fw_unload(sdev);
fw_load_err: fw_load_err:
...@@ -403,6 +402,21 @@ static int sof_probe_continue(struct snd_sof_dev *sdev) ...@@ -403,6 +402,21 @@ static int sof_probe_continue(struct snd_sof_dev *sdev)
snd_sof_free_debug(sdev); snd_sof_free_debug(sdev);
dbg_err: dbg_err:
snd_sof_remove(sdev); snd_sof_remove(sdev);
#else
/*
* when the probe_continue is handled in a work queue, the
* probe does not fail so we don't release resources here.
* They will be released with an explicit call to
* snd_sof_device_remove() when the PCI/ACPI device is removed
*/
fw_run_err:
fw_load_err:
ipc_err:
dbg_err:
#endif
return ret; return ret;
} }
...@@ -484,7 +498,6 @@ int snd_sof_device_remove(struct device *dev) ...@@ -484,7 +498,6 @@ 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_free_trace(sdev); snd_sof_free_trace(sdev);
snd_sof_remove(sdev);
/* /*
* Unregister machine driver. This will unbind the snd_card which * Unregister machine driver. This will unbind the snd_card which
...@@ -494,6 +507,14 @@ int snd_sof_device_remove(struct device *dev) ...@@ -494,6 +507,14 @@ int snd_sof_device_remove(struct device *dev)
if (!IS_ERR_OR_NULL(pdata->pdev_mach)) if (!IS_ERR_OR_NULL(pdata->pdev_mach))
platform_device_unregister(pdata->pdev_mach); platform_device_unregister(pdata->pdev_mach);
/*
* Unregistering the machine driver results in unloading the topology.
* Some widgets, ex: scheduler, attempt to power down the core they are
* scheduled on, when they are unloaded. Therefore, the DSP must be
* removed only after the topology has been unloaded.
*/
snd_sof_remove(sdev);
/* release firmware */ /* release firmware */
release_firmware(pdata->fw); release_firmware(pdata->fw);
pdata->fw = NULL; pdata->fw = NULL;
......
...@@ -220,17 +220,20 @@ static void bdw_get_registers(struct snd_sof_dev *sdev, ...@@ -220,17 +220,20 @@ static void bdw_get_registers(struct snd_sof_dev *sdev,
struct sof_ipc_panic_info *panic_info, struct sof_ipc_panic_info *panic_info,
u32 *stack, size_t stack_words) u32 *stack, size_t stack_words)
{ {
/* first read regsisters */ u32 offset = sdev->dsp_oops_offset;
sof_mailbox_read(sdev, sdev->dsp_oops_offset, xoops, sizeof(*xoops));
/* first read registers */
sof_mailbox_read(sdev, offset, xoops, sizeof(*xoops));
/* note: variable AR register array is not read */
/* then get panic info */ /* then get panic info */
sof_mailbox_read(sdev, sdev->dsp_oops_offset + sizeof(*xoops), offset += xoops->arch_hdr.totalsize;
panic_info, sizeof(*panic_info)); sof_mailbox_read(sdev, offset, panic_info, sizeof(*panic_info));
/* then get the stack */ /* then get the stack */
sof_mailbox_read(sdev, sdev->dsp_oops_offset + sizeof(*xoops) + offset += sizeof(*panic_info);
sizeof(*panic_info), stack, sof_mailbox_read(sdev, offset, stack, stack_words * sizeof(u32));
stack_words * sizeof(u32));
} }
static void bdw_dump(struct snd_sof_dev *sdev, u32 flags) static void bdw_dump(struct snd_sof_dev *sdev, u32 flags)
...@@ -283,6 +286,8 @@ static irqreturn_t bdw_irq_thread(int irq, void *context) ...@@ -283,6 +286,8 @@ static irqreturn_t bdw_irq_thread(int irq, void *context)
SHIM_IMRX, SHIM_IMRX_DONE, SHIM_IMRX, SHIM_IMRX_DONE,
SHIM_IMRX_DONE); SHIM_IMRX_DONE);
spin_lock_irq(&sdev->ipc_lock);
/* /*
* handle immediate reply from DSP core. If the msg is * handle immediate reply from DSP core. If the msg is
* found, set done bit in cmd_done which is called at the * found, set done bit in cmd_done which is called at the
...@@ -294,6 +299,8 @@ static irqreturn_t bdw_irq_thread(int irq, void *context) ...@@ -294,6 +299,8 @@ static irqreturn_t bdw_irq_thread(int irq, void *context)
snd_sof_ipc_reply(sdev, ipcx); snd_sof_ipc_reply(sdev, ipcx);
bdw_dsp_done(sdev); bdw_dsp_done(sdev);
spin_unlock_irq(&sdev->ipc_lock);
} }
ipcd = snd_sof_dsp_read(sdev, BDW_DSP_BAR, SHIM_IPCD); ipcd = snd_sof_dsp_read(sdev, BDW_DSP_BAR, SHIM_IPCD);
...@@ -485,7 +492,6 @@ static void bdw_get_reply(struct snd_sof_dev *sdev) ...@@ -485,7 +492,6 @@ static void bdw_get_reply(struct snd_sof_dev *sdev)
{ {
struct snd_sof_ipc_msg *msg = sdev->msg; struct snd_sof_ipc_msg *msg = sdev->msg;
struct sof_ipc_reply reply; struct sof_ipc_reply reply;
unsigned long flags;
int ret = 0; int ret = 0;
/* /*
...@@ -501,8 +507,6 @@ static void bdw_get_reply(struct snd_sof_dev *sdev) ...@@ -501,8 +507,6 @@ static void bdw_get_reply(struct snd_sof_dev *sdev)
/* get reply */ /* get reply */
sof_mailbox_read(sdev, sdev->host_box.offset, &reply, sizeof(reply)); sof_mailbox_read(sdev, sdev->host_box.offset, &reply, sizeof(reply));
spin_lock_irqsave(&sdev->ipc_lock, flags);
if (reply.error < 0) { if (reply.error < 0) {
memcpy(msg->reply_data, &reply, sizeof(reply)); memcpy(msg->reply_data, &reply, sizeof(reply));
ret = reply.error; ret = reply.error;
...@@ -521,8 +525,6 @@ static void bdw_get_reply(struct snd_sof_dev *sdev) ...@@ -521,8 +525,6 @@ static void bdw_get_reply(struct snd_sof_dev *sdev)
} }
msg->reply_error = ret; msg->reply_error = ret;
spin_unlock_irqrestore(&sdev->ipc_lock, flags);
} }
static void bdw_host_done(struct snd_sof_dev *sdev) static void bdw_host_done(struct snd_sof_dev *sdev)
......
...@@ -265,17 +265,20 @@ static void byt_get_registers(struct snd_sof_dev *sdev, ...@@ -265,17 +265,20 @@ static void byt_get_registers(struct snd_sof_dev *sdev,
struct sof_ipc_panic_info *panic_info, struct sof_ipc_panic_info *panic_info,
u32 *stack, size_t stack_words) u32 *stack, size_t stack_words)
{ {
u32 offset = sdev->dsp_oops_offset;
/* first read regsisters */ /* first read regsisters */
sof_mailbox_read(sdev, sdev->dsp_oops_offset, xoops, sizeof(*xoops)); sof_mailbox_read(sdev, offset, xoops, sizeof(*xoops));
/* note: variable AR register array is not read */
/* then get panic info */ /* then get panic info */
sof_mailbox_read(sdev, sdev->dsp_oops_offset + sizeof(*xoops), offset += xoops->arch_hdr.totalsize;
panic_info, sizeof(*panic_info)); sof_mailbox_read(sdev, offset, panic_info, sizeof(*panic_info));
/* then get the stack */ /* then get the stack */
sof_mailbox_read(sdev, sdev->dsp_oops_offset + sizeof(*xoops) + offset += sizeof(*panic_info);
sizeof(*panic_info), stack, sof_mailbox_read(sdev, offset, stack, stack_words * sizeof(u32));
stack_words * sizeof(u32));
} }
static void byt_dump(struct snd_sof_dev *sdev, u32 flags) static void byt_dump(struct snd_sof_dev *sdev, u32 flags)
...@@ -329,6 +332,9 @@ static irqreturn_t byt_irq_thread(int irq, void *context) ...@@ -329,6 +332,9 @@ static irqreturn_t byt_irq_thread(int irq, void *context)
SHIM_IMRX, SHIM_IMRX,
SHIM_IMRX_DONE, SHIM_IMRX_DONE,
SHIM_IMRX_DONE); SHIM_IMRX_DONE);
spin_lock_irq(&sdev->ipc_lock);
/* /*
* handle immediate reply from DSP core. If the msg is * handle immediate reply from DSP core. If the msg is
* found, set done bit in cmd_done which is called at the * found, set done bit in cmd_done which is called at the
...@@ -340,6 +346,8 @@ static irqreturn_t byt_irq_thread(int irq, void *context) ...@@ -340,6 +346,8 @@ static irqreturn_t byt_irq_thread(int irq, void *context)
snd_sof_ipc_reply(sdev, ipcx); snd_sof_ipc_reply(sdev, ipcx);
byt_dsp_done(sdev); byt_dsp_done(sdev);
spin_unlock_irq(&sdev->ipc_lock);
} }
/* new message from DSP */ /* new message from DSP */
...@@ -383,7 +391,6 @@ static void byt_get_reply(struct snd_sof_dev *sdev) ...@@ -383,7 +391,6 @@ static void byt_get_reply(struct snd_sof_dev *sdev)
{ {
struct snd_sof_ipc_msg *msg = sdev->msg; struct snd_sof_ipc_msg *msg = sdev->msg;
struct sof_ipc_reply reply; struct sof_ipc_reply reply;
unsigned long flags;
int ret = 0; int ret = 0;
/* /*
...@@ -399,8 +406,6 @@ static void byt_get_reply(struct snd_sof_dev *sdev) ...@@ -399,8 +406,6 @@ static void byt_get_reply(struct snd_sof_dev *sdev)
/* get reply */ /* get reply */
sof_mailbox_read(sdev, sdev->host_box.offset, &reply, sizeof(reply)); sof_mailbox_read(sdev, sdev->host_box.offset, &reply, sizeof(reply));
spin_lock_irqsave(&sdev->ipc_lock, flags);
if (reply.error < 0) { if (reply.error < 0) {
memcpy(msg->reply_data, &reply, sizeof(reply)); memcpy(msg->reply_data, &reply, sizeof(reply));
ret = reply.error; ret = reply.error;
...@@ -419,8 +424,6 @@ static void byt_get_reply(struct snd_sof_dev *sdev) ...@@ -419,8 +424,6 @@ static void byt_get_reply(struct snd_sof_dev *sdev)
} }
msg->reply_error = ret; msg->reply_error = ret;
spin_unlock_irqrestore(&sdev->ipc_lock, flags);
} }
static void byt_host_done(struct snd_sof_dev *sdev) static void byt_host_done(struct snd_sof_dev *sdev)
......
...@@ -64,6 +64,8 @@ static irqreturn_t cnl_ipc_irq_thread(int irq, void *context) ...@@ -64,6 +64,8 @@ static irqreturn_t cnl_ipc_irq_thread(int irq, void *context)
CNL_DSP_REG_HIPCCTL, CNL_DSP_REG_HIPCCTL,
CNL_DSP_REG_HIPCCTL_DONE, 0); CNL_DSP_REG_HIPCCTL_DONE, 0);
spin_lock_irq(&sdev->ipc_lock);
/* handle immediate reply from DSP core */ /* handle immediate reply from DSP core */
hda_dsp_ipc_get_reply(sdev); hda_dsp_ipc_get_reply(sdev);
snd_sof_ipc_reply(sdev, msg); snd_sof_ipc_reply(sdev, msg);
...@@ -75,6 +77,8 @@ static irqreturn_t cnl_ipc_irq_thread(int irq, void *context) ...@@ -75,6 +77,8 @@ static irqreturn_t cnl_ipc_irq_thread(int irq, void *context)
cnl_ipc_dsp_done(sdev); cnl_ipc_dsp_done(sdev);
spin_unlock_irq(&sdev->ipc_lock);
ret = IRQ_HANDLED; ret = IRQ_HANDLED;
} }
......
...@@ -161,21 +161,105 @@ int hda_dsp_ctrl_clock_power_gating(struct snd_sof_dev *sdev, bool enable) ...@@ -161,21 +161,105 @@ int hda_dsp_ctrl_clock_power_gating(struct snd_sof_dev *sdev, bool enable)
return 0; return 0;
} }
#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
/*
* While performing reset, controller may not come back properly and causing
* issues, so recommendation is to set CGCTL.MISCBDCGE to 0 then do reset
* (init chip) and then again set CGCTL.MISCBDCGE to 1
*/
int hda_dsp_ctrl_init_chip(struct snd_sof_dev *sdev, bool full_reset) int hda_dsp_ctrl_init_chip(struct snd_sof_dev *sdev, bool full_reset)
{ {
struct hdac_bus *bus = sof_to_bus(sdev); struct hdac_bus *bus = sof_to_bus(sdev);
int ret; struct hdac_stream *stream;
int sd_offset, ret = 0;
if (bus->chip_init)
return 0;
hda_dsp_ctrl_misc_clock_gating(sdev, false); hda_dsp_ctrl_misc_clock_gating(sdev, false);
ret = snd_hdac_bus_init_chip(bus, full_reset);
if (full_reset) {
/* clear WAKESTS */
snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, SOF_HDA_WAKESTS,
SOF_HDA_WAKESTS_INT_MASK,
SOF_HDA_WAKESTS_INT_MASK);
/* reset HDA controller */
ret = hda_dsp_ctrl_link_reset(sdev, true);
if (ret < 0) {
dev_err(sdev->dev, "error: failed to reset HDA controller\n");
return ret;
}
usleep_range(500, 1000);
/* exit HDA controller reset */
ret = hda_dsp_ctrl_link_reset(sdev, false);
if (ret < 0) {
dev_err(sdev->dev, "error: failed to exit HDA controller reset\n");
return ret;
}
usleep_range(1000, 1200);
}
#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
/* check to see if controller is ready */
if (!snd_hdac_chip_readb(bus, GCTL)) {
dev_dbg(bus->dev, "controller not ready!\n");
return -EBUSY;
}
/* Accept unsolicited responses */
snd_hdac_chip_updatel(bus, GCTL, AZX_GCTL_UNSOL, AZX_GCTL_UNSOL);
/* detect codecs */
if (!bus->codec_mask) {
bus->codec_mask = snd_hdac_chip_readw(bus, STATESTS);
dev_dbg(bus->dev, "codec_mask = 0x%lx\n", bus->codec_mask);
}
#endif
/* clear stream status */
list_for_each_entry(stream, &bus->stream_list, list) {
sd_offset = SOF_STREAM_SD_OFFSET(stream);
snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR,
sd_offset +
SOF_HDA_ADSP_REG_CL_SD_STS,
SOF_HDA_CL_DMA_SD_INT_MASK,
SOF_HDA_CL_DMA_SD_INT_MASK);
}
/* clear WAKESTS */
snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, SOF_HDA_WAKESTS,
SOF_HDA_WAKESTS_INT_MASK,
SOF_HDA_WAKESTS_INT_MASK);
#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
/* clear rirb status */
snd_hdac_chip_writeb(bus, RIRBSTS, RIRB_INT_MASK);
#endif
/* clear interrupt status register */
snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTSTS,
SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_ALL_STREAM);
#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
/* initialize the codec command I/O */
snd_hdac_bus_init_cmd_io(bus);
#endif
/* enable CIE and GIE interrupts */
snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTCTL,
SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_GLOBAL_EN,
SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_GLOBAL_EN);
#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
/* program the position buffer */
if (bus->use_posbuf && bus->posbuf.addr) {
snd_hdac_chip_writel(bus, DPLBASE, (u32)bus->posbuf.addr);
snd_hdac_chip_writel(bus, DPUBASE,
upper_32_bits(bus->posbuf.addr));
}
#endif
bus->chip_init = true;
hda_dsp_ctrl_misc_clock_gating(sdev, true); hda_dsp_ctrl_misc_clock_gating(sdev, true);
return ret; return ret;
} }
#endif
...@@ -72,7 +72,6 @@ void hda_dsp_ipc_get_reply(struct snd_sof_dev *sdev) ...@@ -72,7 +72,6 @@ void hda_dsp_ipc_get_reply(struct snd_sof_dev *sdev)
struct snd_sof_ipc_msg *msg = sdev->msg; struct snd_sof_ipc_msg *msg = sdev->msg;
struct sof_ipc_reply reply; struct sof_ipc_reply reply;
struct sof_ipc_cmd_hdr *hdr; struct sof_ipc_cmd_hdr *hdr;
unsigned long flags;
int ret = 0; int ret = 0;
/* /*
...@@ -84,7 +83,6 @@ void hda_dsp_ipc_get_reply(struct snd_sof_dev *sdev) ...@@ -84,7 +83,6 @@ void hda_dsp_ipc_get_reply(struct snd_sof_dev *sdev)
dev_warn(sdev->dev, "unexpected ipc interrupt raised!\n"); dev_warn(sdev->dev, "unexpected ipc interrupt raised!\n");
return; return;
} }
spin_lock_irqsave(&sdev->ipc_lock, flags);
hdr = msg->msg_data; hdr = msg->msg_data;
if (hdr->cmd == (SOF_IPC_GLB_PM_MSG | SOF_IPC_PM_CTX_SAVE)) { if (hdr->cmd == (SOF_IPC_GLB_PM_MSG | SOF_IPC_PM_CTX_SAVE)) {
...@@ -123,7 +121,6 @@ void hda_dsp_ipc_get_reply(struct snd_sof_dev *sdev) ...@@ -123,7 +121,6 @@ void hda_dsp_ipc_get_reply(struct snd_sof_dev *sdev)
out: out:
msg->reply_error = ret; msg->reply_error = ret;
spin_unlock_irqrestore(&sdev->ipc_lock, flags);
} }
static bool hda_dsp_ipc_is_sof(uint32_t msg) static bool hda_dsp_ipc_is_sof(uint32_t msg)
...@@ -172,6 +169,18 @@ irqreturn_t hda_dsp_ipc_irq_thread(int irq, void *context) ...@@ -172,6 +169,18 @@ irqreturn_t hda_dsp_ipc_irq_thread(int irq, void *context)
HDA_DSP_REG_HIPCCTL, HDA_DSP_REG_HIPCCTL,
HDA_DSP_REG_HIPCCTL_DONE, 0); HDA_DSP_REG_HIPCCTL_DONE, 0);
/*
* Make sure the interrupt thread cannot be preempted between
* waking up the sender and re-enabling the interrupt. Also
* protect against a theoretical race with sof_ipc_tx_message():
* if the DSP is fast enough to receive an IPC message, reply to
* it, and the host interrupt processing calls this function on
* a different core from the one, where the sending is taking
* place, the message might not yet be marked as expecting a
* reply.
*/
spin_lock_irq(&sdev->ipc_lock);
/* handle immediate reply from DSP core - ignore ROM messages */ /* handle immediate reply from DSP core - ignore ROM messages */
if (hda_dsp_ipc_is_sof(msg)) { if (hda_dsp_ipc_is_sof(msg)) {
hda_dsp_ipc_get_reply(sdev); hda_dsp_ipc_get_reply(sdev);
...@@ -187,6 +196,8 @@ irqreturn_t hda_dsp_ipc_irq_thread(int irq, void *context) ...@@ -187,6 +196,8 @@ irqreturn_t hda_dsp_ipc_irq_thread(int irq, void *context)
/* set the done bit */ /* set the done bit */
hda_dsp_ipc_dsp_done(sdev); hda_dsp_ipc_dsp_done(sdev);
spin_unlock_irq(&sdev->ipc_lock);
ret = IRQ_HANDLED; ret = IRQ_HANDLED;
} }
......
...@@ -108,17 +108,21 @@ static void hda_dsp_get_registers(struct snd_sof_dev *sdev, ...@@ -108,17 +108,21 @@ static void hda_dsp_get_registers(struct snd_sof_dev *sdev,
struct sof_ipc_panic_info *panic_info, struct sof_ipc_panic_info *panic_info,
u32 *stack, size_t stack_words) u32 *stack, size_t stack_words)
{ {
u32 offset = sdev->dsp_oops_offset;
/* first read registers */ /* first read registers */
sof_block_read(sdev, sdev->mmio_bar, sdev->dsp_oops_offset, xoops, sof_mailbox_read(sdev, offset, xoops, sizeof(*xoops));
sizeof(*xoops));
/* note: variable AR register array is not read */
/* then get panic info */ /* then get panic info */
sof_block_read(sdev, sdev->mmio_bar, sdev->dsp_oops_offset + offset += xoops->arch_hdr.totalsize;
sizeof(*xoops), panic_info, sizeof(*panic_info)); sof_block_read(sdev, sdev->mmio_bar, offset,
panic_info, sizeof(*panic_info));
/* then get the stack */ /* then get the stack */
sof_block_read(sdev, sdev->mmio_bar, sdev->dsp_oops_offset + offset += sizeof(*panic_info);
sizeof(*xoops) + sizeof(*panic_info), stack, sof_block_read(sdev, sdev->mmio_bar, offset, stack,
stack_words * sizeof(u32)); stack_words * sizeof(u32));
} }
...@@ -223,7 +227,9 @@ static int hda_init(struct snd_sof_dev *sdev) ...@@ -223,7 +227,9 @@ static int hda_init(struct snd_sof_dev *sdev)
/* initialise hdac bus */ /* initialise hdac bus */
bus->addr = pci_resource_start(pci, 0); bus->addr = pci_resource_start(pci, 0);
#if IS_ENABLED(CONFIG_PCI)
bus->remap_addr = pci_ioremap_bar(pci, 0); bus->remap_addr = pci_ioremap_bar(pci, 0);
#endif
if (!bus->remap_addr) { if (!bus->remap_addr) {
dev_err(bus->dev, "error: ioremap error\n"); dev_err(bus->dev, "error: ioremap error\n");
return -ENXIO; return -ENXIO;
...@@ -264,9 +270,12 @@ static const char *fixup_tplg_name(struct snd_sof_dev *sdev, ...@@ -264,9 +270,12 @@ static const char *fixup_tplg_name(struct snd_sof_dev *sdev,
return tplg_filename; return tplg_filename;
} }
#endif
static int hda_init_caps(struct snd_sof_dev *sdev) static int hda_init_caps(struct snd_sof_dev *sdev)
{ {
struct hdac_bus *bus = sof_to_bus(sdev); struct hdac_bus *bus = sof_to_bus(sdev);
#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
struct hdac_ext_link *hlink; struct hdac_ext_link *hlink;
struct snd_soc_acpi_mach_params *mach_params; struct snd_soc_acpi_mach_params *mach_params;
struct snd_soc_acpi_mach *hda_mach; struct snd_soc_acpi_mach *hda_mach;
...@@ -274,8 +283,9 @@ static int hda_init_caps(struct snd_sof_dev *sdev) ...@@ -274,8 +283,9 @@ static int hda_init_caps(struct snd_sof_dev *sdev)
struct snd_soc_acpi_mach *mach; struct snd_soc_acpi_mach *mach;
const char *tplg_filename; const char *tplg_filename;
int codec_num = 0; int codec_num = 0;
int ret = 0;
int i; int i;
#endif
int ret = 0;
device_disable_async_suspend(bus->dev); device_disable_async_suspend(bus->dev);
...@@ -283,6 +293,14 @@ static int hda_init_caps(struct snd_sof_dev *sdev) ...@@ -283,6 +293,14 @@ static int hda_init_caps(struct snd_sof_dev *sdev)
if (bus->ppcap) if (bus->ppcap)
dev_dbg(sdev->dev, "PP capability, will probe DSP later.\n"); dev_dbg(sdev->dev, "PP capability, will probe DSP later.\n");
ret = hda_dsp_ctrl_init_chip(sdev, true);
if (ret < 0) {
dev_err(bus->dev, "error: init chip failed with ret: %d\n",
ret);
return ret;
}
#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
if (bus->mlcap) if (bus->mlcap)
snd_hdac_ext_bus_get_ml_capabilities(bus); snd_hdac_ext_bus_get_ml_capabilities(bus);
...@@ -293,12 +311,6 @@ static int hda_init_caps(struct snd_sof_dev *sdev) ...@@ -293,12 +311,6 @@ static int hda_init_caps(struct snd_sof_dev *sdev)
return ret; return ret;
} }
ret = hda_dsp_ctrl_init_chip(sdev, true);
if (ret < 0) {
dev_err(bus->dev, "error: init chip failed with ret: %d\n", ret);
goto out;
}
/* codec detection */ /* codec detection */
if (!bus->codec_mask) { if (!bus->codec_mask) {
dev_info(bus->dev, "no hda codecs found!\n"); dev_info(bus->dev, "no hda codecs found!\n");
...@@ -339,8 +351,10 @@ static int hda_init_caps(struct snd_sof_dev *sdev) ...@@ -339,8 +351,10 @@ static int hda_init_caps(struct snd_sof_dev *sdev)
/* use local variable for readability */ /* use local variable for readability */
tplg_filename = pdata->tplg_filename; tplg_filename = pdata->tplg_filename;
tplg_filename = fixup_tplg_name(sdev, tplg_filename); tplg_filename = fixup_tplg_name(sdev, tplg_filename);
if (!tplg_filename) if (!tplg_filename) {
goto out; hda_codec_i915_exit(sdev);
return ret;
}
pdata->tplg_filename = tplg_filename; pdata->tplg_filename = tplg_filename;
} }
} }
...@@ -364,35 +378,10 @@ static int hda_init_caps(struct snd_sof_dev *sdev) ...@@ -364,35 +378,10 @@ static int hda_init_caps(struct snd_sof_dev *sdev)
*/ */
list_for_each_entry(hlink, &bus->hlink_list, list) list_for_each_entry(hlink, &bus->hlink_list, list)
snd_hdac_ext_bus_link_put(bus, hlink); snd_hdac_ext_bus_link_put(bus, hlink);
#endif
return 0;
out:
hda_codec_i915_exit(sdev);
return ret;
}
#else
static int hda_init_caps(struct snd_sof_dev *sdev)
{
/*
* set CGCTL.MISCBDCGE to 0 during reset and set back to 1
* when reset finished.
* TODO: maybe no need for init_caps?
*/
hda_dsp_ctrl_misc_clock_gating(sdev, 0);
/* clear WAKESTS */
snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, SOF_HDA_WAKESTS,
SOF_HDA_WAKESTS_INT_MASK,
SOF_HDA_WAKESTS_INT_MASK);
return 0; return 0;
} }
#endif
static const struct sof_intel_dsp_desc static const struct sof_intel_dsp_desc
*get_chip_info(struct snd_sof_pdata *pdata) *get_chip_info(struct snd_sof_pdata *pdata)
{ {
...@@ -409,9 +398,8 @@ int hda_dsp_probe(struct snd_sof_dev *sdev) ...@@ -409,9 +398,8 @@ int hda_dsp_probe(struct snd_sof_dev *sdev)
struct pci_dev *pci = to_pci_dev(sdev->dev); struct pci_dev *pci = to_pci_dev(sdev->dev);
struct sof_intel_hda_dev *hdev; struct sof_intel_hda_dev *hdev;
struct hdac_bus *bus; struct hdac_bus *bus;
struct hdac_stream *stream;
const struct sof_intel_dsp_desc *chip; const struct sof_intel_dsp_desc *chip;
int sd_offset, ret = 0; int ret = 0;
/* /*
* detect DSP by checking class/subclass/prog-id information * detect DSP by checking class/subclass/prog-id information
...@@ -468,7 +456,9 @@ int hda_dsp_probe(struct snd_sof_dev *sdev) ...@@ -468,7 +456,9 @@ int hda_dsp_probe(struct snd_sof_dev *sdev)
goto hdac_bus_unmap; goto hdac_bus_unmap;
/* DSP base */ /* DSP base */
#if IS_ENABLED(CONFIG_PCI)
sdev->bar[HDA_DSP_BAR] = pci_ioremap_bar(pci, HDA_DSP_BAR); sdev->bar[HDA_DSP_BAR] = pci_ioremap_bar(pci, HDA_DSP_BAR);
#endif
if (!sdev->bar[HDA_DSP_BAR]) { if (!sdev->bar[HDA_DSP_BAR]) {
dev_err(sdev->dev, "error: ioremap error\n"); dev_err(sdev->dev, "error: ioremap error\n");
ret = -ENXIO; ret = -ENXIO;
...@@ -558,56 +548,9 @@ int hda_dsp_probe(struct snd_sof_dev *sdev) ...@@ -558,56 +548,9 @@ int hda_dsp_probe(struct snd_sof_dev *sdev)
if (ret < 0) if (ret < 0)
goto free_ipc_irq; goto free_ipc_irq;
/* reset HDA controller */ /* enable ppcap interrupt */
ret = hda_dsp_ctrl_link_reset(sdev, true); hda_dsp_ctrl_ppcap_enable(sdev, true);
if (ret < 0) { hda_dsp_ctrl_ppcap_int_enable(sdev, true);
dev_err(sdev->dev, "error: failed to reset HDA controller\n");
goto free_ipc_irq;
}
/* exit HDA controller reset */
ret = hda_dsp_ctrl_link_reset(sdev, false);
if (ret < 0) {
dev_err(sdev->dev, "error: failed to exit HDA controller reset\n");
goto free_ipc_irq;
}
/* clear stream status */
list_for_each_entry(stream, &bus->stream_list, list) {
sd_offset = SOF_STREAM_SD_OFFSET(stream);
snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR,
sd_offset +
SOF_HDA_ADSP_REG_CL_SD_STS,
SOF_HDA_CL_DMA_SD_INT_MASK,
SOF_HDA_CL_DMA_SD_INT_MASK);
}
/* clear WAKESTS */
snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, SOF_HDA_WAKESTS,
SOF_HDA_WAKESTS_INT_MASK,
SOF_HDA_WAKESTS_INT_MASK);
/* clear interrupt status register */
snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTSTS,
SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_ALL_STREAM);
/* enable CIE and GIE interrupts */
snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTCTL,
SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_GLOBAL_EN,
SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_GLOBAL_EN);
/* re-enable CGCTL.MISCBDCGE after reset */
hda_dsp_ctrl_misc_clock_gating(sdev, true);
device_disable_async_suspend(&pci->dev);
/* enable DSP features */
snd_sof_dsp_update_bits(sdev, HDA_DSP_PP_BAR, SOF_HDA_REG_PP_PPCTL,
SOF_HDA_PPCTL_GPROCEN, SOF_HDA_PPCTL_GPROCEN);
/* enable DSP IRQ */
snd_sof_dsp_update_bits(sdev, HDA_DSP_PP_BAR, SOF_HDA_REG_PP_PPCTL,
SOF_HDA_PPCTL_PIE, SOF_HDA_PPCTL_PIE);
/* initialize waitq for code loading */ /* initialize waitq for code loading */
init_waitqueue_head(&sdev->waitq); init_waitqueue_head(&sdev->waitq);
......
...@@ -115,7 +115,7 @@ static void ipc_log_header(struct device *dev, u8 *text, u32 cmd) ...@@ -115,7 +115,7 @@ static void ipc_log_header(struct device *dev, u8 *text, u32 cmd)
} }
break; break;
case SOF_IPC_GLB_COMP_MSG: case SOF_IPC_GLB_COMP_MSG:
str = "GLB_COMP_MSG: SET_VALUE"; str = "GLB_COMP_MSG";
switch (type) { switch (type) {
case SOF_IPC_COMP_SET_VALUE: case SOF_IPC_COMP_SET_VALUE:
str2 = "SET_VALUE"; break; str2 = "SET_VALUE"; break;
...@@ -308,19 +308,8 @@ EXPORT_SYMBOL(sof_ipc_tx_message); ...@@ -308,19 +308,8 @@ EXPORT_SYMBOL(sof_ipc_tx_message);
int snd_sof_ipc_reply(struct snd_sof_dev *sdev, u32 msg_id) int snd_sof_ipc_reply(struct snd_sof_dev *sdev, u32 msg_id)
{ {
struct snd_sof_ipc_msg *msg = &sdev->ipc->msg; struct snd_sof_ipc_msg *msg = &sdev->ipc->msg;
unsigned long flags;
/*
* Protect against a theoretical race with sof_ipc_tx_message(): if the
* DSP is fast enough to receive an IPC message, reply to it, and the
* host interrupt processing calls this function on a different core
* from the one, where the sending is taking place, the message might
* not yet be marked as expecting a reply.
*/
spin_lock_irqsave(&sdev->ipc_lock, flags);
if (msg->ipc_complete) { if (msg->ipc_complete) {
spin_unlock_irqrestore(&sdev->ipc_lock, flags);
dev_err(sdev->dev, "error: no reply expected, received 0x%x", dev_err(sdev->dev, "error: no reply expected, received 0x%x",
msg_id); msg_id);
return -EINVAL; return -EINVAL;
...@@ -330,8 +319,6 @@ int snd_sof_ipc_reply(struct snd_sof_dev *sdev, u32 msg_id) ...@@ -330,8 +319,6 @@ int snd_sof_ipc_reply(struct snd_sof_dev *sdev, u32 msg_id)
msg->ipc_complete = true; msg->ipc_complete = true;
wake_up(&msg->waitq); wake_up(&msg->waitq);
spin_unlock_irqrestore(&sdev->ipc_lock, flags);
return 0; return 0;
} }
EXPORT_SYMBOL(snd_sof_ipc_reply); EXPORT_SYMBOL(snd_sof_ipc_reply);
...@@ -776,16 +763,19 @@ int snd_sof_ipc_valid(struct snd_sof_dev *sdev) ...@@ -776,16 +763,19 @@ int snd_sof_ipc_valid(struct snd_sof_dev *sdev)
} }
} }
if (ready->debug.bits.build) { if (ready->flags & SOF_IPC_INFO_BUILD) {
dev_info(sdev->dev, dev_info(sdev->dev,
"Firmware debug build %d on %s-%s - options:\n" "Firmware debug build %d on %s-%s - options:\n"
" GDB: %s\n" " GDB: %s\n"
" lock debug: %s\n" " lock debug: %s\n"
" lock vdebug: %s\n", " lock vdebug: %s\n",
v->build, v->date, v->time, v->build, v->date, v->time,
ready->debug.bits.gdb ? "enabled" : "disabled", ready->flags & SOF_IPC_INFO_GDB ?
ready->debug.bits.locks ? "enabled" : "disabled", "enabled" : "disabled",
ready->debug.bits.locks_verbose ? "enabled" : "disabled"); ready->flags & SOF_IPC_INFO_LOCKS ?
"enabled" : "disabled",
ready->flags & SOF_IPC_INFO_LOCKSV ?
"enabled" : "disabled");
} }
/* copy the fw_version into debugfs at first boot */ /* copy the fw_version into debugfs at first boot */
......
...@@ -372,6 +372,8 @@ int snd_sof_run_firmware(struct snd_sof_dev *sdev) ...@@ -372,6 +372,8 @@ int snd_sof_run_firmware(struct snd_sof_dev *sdev)
msecs_to_jiffies(sdev->boot_timeout)); msecs_to_jiffies(sdev->boot_timeout));
if (ret == 0) { if (ret == 0) {
dev_err(sdev->dev, "error: firmware boot failure\n"); dev_err(sdev->dev, "error: firmware boot failure\n");
/* after this point FW_READY msg should be ignored */
sdev->boot_complete = true;
snd_sof_dsp_dbg_dump(sdev, SOF_DBG_REGS | SOF_DBG_MBOX | snd_sof_dsp_dbg_dump(sdev, SOF_DBG_REGS | SOF_DBG_MBOX |
SOF_DBG_TEXT | SOF_DBG_PCI); SOF_DBG_TEXT | SOF_DBG_PCI);
return -EIO; return -EIO;
......
...@@ -211,8 +211,8 @@ static int sof_pcm_hw_params(struct snd_pcm_substream *substream, ...@@ -211,8 +211,8 @@ static int sof_pcm_hw_params(struct snd_pcm_substream *substream,
/* save pcm hw_params */ /* save pcm hw_params */
memcpy(&spcm->params[substream->stream], params, sizeof(*params)); memcpy(&spcm->params[substream->stream], params, sizeof(*params));
INIT_WORK(&spcm->stream[substream->stream].period_elapsed_work, /* clear hw_params_upon_resume flag */
sof_pcm_period_elapsed_work); spcm->hw_params_upon_resume[substream->stream] = 0;
return ret; return ret;
} }
...@@ -429,8 +429,8 @@ static int sof_pcm_open(struct snd_pcm_substream *substream) ...@@ -429,8 +429,8 @@ static int sof_pcm_open(struct snd_pcm_substream *substream)
dev_dbg(sdev->dev, "pcm: open stream %d dir %d\n", spcm->pcm.pcm_id, dev_dbg(sdev->dev, "pcm: open stream %d dir %d\n", spcm->pcm.pcm_id,
substream->stream); substream->stream);
/* clear hw_params_upon_resume flag */ INIT_WORK(&spcm->stream[substream->stream].period_elapsed_work,
spcm->hw_params_upon_resume[substream->stream] = 0; sof_pcm_period_elapsed_work);
caps = &spcm->pcm.caps[substream->stream]; caps = &spcm->pcm.caps[substream->stream];
......
...@@ -110,7 +110,7 @@ static void xtensa_stack(struct snd_sof_dev *sdev, void *oops, u32 *stack, ...@@ -110,7 +110,7 @@ static void xtensa_stack(struct snd_sof_dev *sdev, void *oops, u32 *stack,
u32 stack_words) u32 stack_words)
{ {
struct sof_ipc_dsp_oops_xtensa *xoops = oops; struct sof_ipc_dsp_oops_xtensa *xoops = oops;
u32 stack_ptr = xoops->stack; u32 stack_ptr = xoops->plat_hdr.stackptr;
/* 4 * 8chars + 3 ws + 1 terminating NUL */ /* 4 * 8chars + 3 ws + 1 terminating NUL */
unsigned char buf[4 * 8 + 3 + 1]; unsigned char buf[4 * 8 + 3 + 1];
int i; int i;
......
...@@ -1329,6 +1329,15 @@ static int sun4i_codec_spk_event(struct snd_soc_dapm_widget *w, ...@@ -1329,6 +1329,15 @@ static int sun4i_codec_spk_event(struct snd_soc_dapm_widget *w,
gpiod_set_value_cansleep(scodec->gpio_pa, gpiod_set_value_cansleep(scodec->gpio_pa,
!!SND_SOC_DAPM_EVENT_ON(event)); !!SND_SOC_DAPM_EVENT_ON(event));
if (SND_SOC_DAPM_EVENT_ON(event)) {
/*
* Need a delay to wait for DAC to push the data. 700ms seems
* to be the best compromise not to feel this delay while
* playing a sound.
*/
msleep(700);
}
return 0; return 0;
} }
......
...@@ -110,7 +110,7 @@ ...@@ -110,7 +110,7 @@
#define SUN8I_I2S_TX_CHAN_MAP_REG 0x44 #define SUN8I_I2S_TX_CHAN_MAP_REG 0x44
#define SUN8I_I2S_TX_CHAN_SEL_REG 0x34 #define SUN8I_I2S_TX_CHAN_SEL_REG 0x34
#define SUN8I_I2S_TX_CHAN_OFFSET_MASK GENMASK(13, 11) #define SUN8I_I2S_TX_CHAN_OFFSET_MASK GENMASK(13, 12)
#define SUN8I_I2S_TX_CHAN_OFFSET(offset) (offset << 12) #define SUN8I_I2S_TX_CHAN_OFFSET(offset) (offset << 12)
#define SUN8I_I2S_TX_CHAN_EN_MASK GENMASK(11, 4) #define SUN8I_I2S_TX_CHAN_EN_MASK GENMASK(11, 4)
#define SUN8I_I2S_TX_CHAN_EN(num_chan) (((1 << num_chan) - 1) << 4) #define SUN8I_I2S_TX_CHAN_EN(num_chan) (((1 << num_chan) - 1) << 4)
...@@ -460,6 +460,10 @@ static int sun4i_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) ...@@ -460,6 +460,10 @@ static int sun4i_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
regmap_update_bits(i2s->regmap, SUN8I_I2S_TX_CHAN_SEL_REG, regmap_update_bits(i2s->regmap, SUN8I_I2S_TX_CHAN_SEL_REG,
SUN8I_I2S_TX_CHAN_OFFSET_MASK, SUN8I_I2S_TX_CHAN_OFFSET_MASK,
SUN8I_I2S_TX_CHAN_OFFSET(offset)); SUN8I_I2S_TX_CHAN_OFFSET(offset));
regmap_update_bits(i2s->regmap, SUN8I_I2S_RX_CHAN_SEL_REG,
SUN8I_I2S_TX_CHAN_OFFSET_MASK,
SUN8I_I2S_TX_CHAN_OFFSET(offset));
} }
regmap_field_write(i2s->field_fmt_mode, val); regmap_field_write(i2s->field_fmt_mode, val);
......
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