Merge branch 'asoc-5.2' into asoc-5.3
This commit is contained in:
commit
79b3b7c4a3
|
@ -283,6 +283,11 @@ static int simple_dai_link_of(struct asoc_simple_priv *priv,
|
|||
codec_dai =
|
||||
dai_props->codec_dai = &priv->dais[li->dais++];
|
||||
|
||||
ret = asoc_simple_parse_daifmt(dev, node, codec,
|
||||
prefix, &dai_link->dai_fmt);
|
||||
if (ret < 0)
|
||||
goto dai_link_of_err;
|
||||
|
||||
simple_parse_mclk_fs(top, cpu, codec, dai_props, prefix);
|
||||
|
||||
ret = asoc_simple_parse_cpu(cpu, dai_link, &single_cpu);
|
||||
|
@ -293,11 +298,6 @@ static int simple_dai_link_of(struct asoc_simple_priv *priv,
|
|||
if (ret < 0)
|
||||
goto dai_link_of_err;
|
||||
|
||||
ret = asoc_simple_parse_daifmt(dev, node, dai_link->codecs->of_node,
|
||||
prefix, &dai_link->dai_fmt);
|
||||
if (ret < 0)
|
||||
goto dai_link_of_err;
|
||||
|
||||
ret = asoc_simple_parse_platform(plat, dai_link);
|
||||
if (ret < 0)
|
||||
goto dai_link_of_err;
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
if (!card->debugfs_card_root)
|
||||
return;
|
||||
debugfs_remove_recursive(card->debugfs_card_root);
|
||||
card->debugfs_card_root = NULL;
|
||||
}
|
||||
|
||||
static void snd_soc_debugfs_init(void)
|
||||
|
@ -1010,12 +1013,14 @@ static void soc_remove_link_components(struct snd_soc_card *card,
|
|||
struct snd_soc_component *component;
|
||||
struct snd_soc_rtdcom_list *rtdcom;
|
||||
|
||||
mutex_lock(&client_mutex);
|
||||
for_each_rtdcom(rtd, rtdcom) {
|
||||
component = rtdcom->component;
|
||||
|
||||
if (component->driver->remove_order == order)
|
||||
soc_remove_component(component);
|
||||
}
|
||||
mutex_unlock(&client_mutex);
|
||||
}
|
||||
|
||||
static void soc_remove_dai_links(struct snd_soc_card *card)
|
||||
|
@ -2035,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)
|
||||
{
|
||||
/* 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);
|
||||
card->snd_card = NULL;
|
||||
}
|
||||
|
||||
/* remove and free each DAI */
|
||||
soc_remove_dai_links(card);
|
||||
|
|
|
@ -2194,7 +2194,10 @@ static void dapm_debugfs_add_widget(struct snd_soc_dapm_widget *w)
|
|||
|
||||
static void dapm_debugfs_cleanup(struct snd_soc_dapm_context *dapm)
|
||||
{
|
||||
if (!dapm->debugfs_dapm)
|
||||
return;
|
||||
debugfs_remove_recursive(dapm->debugfs_dapm);
|
||||
dapm->debugfs_dapm = NULL;
|
||||
}
|
||||
|
||||
#else
|
||||
|
|
|
@ -349,6 +349,7 @@ int snd_sof_bytes_put(struct snd_kcontrol *kcontrol,
|
|||
struct snd_sof_dev *sdev = scontrol->sdev;
|
||||
struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
|
||||
struct sof_abi_hdr *data = cdata->data;
|
||||
size_t size = data->size + sizeof(*data);
|
||||
int ret, err;
|
||||
|
||||
if (be->max > sizeof(ucontrol->value.bytes.data)) {
|
||||
|
@ -358,10 +359,10 @@ int snd_sof_bytes_put(struct snd_kcontrol *kcontrol,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (data->size > be->max) {
|
||||
if (size > be->max) {
|
||||
dev_err_ratelimited(sdev->dev,
|
||||
"error: size too big %d bytes max is %d\n",
|
||||
data->size, be->max);
|
||||
"error: size too big %zu bytes max is %d\n",
|
||||
size, be->max);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -375,7 +376,7 @@ int snd_sof_bytes_put(struct snd_kcontrol *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 */
|
||||
snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol,
|
||||
|
|
|
@ -382,7 +382,7 @@ static int sof_probe_continue(struct snd_sof_dev *sdev)
|
|||
|
||||
if (IS_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",
|
||||
|
@ -393,8 +393,7 @@ static int sof_probe_continue(struct snd_sof_dev *sdev)
|
|||
|
||||
return 0;
|
||||
|
||||
comp_err:
|
||||
snd_soc_unregister_component(sdev->dev);
|
||||
#if !IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE)
|
||||
fw_run_err:
|
||||
snd_sof_fw_unload(sdev);
|
||||
fw_load_err:
|
||||
|
@ -403,6 +402,21 @@ static int sof_probe_continue(struct snd_sof_dev *sdev)
|
|||
snd_sof_free_debug(sdev);
|
||||
dbg_err:
|
||||
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;
|
||||
}
|
||||
|
@ -484,7 +498,6 @@ int snd_sof_device_remove(struct device *dev)
|
|||
snd_sof_ipc_free(sdev);
|
||||
snd_sof_free_debug(sdev);
|
||||
snd_sof_free_trace(sdev);
|
||||
snd_sof_remove(sdev);
|
||||
|
||||
/*
|
||||
* Unregister machine driver. This will unbind the snd_card which
|
||||
|
@ -494,6 +507,14 @@ int snd_sof_device_remove(struct device *dev)
|
|||
if (!IS_ERR_OR_NULL(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(pdata->fw);
|
||||
pdata->fw = NULL;
|
||||
|
|
|
@ -283,6 +283,8 @@ static irqreturn_t bdw_irq_thread(int irq, void *context)
|
|||
SHIM_IMRX, SHIM_IMRX_DONE,
|
||||
SHIM_IMRX_DONE);
|
||||
|
||||
spin_lock_irq(&sdev->ipc_lock);
|
||||
|
||||
/*
|
||||
* handle immediate reply from DSP core. If the msg is
|
||||
* found, set done bit in cmd_done which is called at the
|
||||
|
@ -294,6 +296,8 @@ static irqreturn_t bdw_irq_thread(int irq, void *context)
|
|||
snd_sof_ipc_reply(sdev, ipcx);
|
||||
|
||||
bdw_dsp_done(sdev);
|
||||
|
||||
spin_unlock_irq(&sdev->ipc_lock);
|
||||
}
|
||||
|
||||
ipcd = snd_sof_dsp_read(sdev, BDW_DSP_BAR, SHIM_IPCD);
|
||||
|
@ -485,7 +489,6 @@ static void bdw_get_reply(struct snd_sof_dev *sdev)
|
|||
{
|
||||
struct snd_sof_ipc_msg *msg = sdev->msg;
|
||||
struct sof_ipc_reply reply;
|
||||
unsigned long flags;
|
||||
int ret = 0;
|
||||
|
||||
/*
|
||||
|
@ -501,8 +504,6 @@ static void bdw_get_reply(struct snd_sof_dev *sdev)
|
|||
/* get reply */
|
||||
sof_mailbox_read(sdev, sdev->host_box.offset, &reply, sizeof(reply));
|
||||
|
||||
spin_lock_irqsave(&sdev->ipc_lock, flags);
|
||||
|
||||
if (reply.error < 0) {
|
||||
memcpy(msg->reply_data, &reply, sizeof(reply));
|
||||
ret = reply.error;
|
||||
|
@ -521,8 +522,6 @@ static void bdw_get_reply(struct snd_sof_dev *sdev)
|
|||
}
|
||||
|
||||
msg->reply_error = ret;
|
||||
|
||||
spin_unlock_irqrestore(&sdev->ipc_lock, flags);
|
||||
}
|
||||
|
||||
static void bdw_host_done(struct snd_sof_dev *sdev)
|
||||
|
|
|
@ -329,6 +329,9 @@ static irqreturn_t byt_irq_thread(int irq, void *context)
|
|||
SHIM_IMRX,
|
||||
SHIM_IMRX_DONE,
|
||||
SHIM_IMRX_DONE);
|
||||
|
||||
spin_lock_irq(&sdev->ipc_lock);
|
||||
|
||||
/*
|
||||
* handle immediate reply from DSP core. If the msg is
|
||||
* found, set done bit in cmd_done which is called at the
|
||||
|
@ -340,6 +343,8 @@ static irqreturn_t byt_irq_thread(int irq, void *context)
|
|||
snd_sof_ipc_reply(sdev, ipcx);
|
||||
|
||||
byt_dsp_done(sdev);
|
||||
|
||||
spin_unlock_irq(&sdev->ipc_lock);
|
||||
}
|
||||
|
||||
/* new message from DSP */
|
||||
|
@ -383,7 +388,6 @@ static void byt_get_reply(struct snd_sof_dev *sdev)
|
|||
{
|
||||
struct snd_sof_ipc_msg *msg = sdev->msg;
|
||||
struct sof_ipc_reply reply;
|
||||
unsigned long flags;
|
||||
int ret = 0;
|
||||
|
||||
/*
|
||||
|
@ -399,8 +403,6 @@ static void byt_get_reply(struct snd_sof_dev *sdev)
|
|||
/* get reply */
|
||||
sof_mailbox_read(sdev, sdev->host_box.offset, &reply, sizeof(reply));
|
||||
|
||||
spin_lock_irqsave(&sdev->ipc_lock, flags);
|
||||
|
||||
if (reply.error < 0) {
|
||||
memcpy(msg->reply_data, &reply, sizeof(reply));
|
||||
ret = reply.error;
|
||||
|
@ -419,8 +421,6 @@ static void byt_get_reply(struct snd_sof_dev *sdev)
|
|||
}
|
||||
|
||||
msg->reply_error = ret;
|
||||
|
||||
spin_unlock_irqrestore(&sdev->ipc_lock, flags);
|
||||
}
|
||||
|
||||
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)
|
|||
CNL_DSP_REG_HIPCCTL,
|
||||
CNL_DSP_REG_HIPCCTL_DONE, 0);
|
||||
|
||||
spin_lock_irq(&sdev->ipc_lock);
|
||||
|
||||
/* handle immediate reply from DSP core */
|
||||
hda_dsp_ipc_get_reply(sdev);
|
||||
snd_sof_ipc_reply(sdev, msg);
|
||||
|
@ -75,6 +77,8 @@ static irqreturn_t cnl_ipc_irq_thread(int irq, void *context)
|
|||
|
||||
cnl_ipc_dsp_done(sdev);
|
||||
|
||||
spin_unlock_irq(&sdev->ipc_lock);
|
||||
|
||||
ret = IRQ_HANDLED;
|
||||
}
|
||||
|
||||
|
|
|
@ -161,21 +161,105 @@ int hda_dsp_ctrl_clock_power_gating(struct snd_sof_dev *sdev, bool enable)
|
|||
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)
|
||||
{
|
||||
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);
|
||||
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);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -72,7 +72,6 @@ void hda_dsp_ipc_get_reply(struct snd_sof_dev *sdev)
|
|||
struct snd_sof_ipc_msg *msg = sdev->msg;
|
||||
struct sof_ipc_reply reply;
|
||||
struct sof_ipc_cmd_hdr *hdr;
|
||||
unsigned long flags;
|
||||
int ret = 0;
|
||||
|
||||
/*
|
||||
|
@ -84,7 +83,6 @@ void hda_dsp_ipc_get_reply(struct snd_sof_dev *sdev)
|
|||
dev_warn(sdev->dev, "unexpected ipc interrupt raised!\n");
|
||||
return;
|
||||
}
|
||||
spin_lock_irqsave(&sdev->ipc_lock, flags);
|
||||
|
||||
hdr = msg->msg_data;
|
||||
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)
|
|||
out:
|
||||
msg->reply_error = ret;
|
||||
|
||||
spin_unlock_irqrestore(&sdev->ipc_lock, flags);
|
||||
}
|
||||
|
||||
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)
|
|||
HDA_DSP_REG_HIPCCTL,
|
||||
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 */
|
||||
if (hda_dsp_ipc_is_sof(msg)) {
|
||||
hda_dsp_ipc_get_reply(sdev);
|
||||
|
@ -187,6 +196,8 @@ irqreturn_t hda_dsp_ipc_irq_thread(int irq, void *context)
|
|||
/* set the done bit */
|
||||
hda_dsp_ipc_dsp_done(sdev);
|
||||
|
||||
spin_unlock_irq(&sdev->ipc_lock);
|
||||
|
||||
ret = IRQ_HANDLED;
|
||||
}
|
||||
|
||||
|
|
|
@ -264,9 +264,12 @@ static const char *fixup_tplg_name(struct snd_sof_dev *sdev,
|
|||
return tplg_filename;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static int hda_init_caps(struct snd_sof_dev *sdev)
|
||||
{
|
||||
struct hdac_bus *bus = sof_to_bus(sdev);
|
||||
#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
|
||||
struct hdac_ext_link *hlink;
|
||||
struct snd_soc_acpi_mach_params *mach_params;
|
||||
struct snd_soc_acpi_mach *hda_mach;
|
||||
|
@ -274,8 +277,9 @@ static int hda_init_caps(struct snd_sof_dev *sdev)
|
|||
struct snd_soc_acpi_mach *mach;
|
||||
const char *tplg_filename;
|
||||
int codec_num = 0;
|
||||
int ret = 0;
|
||||
int i;
|
||||
#endif
|
||||
int ret = 0;
|
||||
|
||||
device_disable_async_suspend(bus->dev);
|
||||
|
||||
|
@ -283,6 +287,14 @@ static int hda_init_caps(struct snd_sof_dev *sdev)
|
|||
if (bus->ppcap)
|
||||
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)
|
||||
snd_hdac_ext_bus_get_ml_capabilities(bus);
|
||||
|
||||
|
@ -293,12 +305,6 @@ static int hda_init_caps(struct snd_sof_dev *sdev)
|
|||
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 */
|
||||
if (!bus->codec_mask) {
|
||||
dev_info(bus->dev, "no hda codecs found!\n");
|
||||
|
@ -339,8 +345,10 @@ static int hda_init_caps(struct snd_sof_dev *sdev)
|
|||
/* use local variable for readability */
|
||||
tplg_filename = pdata->tplg_filename;
|
||||
tplg_filename = fixup_tplg_name(sdev, tplg_filename);
|
||||
if (!tplg_filename)
|
||||
goto out;
|
||||
if (!tplg_filename) {
|
||||
hda_codec_i915_exit(sdev);
|
||||
return ret;
|
||||
}
|
||||
pdata->tplg_filename = tplg_filename;
|
||||
}
|
||||
}
|
||||
|
@ -364,34 +372,9 @@ static int hda_init_caps(struct snd_sof_dev *sdev)
|
|||
*/
|
||||
list_for_each_entry(hlink, &bus->hlink_list, list)
|
||||
snd_hdac_ext_bus_link_put(bus, hlink);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct sof_intel_dsp_desc
|
||||
*get_chip_info(struct snd_sof_pdata *pdata)
|
||||
|
@ -409,9 +392,8 @@ int hda_dsp_probe(struct snd_sof_dev *sdev)
|
|||
struct pci_dev *pci = to_pci_dev(sdev->dev);
|
||||
struct sof_intel_hda_dev *hdev;
|
||||
struct hdac_bus *bus;
|
||||
struct hdac_stream *stream;
|
||||
const struct sof_intel_dsp_desc *chip;
|
||||
int sd_offset, ret = 0;
|
||||
int ret = 0;
|
||||
|
||||
/*
|
||||
* detect DSP by checking class/subclass/prog-id information
|
||||
|
@ -562,49 +544,6 @@ int hda_dsp_probe(struct snd_sof_dev *sdev)
|
|||
if (ret < 0)
|
||||
goto free_ipc_irq;
|
||||
|
||||
/* 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");
|
||||
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);
|
||||
|
|
|
@ -308,19 +308,8 @@ EXPORT_SYMBOL(sof_ipc_tx_message);
|
|||
int snd_sof_ipc_reply(struct snd_sof_dev *sdev, u32 msg_id)
|
||||
{
|
||||
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) {
|
||||
spin_unlock_irqrestore(&sdev->ipc_lock, flags);
|
||||
dev_err(sdev->dev, "error: no reply expected, received 0x%x",
|
||||
msg_id);
|
||||
return -EINVAL;
|
||||
|
@ -330,8 +319,6 @@ int snd_sof_ipc_reply(struct snd_sof_dev *sdev, u32 msg_id)
|
|||
msg->ipc_complete = true;
|
||||
wake_up(&msg->waitq);
|
||||
|
||||
spin_unlock_irqrestore(&sdev->ipc_lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(snd_sof_ipc_reply);
|
||||
|
|
|
@ -211,8 +211,8 @@ static int sof_pcm_hw_params(struct snd_pcm_substream *substream,
|
|||
/* save pcm hw_params */
|
||||
memcpy(&spcm->params[substream->stream], params, sizeof(*params));
|
||||
|
||||
INIT_WORK(&spcm->stream[substream->stream].period_elapsed_work,
|
||||
sof_pcm_period_elapsed_work);
|
||||
/* clear hw_params_upon_resume flag */
|
||||
spcm->hw_params_upon_resume[substream->stream] = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -428,8 +428,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,
|
||||
substream->stream);
|
||||
|
||||
/* clear hw_params_upon_resume flag */
|
||||
spcm->hw_params_upon_resume[substream->stream] = 0;
|
||||
INIT_WORK(&spcm->stream[substream->stream].period_elapsed_work,
|
||||
sof_pcm_period_elapsed_work);
|
||||
|
||||
caps = &spcm->pcm.caps[substream->stream];
|
||||
|
||||
|
|
|
@ -1329,6 +1329,15 @@ static int sun4i_codec_spk_event(struct snd_soc_dapm_widget *w,
|
|||
gpiod_set_value_cansleep(scodec->gpio_pa,
|
||||
!!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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue