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