Merge pull request #190 from tlauda/topic/interrupt_get_level
interrupt: arch_interrupt_get_level
diff --git a/src/audio/dai.c b/src/audio/dai.c
index 3e53566..9c2ed5f 100644
--- a/src/audio/dai.c
+++ b/src/audio/dai.c
@@ -596,7 +596,12 @@
break;
case COMP_TRIGGER_XRUN:
dd->xrun = 1;
- /* fall through */
+ /* stop the DAI unconditionally */
+ dai_trigger(dd->dai, COMP_TRIGGER_STOP, dev->params.direction);
+ ret = dma_stop(dd->dma, dd->chan);
+ if (ret < 0)
+ return ret;
+ break;
case COMP_TRIGGER_PAUSE:
case COMP_TRIGGER_STOP:
wait_init(&dd->complete);
diff --git a/src/drivers/apl-ssp.c b/src/drivers/apl-ssp.c
index 1dd1386..70cb8af 100644
--- a/src/drivers/apl-ssp.c
+++ b/src/drivers/apl-ssp.c
@@ -149,6 +149,7 @@
uint32_t sample_width = 2;
bool inverted_frame = false;
+ bool cfs = false;
int ret = 0;
spin_lock(&ssp->lock);
@@ -215,10 +216,13 @@
break;
case SOF_DAI_FMT_CBS_CFS:
sscr1 |= SSCR1_SCFR;
+ cfs = true;
break;
case SOF_DAI_FMT_CBM_CFS:
sscr1 |= SSCR1_SCLKDIR;
/* FIXME: this mode has not been tested */
+
+ cfs = true;
break;
case SOF_DAI_FMT_CBS_CFM:
sscr1 |= SSCR1_SCFR | SSCR1_SFRMDIR;
@@ -255,6 +259,40 @@
mdivc = mn_reg_read(0x0);
mdivc |= 0x1;
+ /* Additional hardware settings */
+
+ /* Receiver Time-out Interrupt Disabled/Enabled */
+ sscr1 |= (ssp->params.quirks & SOF_DAI_INTEL_SSP_QUIRK_TINTE) ?
+ SSCR1_TINTE : 0;
+
+ /* Peripheral Trailing Byte Interrupts Disable/Enable */
+ sscr1 |= (ssp->params.quirks & SOF_DAI_INTEL_SSP_QUIRK_PINTE) ?
+ SSCR1_PINTE : 0;
+
+ /* Transmit data are driven at the same/opposite clock edge specified
+ * in SSPSP.SCMODE[1:0]
+ */
+ sscr2 |= (ssp->params.quirks & SOF_DAI_INTEL_SSP_QUIRK_SMTATF) ?
+ SSCR2_SMTATF : 0;
+
+ /* Receive data are sampled at the same/opposite clock edge specified
+ * in SSPSP.SCMODE[1:0]
+ */
+ sscr2 |= (ssp->params.quirks & SOF_DAI_INTEL_SSP_QUIRK_MMRATF) ?
+ SSCR2_MMRATF : 0;
+
+ /* Enable/disable the fix for PSP slave mode TXD wait for frame
+ * de-assertion before starting the second channel
+ */
+ sscr2 |= (ssp->params.quirks & SOF_DAI_INTEL_SSP_QUIRK_PSPSTWFDFD) ?
+ SSCR2_PSPSTWFDFD : 0;
+
+ /* Enable/disable the fix for PSP master mode FSRT with dummy stop &
+ * frame end padding capability
+ */
+ sscr2 |= (ssp->params.quirks & SOF_DAI_INTEL_SSP_QUIRK_PSPSRWFDFD) ?
+ SSCR2_PSPSRWFDFD : 0;
+
#ifdef CONFIG_CANNONLAKE
if (!config->ssp.mclk_rate || config->ssp.mclk_rate > F_24000_kHz) {
trace_ssp_error("eci");
@@ -503,7 +541,21 @@
sscr0 |= SSCR0_MOD | SSCR0_FRDC(config->ssp.tdm_slots);
/* set asserted frame length */
- frame_len = 1;
+ frame_len = 1; /* default */
+
+ if (cfs && ssp->params.frame_pulse_width > 0 &&
+ ssp->params.frame_pulse_width <=
+ SOF_DAI_INTEL_SSP_FRAME_PULSE_WIDTH_MAX) {
+ frame_len = ssp->params.frame_pulse_width;
+ }
+
+ /* frame_pulse_width must less or equal 38 */
+ if (ssp->params.frame_pulse_width >
+ SOF_DAI_INTEL_SSP_FRAME_PULSE_WIDTH_MAX) {
+ trace_ssp_error("efa");
+ ret = -EINVAL;
+ goto out;
+ }
/*
* handle frame polarity, DSP_A default is rising/active high,
@@ -527,8 +579,21 @@
sscr0 |= SSCR0_MOD | SSCR0_FRDC(config->ssp.tdm_slots);
/* set asserted frame length */
- frame_len = 1;
+ frame_len = 1; /* default */
+ if (cfs && ssp->params.frame_pulse_width > 0 &&
+ ssp->params.frame_pulse_width <=
+ SOF_DAI_INTEL_SSP_FRAME_PULSE_WIDTH_MAX) {
+ frame_len = ssp->params.frame_pulse_width;
+ }
+
+ /* frame_pulse_width must less or equal 38 */
+ if (ssp->params.frame_pulse_width >
+ SOF_DAI_INTEL_SSP_FRAME_PULSE_WIDTH_MAX) {
+ trace_ssp_error("efb");
+ ret = -EINVAL;
+ goto out;
+ }
/*
* handle frame polarity, DSP_B default is rising/active high,
* non-inverted(inverted_frame=0) -- active high(SFRMP=1),
diff --git a/src/drivers/dw-dma.c b/src/drivers/dw-dma.c
index d4f13bf..c5bbe19 100644
--- a/src/drivers/dw-dma.c
+++ b/src/drivers/dw-dma.c
@@ -484,19 +484,30 @@
static int dw_dma_stop(struct dma *dma, int channel)
{
struct dma_pdata *p = dma_get_drvdata(dma);
- int ret = 0;
+ int ret = 0;
+ int i = 0;
+ struct dw_lli2 *lli;
uint32_t flags;
spin_lock_irq(&dma->lock, flags);
trace_dma("DDi");
- /* is channel stii active ? */
- if ((dw_read(dma, DW_DMA_CHAN_EN) & (0x1 << channel))) {
- trace_dma_error("ea0");
- trace_error_value(channel);
+ dw_write(dma, DW_DMA_CHAN_EN, CHAN_DISABLE(channel));
+
+#if DW_USE_HW_LLI
+ for (i = 0; i < p->chan[channel].desc_count; i++) {
+ lli = p->chan[channel].lli;
+ lli->ctrl_hi &= ~DW_CTLH_DONE(1);
+ lli++;
}
+ dcache_writeback_region(p->chan[channel].lli,
+ sizeof(struct dw_lli2) * p->chan[channel].desc_count);
+#endif
+
+ dw_write(dma, DW_CLEAR_BLOCK, 0x1 << channel);
+
p->chan[channel].status = COMP_STATE_PREPARE;
spin_unlock_irq(&dma->lock, flags);
diff --git a/src/drivers/hda-dma.c b/src/drivers/hda-dma.c
index 948b990..f8fce18 100644
--- a/src/drivers/hda-dma.c
+++ b/src/drivers/hda-dma.c
@@ -44,7 +44,9 @@
#include <sof/ipc.h>
#include <sof/pm_runtime.h>
#include <sof/wait.h>
+#include <sof/audio/format.h>
#include <platform/dma.h>
+#include <platform/platform.h>
#include <arch/cache.h>
#include <uapi/ipc.h>
@@ -367,7 +369,8 @@
host_dma_reg_write(dma, channel, DGBS, buffer_bytes);
host_dma_reg_write(dma, channel, DGBFPI, 0);
host_dma_reg_write(dma, channel, DGBSP, period_bytes);
- host_dma_reg_write(dma, channel, DGMBS, period_bytes);
+ host_dma_reg_write(dma, channel, DGMBS,
+ ALIGN_UP(period_bytes, PLATFORM_HDA_BUFFER_ALIGNMENT));
host_dma_reg_write(dma, channel, DGLLPI, 0);
host_dma_reg_write(dma, channel, DGLPIBI, 0);
diff --git a/src/include/sof/audio/format.h b/src/include/sof/audio/format.h
index f00b6f9..67c1632 100644
--- a/src/include/sof/audio/format.h
+++ b/src/include/sof/audio/format.h
@@ -53,6 +53,13 @@
#define MINUS_80DB_Q1_31 214748 /* 10^(-80/20) */
#define MINUS_90DB_Q1_31 67909 /* 10^(-90/20) */
+/* Align the number to the nearest alignment value */
+#define ALIGN_UP(size, alignment) \
+ (((size) % (alignment) == 0) ? (size) : \
+ ((size) - ((size) % (alignment)) + (alignment)))
+#define ALIGN_DOWN(size, alignment) \
+ ((size) - ((size) % (alignment)))
+
/* Compute the number of shifts
* This will result in a compiler overflow error if shift bits are out of
* range as INT64_MAX/MIN is greater than 32 bit Q shift parameter
diff --git a/src/include/sof/ssp.h b/src/include/sof/ssp.h
index b5e8175..e57aa84 100644
--- a/src/include/sof/ssp.h
+++ b/src/include/sof/ssp.h
@@ -134,9 +134,13 @@
#elif defined CONFIG_APOLLOLAKE || defined CONFIG_CANNONLAKE \
|| defined CONFIG_HASWELL || defined CONFIG_BROADWELL
#define SSCR2_TURM1 BIT(1)
+#define SSCR2_PSPSRWFDFD BIT(3)
+#define SSCR2_PSPSTWFDFD BIT(4)
#define SSCR2_SDFD BIT(14)
#define SSCR2_SDPM BIT(16)
#define SSCR2_LJDFD BIT(17)
+#define SSCR2_MMRATF BIT(18)
+#define SSCR2_SMTATF BIT(19)
#endif
diff --git a/src/include/uapi/ipc.h b/src/include/uapi/ipc.h
index 4cf569f..2cb246d 100644
--- a/src/include/uapi/ipc.h
+++ b/src/include/uapi/ipc.h
@@ -226,6 +226,23 @@
#define SOF_DAI_FMT_INV_MASK 0x0f00
#define SOF_DAI_FMT_MASTER_MASK 0xf000
+ /* ssc1: TINTE */
+#define SOF_DAI_INTEL_SSP_QUIRK_TINTE (1 << 0)
+ /* ssc1: PINTE */
+#define SOF_DAI_INTEL_SSP_QUIRK_PINTE (1 << 1)
+ /* ssc2: SMTATF */
+#define SOF_DAI_INTEL_SSP_QUIRK_SMTATF (1 << 2)
+ /* ssc2: MMRATF */
+#define SOF_DAI_INTEL_SSP_QUIRK_MMRATF (1 << 3)
+ /* ssc2: PSPSTWFDFD */
+#define SOF_DAI_INTEL_SSP_QUIRK_PSPSTWFDFD (1 << 4)
+ /* ssc2: PSPSRWFDFD */
+#define SOF_DAI_INTEL_SSP_QUIRK_PSPSRWFDFD (1 << 5)
+ /* here is the possibility to define others aux macros */
+
+
+#define SOF_DAI_INTEL_SSP_FRAME_PULSE_WIDTH_MAX 38
+
/** \brief Types of DAI */
enum sof_ipc_dai_type {
SOF_DAI_INTEL_NONE = 0, /**< None */
@@ -259,8 +276,10 @@
uint32_t bclk_keep_active;
uint32_t fs_keep_active;
- //uint32_t quirks; // FIXME: is 32 bits enough ?
+ uint16_t frame_pulse_width;
+ uint32_t quirks; // FIXME: is 32 bits enough ?
+ uint16_t padding;
/* private data, e.g. for quirks */
//uint32_t pdata[10]; // FIXME: would really need ~16 u32
} __attribute__((packed));
diff --git a/src/platform/apollolake/include/platform/platform.h b/src/platform/apollolake/include/platform/platform.h
index d611a1c..c110068 100644
--- a/src/platform/apollolake/include/platform/platform.h
+++ b/src/platform/apollolake/include/platform/platform.h
@@ -41,6 +41,9 @@
struct sof;
+/* DGMBS align value */
+#define PLATFORM_HDA_BUFFER_ALIGNMENT 0x20
+
/* Host page size */
#define HOST_PAGE_SIZE 4096
#define PLATFORM_PAGE_TABLE_SIZE 256
diff --git a/src/platform/cannonlake/include/platform/platform.h b/src/platform/cannonlake/include/platform/platform.h
index 30f5580..a94465d 100644
--- a/src/platform/cannonlake/include/platform/platform.h
+++ b/src/platform/cannonlake/include/platform/platform.h
@@ -47,6 +47,9 @@
#define PLATFORM_SSP_COUNT 3
#define MAX_GPDMA_COUNT 2
+/* DGMBS align value */
+#define PLATFORM_HDA_BUFFER_ALIGNMENT 0x20
+
/* Host page size */
#define HOST_PAGE_SIZE 4096
#define PLATFORM_PAGE_TABLE_SIZE 256