You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by ac...@apache.org on 2020/01/28 14:33:04 UTC
[incubator-nuttx] branch master updated: Generic SPI interface for
controlling an LCD display
This is an automated email from the ASF dual-hosted git repository.
acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
The following commit(s) were added to refs/heads/master by this push:
new e99a8d1 Generic SPI interface for controlling an LCD display
e99a8d1 is described below
commit e99a8d192ddeae83b5b6a88d9e13a6c56b58c256
Author: Dave Marples <da...@marples.net>
AuthorDate: Tue Jan 28 11:30:34 2020 -0300
Generic SPI interface for controlling an LCD display
---
arch/arm/src/imxrt/imxrt_lpspi.c | 317 ++++++++++++++++++++---------------
drivers/lcd/Kconfig | 17 ++
drivers/lcd/Make.defs | 4 +
drivers/lcd/lcddrv_spiif.c | 347 +++++++++++++++++++++++++++++++++++++++
include/nuttx/lcd/lcddrv_spiif.h | 144 ++++++++++++++++
5 files changed, 698 insertions(+), 131 deletions(-)
diff --git a/arch/arm/src/imxrt/imxrt_lpspi.c b/arch/arm/src/imxrt/imxrt_lpspi.c
index b33cee8..8c88386 100644
--- a/arch/arm/src/imxrt/imxrt_lpspi.c
+++ b/arch/arm/src/imxrt/imxrt_lpspi.c
@@ -1,4 +1,4 @@
-/************************************************************************************
+/*****************************************************************************
* arm/arm/src/imxrt/imxrt_lpspi.c
*
* Copyright (C) 2018 Gregory Nutt. All rights reserved.
@@ -32,34 +32,35 @@
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
- ************************************************************************************/
+ *****************************************************************************/
-/************************************************************************************
- * The external functions, imxrt_lpspi1/2/3/4select and imxrt_lpspi1/2/3/4status
- * must be provided by board-specific logic. They are implementations of the select
- * and status methods of the SPI interface defined by struct imxrt_lpspi_ops_s (see
- * include/nuttx/spi/spi.h). All other methods (including imxrt_lpspibus_initialize())
- * are provided by common IMXRT logic. To use this common SPI logic on your
- * board:
+/*****************************************************************************
+ * The external functions, imxrt_lpspi1/2/3/4select and
+ * imxrt_lpspi1/2/3/4status must be provided by board-specific logic.
+ * They are implementations of the select and status methods of the SPI
+ * interface defined by struct imxrt_lpspi_ops_s (see
+ * include/nuttx/spi/spi.h). All other methods (including
+ * imxrt_lpspibus_initialize()) are provided by common IMXRT logic.
+ * To use this common SPI logic on your board:
*
* 1. Provide logic in imxrt_boardinitialize() to configure SPI chip select
* pins.
* 2. Provide imxrt_lpspi1/2/3/4select() and imxrt_lpspi1/2/3/4status()
- * functions in your board-specific logic. These functions will perform chip
- * selection and status operations using GPIOs in the way your board is
- * configured.
- * 3. Add a calls to imxrt_lpspibus_initialize() in your low level application
- * initialization logic
- * 4. The handle returned by imxrt_lpspibus_initialize() may then be used to bind the
- * SPI driver to higher level logic (e.g., calling
+ * functions in your board-specific logic. These functions will perform
+ * chip selection and status operations using GPIOs in the way your board
+ * is configured.
+ * 3. Add a calls to imxrt_lpspibus_initialize() in your low level
+ * application initialization logic
+ * 4. The handle returned by imxrt_lpspibus_initialize() may then be used to
+ * bind the SPI driver to higher level logic (e.g., calling
* mmcsd_lpspislotinitialize(), for example, will bind the SPI driver to
* the SPI MMC/SD driver).
*
- ************************************************************************************/
+ *****************************************************************************/
-/************************************************************************************
+/*****************************************************************************
* Included Files
- ************************************************************************************/
+ *****************************************************************************/
#include <nuttx/config.h>
@@ -94,11 +95,11 @@
#if defined(CONFIG_IMXRT_LPSPI1) || defined(CONFIG_IMXRT_LPSPI2) || \
defined(CONFIG_IMXRT_LPSPI3) || defined(CONFIG_IMXRT_LPSPI4)
-/************************************************************************************
+/*****************************************************************************
* Pre-processor Definitions
- ************************************************************************************/
+ ****************************************************************************/
-/* Configuration ********************************************************************/
+/* Configuration ************************************************************/
/* SPI interrupts */
@@ -116,9 +117,9 @@
# error "Cannot enable both interrupt mode and DMA mode for SPI"
#endif
-/************************************************************************************
+/*****************************************************************************
* Private Types
- ************************************************************************************/
+ ****************************************************************************/
struct imxrt_lpspidev_s
{
@@ -141,9 +142,9 @@ enum imxrt_delay_e
LPSPI_BETWEEN_TRANSFER /* Delay between transfers. */
};
-/************************************************************************************
+/*****************************************************************************
* Private Function Prototypes
- ************************************************************************************/
+ ****************************************************************************/
/* Helpers */
@@ -151,17 +152,19 @@ static inline uint32_t imxrt_lpspi_getreg32(FAR struct imxrt_lpspidev_s *priv,
uint8_t offset);
static inline void imxrt_lpspi_putreg32(FAR struct imxrt_lpspidev_s *priv,
uint8_t offset, uint32_t value);
-static inline uint16_t imxrt_lpspi_readword(FAR struct imxrt_lpspidev_s *priv);
+static inline uint16_t imxrt_lpspi_readword(
+ FAR struct imxrt_lpspidev_s *priv);
static inline void imxrt_lpspi_writeword(FAR struct imxrt_lpspidev_s *priv,
uint16_t byte);
-static inline bool imxrt_lpspi_9to16bitmode(FAR struct imxrt_lpspidev_s *priv);
+static inline bool imxrt_lpspi_9to16bitmode(
+ FAR struct imxrt_lpspidev_s *priv);
static inline void imxrt_lpspi_master_set_delays(FAR struct imxrt_lpspidev_s
*priv, uint32_t delay_ns,
enum imxrt_delay_e type);
-static inline void imxrt_lpspi_master_set_delay_scaler(FAR struct
- imxrt_lpspidev_s *priv,
- uint32_t scaler,
- enum imxrt_delay_e type);
+static inline void imxrt_lpspi_master_set_delay_scaler(
+ FAR struct imxrt_lpspidev_s *priv,
+ uint32_t scaler,
+ enum imxrt_delay_e type);
/* SPI methods */
@@ -182,7 +185,8 @@ static void imxrt_lpspi_exchange(FAR struct spi_dev_s *dev,
#ifndef CONFIG_SPI_EXCHANGE
static void imxrt_lpspi_sndblock(FAR struct spi_dev_s *dev,
FAR const void *txbuffer, size_t nwords);
-static void imxrt_lpspi_recvblock(FAR struct spi_dev_s *dev, FAR void *rxbuffer,
+static void imxrt_lpspi_recvblock(FAR struct spi_dev_s *dev,
+ FAR void *rxbuffer,
size_t nwords);
#endif
@@ -190,9 +194,9 @@ static void imxrt_lpspi_recvblock(FAR struct spi_dev_s *dev, FAR void *rxbuffer,
static void imxrt_lpspi_bus_initialize(FAR struct imxrt_lpspidev_s *priv);
-/************************************************************************************
+/*****************************************************************************
* Private Data
- ************************************************************************************/
+ *****************************************************************************/
#ifdef CONFIG_IMXRT_LPSPI1
static const struct spi_ops_s g_spi1ops =
@@ -378,11 +382,11 @@ static struct imxrt_lpspidev_s g_lpspi4dev =
};
#endif
-/************************************************************************************
+/*****************************************************************************
* Private Functions
- ************************************************************************************/
+ *****************************************************************************/
-/************************************************************************************
+/*****************************************************************************
* Name: imxrt_lpspi_getreg8
*
* Description:
@@ -395,7 +399,7 @@ static struct imxrt_lpspidev_s g_lpspi4dev =
* Returned Value:
* The contents of the 8-bit register
*
- ************************************************************************************/
+ *****************************************************************************/
static inline uint8_t imxrt_lpspi_getreg8(FAR struct imxrt_lpspidev_s *priv,
uint8_t offset)
@@ -403,7 +407,7 @@ static inline uint8_t imxrt_lpspi_getreg8(FAR struct imxrt_lpspidev_s *priv,
return getreg8(priv->spibase + offset);
}
-/************************************************************************************
+/*****************************************************************************
* Name: imxrt_lpspi_putreg8
*
* Description:
@@ -414,7 +418,7 @@ static inline uint8_t imxrt_lpspi_getreg8(FAR struct imxrt_lpspidev_s *priv,
* offset - offset to the register of interest
* value - the 8-bit value to be written
*
- ************************************************************************************/
+ *****************************************************************************/
static inline void imxrt_lpspi_putreg8(FAR struct imxrt_lpspidev_s *priv,
uint8_t offset, uint8_t value)
@@ -422,7 +426,7 @@ static inline void imxrt_lpspi_putreg8(FAR struct imxrt_lpspidev_s *priv,
putreg8(value, priv->spibase + offset);
}
-/************************************************************************************
+/*****************************************************************************
* Name: imxrt_lpspi_getreg
*
* Description:
@@ -435,7 +439,7 @@ static inline void imxrt_lpspi_putreg8(FAR struct imxrt_lpspidev_s *priv,
* Returned Value:
* The contents of the 32-bit register
*
- ************************************************************************************/
+ *****************************************************************************/
static inline uint32_t imxrt_lpspi_getreg32(FAR struct imxrt_lpspidev_s *priv,
uint8_t offset)
@@ -443,7 +447,7 @@ static inline uint32_t imxrt_lpspi_getreg32(FAR struct imxrt_lpspidev_s *priv,
return getreg32(priv->spibase + offset);
}
-/************************************************************************************
+/*****************************************************************************
* Name: imxrt_lpspi_putreg
*
* Description:
@@ -457,7 +461,7 @@ static inline uint32_t imxrt_lpspi_getreg32(FAR struct imxrt_lpspidev_s *priv,
* Returned Value:
* The contents of the 32-bit register
*
- ************************************************************************************/
+ *****************************************************************************/
static inline void imxrt_lpspi_putreg32(FAR struct imxrt_lpspidev_s *priv,
uint8_t offset, uint32_t value)
@@ -465,7 +469,7 @@ static inline void imxrt_lpspi_putreg32(FAR struct imxrt_lpspidev_s *priv,
putreg32(value, priv->spibase + offset);
}
-/************************************************************************************
+/*****************************************************************************
* Name: imxrt_lpspi_readword
*
* Description:
@@ -477,20 +481,21 @@ static inline void imxrt_lpspi_putreg32(FAR struct imxrt_lpspidev_s *priv,
* Returned Value:
* word as read
*
- ************************************************************************************/
+ *****************************************************************************/
static inline uint16_t imxrt_lpspi_readword(FAR struct imxrt_lpspidev_s *priv)
{
/* Wait until the receive buffer is not empty */
- while ((imxrt_lpspi_getreg32(priv, IMXRT_LPSPI_SR_OFFSET) & LPSPI_SR_RDF) == 0);
+ while ((imxrt_lpspi_getreg32(priv, IMXRT_LPSPI_SR_OFFSET)
+ & LPSPI_SR_RDF) == 0);
/* Then return the received byte */
return (uint16_t) imxrt_lpspi_getreg32(priv, IMXRT_LPSPI_RDR_OFFSET);
}
-/************************************************************************************
+/*****************************************************************************
* Name: imxrt_lpspi_writeword
*
* Description:
@@ -503,21 +508,22 @@ static inline uint16_t imxrt_lpspi_readword(FAR struct imxrt_lpspidev_s *priv)
* Returned Value:
* None
*
- ************************************************************************************/
+ *****************************************************************************/
static inline void imxrt_lpspi_writeword(FAR struct imxrt_lpspidev_s *priv,
uint16_t word)
{
/* Wait until the transmit buffer is empty */
- while ((imxrt_lpspi_getreg32(priv, IMXRT_LPSPI_SR_OFFSET) & LPSPI_SR_TDF) == 0);
+ while ((imxrt_lpspi_getreg32(priv, IMXRT_LPSPI_SR_OFFSET)
+ & LPSPI_SR_TDF) == 0);
/* Then send the word */
imxrt_lpspi_putreg32(priv, IMXRT_LPSPI_TDR_OFFSET, word);
}
-/************************************************************************************
+/*****************************************************************************
* Name: imxrt_lpspi_readbyte
*
* Description:
@@ -529,20 +535,21 @@ static inline void imxrt_lpspi_writeword(FAR struct imxrt_lpspidev_s *priv,
* Returned Value:
* Byte as read
*
- ************************************************************************************/
+ *****************************************************************************/
static inline uint8_t imxrt_lpspi_readbyte(FAR struct imxrt_lpspidev_s *priv)
{
/* Wait until the receive buffer is not empty */
- while ((imxrt_lpspi_getreg32(priv, IMXRT_LPSPI_SR_OFFSET) & LPSPI_SR_RDF) == 0);
+ while ((imxrt_lpspi_getreg32(priv, IMXRT_LPSPI_SR_OFFSET)
+ & LPSPI_SR_RDF) == 0);
/* Then return the received byte */
return imxrt_lpspi_getreg8(priv, IMXRT_LPSPI_RDR_OFFSET);
}
-/************************************************************************************
+/*****************************************************************************
* Name: imxrt_lpspi_writebyte
*
* Description:
@@ -555,21 +562,22 @@ static inline uint8_t imxrt_lpspi_readbyte(FAR struct imxrt_lpspidev_s *priv)
* Returned Value:
* None
*
- ************************************************************************************/
+ *****************************************************************************/
static inline void imxrt_lpspi_writebyte(FAR struct imxrt_lpspidev_s *priv,
uint8_t byte)
{
/* Wait until the transmit buffer is empty */
- while ((imxrt_lpspi_getreg32(priv, IMXRT_LPSPI_SR_OFFSET) & LPSPI_SR_TDF) == 0);
+ while ((imxrt_lpspi_getreg32(priv, IMXRT_LPSPI_SR_OFFSET)
+ & LPSPI_SR_TDF) == 0);
/* Then send the byte */
imxrt_lpspi_putreg8(priv, IMXRT_LPSPI_TDR_OFFSET, byte);
}
-/************************************************************************************
+/*****************************************************************************
* Name: imxrt_lpspi_9to16bitmode
*
* Description:
@@ -581,7 +589,7 @@ static inline void imxrt_lpspi_writebyte(FAR struct imxrt_lpspidev_s *priv,
* Returned Value:
* true: >8 bit mode-bit mode, false: <= 8-bit mode
*
- ************************************************************************************/
+ *****************************************************************************/
static inline bool imxrt_lpspi_9to16bitmode(FAR struct imxrt_lpspidev_s *priv)
{
@@ -600,7 +608,7 @@ static inline bool imxrt_lpspi_9to16bitmode(FAR struct imxrt_lpspidev_s *priv)
return ret;
}
-/************************************************************************************
+/*****************************************************************************
* Name: imxrt_lpspi_modifyreg
*
* Description:
@@ -615,7 +623,7 @@ static inline bool imxrt_lpspi_9to16bitmode(FAR struct imxrt_lpspidev_s *priv)
* Returned Value:
* None
*
- ************************************************************************************/
+ *****************************************************************************/
static void imxrt_lpspi_modifyreg32(FAR struct imxrt_lpspidev_s *priv,
uint8_t offset, uint32_t clrbits,
@@ -624,7 +632,7 @@ static void imxrt_lpspi_modifyreg32(FAR struct imxrt_lpspidev_s *priv,
modifyreg32(priv->spibase + offset, clrbits, setbits);
}
-/************************************************************************************
+/*****************************************************************************
* Name: imxrt_lpspi_master_set_delays
*
* Description:
@@ -638,11 +646,12 @@ static void imxrt_lpspi_modifyreg32(FAR struct imxrt_lpspidev_s *priv,
* Returned Value:
* None
*
- ************************************************************************************/
+ *****************************************************************************/
-static inline void imxrt_lpspi_master_set_delay_scaler(FAR struct imxrt_lpspidev_s *priv,
- uint32_t scaler,
- enum imxrt_delay_e type)
+static inline void imxrt_lpspi_master_set_delay_scaler(
+ FAR struct imxrt_lpspidev_s *priv,
+ uint32_t scaler,
+ enum imxrt_delay_e type)
{
switch (type)
{
@@ -661,15 +670,15 @@ static inline void imxrt_lpspi_master_set_delay_scaler(FAR struct imxrt_lpspidev
break;
case LPSPI_BETWEEN_TRANSFER:
- imxrt_lpspi_modifyreg32(priv, IMXRT_LPSPI_CCR_OFFSET, LPSPI_CCR_DBT_MASK,
- 0);
+ imxrt_lpspi_modifyreg32(priv, IMXRT_LPSPI_CCR_OFFSET,
+ LPSPI_CCR_DBT_MASK, 0);
imxrt_lpspi_modifyreg32(priv, IMXRT_LPSPI_CCR_OFFSET, 0,
LPSPI_CCR_DBT(scaler));
break;
}
}
-/************************************************************************************
+/*****************************************************************************
* Name: imxrt_lpspi_master_set_delays
*
* Description:
@@ -683,10 +692,12 @@ static inline void imxrt_lpspi_master_set_delay_scaler(FAR struct imxrt_lpspidev
* Returned Value:
* None
*
- ************************************************************************************/
-static inline void imxrt_lpspi_master_set_delays(FAR struct imxrt_lpspidev_s *priv,
- uint32_t delay_ns,
- enum imxrt_delay_e type)
+ *****************************************************************************/
+
+static inline void imxrt_lpspi_master_set_delays(
+ FAR struct imxrt_lpspidev_s *priv,
+ uint32_t delay_ns,
+ enum imxrt_delay_e type)
{
uint32_t pll3_div;
uint32_t pll_freq;
@@ -719,8 +730,9 @@ static inline void imxrt_lpspi_master_set_delays(FAR struct imxrt_lpspidev_s *pr
*/
src_freq = pll_freq /
- ((getreg32(IMXRT_CCM_ANALOG_PFD_480) & CCM_ANALOG_PFD_480_PFD0_FRAC_MASK) >>
- CCM_ANALOG_PFD_480_PFD0_FRAC_SHIFT);
+ ((getreg32(IMXRT_CCM_ANALOG_PFD_480)
+ & CCM_ANALOG_PFD_480_PFD0_FRAC_MASK) >>
+ CCM_ANALOG_PFD_480_PFD0_FRAC_SHIFT);
src_freq *= 18;
src_freq /= ((getreg32(IMXRT_CCM_CBCMR) & CCM_CBCMR_LPSPI_PODF_MASK) >>
CCM_CBCMR_LPSPI_PODF_SHIFT) + 1;
@@ -797,9 +809,9 @@ static inline void imxrt_lpspi_master_set_delays(FAR struct imxrt_lpspidev_s *pr
for (scaler = 0; (scaler < 256) && min_diff; scaler++)
{
/* Calculate the real delay value as we cycle through the scaler
- * values. Due to large size of calculated values (uint64_t), we need
- * to break up the calculation into several steps to ensure accurate
- * calculated results
+ * values. Due to large size of calculated values (uint64_t),
+ * we need to break up the calculation into several steps to
+ * ensure accurate calculated results
*/
real_delay = 1000000000U;
@@ -829,7 +841,7 @@ static inline void imxrt_lpspi_master_set_delays(FAR struct imxrt_lpspidev_s *pr
}
}
-/************************************************************************************
+/*****************************************************************************
* Name: imxrt_lpspi_lock
*
* Description:
@@ -848,7 +860,7 @@ static inline void imxrt_lpspi_master_set_delays(FAR struct imxrt_lpspidev_s *pr
* Returned Value:
* None
*
- ************************************************************************************/
+ *****************************************************************************/
static int imxrt_lpspi_lock(FAR struct spi_dev_s *dev, bool lock)
{
@@ -867,7 +879,7 @@ static int imxrt_lpspi_lock(FAR struct spi_dev_s *dev, bool lock)
return ret;
}
-/************************************************************************************
+/*****************************************************************************
* Name: imxrt_lpspi_setfrequency
*
* Description:
@@ -880,7 +892,7 @@ static int imxrt_lpspi_lock(FAR struct spi_dev_s *dev, bool lock)
* Returned Value:
* Returns the actual frequency selected
*
- ************************************************************************************/
+ *****************************************************************************/
static uint32_t imxrt_lpspi_setfrequency(FAR struct spi_dev_s *dev,
uint32_t frequency)
@@ -909,7 +921,8 @@ static uint32_t imxrt_lpspi_setfrequency(FAR struct spi_dev_s *dev,
men = imxrt_lpspi_getreg32(priv, IMXRT_LPSPI_CR_OFFSET) & LPSPI_CR_MEN;
if (men)
{
- imxrt_lpspi_modifyreg32(priv, IMXRT_LPSPI_CR_OFFSET, LPSPI_CR_MEN, 0);
+ imxrt_lpspi_modifyreg32(priv, IMXRT_LPSPI_CR_OFFSET,
+ LPSPI_CR_MEN, 0);
}
if ((getreg32(IMXRT_CCM_ANALOG_PLL_USB1) &
@@ -930,8 +943,9 @@ static uint32_t imxrt_lpspi_setfrequency(FAR struct spi_dev_s *dev,
*/
src_freq = pll_freq /
- ((getreg32(IMXRT_CCM_ANALOG_PFD_480) & CCM_ANALOG_PFD_480_PFD0_FRAC_MASK) >>
- CCM_ANALOG_PFD_480_PFD0_FRAC_SHIFT);
+ ((getreg32(IMXRT_CCM_ANALOG_PFD_480)
+ & CCM_ANALOG_PFD_480_PFD0_FRAC_MASK) >>
+ CCM_ANALOG_PFD_480_PFD0_FRAC_SHIFT);
src_freq *= 18;
src_freq /= ((getreg32(IMXRT_CCM_CBCMR) & CCM_CBCMR_LPSPI_PODF_MASK) >>
CCM_CBCMR_LPSPI_PODF_SHIFT) + 1;
@@ -994,14 +1008,15 @@ static uint32_t imxrt_lpspi_setfrequency(FAR struct spi_dev_s *dev,
if (men)
{
- imxrt_lpspi_modifyreg32(priv, IMXRT_LPSPI_CR_OFFSET, 0, LPSPI_CR_MEN);
+ imxrt_lpspi_modifyreg32(priv, IMXRT_LPSPI_CR_OFFSET, 0,
+ LPSPI_CR_MEN);
}
}
return priv->actual;
}
-/************************************************************************************
+/*****************************************************************************
* Name: imxrt_lpspi_setmode
*
* Description:
@@ -1014,9 +1029,10 @@ static uint32_t imxrt_lpspi_setfrequency(FAR struct spi_dev_s *dev,
* Returned Value:
* Returns the actual frequency selected
*
- ************************************************************************************/
+ *****************************************************************************/
-static void imxrt_lpspi_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode)
+static void imxrt_lpspi_setmode(FAR struct spi_dev_s *dev,
+ enum spi_mode_e mode)
{
FAR struct imxrt_lpspidev_s *priv = (FAR struct imxrt_lpspidev_s *)dev;
uint32_t setbits;
@@ -1034,7 +1050,8 @@ static void imxrt_lpspi_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode)
men = imxrt_lpspi_getreg32(priv, IMXRT_LPSPI_CR_OFFSET) & LPSPI_CR_MEN;
if (men)
{
- imxrt_lpspi_modifyreg32(priv, IMXRT_LPSPI_CR_OFFSET, LPSPI_CR_MEN, 0);
+ imxrt_lpspi_modifyreg32(priv, IMXRT_LPSPI_CR_OFFSET,
+ LPSPI_CR_MEN, 0);
}
switch (mode)
@@ -1081,12 +1098,13 @@ static void imxrt_lpspi_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode)
if (men)
{
- imxrt_lpspi_modifyreg32(priv, IMXRT_LPSPI_CR_OFFSET, 0, LPSPI_CR_MEN);
+ imxrt_lpspi_modifyreg32(priv, IMXRT_LPSPI_CR_OFFSET, 0,
+ LPSPI_CR_MEN);
}
}
}
-/************************************************************************************
+/*****************************************************************************
* Name: imxrt_lpspi_setbits
*
* Description:
@@ -1099,7 +1117,7 @@ static void imxrt_lpspi_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode)
* Returned Value:
* None
*
- ************************************************************************************/
+ *****************************************************************************/
static void imxrt_lpspi_setbits(FAR struct spi_dev_s *dev, int nbits)
{
@@ -1113,7 +1131,6 @@ static void imxrt_lpspi_setbits(FAR struct spi_dev_s *dev, int nbits)
if (nbits != priv->nbits)
{
-
if (nbits < 2 || nbits > 4096)
{
return;
@@ -1124,14 +1141,17 @@ static void imxrt_lpspi_setbits(FAR struct spi_dev_s *dev, int nbits)
men = imxrt_lpspi_getreg32(priv, IMXRT_LPSPI_CR_OFFSET) & LPSPI_CR_MEN;
if (men)
{
- imxrt_lpspi_modifyreg32(priv, IMXRT_LPSPI_CR_OFFSET, LPSPI_CR_MEN, 0);
+ imxrt_lpspi_modifyreg32(priv, IMXRT_LPSPI_CR_OFFSET,
+ LPSPI_CR_MEN, 0);
}
imxrt_lpspi_modifyreg32(priv, IMXRT_LPSPI_TCR_OFFSET,
LPSPI_TCR_FRAMESZ_MASK,
LPSPI_TCR_FRAMESZ(nbits - 1));
- /* Save the selection so the subsequence re-configurations will be faster */
+ /* Save the selection so the subsequence re-configurations
+ * will be faster
+ */
priv->nbits = savbits; /* nbits has been clobbered... save the signed
* value. */
@@ -1140,12 +1160,13 @@ static void imxrt_lpspi_setbits(FAR struct spi_dev_s *dev, int nbits)
if (men)
{
- imxrt_lpspi_modifyreg32(priv, IMXRT_LPSPI_CR_OFFSET, 0, LPSPI_CR_MEN);
+ imxrt_lpspi_modifyreg32(priv, IMXRT_LPSPI_CR_OFFSET, 0,
+ LPSPI_CR_MEN);
}
}
}
-/****************************************************************************
+/*****************************************************************************
* Name: imxrt_lpspi_hwfeatures
*
* Description:
@@ -1197,7 +1218,7 @@ static int imxrt_lpspi_hwfeatures(FAR struct spi_dev_s *dev,
}
#endif
-/************************************************************************************
+/*****************************************************************************
* Name: imxrt_lpspi_send
*
* Description:
@@ -1211,7 +1232,7 @@ static int imxrt_lpspi_hwfeatures(FAR struct spi_dev_s *dev,
* Returned Value:
* response
*
- ************************************************************************************/
+ *****************************************************************************/
static uint16_t imxrt_lpspi_send(FAR struct spi_dev_s *dev, uint16_t wd)
{
@@ -1240,7 +1261,7 @@ static uint16_t imxrt_lpspi_send(FAR struct spi_dev_s *dev, uint16_t wd)
return ret;
}
-/************************************************************************************
+/*****************************************************************************
* Name: imxrt_lpspi_exchange (no DMA). aka imxrt_lpspi_exchange_nodma
*
* Description:
@@ -1253,12 +1274,13 @@ static uint16_t imxrt_lpspi_send(FAR struct spi_dev_s *dev, uint16_t wd)
* nwords - the length of data to be exchaned in units of words.
* The wordsize is determined by the number of bits-per-word
* selected for the SPI interface. If nbits <= 8, the data is
- * packed into uint8_t's; if nbits >8, the data is packed into uint16_t's
+ * packed into uint8_t's; if nbits >8, the data is packed
+ * into uint16_t's
*
* Returned Value:
* None
*
- ************************************************************************************/
+ *****************************************************************************/
#if !defined(CONFIG_IMXRT_LPSPI_DMA) || defined(CONFIG_IMXRT_DMACAPABLE)
#if !defined(CONFIG_IMXRT_LPSPI_DMA)
@@ -1359,12 +1381,13 @@ static void imxrt_lpspi_exchange_nodma(FAR struct spi_dev_s *dev,
* nwords - the length of data to send from the buffer in number of words.
* The wordsize is determined by the number of bits-per-word
* selected for the SPI interface. If nbits <= 8, the data is
- * packed into uint8_t's; if nbits >8, the data is packed into uint16_t's
+ * packed into uint8_t's; if nbits >8, the data is packed into
+ * uint16_t's
*
* Returned Value:
* None
*
- ************************************************************************************/
+ *****************************************************************************/
#ifndef CONFIG_SPI_EXCHANGE
static void imxrt_lpspi_sndblock(FAR struct spi_dev_s *dev,
@@ -1375,7 +1398,7 @@ static void imxrt_lpspi_sndblock(FAR struct spi_dev_s *dev,
}
#endif
-/************************************************************************************
+/*****************************************************************************
* Name: imxrt_lpspi_recvblock
*
* Description:
@@ -1384,32 +1407,33 @@ static void imxrt_lpspi_sndblock(FAR struct spi_dev_s *dev,
* Input Parameters:
* dev - Device-specific state data
* rxbuffer - A pointer to the buffer in which to receive data
- * nwords - the length of data that can be received in the buffer in number
- * of words. The wordsize is determined by the number of bits-per-word
- * selected for the SPI interface. If nbits <= 8, the data is
- * packed into uint8_t's; if nbits >8, the data is packed into uint16_t's
+ * nwords - the length of data that can be received in the buffer in
+ * number of words. The wordsize is determined by the number of
+ * bits-per-word selected for the SPI interface. If
+ * nbits <= 8, the data is packed into uint8_t's;
+ * if nbits >8, the data is packed into uint16_t's
*
* Returned Value:
* None
*
- ************************************************************************************/
+ *****************************************************************************/
#ifndef CONFIG_SPI_EXCHANGE
-static void imxrt_lpspi_recvblock(FAR struct spi_dev_s *dev, FAR void *rxbuffer,
- size_t nwords)
+static void imxrt_lpspi_recvblock(FAR struct spi_dev_s *dev,
+ FAR void *rxbuffer, size_t nwords)
{
spiinfo("rxbuffer=%p nwords=%d\n", rxbuffer, nwords);
return imxrt_lpspi_exchange(dev, NULL, rxbuffer, nwords);
}
#endif
-/************************************************************************************
+/*****************************************************************************
* Name: imxrt_lpspi_clock_enable
*
* Description:
* Ungate LPSPI clock
*
- ************************************************************************************/
+ *****************************************************************************/
void imxrt_lpspi_clock_enable(uint32_t base)
{
@@ -1431,13 +1455,13 @@ void imxrt_lpspi_clock_enable(uint32_t base)
}
}
-/************************************************************************************
+/*****************************************************************************
* Name: imxrt_lpspi_clock_disable
*
* Description:
* Gate LPSPI clock
*
- ************************************************************************************/
+ *****************************************************************************/
void imxrt_lpspi_clock_disable(uint32_t base)
{
@@ -1459,11 +1483,12 @@ void imxrt_lpspi_clock_disable(uint32_t base)
}
}
-/************************************************************************************
+/*****************************************************************************
* Name: imxrt_lpspi_bus_initialize
*
* Description:
- * Initialize the selected SPI bus in its default state (Master, 8-bit, mode 0, etc.)
+ * Initialize the selected SPI bus in its default state
+ * (Master, 8-bit, mode 0, etc.)
*
* Input Parameters:
* priv - private SPI device structure
@@ -1471,7 +1496,7 @@ void imxrt_lpspi_clock_disable(uint32_t base)
* Returned Value:
* None
*
- ************************************************************************************/
+ *****************************************************************************/
static void imxrt_lpspi_bus_initialize(struct imxrt_lpspidev_s *priv)
{
@@ -1493,13 +1518,15 @@ static void imxrt_lpspi_bus_initialize(struct imxrt_lpspidev_s *priv)
imxrt_lpspi_modifyreg32(priv, IMXRT_LPSPI_CFGR1_OFFSET, 0,
LPSPI_CFGR1_MASTER);
- /* Set specific PCS to active high or low */
- /* TODO: Not needed for now */
+ /* Set specific PCS to active high or low
+ * TODO: Not needed for now
+ */
/* Set Configuration Register 1 related setting. */
reg = imxrt_lpspi_getreg32(priv, IMXRT_LPSPI_CFGR1_OFFSET);
- reg &= ~(LPSPI_CFGR1_OUTCFG | LPSPI_CFGR1_PINCFG_MASK | LPSPI_CFGR1_NOSTALL);
+ reg &= ~(LPSPI_CFGR1_OUTCFG | LPSPI_CFGR1_PINCFG_MASK
+ | LPSPI_CFGR1_NOSTALL);
reg |= LPSPI_CFGR1_OUTCFG_RETAIN | LPSPI_CFGR1_PINCFG_SIN_SOUT;
imxrt_lpspi_putreg32(priv, IMXRT_LPSPI_CFGR1_OFFSET, reg);
@@ -1527,11 +1554,11 @@ static void imxrt_lpspi_bus_initialize(struct imxrt_lpspidev_s *priv)
imxrt_lpspi_modifyreg32(priv, IMXRT_LPSPI_CR_OFFSET, 0, LPSPI_CR_MEN);
}
-/************************************************************************************
+/*****************************************************************************
* Public Functions
- ************************************************************************************/
+ *****************************************************************************/
-/************************************************************************************
+/*****************************************************************************
* Name: imxrt_lpspibus_initialize
*
* Description:
@@ -1543,7 +1570,7 @@ static void imxrt_lpspi_bus_initialize(struct imxrt_lpspidev_s *priv)
* Returned Value:
* Valid SPI device structure reference on success; a NULL on failure
*
- ************************************************************************************/
+ ****************************************************************************/
FAR struct spi_dev_s *imxrt_lpspibus_initialize(int bus)
{
@@ -1560,13 +1587,20 @@ FAR struct spi_dev_s *imxrt_lpspibus_initialize(int bus)
/* Only configure if the bus is not already configured */
- if ((imxrt_lpspi_getreg32(priv, IMXRT_LPSPI_CR_OFFSET) & LPSPI_CR_MEN) == 0)
+ if ((imxrt_lpspi_getreg32(priv, IMXRT_LPSPI_CR_OFFSET)
+ & LPSPI_CR_MEN) == 0)
{
/* Configure SPI1 pins: SCK, MISO, and MOSI */
imxrt_config_gpio(GPIO_LPSPI1_SCK);
imxrt_config_gpio(GPIO_LPSPI1_MISO);
imxrt_config_gpio(GPIO_LPSPI1_MOSI);
+#ifdef GPIO_LPSPI1_CS
+ imxrt_config_gpio(GPIO_LPSPI1_CS);
+#endif
+#if defined(GPIO_LPSPI1_DC) && defined(CONFIG_SPI_CMDDATA)
+ imxrt_config_gpio(GPIO_LPSPI1_DC);
+#endif
/* Set up default configuration: Master, 8-bit, etc. */
@@ -1584,13 +1618,20 @@ FAR struct spi_dev_s *imxrt_lpspibus_initialize(int bus)
/* Only configure if the bus is not already configured */
- if ((imxrt_lpspi_getreg32(priv, IMXRT_LPSPI_CR_OFFSET) & LPSPI_CR_MEN) == 0)
+ if ((imxrt_lpspi_getreg32(priv, IMXRT_LPSPI_CR_OFFSET)
+ & LPSPI_CR_MEN) == 0)
{
/* Configure SPI2 pins: SCK, MISO, and MOSI */
imxrt_config_gpio(GPIO_LPSPI2_SCK);
imxrt_config_gpio(GPIO_LPSPI2_MISO);
imxrt_config_gpio(GPIO_LPSPI2_MOSI);
+#ifdef GPIO_LPSPI2_CS
+ imxrt_config_gpio(GPIO_LPSPI2_CS);
+#endif
+#if defined(GPIO_LPSPI2_DC) && defined(CONFIG_SPI_CMDDATA)
+ imxrt_config_gpio(GPIO_LPSPI2_DC);
+#endif
/* Set up default configuration: Master, 8-bit, etc. */
@@ -1608,13 +1649,20 @@ FAR struct spi_dev_s *imxrt_lpspibus_initialize(int bus)
/* Only configure if the bus is not already configured */
- if ((imxrt_lpspi_getreg32(priv, IMXRT_LPSPI_CR_OFFSET) & LPSPI_CR_MEN) == 0)
+ if ((imxrt_lpspi_getreg32(priv, IMXRT_LPSPI_CR_OFFSET)
+ & LPSPI_CR_MEN) == 0)
{
/* Configure SPI3 pins: SCK, MISO, and MOSI */
imxrt_config_gpio(GPIO_LPSPI3_SCK);
imxrt_config_gpio(GPIO_LPSPI3_MISO);
imxrt_config_gpio(GPIO_LPSPI3_MOSI);
+#ifdef GPIO_LPSPI3_CS
+ imxrt_config_gpio(GPIO_LPSPI3_CS);
+#endif
+#if defined(GPIO_LPSPI3_DC) && defined(CONFIG_SPI_CMDDATA)
+ imxrt_config_gpio(GPIO_LPSPI3_DC);
+#endif
/* Set up default configuration: Master, 8-bit, etc. */
@@ -1632,13 +1680,20 @@ FAR struct spi_dev_s *imxrt_lpspibus_initialize(int bus)
/* Only configure if the bus is not already configured */
- if ((imxrt_lpspi_getreg32(priv, IMXRT_LPSPI_CR_OFFSET) & LPSPI_CR_MEN) == 0)
+ if ((imxrt_lpspi_getreg32(priv, IMXRT_LPSPI_CR_OFFSET)
+ & LPSPI_CR_MEN) == 0)
{
/* Configure SPI4 pins: SCK, MISO, and MOSI */
imxrt_config_gpio(GPIO_LPSPI4_SCK);
imxrt_config_gpio(GPIO_LPSPI4_MISO);
imxrt_config_gpio(GPIO_LPSPI4_MOSI);
+#ifdef GPIO_LPSPI4_CS
+ imxrt_config_gpio(GPIO_LPSPI4_CS);
+#endif
+#if defined(GPIO_LPSPI4_DC) && defined(CONFIG_SPI_CMDDATA)
+ imxrt_config_gpio(GPIO_LPSPI4_DC);
+#endif
/* Set up default configuration: Master, 8-bit, etc. */
diff --git a/drivers/lcd/Kconfig b/drivers/lcd/Kconfig
index 9bc3ac2..88a9f5a 100644
--- a/drivers/lcd/Kconfig
+++ b/drivers/lcd/Kconfig
@@ -1134,6 +1134,23 @@ config LCD_ILI9341_IFACE1_RGB565
endchoice
endif
+config LCD_LCDDRV_SPIIF
+ bool "Generic SPI Interface Driver (for ILI9341 or others)"
+ default n
+ depends on LCD_ILI9341
+ ---help---
+ SPI Interface shim to allow LCD and ePaper to be bound to
+ a normal SPI port.
+
+config LCD_LCDDRV_SPEED
+ int "Generic SPI Interface speed"
+ default 10000000
+ depends on LCD_LCDDRV_SPIIF
+ ---help---
+ SPI Interface speed. According to the specification this is generally
+ quite limited, but people have had success with much faster
+ speeds than the spec sheets say. YMMV.
+
config LCD_RA8875
bool "RA8875 LCD Display Controller"
default n
diff --git a/drivers/lcd/Make.defs b/drivers/lcd/Make.defs
index bfc50ba..b40aca2 100644
--- a/drivers/lcd/Make.defs
+++ b/drivers/lcd/Make.defs
@@ -124,6 +124,10 @@ ifeq ($(CONFIG_LCD_ILI9341),y)
CSRCS += ili9341.c
endif
+ifeq ($(CONFIG_LCD_LCDDRV_SPIIF),y)
+ CSRCS += lcddrv_spiif.c
+endif
+
ifeq ($(CONFIG_LCD_RA8875),y)
CSRCS += ra8875.c
endif
diff --git a/drivers/lcd/lcddrv_spiif.c b/drivers/lcd/lcddrv_spiif.c
new file mode 100644
index 0000000..d1dbb3e
--- /dev/null
+++ b/drivers/lcd/lcddrv_spiif.c
@@ -0,0 +1,347 @@
+/****************************************************************************
+ * drivers/lcd/lcddrv_spiif.c
+ *
+ * Generic Driver interface for the Single Chip LCD driver connected
+ * via spi driver
+ *
+ * Copyright (C) 2019 Greg Nutt. All rights reserved.
+ * Author: Dave Marples <da...@marples.net>
+ * Based on work from Marco Krahl <oc...@gmail.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior writen permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/types.h>
+#include <stdbool.h>
+#include <errno.h>
+#include <debug.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <nuttx/kmalloc.h>
+
+#include <nuttx/irq.h>
+#include <nuttx/arch.h>
+#include <nuttx/spi/spi.h>
+#include <nuttx/lcd/lcddrv_spiif.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Type Definition
+ ****************************************************************************/
+
+struct lcddrv_spiif_lcd_s
+{
+ /* Publically visible device structure */
+
+ struct lcddrv_lcd_s dev;
+
+ /* Reference to spi device structure */
+
+ struct spi_dev_s *spi;
+};
+
+/****************************************************************************
+ * Private Function Protototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: lcddrv_spiif_backlight
+ *
+ * Description:
+ * Set the backlight level of the connected display.
+ *
+ * Input Parameters:
+ * spi - Reference to the public driver structure
+ * level - backlight level
+ *
+ * Returned Value:
+ * OK - On Success
+ *
+ ****************************************************************************/
+
+static int lcddrv_spiif_backlight(struct lcddrv_lcd_s *lcd, int level)
+{
+ return spiif_backlight(lcd, level);
+}
+
+/****************************************************************************
+ * Name: lcddrv_spiif_select
+ *
+ * Description:
+ * Select the SPI, locking and re-configuring if necessary
+ *
+ * Input Parameters:
+ * spi - Reference to the public driver structure
+ * isCommand - Flag indicating is command mode
+ *
+ * Returned Value:
+ *
+ ****************************************************************************/
+
+static void lcddrv_spiif_select(FAR struct lcddrv_lcd_s *lcd)
+{
+ FAR struct lcddrv_spiif_lcd_s *priv = (FAR struct lcddrv_spiif_lcd_s *)lcd;
+
+ SPI_LOCK(priv->spi, true);
+ SPI_SELECT(priv->spi, SPIDEV_DISPLAY(0), true);
+}
+
+/****************************************************************************
+ * Name: lcddrv_spiif_deselect
+ *
+ * Description:
+ * De-select the SPI
+ *
+ * Input Parameters:
+ * spi - Reference to the public driver structure
+ *
+ * Returned Value:
+ *
+ ****************************************************************************/
+
+static void lcddrv_spiif_deselect(FAR struct lcddrv_lcd_s *lcd)
+{
+ FAR struct lcddrv_spiif_lcd_s *priv = (FAR struct lcddrv_spiif_lcd_s *)lcd;
+
+ SPI_CMDDATA(priv->spi, SPIDEV_DISPLAY(0), false);
+ SPI_SELECT(priv->spi, SPIDEV_DISPLAY(0), false);
+ SPI_LOCK(priv->spi, false);
+}
+
+/****************************************************************************
+ * Name: lcddrv_spiif_sendmulti
+ *
+ * Description:
+ * Send a number of pixel words to the lcd driver gram.
+ *
+ * Input Parameters:
+ * lcd - Reference to the lcddrv_lcd_s driver structure
+ * wd - Reference to the words to send
+ * nwords - number of words to send
+ *
+ * Returned Value:
+ * OK - On Success
+ *
+ ****************************************************************************/
+
+static int lcddrv_spiif_sendmulti(FAR struct lcddrv_lcd_s *lcd,
+ FAR const uint16_t *wd, uint32_t nwords)
+{
+ FAR struct lcddrv_spiif_lcd_s *priv = (FAR struct lcddrv_spiif_lcd_s *)lcd;
+
+ SPI_SETBITS(priv->spi, 16);
+ for (uint32_t t = 0; t < nwords; t++)
+ {
+ SPI_SEND(priv->spi, *wd++);
+ }
+
+ SPI_SETBITS(priv->spi, 8);
+
+ return OK;
+};
+
+/****************************************************************************
+ * Name: lcddrv_spiif_recv
+ *
+ * Description:
+ * Receive a parameter from the lcd driver.
+ *
+ * Input Parameters:
+ * lcd - Reference to the lcddrv_lcd_s driver structure
+ * param - Reference to where parameter receive
+ *
+ * Returned Value:
+ * OK - On Success
+ *
+ ****************************************************************************/
+
+static int lcddrv_spiif_recv(FAR struct lcddrv_lcd_s *lcd,
+ uint8_t *param)
+{
+ FAR struct lcddrv_spiif_lcd_s *priv = (FAR struct lcddrv_spiif_lcd_s *)lcd;
+
+ lcdinfo("param=%04x\n", param);
+ SPI_RECVBLOCK(priv->spi, param, 1);
+ return OK;
+}
+
+/****************************************************************************
+ * Name: lcddrv_spiif_send
+ *
+ * Description:
+ * Send to the lcd
+ *
+ * Input Parameters:
+ * lcd - Reference to the lcddrv_lcd_s driver structure
+ * param - Reference to where parameter to send is located
+ *
+ * Returned Value:
+ * OK - On Success
+ *
+ ****************************************************************************/
+
+static int lcddrv_spiif_send(FAR struct lcddrv_lcd_s *lcd,
+ const uint8_t param)
+{
+ uint8_t r;
+ FAR struct lcddrv_spiif_lcd_s *priv = (FAR struct lcddrv_spiif_lcd_s *)lcd;
+
+ r = SPI_SEND(priv->spi, param);
+ return r;
+}
+
+/****************************************************************************
+ * Name: lcddrv_spiif_sendcmd
+ *
+ * Description:
+ * Send command to the lcd
+ *
+ * Input Parameters:
+ * lcd - Reference to the lcddrv_lcd_s driver structure
+ * param - Reference to where parameter to send is located
+ *
+ * Returned Value:
+ * OK - On Success
+ *
+ ****************************************************************************/
+
+static int lcddrv_spiif_sendcmd(FAR struct lcddrv_lcd_s *lcd,
+ const uint8_t param)
+{
+ uint8_t r;
+ FAR struct lcddrv_spiif_lcd_s *priv = (FAR struct lcddrv_spiif_lcd_s *)lcd;
+
+ lcdinfo("param=%04x\n", param);
+ SPI_CMDDATA(priv->spi, SPIDEV_DISPLAY(0), true);
+ r = SPI_SEND(priv->spi, param);
+ SPI_CMDDATA(priv->spi, SPIDEV_DISPLAY(0), false);
+ return r;
+}
+
+/****************************************************************************
+ * Name: lcddrv_spiif_recvmulti
+ *
+ * Description:
+ * Receive pixel words from the lcd driver gram.
+ *
+ * Input Parameters:
+ * lcd - Reference to the public driver structure
+ * wd - Reference to where the pixel words receive
+ * nwords - number of pixel words to receive
+ *
+ * Returned Value:
+ * OK - On Success
+ *
+ ****************************************************************************/
+
+static int lcddrv_spiif_recvmulti(FAR struct lcddrv_lcd_s *lcd,
+ FAR uint16_t *wd, uint32_t nwords)
+{
+ FAR struct lcddrv_spiif_lcd_s *priv = (FAR struct lcddrv_spiif_lcd_s *)lcd;
+
+ lcdinfo("wd=%p, nwords=%d\n", wd, nwords);
+ SPI_SETBITS(priv->spi, 16);
+ SPI_RECVBLOCK(priv->spi, wd, nwords);
+ SPI_SETBITS(priv->spi, 8);
+ return OK;
+}
+
+/****************************************************************************
+ * Name: FAR struct lcddrv_lcd_s *lcddrv_spiif_initialize
+ *
+ * Description:
+ * Initialize the device structure to control the LCD Single chip driver.
+ *
+ * Input Parameters:
+ * spi : handle to the spi to use
+ *
+ * Returned Value:
+ * On success, this function returns a reference to the LCD control object
+ * for the specified LCDDRV LCD Single chip driver.
+ * NULL is returned on failure.
+ *
+ ****************************************************************************/
+
+FAR struct lcddrv_lcd_s *lcddrv_spiif_initialize(struct spi_dev_s *spi)
+{
+ FAR struct lcddrv_spiif_lcd_s *priv =
+ (struct lcddrv_spiif_lcd_s *)kmm_zalloc(sizeof(struct lcddrv_spiif_lcd_s));
+
+ if (!priv)
+ {
+ return NULL;
+ }
+
+ lcdinfo("initialize lcddrv spi subdriver\n");
+
+ priv->spi = spi;
+
+ if (!priv->spi)
+ {
+ kmm_free(priv);
+ return 0;
+ }
+
+ SPI_SETFREQUENCY(spi, CONFIG_LCD_LCDDRV_SPEED);
+ SPI_SETBITS(spi, 8);
+
+ /* Hook in our driver routines */
+
+ priv->dev.select = lcddrv_spiif_select;
+ priv->dev.deselect = lcddrv_spiif_deselect;
+ priv->dev.sendparam = lcddrv_spiif_send;
+ priv->dev.sendcmd = lcddrv_spiif_sendcmd;
+ priv->dev.recvparam = lcddrv_spiif_recv;
+ priv->dev.sendgram = lcddrv_spiif_sendmulti;
+ priv->dev.recvgram = lcddrv_spiif_recvmulti;
+ priv->dev.backlight = lcddrv_spiif_backlight;
+
+ return &priv->dev;
+}
diff --git a/include/nuttx/lcd/lcddrv_spiif.h b/include/nuttx/lcd/lcddrv_spiif.h
new file mode 100644
index 0000000..aefa5e3
--- /dev/null
+++ b/include/nuttx/lcd/lcddrv_spiif.h
@@ -0,0 +1,144 @@
+/*****************************************************************************
+ * include/nuttx/lcd/lcddrv_spiif.h
+ *
+ * Copyright (C) 2014 Gregory Nutt. All rights reserved.
+ * Authors: Gregory Nutt <gn...@nuttx.org>
+ * Dave Marples <da...@marples.net>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+#ifndef __INCLUDE_NUTTX_LCD_LCDDRV_SPIIF_H
+#define __INCLUDE_NUTTX_LCD_LCDDRV_SPIIF_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include <nuttx/spi/spi.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+struct lcddrv_lcd_s
+{
+ /* Interface to control the ILI9341 lcd driver
+ *
+ * - select Select the device (as neccessary) before performing
+ * any operations.
+ * - deselect Deselect the device (as necessary).
+ * - send Send specific parameter to the LCD driver.
+ * - recv Receive specific parameter from the LCD driver.
+ * - sendmulti Send pixel data to the LCD drivers gram.
+ * - recvmulti Receive pixel data from the LCD drivers gram.
+ * - backlight Change the backlight level of the connected display.
+ * In the context of the ili9341 that means change the
+ * backlight level of the connected LED driver.
+ * The implementation in detail is part of the platform
+ * specific sub driver.
+ */
+
+ CODE void (*select)(FAR struct lcddrv_lcd_s *lcd);
+ CODE void (*deselect)(FAR struct lcddrv_lcd_s *lcd);
+ CODE int (*sendcmd)(FAR struct lcddrv_lcd_s *lcd, const uint8_t cmd);
+ CODE int (*sendparam)(FAR struct lcddrv_lcd_s *lcd, const uint8_t param);
+ CODE int (*recvparam)(FAR struct lcddrv_lcd_s *lcd, uint8_t *param);
+ CODE int (*recvgram)(FAR struct lcddrv_lcd_s *lcd,
+ uint16_t *wd, uint32_t nwords);
+ CODE int (*sendgram)(FAR struct lcddrv_lcd_s *lcd,
+ const uint16_t *wd, uint32_t nwords);
+ CODE int (*backlight)(FAR struct lcddrv_lcd_s *lcd, int level);
+
+ /* mcu interface specific data following */
+};
+
+/*****************************************************************************
+ * Public Data
+ *****************************************************************************/
+
+#ifdef __cplusplus
+#define EXTERN extern "C"
+extern "C"
+{
+#else
+#define EXTERN extern
+#endif
+
+/*****************************************************************************
+ * Public Function Prototypes
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Name: spiif_backlight
+ * (Provided by integrating platform)
+ *
+ * Description:
+ * Set the backlight level of the connected display.
+ *
+ * Input Parameters:
+ * spi - Reference to the public driver structure
+ * level - backlight level
+ *
+ * Returned Value:
+ * OK - On Success
+ *
+ ****************************************************************************/
+
+extern int spiif_backlight(struct lcddrv_lcd_s *lcd, int level);
+
+/****************************************************************************
+ * Name: FAR struct lcddrv_lcd_s *lcddrv_spiif_initialize
+ *
+ * Description:
+ * Initialize the device structure to control the LCD Single chip driver.
+ *
+ * Input Parameters:
+ * path : path to spi device to use
+ *
+ * Returned Value:
+ * On success, this function returns a reference to the LCD control object
+ * for the specified LCDDRV LCD Single chip driver.
+ * NULL is returned on failure.
+ *
+ ****************************************************************************/
+
+FAR struct lcddrv_lcd_s *lcddrv_spiif_initialize(struct spi_dev_s *spi);
+
+#undef EXTERN
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __INCLUDE_NUTTX_LCD_LCDDRV_SPIIF_H */