1
1
/*
2
2
* Copyright 2023 NXP
3
+ * Copyright 2024 TiaC Systems
3
4
*
4
5
* SPDX-License-Identifier: Apache-2.0
5
6
*/
9
10
#include <zephyr/drivers/mipi_dbi.h>
10
11
#include <zephyr/drivers/spi.h>
11
12
#include <zephyr/drivers/gpio.h>
13
+ #include <zephyr/sys/byteorder.h>
12
14
13
15
#include <zephyr/logging/log.h>
14
16
LOG_MODULE_REGISTER (mipi_dbi_spi , CONFIG_MIPI_DBI_LOG_LEVEL );
@@ -20,6 +22,8 @@ struct mipi_dbi_spi_config {
20
22
const struct gpio_dt_spec cmd_data ;
21
23
/* Reset GPIO */
22
24
const struct gpio_dt_spec reset ;
25
+ /* Minimum transfer bits */
26
+ const uint8_t xfr_min_bits ;
23
27
};
24
28
25
29
struct mipi_dbi_spi_data {
@@ -38,6 +42,18 @@ struct mipi_dbi_spi_data {
38
42
#define MIPI_DBI_SPI_READ_REQUIRED DT_INST_FOREACH_STATUS_OKAY(_WRITE_ONLY_ABSENT) 0
39
43
uint32_t var = MIPI_DBI_SPI_READ_REQUIRED ;
40
44
45
+ /* Expands to 1 if the node does reflect the enum in `xfr-min-bits` property */
46
+ #define _XFR_8BITS (n ) (DT_INST_PROP(n, xfr_min_bits) == MIPI_DBI_SPI_XFR_8BIT) |
47
+ #define _XFR_16BITS (n ) (DT_INST_PROP(n, xfr_min_bits) == MIPI_DBI_SPI_XFR_16BIT) |
48
+
49
+ /* This macros will evaluate to 1 if any of the nodes with zephyr,mipi-dbi-spi
50
+ * have the `xfr-min-bits` property to corresponding enum value. The intention
51
+ * here is to allow the write helper functions to be optimized out when not all
52
+ * minimum transfer bits will be needed.
53
+ */
54
+ #define MIPI_DBI_SPI_WRITE_8BIT_REQUIRED DT_INST_FOREACH_STATUS_OKAY(_XFR_8BITS) 0
55
+ #define MIPI_DBI_SPI_WRITE_16BIT_REQUIRED DT_INST_FOREACH_STATUS_OKAY(_XFR_16BITS) 0
56
+
41
57
/* In Type C mode 1 MIPI BIT communication, the 9th bit of the word
42
58
* (first bit sent in each word) indicates if the word is a command or
43
59
* data. Typically 0 indicates a command and 1 indicates data, but some
@@ -93,11 +109,13 @@ mipi_dbi_spi_write_helper_3wire(const struct device *dev,
93
109
return ret ;
94
110
}
95
111
112
+ #if MIPI_DBI_SPI_WRITE_8BIT_REQUIRED
113
+
96
114
static inline int
97
- mipi_dbi_spi_write_helper_4wire (const struct device * dev ,
98
- const struct mipi_dbi_config * dbi_config ,
99
- bool cmd_present , uint8_t cmd ,
100
- const uint8_t * data_buf , size_t len )
115
+ mipi_dbi_spi_write_helper_4wire_8bit (const struct device * dev ,
116
+ const struct mipi_dbi_config * dbi_config ,
117
+ bool cmd_present , uint8_t cmd ,
118
+ const uint8_t * data_buf , size_t len )
101
119
{
102
120
const struct mipi_dbi_spi_config * config = dev -> config ;
103
121
struct spi_buf buffer ;
@@ -140,11 +158,104 @@ mipi_dbi_spi_write_helper_4wire(const struct device *dev,
140
158
return ret ;
141
159
}
142
160
161
+ #endif /* MIPI_DBI_SPI_WRITE_8BIT_REQUIRED */
162
+
163
+ #if MIPI_DBI_SPI_WRITE_16BIT_REQUIRED
164
+
165
+ static inline int
166
+ mipi_dbi_spi_write_helper_4wire_16bit (const struct device * dev ,
167
+ const struct mipi_dbi_config * dbi_config ,
168
+ bool cmd_present , uint8_t cmd ,
169
+ const uint8_t * data_buf , size_t len )
170
+ {
171
+ const struct mipi_dbi_spi_config * config = dev -> config ;
172
+ struct spi_buf buffer ;
173
+ struct spi_buf_set buf_set = {
174
+ .buffers = & buffer ,
175
+ .count = 1 ,
176
+ };
177
+ uint16_t data16 ;
178
+ int ret = 0 ;
179
+
180
+ /*
181
+ * 4 wire mode with toggle the command/data GPIO
182
+ * to indicate if we are sending a command or data
183
+ * but send 16-bit blocks (with bit stuffing).
184
+ */
185
+
186
+ if (cmd_present ) {
187
+ data16 = sys_cpu_to_be16 (cmd );
188
+ buffer .buf = & data16 ;
189
+ buffer .len = sizeof (data16 );
190
+
191
+ /* Set CD pin low for command */
192
+ gpio_pin_set_dt (& config -> cmd_data , 0 );
193
+ ret = spi_write (config -> spi_dev , & dbi_config -> config ,
194
+ & buf_set );
195
+ if (ret < 0 ) {
196
+ goto out ;
197
+ }
198
+
199
+ /* Set CD pin high for data, if there are any */
200
+ if (len > 0 ) {
201
+ gpio_pin_set_dt (& config -> cmd_data , 1 );
202
+ }
203
+
204
+ /* iterate command data */
205
+ for (int i = 0 ; i < len ; i ++ ) {
206
+ data16 = sys_cpu_to_be16 (data_buf [i ]);
207
+
208
+ ret = spi_write (config -> spi_dev , & dbi_config -> config ,
209
+ & buf_set );
210
+ if (ret < 0 ) {
211
+ goto out ;
212
+ }
213
+ }
214
+ } else {
215
+ int stuffing = len % sizeof (data16 );
216
+
217
+ /* Set CD pin high for data, if there are any */
218
+ if (len > 0 ) {
219
+ gpio_pin_set_dt (& config -> cmd_data , 1 );
220
+ }
221
+
222
+ /* pass through generic device data */
223
+ if (len - stuffing > 0 ) {
224
+ buffer .buf = (void * )data_buf ;
225
+ buffer .len = len - stuffing ;
226
+
227
+ ret = spi_write (config -> spi_dev , & dbi_config -> config ,
228
+ & buf_set );
229
+ if (ret < 0 ) {
230
+ goto out ;
231
+ }
232
+ }
233
+
234
+ /* iterate remaining data with stuffing */
235
+ for (int i = len - stuffing ; i < len ; i ++ ) {
236
+ data16 = sys_cpu_to_be16 (data_buf [i ]);
237
+ buffer .buf = & data16 ;
238
+ buffer .len = sizeof (data16 );
239
+
240
+ ret = spi_write (config -> spi_dev , & dbi_config -> config ,
241
+ & buf_set );
242
+ if (ret < 0 ) {
243
+ goto out ;
244
+ }
245
+ }
246
+ }
247
+ out :
248
+ return ret ;
249
+ }
250
+
251
+ #endif /* MIPI_DBI_SPI_WRITE_16BIT_REQUIRED */
252
+
143
253
static int mipi_dbi_spi_write_helper (const struct device * dev ,
144
254
const struct mipi_dbi_config * dbi_config ,
145
255
bool cmd_present , uint8_t cmd ,
146
256
const uint8_t * data_buf , size_t len )
147
257
{
258
+ const struct mipi_dbi_spi_config * config = dev -> config ;
148
259
struct mipi_dbi_spi_data * data = dev -> data ;
149
260
int ret = 0 ;
150
261
@@ -158,20 +269,36 @@ static int mipi_dbi_spi_write_helper(const struct device *dev,
158
269
ret = mipi_dbi_spi_write_helper_3wire (dev , dbi_config ,
159
270
cmd_present , cmd ,
160
271
data_buf , len );
161
- if (ret < 0 ) {
272
+ goto out ;
273
+ }
274
+
275
+ if (dbi_config -> mode == MIPI_DBI_MODE_SPI_4WIRE ) {
276
+
277
+ #if MIPI_DBI_SPI_WRITE_8BIT_REQUIRED
278
+ if (config -> xfr_min_bits == MIPI_DBI_SPI_XFR_8BIT ) {
279
+ ret = mipi_dbi_spi_write_helper_4wire_8bit (
280
+ dev , dbi_config ,
281
+ cmd_present , cmd ,
282
+ data_buf , len );
162
283
goto out ;
163
284
}
164
- } else if (dbi_config -> mode == MIPI_DBI_MODE_SPI_4WIRE ) {
165
- ret = mipi_dbi_spi_write_helper_4wire (dev , dbi_config ,
166
- cmd_present , cmd ,
167
- data_buf , len );
168
- if (ret < 0 ) {
285
+ #endif
286
+
287
+ #if MIPI_DBI_SPI_WRITE_16BIT_REQUIRED
288
+ if (config -> xfr_min_bits == MIPI_DBI_SPI_XFR_16BIT ) {
289
+ ret = mipi_dbi_spi_write_helper_4wire_16bit (
290
+ dev , dbi_config ,
291
+ cmd_present , cmd ,
292
+ data_buf , len );
169
293
goto out ;
170
294
}
171
- } else {
172
- /* Otherwise, unsupported mode */
173
- ret = - ENOTSUP ;
295
+ #endif
296
+
174
297
}
298
+
299
+ /* Otherwise, unsupported mode */
300
+ ret = - ENOTSUP ;
301
+
175
302
out :
176
303
k_mutex_unlock (& data -> lock );
177
304
return ret ;
@@ -433,6 +560,7 @@ static DEVICE_API(mipi_dbi, mipi_dbi_spi_driver_api) = {
433
560
DT_INST_PHANDLE(n, spi_dev)), \
434
561
.cmd_data = GPIO_DT_SPEC_INST_GET_OR(n, dc_gpios, {}), \
435
562
.reset = GPIO_DT_SPEC_INST_GET_OR(n, reset_gpios, {}), \
563
+ .xfr_min_bits = DT_INST_PROP(n, xfr_min_bits) \
436
564
}; \
437
565
static struct mipi_dbi_spi_data mipi_dbi_spi_data_##n; \
438
566
\
0 commit comments