1 // SPDX-License-Identifier: GPL-2.0
2 #include <linux/export.h>
3 #include <linux/errno.h>
4 #include <linux/gpio/consumer.h>
5 #include <linux/spi/spi.h>
8 int fbtft_write_spi(struct fbtft_par
*par
, void *buf
, size_t len
)
10 struct spi_transfer t
= {
16 fbtft_par_dbg_hex(DEBUG_WRITE
, par
, par
->info
->device
, u8
, buf
, len
,
17 "%s(len=%zu): ", __func__
, len
);
20 dev_err(par
->info
->device
,
21 "%s: par->spi is unexpectedly NULL\n", __func__
);
26 spi_message_add_tail(&t
, &m
);
27 return spi_sync(par
->spi
, &m
);
29 EXPORT_SYMBOL(fbtft_write_spi
);
32 * fbtft_write_spi_emulate_9() - write SPI emulating 9-bit
34 * @buf: Buffer to write
35 * @len: Length of buffer (must be divisible by 8)
37 * When 9-bit SPI is not available, this function can be used to emulate that.
38 * par->extra must hold a transformation buffer used for transfer.
40 int fbtft_write_spi_emulate_9(struct fbtft_par
*par
, void *buf
, size_t len
)
44 size_t size
= len
/ 2;
49 fbtft_par_dbg_hex(DEBUG_WRITE
, par
, par
->info
->device
, u8
, buf
, len
,
50 "%s(len=%zu): ", __func__
, len
);
53 dev_err(par
->info
->device
, "%s: error: par->extra is NULL\n",
58 dev_err(par
->info
->device
,
59 "error: len=%zu must be divisible by 8\n", len
);
63 for (i
= 0; i
< size
; i
+= 8) {
66 for (j
= 0; j
< 7; j
++) {
67 dc
= (*src
& 0x0100) ? 1 : 0;
74 tmp
|= ((*src
& 0x0100) ? 1 : 0);
75 *(__be64
*)dst
= cpu_to_be64(tmp
);
77 *dst
++ = (u8
)(*src
++ & 0x00FF);
81 return spi_write(par
->spi
, par
->extra
, size
+ added
);
83 EXPORT_SYMBOL(fbtft_write_spi_emulate_9
);
85 int fbtft_read_spi(struct fbtft_par
*par
, void *buf
, size_t len
)
88 u8 txbuf
[32] = { 0, };
89 struct spi_transfer t
= {
97 dev_err(par
->info
->device
,
98 "%s: par->spi is unexpectedly NULL\n", __func__
);
102 if (par
->startbyte
) {
104 dev_err(par
->info
->device
,
105 "len=%zu can't be larger than 32 when using 'startbyte'\n",
109 txbuf
[0] = par
->startbyte
| 0x3;
111 fbtft_par_dbg_hex(DEBUG_READ
, par
, par
->info
->device
, u8
,
112 txbuf
, len
, "%s(len=%zu) txbuf => ",
116 spi_message_init(&m
);
117 spi_message_add_tail(&t
, &m
);
118 ret
= spi_sync(par
->spi
, &m
);
119 fbtft_par_dbg_hex(DEBUG_READ
, par
, par
->info
->device
, u8
, buf
, len
,
120 "%s(len=%zu) buf <= ", __func__
, len
);
124 EXPORT_SYMBOL(fbtft_read_spi
);
127 * Optimized use of gpiolib is twice as fast as no optimization
128 * only one driver can use the optimized version at a time
130 int fbtft_write_gpio8_wr(struct fbtft_par
*par
, void *buf
, size_t len
)
134 #ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO
138 fbtft_par_dbg_hex(DEBUG_WRITE
, par
, par
->info
->device
, u8
, buf
, len
,
139 "%s(len=%zu): ", __func__
, len
);
144 /* Start writing by pulling down /WR */
145 gpiod_set_value(par
->gpio
.wr
, 0);
148 #ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO
149 if (data
== prev_data
) {
150 gpiod_set_value(par
->gpio
.wr
, 0); /* used as delay */
152 for (i
= 0; i
< 8; i
++) {
153 if ((data
& 1) != (prev_data
& 1))
154 gpiod_set_value(par
->gpio
.db
[i
],
161 for (i
= 0; i
< 8; i
++) {
162 gpiod_set_value(par
->gpio
.db
[i
], data
& 1);
168 gpiod_set_value(par
->gpio
.wr
, 1);
170 #ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO
171 prev_data
= *(u8
*)buf
;
178 EXPORT_SYMBOL(fbtft_write_gpio8_wr
);
180 int fbtft_write_gpio16_wr(struct fbtft_par
*par
, void *buf
, size_t len
)
184 #ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO
185 static u16 prev_data
;
188 fbtft_par_dbg_hex(DEBUG_WRITE
, par
, par
->info
->device
, u8
, buf
, len
,
189 "%s(len=%zu): ", __func__
, len
);
194 /* Start writing by pulling down /WR */
195 gpiod_set_value(par
->gpio
.wr
, 0);
198 #ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO
199 if (data
== prev_data
) {
200 gpiod_set_value(par
->gpio
.wr
, 0); /* used as delay */
202 for (i
= 0; i
< 16; i
++) {
203 if ((data
& 1) != (prev_data
& 1))
204 gpiod_set_value(par
->gpio
.db
[i
],
211 for (i
= 0; i
< 16; i
++) {
212 gpiod_set_value(par
->gpio
.db
[i
], data
& 1);
218 gpiod_set_value(par
->gpio
.wr
, 1);
220 #ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO
221 prev_data
= *(u16
*)buf
;
229 EXPORT_SYMBOL(fbtft_write_gpio16_wr
);
231 int fbtft_write_gpio16_wr_latched(struct fbtft_par
*par
, void *buf
, size_t len
)
233 dev_err(par
->info
->device
, "%s: function not implemented\n", __func__
);
236 EXPORT_SYMBOL(fbtft_write_gpio16_wr_latched
);