1 // SPDX-License-Identifier: GPL-2.0
2 #include <linux/export.h>
3 #include <linux/errno.h>
4 #include <linux/gpio.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=%d): ", __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=%d): ", __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=%d) txbuf => ", __func__, len);
115 spi_message_init(&m);
116 spi_message_add_tail(&t, &m);
117 ret = spi_sync(par->spi, &m);
118 fbtft_par_dbg_hex(DEBUG_READ, par, par->info->device, u8, buf, len,
119 "%s(len=%d) buf <= ", __func__, len);
123 EXPORT_SYMBOL(fbtft_read_spi);
126 * Optimized use of gpiolib is twice as fast as no optimization
127 * only one driver can use the optimized version at a time
129 int fbtft_write_gpio8_wr(struct fbtft_par *par, void *buf, size_t len)
133 #ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO
137 fbtft_par_dbg_hex(DEBUG_WRITE, par, par->info->device, u8, buf, len,
138 "%s(len=%d): ", __func__, len);
143 /* Start writing by pulling down /WR */
144 gpio_set_value(par->gpio.wr, 0);
147 #ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO
148 if (data == prev_data) {
149 gpio_set_value(par->gpio.wr, 0); /* used as delay */
151 for (i = 0; i < 8; i++) {
152 if ((data & 1) != (prev_data & 1))
153 gpio_set_value(par->gpio.db[i],
160 for (i = 0; i < 8; i++) {
161 gpio_set_value(par->gpio.db[i], data & 1);
167 gpio_set_value(par->gpio.wr, 1);
169 #ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO
170 prev_data = *(u8 *)buf;
177 EXPORT_SYMBOL(fbtft_write_gpio8_wr);
179 int fbtft_write_gpio16_wr(struct fbtft_par *par, void *buf, size_t len)
183 #ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO
184 static u16 prev_data;
187 fbtft_par_dbg_hex(DEBUG_WRITE, par, par->info->device, u8, buf, len,
188 "%s(len=%d): ", __func__, len);
193 /* Start writing by pulling down /WR */
194 gpio_set_value(par->gpio.wr, 0);
197 #ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO
198 if (data == prev_data) {
199 gpio_set_value(par->gpio.wr, 0); /* used as delay */
201 for (i = 0; i < 16; i++) {
202 if ((data & 1) != (prev_data & 1))
203 gpio_set_value(par->gpio.db[i],
210 for (i = 0; i < 16; i++) {
211 gpio_set_value(par->gpio.db[i], data & 1);
217 gpio_set_value(par->gpio.wr, 1);
219 #ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO
220 prev_data = *(u16 *)buf;
228 EXPORT_SYMBOL(fbtft_write_gpio16_wr);
230 int fbtft_write_gpio16_wr_latched(struct fbtft_par *par, void *buf, size_t len)
232 dev_err(par->info->device, "%s: function not implemented\n", __func__);
235 EXPORT_SYMBOL(fbtft_write_gpio16_wr_latched);