LCOV - code coverage report
Current view: top level - zephyr/drivers - mipi_dbi.h Hit Total Coverage
Test: new.info Lines: 17 23 73.9 %
Date: 2024-12-22 00:14:23

          Line data    Source code
       1           1 : /*
       2             :  * Copyright 2023 NXP
       3             :  *
       4             :  * SPDX-License-Identifier: Apache-2.0
       5             :  */
       6             : 
       7             : /**
       8             :  * @file
       9             :  * @brief Public APIs for MIPI-DBI drivers
      10             :  *
      11             :  * MIPI-DBI defines the following 3 interfaces:
      12             :  * Type A: Motorola 6800 type parallel bus
      13             :  * Type B: Intel 8080 type parallel bus
      14             :  * Type C: SPI Type (1 bit bus) with 3 options:
      15             :  *     1. 9 write clocks per byte, final bit is command/data selection bit
      16             :  *     2. Same as above, but 16 write clocks per byte
      17             :  *     3. 8 write clocks per byte. Command/data selected via GPIO pin
      18             :  * The current driver interface does not support type C with 16 write clocks (option 2).
      19             :  */
      20             : 
      21             : #ifndef ZEPHYR_INCLUDE_DRIVERS_MIPI_DBI_H_
      22             : #define ZEPHYR_INCLUDE_DRIVERS_MIPI_DBI_H_
      23             : 
      24             : /**
      25             :  * @brief MIPI-DBI driver APIs
      26             :  * @defgroup mipi_dbi_interface MIPI-DBI driver APIs
      27             :  * @since 3.6
      28             :  * @version 0.1.0
      29             :  * @ingroup io_interfaces
      30             :  * @{
      31             :  */
      32             : 
      33             : #include <zephyr/device.h>
      34             : #include <zephyr/drivers/display.h>
      35             : #include <zephyr/display/mipi_display.h>
      36             : #include <zephyr/drivers/spi.h>
      37             : #include <zephyr/dt-bindings/mipi_dbi/mipi_dbi.h>
      38             : 
      39             : #ifdef __cplusplus
      40             : extern "C" {
      41             : #endif
      42             : 
      43             : /**
      44             :  * @brief initialize a MIPI DBI SPI configuration struct from devicetree
      45             :  *
      46             :  * This helper allows drivers to initialize a MIPI DBI SPI configuration
      47             :  * structure using devicetree.
      48             :  * @param node_id Devicetree node identifier for the MIPI DBI device whose
      49             :  *                struct spi_config to create an initializer for
      50             :  * @param operation_ the desired operation field in the struct spi_config
      51             :  * @param delay_ the desired delay field in the struct spi_config's
      52             :  *               spi_cs_control, if there is one
      53             :  */
      54           1 : #define MIPI_DBI_SPI_CONFIG_DT(node_id, operation_, delay_)             \
      55             :         {                                                               \
      56             :                 .frequency = DT_PROP(node_id, mipi_max_frequency),      \
      57             :                 .operation = (operation_) |                             \
      58             :                         DT_PROP_OR(node_id, duplex, 0) |                        \
      59             :                         COND_CODE_1(DT_PROP(node_id, mipi_cpol), SPI_MODE_CPOL, (0)) |  \
      60             :                         COND_CODE_1(DT_PROP(node_id, mipi_cpha), SPI_MODE_CPHA, (0)) |  \
      61             :                         COND_CODE_1(DT_PROP(node_id, mipi_hold_cs), SPI_HOLD_ON_CS, (0)),       \
      62             :                 .slave = DT_REG_ADDR(node_id),                          \
      63             :                 .cs = {                                                 \
      64             :                         .gpio = GPIO_DT_SPEC_GET_BY_IDX_OR(DT_PHANDLE(DT_PARENT(node_id), \
      65             :                                                            spi_dev), cs_gpios, \
      66             :                                                            DT_REG_ADDR_RAW(node_id), \
      67             :                                                            {}),         \
      68             :                         .delay = (delay_),                              \
      69             :                 },                                                      \
      70             :         }
      71             : 
      72             : /**
      73             :  * @brief Initialize a MIPI DBI SPI configuration from devicetree instance
      74             :  *
      75             :  * This helper initializes a MIPI DBI SPI configuration from a devicetree
      76             :  * instance. It is equivalent to MIPI_DBI_SPI_CONFIG_DT(DT_DRV_INST(inst))
      77             :  * @param inst Instance number to initialize configuration from
      78             :  * @param operation_ the desired operation field in the struct spi_config
      79             :  * @param delay_ the desired delay field in the struct spi_config's
      80             :  *               spi_cs_control, if there is one
      81             :  */
      82           1 : #define MIPI_DBI_SPI_CONFIG_DT_INST(inst, operation_, delay_)           \
      83             :         MIPI_DBI_SPI_CONFIG_DT(DT_DRV_INST(inst), operation_, delay_)
      84             : 
      85             : /**
      86             :  * @brief Initialize a MIPI DBI configuration from devicetree
      87             :  *
      88             :  * This helper allows drivers to initialize a MIPI DBI configuration
      89             :  * structure from devicetree. It sets the MIPI DBI mode, as well
      90             :  * as configuration fields in the SPI configuration structure
      91             :  * @param node_id Devicetree node identifier for the MIPI DBI device to
      92             :  *                initialize
      93             :  * @param operation_ the desired operation field in the struct spi_config
      94             :  * @param delay_ the desired delay field in the struct spi_config's
      95             :  *               spi_cs_control, if there is one
      96             :  */
      97           1 : #define MIPI_DBI_CONFIG_DT(node_id, operation_, delay_)                 \
      98             :         {                                                               \
      99             :                 .mode = DT_STRING_UPPER_TOKEN(node_id, mipi_mode),      \
     100             :                 .config = MIPI_DBI_SPI_CONFIG_DT(node_id, operation_, delay_), \
     101             :         }
     102             : 
     103             : /**
     104             :  * @brief Initialize a MIPI DBI configuration from device instance
     105             :  *
     106             :  * Equivalent to MIPI_DBI_CONFIG_DT(DT_DRV_INST(inst), operation_, delay_)
     107             :  * @param inst Instance of the device to initialize a MIPI DBI configuration for
     108             :  * @param operation_ the desired operation field in the struct spi_config
     109             :  * @param delay_ the desired delay field in the struct spi_config's
     110             :  *               spi_cs_control, if there is one
     111             :  */
     112           1 : #define MIPI_DBI_CONFIG_DT_INST(inst, operation_, delay_)               \
     113             :         MIPI_DBI_CONFIG_DT(DT_DRV_INST(inst), operation_, delay_)
     114             : 
     115             : /**
     116             :  * @brief Get the MIPI DBI TE mode from devicetree
     117             :  *
     118             :  * Gets the MIPI DBI TE mode from a devicetree property.
     119             :  * @param node_id Devicetree node identifier for the MIPI DBI device with the
     120             :  *                TE mode property
     121             :  * @param edge_prop Property name for the TE mode that should be read from
     122             :  *                  devicetree
     123             :  */
     124           1 : #define MIPI_DBI_TE_MODE_DT(node_id, edge_prop)                           \
     125             :         DT_STRING_UPPER_TOKEN(node_id, edge_prop)
     126             : 
     127             : /**
     128             :  * @brief Get the MIPI DBI TE mode for device instance
     129             :  *
     130             :  * Gets the MIPI DBI TE mode from a devicetree property. Equivalent to
     131             :  * MIPI_DBI_TE_MODE_DT(DT_DRV_INST(inst), edge_mode).
     132             :  * @param inst Instance of the device to get the TE mode for
     133             :  * @param edge_prop Property name for the TE mode that should be read from
     134             :  *                  devicetree
     135             :  */
     136           1 : #define MIPI_DBI_TE_MODE_DT_INST(inst, edge_prop)                         \
     137             :         DT_STRING_UPPER_TOKEN(DT_DRV_INST(inst), edge_prop)
     138             : 
     139             : /**
     140             :  * @brief MIPI DBI controller configuration
     141             :  *
     142             :  * Configuration for MIPI DBI controller write
     143             :  */
     144           1 : struct mipi_dbi_config {
     145             :         /** MIPI DBI mode */
     146           1 :         uint8_t mode;
     147             :         /** SPI configuration */
     148           1 :         struct spi_config config;
     149             : };
     150             : 
     151             : 
     152             : /** MIPI-DBI host driver API */
     153           1 : __subsystem struct mipi_dbi_driver_api {
     154           0 :         int (*command_write)(const struct device *dev,
     155             :                              const struct mipi_dbi_config *config, uint8_t cmd,
     156             :                              const uint8_t *data, size_t len);
     157           0 :         int (*command_read)(const struct device *dev,
     158             :                             const struct mipi_dbi_config *config, uint8_t *cmds,
     159             :                             size_t num_cmds, uint8_t *response, size_t len);
     160           0 :         int (*write_display)(const struct device *dev,
     161             :                              const struct mipi_dbi_config *config,
     162             :                              const uint8_t *framebuf,
     163             :                              struct display_buffer_descriptor *desc,
     164             :                              enum display_pixel_format pixfmt);
     165           0 :         int (*reset)(const struct device *dev, k_timeout_t delay);
     166           0 :         int (*release)(const struct device *dev,
     167             :                        const struct mipi_dbi_config *config);
     168           0 :         int (*configure_te)(const struct device *dev,
     169             :                             uint8_t edge,
     170             :                             k_timeout_t delay);
     171             : };
     172             : 
     173             : /**
     174             :  * @brief Write a command to the display controller
     175             :  *
     176             :  * Writes a command, along with an optional data buffer to the display.
     177             :  * If data buffer and buffer length are NULL and 0 respectively, then
     178             :  * only a command will be sent. Note that if the SPI configuration passed
     179             :  * to this function locks the SPI bus, it is the caller's responsibility
     180             :  * to release it with mipi_dbi_release()
     181             :  *
     182             :  * @param dev mipi dbi controller
     183             :  * @param config MIPI DBI configuration
     184             :  * @param cmd command to write to display controller
     185             :  * @param data optional data buffer to write after command
     186             :  * @param len size of data buffer in bytes. Set to 0 to skip sending data.
     187             :  * @retval 0 command write succeeded
     188             :  * @retval -EIO I/O error
     189             :  * @retval -ETIMEDOUT transfer timed out
     190             :  * @retval -EBUSY controller is busy
     191             :  * @retval -ENOSYS not implemented
     192             :  */
     193           1 : static inline int mipi_dbi_command_write(const struct device *dev,
     194             :                                          const struct mipi_dbi_config *config,
     195             :                                          uint8_t cmd, const uint8_t *data,
     196             :                                          size_t len)
     197             : {
     198             :         const struct mipi_dbi_driver_api *api =
     199             :                 (const struct mipi_dbi_driver_api *)dev->api;
     200             : 
     201             :         if (api->command_write == NULL) {
     202             :                 return -ENOSYS;
     203             :         }
     204             :         return api->command_write(dev, config, cmd, data, len);
     205             : }
     206             : 
     207             : /**
     208             :  * @brief Read a command response from the display controller
     209             :  *
     210             :  * Reads a command response from the display controller.
     211             :  *
     212             :  * @param dev mipi dbi controller
     213             :  * @param config MIPI DBI configuration
     214             :  * @param cmds array of one byte commands to send to display controller
     215             :  * @param num_cmd number of commands to write to display controller
     216             :  * @param response response buffer, filled with display controller response
     217             :  * @param len size of response buffer in bytes.
     218             :  * @retval 0 command read succeeded
     219             :  * @retval -EIO I/O error
     220             :  * @retval -ETIMEDOUT transfer timed out
     221             :  * @retval -EBUSY controller is busy
     222             :  * @retval -ENOSYS not implemented
     223             :  */
     224           1 : static inline int mipi_dbi_command_read(const struct device *dev,
     225             :                                         const struct mipi_dbi_config *config,
     226             :                                         uint8_t *cmds, size_t num_cmd,
     227             :                                         uint8_t *response, size_t len)
     228             : {
     229             :         const struct mipi_dbi_driver_api *api =
     230             :                 (const struct mipi_dbi_driver_api *)dev->api;
     231             : 
     232             :         if (api->command_read == NULL) {
     233             :                 return -ENOSYS;
     234             :         }
     235             :         return api->command_read(dev, config, cmds, num_cmd, response, len);
     236             : }
     237             : 
     238             : /**
     239             :  * @brief Write a display buffer to the display controller.
     240             :  *
     241             :  * Writes a display buffer to the controller. If the controller requires
     242             :  * a "Write memory" command before writing display data, this should be
     243             :  * sent with @ref mipi_dbi_command_write
     244             :  * @param dev mipi dbi controller
     245             :  * @param config MIPI DBI configuration
     246             :  * @param framebuf: framebuffer to write to display
     247             :  * @param desc: descriptor of framebuffer to write. Note that the pitch must
     248             :  *   be equal to width. "buf_size" field determines how many bytes will be
     249             :  *   written.
     250             :  * @param pixfmt: pixel format of framebuffer data
     251             :  * @retval 0 buffer write succeeded.
     252             :  * @retval -EIO I/O error
     253             :  * @retval -ETIMEDOUT transfer timed out
     254             :  * @retval -EBUSY controller is busy
     255             :  * @retval -ENOSYS not implemented
     256             :  */
     257           1 : static inline int mipi_dbi_write_display(const struct device *dev,
     258             :                                          const struct mipi_dbi_config *config,
     259             :                                          const uint8_t *framebuf,
     260             :                                          struct display_buffer_descriptor *desc,
     261             :                                          enum display_pixel_format pixfmt)
     262             : {
     263             :         const struct mipi_dbi_driver_api *api =
     264             :                 (const struct mipi_dbi_driver_api *)dev->api;
     265             : 
     266             :         if (api->write_display == NULL) {
     267             :                 return -ENOSYS;
     268             :         }
     269             :         return api->write_display(dev, config, framebuf, desc, pixfmt);
     270             : }
     271             : 
     272             : /**
     273             :  * @brief Resets attached display controller
     274             :  *
     275             :  * Resets the attached display controller.
     276             :  * @param dev mipi dbi controller
     277             :  * @param delay_ms duration to set reset signal for, in milliseconds
     278             :  * @retval 0 reset succeeded
     279             :  * @retval -EIO I/O error
     280             :  * @retval -ENOSYS not implemented
     281             :  * @retval -ENOTSUP not supported
     282             :  */
     283           1 : static inline int mipi_dbi_reset(const struct device *dev, uint32_t delay_ms)
     284             : {
     285             :         const struct mipi_dbi_driver_api *api =
     286             :                 (const struct mipi_dbi_driver_api *)dev->api;
     287             : 
     288             :         if (api->reset == NULL) {
     289             :                 return -ENOSYS;
     290             :         }
     291             :         return api->reset(dev, K_MSEC(delay_ms));
     292             : }
     293             : 
     294             : /**
     295             :  * @brief Releases a locked MIPI DBI device.
     296             :  *
     297             :  * Releases a lock on a MIPI DBI device and/or the device's CS line if and
     298             :  * only if the given config parameter was the last one to be used in any
     299             :  * of the above functions, and if it has the SPI_LOCK_ON bit set and/or
     300             :  * the SPI_HOLD_ON_CS bit set into its operation bits field.
     301             :  * This lock functions exactly like the SPI lock, and can be used if the caller
     302             :  * needs to keep CS asserted for multiple transactions, or the MIPI DBI device
     303             :  * locked.
     304             :  * @param dev mipi dbi controller
     305             :  * @param config MIPI DBI configuration
     306             :  * @retval 0 reset succeeded
     307             :  * @retval -EIO I/O error
     308             :  * @retval -ENOSYS not implemented
     309             :  * @retval -ENOTSUP not supported
     310             :  */
     311           1 : static inline int mipi_dbi_release(const struct device *dev,
     312             :                                    const struct mipi_dbi_config *config)
     313             : {
     314             :         const struct mipi_dbi_driver_api *api =
     315             :                 (const struct mipi_dbi_driver_api *)dev->api;
     316             : 
     317             :         if (api->release == NULL) {
     318             :                 return -ENOSYS;
     319             :         }
     320             :         return api->release(dev, config);
     321             : }
     322             : 
     323             : /**
     324             :  * @brief Configures MIPI DBI tearing effect signal
     325             :  *
     326             :  * Many displays provide a tearing effect signal, which can be configured
     327             :  * to pulse at each vsync interval or each hsync interval. This signal can be
     328             :  * used by the MCU to determine when to transmit a new frame so that the
     329             :  * read pointer of the display never overlaps with the write pointer from the
     330             :  * MCU. This function configures the MIPI DBI controller to delay transmitting
     331             :  * display frames until the selected tearing effect signal edge occurs.
     332             :  *
     333             :  * The delay will occur on the on each call to @ref mipi_dbi_write_display
     334             :  * where the ``frame_incomplete`` flag was set within the buffer descriptor
     335             :  * provided with the prior call, as this indicates the buffer being written
     336             :  * in this call is the first buffer of a new frame.
     337             :  *
     338             :  * Note that most display controllers will need to enable the TE signal
     339             :  * using vendor specific commands before the MIPI DBI controller can react
     340             :  * to it.
     341             :  *
     342             :  * @param dev mipi dbi controller
     343             :  * @param edge which edge of the TE signal to start transmitting on
     344             :  * @param delay_us how many microseconds after TE edge to start transmission
     345             :  * @retval -EIO I/O error
     346             :  * @retval -ENOSYS not implemented
     347             :  * @retval -ENOTSUP not supported
     348             :  */
     349           1 : static inline int mipi_dbi_configure_te(const struct device *dev,
     350             :                                         uint8_t edge,
     351             :                                         uint32_t delay_us)
     352             : {
     353             :         const struct mipi_dbi_driver_api *api =
     354             :                 (const struct mipi_dbi_driver_api *)dev->api;
     355             : 
     356             :         if (api->configure_te == NULL) {
     357             :                 return -ENOSYS;
     358             :         }
     359             :         return api->configure_te(dev, edge, K_USEC(delay_us));
     360             : }
     361             : 
     362             : #ifdef __cplusplus
     363             : }
     364             : #endif
     365             : 
     366             : /**
     367             :  * @}
     368             :  */
     369             : 
     370             : #endif /* ZEPHYR_INCLUDE_DRIVERS_MIPI_DBI_H_ */

Generated by: LCOV version 1.14