Skip to content
Closed
Changes from 1 commit
Commits
Show all changes
75 commits
Select commit Hold shift + click to select a range
c09866c
ASoC: core: Allow topology to override machine driver FE DAI link con…
lrgirdwo Jan 8, 2018
c59e0d3
[SQUASHME?] ASoC: core: Add name prefix for machines with topology re…
lrgirdwo Mar 9, 2018
c0c46a1
ASoC: topology: Give more data to clients via callbacks
lrgirdwo Jan 8, 2018
7b47108
ASoC: topology: Add callback for DAPM route load/unload
lrgirdwo Jan 8, 2018
0795a17
ALSA: core: Allow drivers to set R/W wait time.
lrgirdwo Jan 8, 2018
908d35a
ASoC: DAPM: Check for DAI private data - NEEDED ???
lrgirdwo Jan 8, 2018
cf8e473
ASoC: Intel: rename 'reef' to 'sof' in ACPI matching table
plbossart Mar 12, 2018
2bb970f
ASoC: Intel: Skylake: cleanup before moving ACPI tables
plbossart May 29, 2018
c8542b3
ASoC: Intel: move SKL+ codec ACPI tables to common directory
plbossart May 29, 2018
0779134
ASoC: Intel: common: add firmware/topology information for SOF
plbossart May 29, 2018
9b9f68a
ASoC: SOF: Add Sound Open Firmware driver core
lrgirdwo Jan 8, 2018
40ac5ea
ASoC: SOF: Add Sound Open Firmware KControl support
lrgirdwo Jan 8, 2018
936c53a
ASoC: SOF: Add driver debug support.
lrgirdwo Jan 8, 2018
39315dd
ASoC: SOF: Add support for IPC IO between DSP and Host
lrgirdwo Jan 8, 2018
6245e5e
ASoC: SOF: Add PCM operations support
lrgirdwo Jan 8, 2018
2abf96d
ASoC: SOF: Add support for loading topologies
lrgirdwo Jan 8, 2018
1ebacc8
ASoC: SOF: Add DSP firmware trace event support
lrgirdwo Jan 8, 2018
a1e523d
ASoC: SOF: Add DSP HW abstraction operations
lrgirdwo Jan 8, 2018
121138b
ASoC: SOF: Add firmware loader support
lrgirdwo Jan 8, 2018
b4f4dc0
ASoC: SOF: Add compressed PCM support
lrgirdwo Jan 8, 2018
a1ed847
ASoC: SOF: Add PM support
lrgirdwo Jan 16, 2018
a46071d
ASoC: SOF: Add Nocodec machine driver support
lrgirdwo Jan 8, 2018
2a80a39
ASoC: SOF: Intel: Add BYT, CHT and BSW DSP HW support.
lrgirdwo Jan 8, 2018
308c3a9
ASoC: SOF: Intel: Add HSW HW DSP support
lrgirdwo Jan 8, 2018
9adbdbc
ASoC: SOF: Intel: Add support for BDW HW DSP support
lrgirdwo Jan 8, 2018
ddcad8b
ASoC: SOF: Intel: Add APL/CNL HW DSP support
lrgirdwo Jan 8, 2018
fc43fc9
ASoC: SOF: Intel: Add HDA controller for Intel DSP
lrgirdwo May 9, 2018
17eb800
ASoC: SOF: Intel: Add Intel specific HDA DSP HW operations
lrgirdwo May 9, 2018
042e224
ASoC: SOF: Intel: Add Intel specific HDA IPC mechanisms.
lrgirdwo May 9, 2018
aef0e8e
ASoC: SOF: Intel: Add Intel specific HDA firmware loader
lrgirdwo May 9, 2018
d870d10
ASoC: SOF: Intel: Add Intel specific HDA PCM operations
lrgirdwo May 9, 2018
0f92982
ASoC: SOF: Intel: Add Intel specific HDA stream operations
lrgirdwo May 9, 2018
6176aa8
ASoC: SOF: Intel: Add Intel specific HDA trace operations
lrgirdwo May 9, 2018
99815a5
ASoC: SOF: Intel: Add platform differentiation for SKL, APL and CNL
lrgirdwo May 9, 2018
56134da
ASoC: SOF: Add userspace ABI support
lrgirdwo Jan 8, 2018
03ab0f0
ASoC: SOF: Add VirtIO support
lrgirdwo Jan 8, 2018
8088bfb
ASoC: SOF: Add SPI device support
lrgirdwo Jan 8, 2018
6eddaa6
ASoC: SOF: Add ACPI device support
lrgirdwo Jan 8, 2018
2c322db
ASoC: SOF: Add PCI device support
lrgirdwo Jan 8, 2018
b9d911e
ASoC: SOF: Add Build support for SOF core and Intel drivers
lrgirdwo Jan 8, 2018
f9aee53
ASoC: Intel: Kconfig: disable SST and legacy drivers when SOF is sele…
plbossart May 31, 2018
2ceaf38
ASoC: SOF: refine dapm route loading in sof
RanderWang May 25, 2018
ecad572
ASoC: SOF: parse Xtensa exception causes
xiulipan May 25, 2018
b3637b0
ASoC: uapi: sof: Add ipc config params and topology tokens for DMIC D…
ranj063 May 27, 2018
d689361
ASoC: SOF: Add support for parsing DMIC specific tokens from topology
ranj063 May 27, 2018
e16acb0
ASoC: SOF: support DMIC DAI type during link fixup
ranj063 May 27, 2018
82f920d
[WORKAROUND] ASoC: SOF: start HDA DMA at hw_params() stage and remove…
keyonjie May 15, 2018
4e41f9e
ASoC: Intel: make bytcht_da7213 with SOF
plbossart Mar 9, 2018
3687d90
ASoC: Intel: make cht_bsw_max98090 work with SOF
plbossart Mar 9, 2018
69ebc99
ASoC: Intel: cht-bsw-rt5645: work with SOF
plbossart Nov 10, 2017
ce28883
ASoC: Intel: cht-bsw-rt5672: work with SOF
plbossart Nov 30, 2017
ca9d0b8
ASoC: Intel: make bytcr_rt5640 work with SOF
plbossart Dec 21, 2017
732b420
ASoC: Intel: Make sure HSW/BDW based machine drivers build for SOF
lrgirdwo Dec 7, 2017
c52dd1b
ASoC: Intel: Kconfig: expose common option between SST and SOF drivers
plbossart Jan 9, 2018
9c02407
ASoC: Intel: select relevant machine drivers for SOF
plbossart Dec 7, 2017
93687f2
ASoC: Intel: add machine driver for BXT/APL with pcm512x codec
plbossart Apr 23, 2018
1ca41e3
ASoC: Intel: add rt274 machine driver for cnl
RanderWang May 18, 2018
cb542f6
ASoC: Intel: make cnl_rt274 work with SOF
plbossart May 18, 2018
9537c0f
ASoC: tdf8532: NXP TDF8532 audio class-D amplifier driver
May 15, 2018
0f2257b
ASoC: tdf8532: Fix compilation warnings
May 15, 2018
f72a2a0
ASoC: tdf8532: Add delay while reading a packet from I2C
May 15, 2018
ed11dce
ASoC: tdf8532: Fix the codec status error issue on APL-GPMRB
May 15, 2018
ce0d208
ASoC: Intel: Boards: Add BXTP MRB machine driver for NXP TDF8532
keyonjie May 22, 2018
8921f8e
ASoC: Intel: bxt-tdf8532: reuse machine driver for GP-MRB
keyonjie May 22, 2018
20d41f6
ASoC: Intel: bxt-tdf8532: FIX: don't use add_dai_link() for SOF
keyonjie May 28, 2018
3f4da86
ALSA: HACK: Fix rmmod crash
lrgirdwo Nov 3, 2017
8f3da6d
[NOT FOR UPSTREAM] ASoC: SOF: enable DEBUG by default
plbossart Apr 16, 2018
93dc8cc
ASoC: Intel: replace snd_soc_codec to snd_soc_component in bxt-pcm512x
xiulipan Jun 7, 2018
6fa8f18
ASoC: Intel: bytcr_rt5651: work with sof only with SSP2 AIF1
xiulipan Jun 6, 2018
ce9b373
ASoC: SOF: topology: free volume table while unloading pga widget
ranj063 Jun 10, 2018
f4ac2b9
acpi: blacklist: remove quirk for Dell XPS13 when SOF is enabled
plbossart Jun 12, 2018
3670189
ASoC: Intel: common: add ACPI match for CannonLake
plbossart Jun 12, 2018
c7bb52f
ASoC: SOF: fix warning about assigning __le to u16 type
ranj063 Jun 12, 2018
5b36be0
ASoC: SOF: topology: fix dmic pdm token offsets
ranj063 Jun 12, 2018
1e0f505
ASoC: SOF: topology: fix logic for parsing dmic pdm tokens
ranj063 Jun 12, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
ASoC: SOF: Intel: Add Intel specific HDA IPC mechanisms.
Add HDA specific IPC mechanism for Intel DSP HW.

Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
  • Loading branch information
lrgirdwo authored and plbossart committed Jun 4, 2018
commit 042e224e496cff13d5e7205fa91badbae1ed2b69
367 changes: 367 additions & 0 deletions sound/soc/sof/intel/hda-ipc.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,367 @@
// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* Copyright(c) 2017 Intel Corporation. All rights reserved.
*
* Authors: Liam Girdwood <liam.r.girdwood@linux.intel.com>
* Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
* Jeeja KP <jeeja.kp@intel.com>
* Rander Wang <rander.wang@intel.com>
* Keyon Jie <yang.jie@linux.intel.com>
*/

/*
* Hardware interface for generic Intel audio DSP HDA IP
*/

#include <linux/delay.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/dma-mapping.h>
#include <linux/firmware.h>
#include <linux/pci.h>
#include <sound/hdaudio_ext.h>
#include <sound/sof.h>
#include <sound/pcm_params.h>
#include <linux/pm_runtime.h>

#include "../sof-priv.h"
#include "../ops.h"
#include "hda.h"

int hda_dsp_ipc_cmd_done(struct snd_sof_dev *sdev)
{
/* tell DSP cmd is done - clear busy interrupt */
snd_sof_dsp_update_bits_forced(sdev, HDA_DSP_BAR,
HDA_DSP_REG_HIPCT,
HDA_DSP_REG_HIPCT_BUSY,
HDA_DSP_REG_HIPCT_BUSY);
return 0;
}

int hda_dsp_ipc_is_ready(struct snd_sof_dev *sdev)
{
u64 val;

/* is DSP ready for next IPC command */
val = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_HIPCI);
if (val & HDA_DSP_REG_HIPCI_BUSY)
return 0;

return 1;
}

int hda_dsp_ipc_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg)
{
u32 cmd = msg->header;

/* send IPC message to DSP */
hda_dsp_mailbox_write(sdev, sdev->host_box.offset, msg->msg_data,
msg->msg_size);
snd_sof_dsp_write(sdev, HDA_DSP_BAR, HDA_DSP_REG_HIPCI,
cmd | HDA_DSP_REG_HIPCI_BUSY);

return 0;
}

int hda_dsp_ipc_get_reply(struct snd_sof_dev *sdev,
struct snd_sof_ipc_msg *msg)
{
struct sof_ipc_reply reply;
int ret = 0;
u32 size;

/* get IPC reply from DSP in the mailbox */
hda_dsp_mailbox_read(sdev, sdev->host_box.offset, &reply,
sizeof(reply));
if (reply.error < 0) {
size = sizeof(reply);
ret = reply.error;
} else {
/* reply correct size ? */
if (reply.hdr.size != msg->reply_size) {
dev_err(sdev->dev, "error: reply expected 0x%zx got 0x%x bytes\n",
msg->reply_size, reply.hdr.size);
size = msg->reply_size;
ret = -EINVAL;
} else {
size = reply.hdr.size;
}
}

/* read the message */
if (msg->msg_data && size > 0)
hda_dsp_mailbox_read(sdev, sdev->host_box.offset,
msg->reply_data, size);

return ret;
}

/* IPC handler thread */
irqreturn_t hda_dsp_ipc_irq_thread(int irq, void *context)
{
struct snd_sof_dev *sdev = (struct snd_sof_dev *)context;
u32 hipci, hipcie, hipct, hipcte, msg = 0, msg_ext = 0;
irqreturn_t ret = IRQ_NONE;

/* here we handle IPC interrupts only */
if (!(sdev->irq_status & HDA_DSP_ADSPIS_IPC))
return ret;

/* read IPC status */
hipcie = snd_sof_dsp_read(sdev, HDA_DSP_BAR,
HDA_DSP_REG_HIPCIE);
hipct = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_HIPCT);

/* is this a reply message from the DSP */
if (hipcie & HDA_DSP_REG_HIPCIE_DONE) {

hipci = snd_sof_dsp_read(sdev, HDA_DSP_BAR,
HDA_DSP_REG_HIPCI);
msg = hipci & HDA_DSP_REG_HIPCI_MSG_MASK;
msg_ext = hipcie & HDA_DSP_REG_HIPCIE_MSG_MASK;

dev_vdbg(sdev->dev,
"ipc: firmware response, msg:0x%x, msg_ext:0x%x\n",
msg, msg_ext);

/* mask Done interrupt */
snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR,
HDA_DSP_REG_HIPCCTL,
HDA_DSP_REG_HIPCCTL_DONE, 0);

/* handle immediate reply from DSP core - ignore ROM messages */
if (msg != 0x1004000)
snd_sof_ipc_reply(sdev, msg);

/* clear DONE bit - tell DSP we have completed the operation */
snd_sof_dsp_update_bits_forced(sdev, HDA_DSP_BAR,
HDA_DSP_REG_HIPCIE,
HDA_DSP_REG_HIPCIE_DONE,
HDA_DSP_REG_HIPCIE_DONE);

/* unmask Done interrupt */
snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR,
HDA_DSP_REG_HIPCCTL,
HDA_DSP_REG_HIPCCTL_DONE,
HDA_DSP_REG_HIPCCTL_DONE);

ret = IRQ_HANDLED;
}

/* is this a new message from DSP */
if (hipct & HDA_DSP_REG_HIPCT_BUSY) {

hipcte = snd_sof_dsp_read(sdev, HDA_DSP_BAR,
HDA_DSP_REG_HIPCTE);
msg = hipct & HDA_DSP_REG_HIPCT_MSG_MASK;
msg_ext = hipcte & HDA_DSP_REG_HIPCTE_MSG_MASK;

dev_vdbg(sdev->dev,
"ipc: firmware initiated, msg:0x%x, msg_ext:0x%x\n",
msg, msg_ext);

/* handle messages from DSP */
if ((hipct & SOF_IPC_PANIC_MAGIC_MASK) == SOF_IPC_PANIC_MAGIC) {
/* this is a PANIC message !! */
snd_sof_dsp_panic(sdev, HDA_DSP_PANIC_OFFSET(msg_ext));
} else {
/* normal message - process normally*/
snd_sof_ipc_msgs_rx(sdev);
}

/* clear busy interrupt */
snd_sof_dsp_update_bits_forced(sdev, HDA_DSP_BAR,
HDA_DSP_REG_HIPCT,
HDA_DSP_REG_HIPCT_BUSY,
HDA_DSP_REG_HIPCT_BUSY);
ret = IRQ_HANDLED;
}

if (ret == IRQ_HANDLED) {
/* reenable IPC interrupt */
snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, HDA_DSP_REG_ADSPIC,
HDA_DSP_ADSPIC_IPC, HDA_DSP_ADSPIC_IPC);
}

/* wake up sleeper if we are loading code */
if (sdev->code_loading) {
sdev->code_loading = 0;
wake_up(&sdev->waitq);
}

return ret;
}

/* is this IRQ for ADSP ? - we only care about IPC here */
irqreturn_t hda_dsp_ipc_irq_handler(int irq, void *context)
{
struct snd_sof_dev *sdev = (struct snd_sof_dev *)context;
int ret = IRQ_NONE;

spin_lock(&sdev->hw_lock);

/* store status */
sdev->irq_status = snd_sof_dsp_read(sdev, HDA_DSP_BAR,
HDA_DSP_REG_ADSPIS);

/* invalid message ? */
if (sdev->irq_status == 0xffffffff)
goto out;

/* IPC message ? */
if (sdev->irq_status & HDA_DSP_ADSPIS_IPC) {
/* disable IPC interrupt */
snd_sof_dsp_update_bits_unlocked(sdev, HDA_DSP_BAR,
HDA_DSP_REG_ADSPIC,
HDA_DSP_ADSPIC_IPC, 0);
ret = IRQ_WAKE_THREAD;
}

out:
spin_unlock(&sdev->hw_lock);
return ret;
}

/*
* IPC Firmware ready.
*/

static void ipc_get_windows(struct snd_sof_dev *sdev)
{
struct sof_ipc_window_elem *elem;
u32 outbox_offset = 0;
u32 stream_offset = 0;
u32 inbox_offset = 0;
u32 outbox_size = 0;
u32 stream_size = 0;
u32 inbox_size = 0;
int i;

if (!sdev->info_window) {
dev_err(sdev->dev, "error: have no window info\n");
return;
}

for (i = 0; i < sdev->info_window->num_windows; i++) {
elem = &sdev->info_window->window[i];

switch (elem->type) {
case SOF_IPC_REGION_UPBOX:
inbox_offset =
elem->offset + SRAM_WINDOW_OFFSET(elem->id);
inbox_size = elem->size;
snd_sof_debugfs_create_item(sdev,
sdev->bar[HDA_DSP_BAR] +
inbox_offset,
elem->size, "inbox");
break;
case SOF_IPC_REGION_DOWNBOX:
outbox_offset =
elem->offset + SRAM_WINDOW_OFFSET(elem->id);
outbox_size = elem->size;
snd_sof_debugfs_create_item(sdev,
sdev->bar[HDA_DSP_BAR] +
outbox_offset,
elem->size, "outbox");
break;
case SOF_IPC_REGION_TRACE:
snd_sof_debugfs_create_item(sdev,
sdev->bar[HDA_DSP_BAR] +
elem->offset +
SRAM_WINDOW_OFFSET
(elem->id),
elem->size, "etrace");
break;
case SOF_IPC_REGION_DEBUG:
snd_sof_debugfs_create_item(sdev,
sdev->bar[HDA_DSP_BAR] +
elem->offset +
SRAM_WINDOW_OFFSET
(elem->id),
elem->size, "debug");
break;
case SOF_IPC_REGION_STREAM:
stream_offset =
elem->offset + SRAM_WINDOW_OFFSET(elem->id);
stream_size = elem->size;
snd_sof_debugfs_create_item(sdev,
sdev->bar[HDA_DSP_BAR] +
elem->offset +
SRAM_WINDOW_OFFSET
(elem->id),
elem->size, "stream");
break;
case SOF_IPC_REGION_REGS:
snd_sof_debugfs_create_item(sdev,
sdev->bar[HDA_DSP_BAR] +
elem->offset +
SRAM_WINDOW_OFFSET
(elem->id),
elem->size, "regs");
break;
case SOF_IPC_REGION_EXCEPTION:
sdev->dsp_oops_offset = elem->offset +
SRAM_WINDOW_OFFSET(elem->id);
snd_sof_debugfs_create_item(sdev,
sdev->bar[HDA_DSP_BAR] +
elem->offset +
SRAM_WINDOW_OFFSET
(elem->id),
elem->size, "exception");
break;
default:
dev_err(sdev->dev, "error: get illegal window info\n");
return;
}
}

if (outbox_size == 0 || inbox_size == 0) {
dev_err(sdev->dev, "error: get illegal mailbox window\n");
return;
}

snd_sof_dsp_mailbox_init(sdev, inbox_offset, inbox_size,
outbox_offset, outbox_size);
sdev->stream_box.offset = stream_offset;
sdev->stream_box.size = stream_size;

dev_dbg(sdev->dev, " mailbox upstream 0x%x - size 0x%x\n",
inbox_offset, inbox_size);
dev_dbg(sdev->dev, " mailbox downstream 0x%x - size 0x%x\n",
outbox_offset, outbox_size);
dev_dbg(sdev->dev, " stream region 0x%x - size 0x%x\n",
stream_offset, stream_size);
}

int hda_dsp_ipc_fw_ready(struct snd_sof_dev *sdev, u32 msg_id)
{
struct sof_ipc_fw_ready *fw_ready = &sdev->fw_ready;
struct sof_ipc_fw_version *v = &fw_ready->version;
u32 offset;

/* mailbox must be on 4k boundary */
offset = HDA_DSP_MBOX_UPLINK_OFFSET;

dev_dbg(sdev->dev, "ipc: DSP is ready 0x%8.8x offset 0x%x\n",
msg_id, offset);

/* copy data from the DSP FW ready offset */
hda_dsp_block_read(sdev, offset, fw_ready, sizeof(*fw_ready));
dev_info(sdev->dev,
" Firmware info: version %d.%d-%s build %d on %s:%s\n",
v->major, v->minor, v->tag, v->build, v->date, v->time);

/* now check for extended data */
snd_sof_fw_parse_ext_data(sdev, HDA_DSP_MBOX_UPLINK_OFFSET +
sizeof(struct sof_ipc_fw_ready));

ipc_get_windows(sdev);

return 0;
}