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));