drivers: mipi_dbi: add support for mipi_dbi_configure_te

Many MIPI DBI displays support a "tearing effect" signal, which can be
configured to signal each v-sync or h-sync interval. This signal can be
used by the MIPI DBI controller to synchronize writes with the
controller, and avoid tearing effects on the screen (which occur when
the write pointer from the MCU overlaps with the panel's read pointer in
the display controller's graphics RAM).

Add the `mipi_dbi_configure_te` API, which allows display controllers to
configure MIPI DBI controller to wait for a TE edge before streaming
display data. Allow the tearing enable parameters to be configured via
devicetree settings, since these will vary based on the MIPI DBI
controller and display controller in use.

Signed-off-by: Daniel DeGrasse <daniel.degrasse@nxp.com>
This commit is contained in:
Daniel DeGrasse 2024-11-11 20:33:36 +00:00 committed by Benjamin Cabé
commit b1d1b70ddb
3 changed files with 118 additions and 0 deletions

View file

@ -26,3 +26,21 @@ properties:
- "MIPI_DBI_MODE_8080_BUS_16_BIT"
- "MIPI_DBI_MODE_8080_BUS_9_BIT"
- "MIPI_DBI_MODE_8080_BUS_8_BIT"
te-mode:
type: string
default: "MIPI_DBI_TE_NO_EDGE"
description: |
MIPI DBI tearing enable signal mode. Defaults to disabled.
enum:
- "MIPI_DBI_TE_NO_EDGE"
- "MIPI_DBI_TE_RISING_EDGE"
- "MIPI_DBI_TE_FALLING_EDGE"
te-delay:
type: int
default: 0
description: |
Delay in microseconds to wait before transmitting display data after a
tearing enable synchronization signal is seen. Defaults to 0 since most
controllers will not need a delay.

View file

@ -112,6 +112,30 @@ extern "C" {
#define MIPI_DBI_CONFIG_DT_INST(inst, operation_, delay_) \
MIPI_DBI_CONFIG_DT(DT_DRV_INST(inst), operation_, delay_)
/**
* @brief Get the MIPI DBI TE mode from devicetree
*
* Gets the MIPI DBI TE mode from a devicetree property.
* @param node_id Devicetree node identifier for the MIPI DBI device with the
* TE mode property
* @param edge_prop Property name for the TE mode that should be read from
* devicetree
*/
#define MIPI_DBI_TE_MODE_DT(node_id, edge_prop) \
DT_STRING_UPPER_TOKEN(node_id, edge_prop)
/**
* @brief Get the MIPI DBI TE mode for device instance
*
* Gets the MIPI DBI TE mode from a devicetree property. Equivalent to
* MIPI_DBI_TE_MODE_DT(DT_DRV_INST(inst), edge_mode).
* @param inst Instance of the device to get the TE mode for
* @param edge_prop Property name for the TE mode that should be read from
* devicetree
*/
#define MIPI_DBI_TE_MODE_DT_INST(inst, edge_prop) \
DT_STRING_UPPER_TOKEN(DT_DRV_INST(inst), edge_prop)
/**
* @brief MIPI DBI controller configuration
*
@ -141,6 +165,9 @@ __subsystem struct mipi_dbi_driver_api {
int (*reset)(const struct device *dev, k_timeout_t delay);
int (*release)(const struct device *dev,
const struct mipi_dbi_config *config);
int (*configure_te)(const struct device *dev,
uint8_t edge,
k_timeout_t delay);
};
/**
@ -293,6 +320,45 @@ static inline int mipi_dbi_release(const struct device *dev,
return api->release(dev, config);
}
/**
* @brief Configures MIPI DBI tearing effect signal
*
* Many displays provide a tearing effect signal, which can be configured
* to pulse at each vsync interval or each hsync interval. This signal can be
* used by the MCU to determine when to transmit a new frame so that the
* read pointer of the display never overlaps with the write pointer from the
* MCU. This function configures the MIPI DBI controller to delay transmitting
* display frames until the selected tearing effect signal edge occurs.
*
* The delay will occur on the on each call to @ref mipi_dbi_write_display
* where the ``frame_incomplete`` flag was set within the buffer descriptor
* provided with the prior call, as this indicates the buffer being written
* in this call is the first buffer of a new frame.
*
* Note that most display controllers will need to enable the TE signal
* using vendor specific commands before the MIPI DBI controller can react
* to it.
*
* @param dev mipi dbi controller
* @param edge which edge of the TE signal to start transmitting on
* @param delay_us how many microseconds after TE edge to start transmission
* @retval -EIO I/O error
* @retval -ENOSYS not implemented
* @retval -ENOTSUP not supported
*/
static inline int mipi_dbi_configure_te(const struct device *dev,
uint8_t edge,
uint32_t delay_us)
{
const struct mipi_dbi_driver_api *api =
(const struct mipi_dbi_driver_api *)dev->api;
if (api->configure_te == NULL) {
return -ENOSYS;
}
return api->configure_te(dev, edge, K_USEC(delay_us));
}
#ifdef __cplusplus
}
#endif

View file

@ -110,6 +110,40 @@
#define MIPI_DBI_MODE_8080_BUS_9_BIT 0x7
#define MIPI_DBI_MODE_8080_BUS_8_BIT 0x8
/** MIPI DBI tearing enable synchronization is disabled. */
#define MIPI_DBI_TE_NO_EDGE 0x0
/**
* MIPI DBI tearing enable synchronization on rising edge of TE signal.
* The controller will only send display write data on a rising edge of TE.
* This should be used when the controller can send a frame worth of data
* data to the display panel faster than the display panel can read a frame
* from its RAM
*
* .------. .------.
* TE -----' '------------------------' '-------------
* -----. .----------------------.
* CS '--------' '--------------------
*/
#define MIPI_DBI_TE_RISING_EDGE 0x1
/**
* MIPI DBI tearing enable synchronization on falling edge of TE signal.
* The controller will only send display write data on a falling edge of TE.
* This should be used when the controller sends a frame worth of data
* data to the display panel slower than the display panel can read a frame
* from its RAM. TE synchronization in this mode will only work if the
* controller can complete the write before the display panel completes 2
* read cycles, otherwise the read pointer will "catch up" with the write
* pointer.
*
* .------. .------.
* TE -----' '------------------------' '-------------
* ------------. .-----
* CS '---------------------------------------'
*/
#define MIPI_DBI_TE_FALLING_EDGE 0x2
/**
* SPI transfer of DBI commands as 8-bit blocks, the default behaviour in
* SPI 4 wire (Type C3) mode. The clocking diagram corresponds exactly to