summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregory Nutt <gnutt@nuttx.org>2014-08-01 14:10:37 -0600
committerGregory Nutt <gnutt@nuttx.org>2014-08-01 14:10:37 -0600
commitbacb9004a6a8c8eef75c0b3f1db8d07abcc54b7a (patch)
tree87369ed0a7872f25dff8e239354658a9bcebbca1
parent0ca062d467e67aafa6b03a0fc908bd181773a45d (diff)
downloadnuttx-bacb9004a6a8c8eef75c0b3f1db8d07abcc54b7a.tar.gz
nuttx-bacb9004a6a8c8eef75c0b3f1db8d07abcc54b7a.tar.bz2
nuttx-bacb9004a6a8c8eef75c0b3f1db8d07abcc54b7a.zip
SAMA5 SSC: Start Delay is now configurable
-rw-r--r--nuttx/arch/arm/src/sama5/Kconfig36
-rw-r--r--nuttx/arch/arm/src/sama5/sam_ssc.c140
-rw-r--r--nuttx/configs/sama5d3x-ek/README.txt4
-rw-r--r--nuttx/configs/sama5d4-ek/README.txt4
4 files changed, 128 insertions, 56 deletions
diff --git a/nuttx/arch/arm/src/sama5/Kconfig b/nuttx/arch/arm/src/sama5/Kconfig
index 0877e6b0f..f8747160c 100644
--- a/nuttx/arch/arm/src/sama5/Kconfig
+++ b/nuttx/arch/arm/src/sama5/Kconfig
@@ -2163,6 +2163,15 @@ config SAMA5_SSC0_RX_FSLEN
This setting determines the pulse length of the Receive Frame Sync
signal in units of receive clock periods.
+config SAMA5_SSC0_RX_STTDLY
+ int "Receive Start Delay Length"
+ default 0
+ range 0 255
+ ---help---
+ This setting determines the pulse length to the start of data in
+ receive clock periods. It must be greater than or equal to the RX
+ frame synch length. Zero means no start delay.
+
endif # SAMA5_SSC0_RX
config SAMA5_SSC0_TX
@@ -2224,6 +2233,15 @@ config SAMA5_SSC0_TX_FSLEN
feature. In that case the TD line is driven with the default value
during the Transmit Frame Sync signal.
+config SAMA5_SSC0_TX_STTDLY
+ int "Transmit Start Delay Length"
+ default 0
+ range 0 255
+ ---help---
+ This setting determines the pulse length to the start of data in
+ transmit clock periods. It must be greater than or equal to the RX
+ frame synch length. Zero means no start delay.
+
endif # SAMA5_SSC0_TX
config SAMA5_SSC0_MCKDIV_SAMPLERATE
@@ -2317,6 +2335,15 @@ config SAMA5_SSC1_RX_FSLEN
This setting determines the pulse length of the Receive Frame Sync
signal in units of receive clock periods.
+config SAMA5_SSC1_RX_STTDLY
+ int "Receive Start Delay Length"
+ default 0
+ range 0 255
+ ---help---
+ This setting determines the pulse length to the start of data of
+ receive clock periods. It must be greater than or equal to the RX
+ frame synch length. Zero means no start delay.
+
endif # SAMA5_SSC1_RX
config SAMA5_SSC1_TX
@@ -2378,6 +2405,15 @@ config SAMA5_SSC1_TX_FSLEN
feature. In that case the TD line is driven with the default value
during the Transmit Frame Sync signal.
+config SAMA5_SSC1_TX_STTDLY
+ int "Transmit Start Delay Length"
+ default 0
+ range 0 255
+ ---help---
+ This setting determines the pulse length to the start of data in
+ transmit clock periods. It must be greater than or equal to the RX
+ frame synch length. Zero means no start delay.
+
endif # SAMA5_SSC1_TX
config SAMA5_SSC1_MCKDIV_SAMPLERATE
diff --git a/nuttx/arch/arm/src/sama5/sam_ssc.c b/nuttx/arch/arm/src/sama5/sam_ssc.c
index c410c9458..7f7dfc00a 100644
--- a/nuttx/arch/arm/src/sama5/sam_ssc.c
+++ b/nuttx/arch/arm/src/sama5/sam_ssc.c
@@ -84,11 +84,15 @@
# error Work queue support is required (CONFIG_SCHED_WORKQUEUE)
#endif
+#ifndef CONFIG_AUDIO
+# error CONFIG_AUDIO required by this driver
+#endif
+
#ifndef SAMA5_SSC_MAXINFLIGHT
# define SAMA5_SSC_MAXINFLIGHT 16
#endif
-/* Assume no RX/TX support */
+/* Assume no RX/TX support until we learn better */
#undef SSC_HAVE_RX
#undef SSC_HAVE_TX
@@ -117,7 +121,7 @@
/* Check for SSC0 RX support */
-# if (defined(CONFIG_SAMA5_SSC0) && defined(CONFIG_SAMA5_SSC0_RX))
+# if defined(CONFIG_SAMA5_SSC0_RX)
# define SSC_HAVE_RX 1
# ifndef CONFIG_SSC0_RX_FSLEN
@@ -127,11 +131,21 @@
# if CONFIG_SSC0_RX_FSLEN < 1 || CONFIG_SSC0_RX_FSLEN > 255
# error Invalid value for CONFIG_SSC0_RX_FSLEN
# endif
+
+# ifndef CONFIG_SSC0_RX_STTDLY
+# define CONFIG_SSC0_RX_STTDLY CONFIG_SSC0_RX_FSLEN
+# endif
+
+# if CONFIG_SSC0_RX_STTDLY < 0 || \
+ CONFIG_SSC0_RX_STTDLY < CONFIG_SSC0_RX_FSLEN || \
+ CONFIG_SSC0_RX_STTDLY > 255
+# error Invalid value for CONFIG_SSC0_RX_STTDLY
+# endif
# endif
/* Check for SSC0 TX support */
-# if (defined(CONFIG_SAMA5_SSC0) && defined(CONFIG_SAMA5_SSC0_TX))
+# if defined(CONFIG_SAMA5_SSC0_TX)
# define SSC_HAVE_TX 1
# ifndef CONFIG_SSC0_TX_FSLEN
@@ -141,6 +155,20 @@
# if CONFIG_SSC0_TX_FSLEN < 0 || CONFIG_SSC0_TX_FSLEN > 255
# error Invalid value for CONFIG_SSC0_TX_FSLEN
# endif
+
+# ifndef CONFIG_SSC0_TX_STTDLY
+# if CONFIG_SSC0_TX_FSLEN > 0
+# define CONFIG_SSC0_TX_STTDLY CONFIG_SSC0_TX_FSLEN
+# else
+# define CONFIG_SSC0_TX_STTDLY 0
+# endif
+# endif
+
+# if CONFIG_SSC0_TX_STTDLY < 0 || \
+ CONFIG_SSC0_TX_STTDLY < CONFIG_SSC0_TX_FSLEN || \
+ CONFIG_SSC0_TX_STTDLY > 255
+# error Invalid value for CONFIG_SSC0_TX_STTDLY
+# endif
# endif
#endif
@@ -169,7 +197,7 @@
/* Check for SSC1 RX support */
-# if (defined(CONFIG_SAMA5_SSC1) && defined(CONFIG_SAMA5_SSC1_RX))
+# if defined(CONFIG_SAMA5_SSC1_RX)
# define SSC_HAVE_RX 1
# ifndef CONFIG_SSC1_RX_FSLEN
@@ -179,11 +207,22 @@
# if CONFIG_SSC1_RX_FSLEN < 1 || CONFIG_SSC1_RX_FSLEN > 255
# error Invalid value for CONFIG_SSC1_RX_FSLEN
# endif
+
+# ifndef CONFIG_SSC1_RX_STTDLY
+# define CONFIG_SSC1_RX_STTDLY CONFIG_SSC1_RX_FSLEN
+# endif
+
+# if CONFIG_SSC1_RX_STTDLY < 0 || \
+ CONFIG_SSC1_RX_STTDLY < CONFIG_SSC1_RX_FSLEN || \
+ CONFIG_SSC1_RX_STTDLY > 255
+# error Invalid value for CONFIG_SSC1_RX_STTDLY
+# endif
+
# endif
-/* Check for SSC0 TX support */
+/* Check for SSC1 TX support */
-# if (defined(CONFIG_SAMA5_SSC1) && defined(CONFIG_SAMA5_SSC1_TX))
+# if defined(CONFIG_SAMA5_SSC1_TX)
# define SSC_HAVE_TX 1
# ifndef CONFIG_SSC1_TX_FSLEN
@@ -193,12 +232,22 @@
# if CONFIG_SSC1_TX_FSLEN < 0 || CONFIG_SSC1_TX_FSLEN > 255
# error Invalid value for CONFIG_SSC1_TX_FSLEN
# endif
-# endif
-#endif
+# ifndef CONFIG_SSC1_TX_STTDLY
+# if CONFIG_SSC1_TX_FSLEN > 0
+# define CONFIG_SSC1_TX_STTDLY CONFIG_SSC1_TX_FSLEN
+# else
+# define CONFIG_SSC1_TX_STTDLY 0
+# endif
+# endif
+
+# if CONFIG_SSC1_TX_STTDLY < 0 || \
+ CONFIG_SSC1_TX_STTDLY < CONFIG_SSC1_TX_FSLEN || \
+ CONFIG_SSC1_TX_STTDLY > 255
+# error Invalid value for CONFIG_SSC1_TX_STTDLY
+# endif
+# endif
-#ifndef CONFIG_AUDIO
-# error CONFIG_AUDIO required by this driver
#endif
/* Check if we need to build RX and/or TX support */
@@ -244,7 +293,6 @@
* REVISIT: These will probably need to be configurable
*/
-#define SSC_STTDLY(f) (f) /* Delay to data start in clocks (same as FSLEN) */
#define SSC_DATNB (1) /* Number words per per frame */
#define SCC_PERIOD(s,d) ((s) + (d) * SSC_DATNB)
@@ -294,7 +342,7 @@
DMACH_FLAG_PERIPHISPERIPH | DMACH_FLAG_PERIPHWIDTH_8BITS | \
DMACH_FLAG_PERIPHCHUNKSIZE_1 | DMACH_FLAG_MEMPID_MAX | \
DMACH_FLAG_MEM_IF | DMACH_FLAG_MEMWIDTH_16BITS | \
- DMACH_FLAG_MEMINCREMENT | DMACH_FLAG_MEMCHUNKSIZE_4| \
+ DMACH_FLAG_MEMINCREMENT | DMACH_FLAG_MEMCHUNKSIZE_1| \
DMACH_FLAG_MEMBURST_4)
#define DMA16_FLAGS \
@@ -302,7 +350,7 @@
DMACH_FLAG_PERIPHISPERIPH | DMACH_FLAG_PERIPHWIDTH_16BITS | \
DMACH_FLAG_PERIPHCHUNKSIZE_1 | DMACH_FLAG_MEMPID_MAX | \
DMACH_FLAG_MEM_IF | DMACH_FLAG_MEMWIDTH_16BITS | \
- DMACH_FLAG_MEMINCREMENT | DMACH_FLAG_MEMCHUNKSIZE_4 | \
+ DMACH_FLAG_MEMINCREMENT | DMACH_FLAG_MEMCHUNKSIZE_1 | \
DMACH_FLAG_MEMBURST_4)
#define DMA32_FLAGS \
@@ -310,7 +358,7 @@
DMACH_FLAG_PERIPHISPERIPH | DMACH_FLAG_PERIPHWIDTH_32BITS | \
DMACH_FLAG_PERIPHCHUNKSIZE_1 | DMACH_FLAG_MEMPID_MAX | \
DMACH_FLAG_MEM_IF | DMACH_FLAG_MEMWIDTH_32BITS | \
- DMACH_FLAG_MEMINCREMENT | DMACH_FLAG_MEMCHUNKSIZE_4 | \
+ DMACH_FLAG_MEMINCREMENT | DMACH_FLAG_MEMCHUNKSIZE_1 | \
DMACH_FLAG_MEMBURST_4)
/* DMA timeout. The value is not critical; we just don't want the system to
@@ -407,6 +455,8 @@ struct sam_ssc_s
uint8_t pid; /* Peripheral ID */
uint8_t rxfslen; /* RX frame sync length */
uint8_t txfslen; /* TX frame sync length */
+ uint8_t rxsttdly; /* RX start delay */
+ uint8_t txsttdly; /* TX start delay */
uint8_t rxenab:1; /* True: RX transfers enabled */
uint8_t txenab:1; /* True: TX transfers enabled */
uint8_t loopback:1; /* True: Loopback mode */
@@ -2390,23 +2440,12 @@ static int ssc_rx_configure(struct sam_ssc_s *priv)
#ifdef SSC_HAVE_RX
uint32_t regval;
uint32_t fslen;
- uint32_t sttdly;
- /* Get transfer waveform. First get the RX sync time (in RX clocks) */
+ /* Get the RX sync time (in RX clocks) */
DEBUGASSERT(priv->rxfslen > 0);
fslen = priv->rxfslen - 1;
- /* Start delay extends to sometime after RX synch */
-
- sttdly = SSC_STTDLY(fslen);
- if (sttdly > 0)
- {
- /* Decrement as need by the register file */
-
- sttdly--;
- }
-
/* RCMR settings */
/* Configure the receiver input clock */
@@ -2470,7 +2509,7 @@ static int ssc_rx_configure(struct sam_ssc_s *priv)
*/
regval |= (SSC_RCMR_CKI | SSC_RCMR_CKG_CONT | SSC_RCMR_START_EDGE |
- SSC_RCMR_STTDLY(sttdly) | SSC_RCMR_PERIOD(0));
+ SSC_RCMR_STTDLY(priv->rxsttdly) | SSC_RCMR_PERIOD(0));
ssc_putreg(priv, SAM_SSC_RCMR_OFFSET, regval);
/* RFMR settings. Some of these settings will need to be configurable as well.
@@ -2521,26 +2560,16 @@ static int ssc_tx_configure(struct sam_ssc_s *priv)
uint32_t regval;
uint32_t fslen;
uint32_t period;
- uint32_t sttdly;
- /* Get transfer waveform. Get the TX synch in (in TX clocks) */
+ /* Get the TX synch in (in TX clocks) */
fslen = priv->txfslen > 0 ? priv->txfslen - 1 : 0;
- /* Start delay extends to sometime after the TX synch */
-
- sttdly = SSC_STTDLY(fslen);
-
- /* From these, we can get the full period of the waveform */
-
- period = SCC_PERIOD(sttdly, priv->datalen);
-
- /* Decrement the start delay as required by the register field */
+ /* From the start delay and the datalength , we can get the full
+ * period of the waveform.
+ */
- if (sttdly > 0)
- {
- sttdly--;
- }
+ period = SCC_PERIOD(priv->txsttdly, priv->datalen);
/* TCMR settings */
/* Configure the transmitter input clock */
@@ -2612,12 +2641,12 @@ static int ssc_tx_configure(struct sam_ssc_s *priv)
if (priv->txclk == SSC_CLKSRC_MCKDIV)
{
regval |= (SSC_TCMR_CKG_CONT | SSC_TCMR_START_CONT |
- SSC_TCMR_STTDLY(sttdly) | SSC_TCMR_PERIOD(period / 2 - 1));
+ SSC_TCMR_STTDLY(priv->txsttdly) | SSC_TCMR_PERIOD(period / 2 - 1));
}
else
{
regval |= (SSC_TCMR_CKG_CONT | SSC_TCMR_START_EDGE |
- SSC_TCMR_STTDLY(sttdly) | SSC_TCMR_PERIOD(0));
+ SSC_TCMR_STTDLY(priv->txsttdly) | SSC_TCMR_PERIOD(0));
}
ssc_putreg(priv, SAM_SSC_TCMR_OFFSET, regval);
@@ -2652,7 +2681,7 @@ static int ssc_tx_configure(struct sam_ssc_s *priv)
SSC_TFMR_MSBF | SSC_TFMR_DATNB(SSC_DATNB - 1) |
SSC_TFMR_FSOS_NONE);
}
-dbg("##### TFMR BEFORE: datalen=%d regval=%08x txfslen=%02x\n", priv->datalen, regval, priv->txfslen);
+
/* Is the TX frame synch enabled? */
if (priv->txfslen > 0)
@@ -2662,7 +2691,6 @@ dbg("##### TFMR BEFORE: datalen=%d regval=%08x txfslen=%02x\n", priv->datalen, r
regval |= (SSC_TFMR_FSDEN | SSC_TFMR_FSLEN(fslen & 0x0f) |
SSC_TFMR_FSLENEXT((fslen >> 4) & 0x0f));
}
-dbg("##### TFMR AFTER: regval=%08x\n", regval);
ssc_putreg(priv, SAM_SSC_TFMR_OFFSET, regval);
@@ -3038,9 +3066,10 @@ static void ssc0_configure(struct sam_ssc_s *priv)
#endif
- /* Remember the configured RX frame synch length */
+ /* Remember parameters of the configured waveform */
- priv->rxfslen = CONFIG_SSC0_RX_FSLEN;
+ priv->rxfslen = CONFIG_SSC0_RX_FSLEN;
+ priv->rxsttdly = CONFIG_SSC0_RX_STTDLY;
/* Remember the configured RX clock output */
@@ -3108,9 +3137,10 @@ static void ssc0_configure(struct sam_ssc_s *priv)
#endif /* CONFIG_SAMA5_SSC0_TX */
- /* Remember the configured TX frame synch length */
+ /* Remember parameters of the configured waveform */
- priv->txfslen = CONFIG_SSC0_TX_FSLEN;
+ priv->txfslen = CONFIG_SSC0_TX_FSLEN;
+ priv->txsttdly = CONFIG_SSC0_TX_STTDLY;
/* Set/clear loopback mode */
@@ -3174,9 +3204,10 @@ static void ssc1_configure(struct sam_ssc_s *priv)
#endif
- /* Remember the configured RX frame synch length */
+ /* Remember parameters of the configured waveform */
- priv->rxfslen = CONFIG_SSC1_RX_FSLEN;
+ priv->rxfslen = CONFIG_SSC1_RX_FSLEN;
+ priv->rxsttdly = CONFIG_SSC1_RX_STTDLY;
/* Remember the configured RX clock output */
@@ -3244,9 +3275,10 @@ static void ssc1_configure(struct sam_ssc_s *priv)
#endif /* CONFIG_SAMA5_SSC1_TX */
- /* Remember the configured TX frame synch length */
+ /* Remember parameters of the configured waveform */
- priv->txfslen = CONFIG_SSC1_TX_FSLEN;
+ priv->txfslen = CONFIG_SSC1_TX_FSLEN;
+ priv->txsttdly = CONFIG_SSC1_TX_STTDLY;
/* Set/clear loopback mode */
diff --git a/nuttx/configs/sama5d3x-ek/README.txt b/nuttx/configs/sama5d3x-ek/README.txt
index 0e116e099..a4bc1e2fa 100644
--- a/nuttx/configs/sama5d3x-ek/README.txt
+++ b/nuttx/configs/sama5d3x-ek/README.txt
@@ -2735,9 +2735,11 @@ I2S Audio Support
CONFIG_SAMA5_SSC0_RX=y : Support a receiver (although it is not used!)
CONFIG_SAMA5_SSC0_RX_RKINPUT=y : Receiver gets clock the RK0 input
CONFIG_SAMA5_SSC0_RX_FSLEN=1 : Minimal frame sync length
+ CONFIG_SAMA5_SSC0_RX_STTDLY=1 : Start delay
CONFIG_SAMA5_SSC0_TX=y : Support a transmitter
- CONFIG_SAMA5_SSC0_TX_RXCLK=y : Transmitter gets clock the RCLCK
+ CONFIG_SAMA5_SSC0_TX_RXCLK=y : Transmitter gets clock the RXCLCK
CONFIG_SAMA5_SSC0_TX_FSLEN=0 : Disable frame synch generation
+ CONFIG_SAMA5_SSC0_TX_STTDLY=1 : Start delay
CONFIG_SAMA5_SSC0_TX_TKOUTPUT_NONE=y : No output
Audio
diff --git a/nuttx/configs/sama5d4-ek/README.txt b/nuttx/configs/sama5d4-ek/README.txt
index 8163f7b03..f055aad64 100644
--- a/nuttx/configs/sama5d4-ek/README.txt
+++ b/nuttx/configs/sama5d4-ek/README.txt
@@ -2790,9 +2790,11 @@ Audio Support
CONFIG_SAMA5_SSC0_RX=y : Support a receiver (although it is not used!)
CONFIG_SAMA5_SSC0_RX_RKINPUT=y : Receiver gets clock the RK0 input
CONFIG_SAMA5_SSC0_RX_FSLEN=1 : Minimal frame sync length
+ CONFIG_SAMA5_SSC0_RX_STTDLY=1 : Start delay
CONFIG_SAMA5_SSC0_TX=y : Support a transmitter
- CONFIG_SAMA5_SSC0_TX_RXCLK=y : Transmitter gets clock the RCLCK
+ CONFIG_SAMA5_SSC0_TX_RXCLK=y : Transmitter gets clock the RXCLCK
CONFIG_SAMA5_SSC0_TX_FSLEN=0 : Disable frame synch generation
+ CONFIG_SAMA5_SSC0_TX_STTDLY=1 : Start delay
CONFIG_SAMA5_SSC0_TX_TKOUTPUT_NONE=y : No output
Audio