Merge pull request #150 from bkokoszx/ssp_master_slave_hwd
apl-ssp: setting additional bits in ssp registers
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/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));