0001
0002 #include <linux/export.h>
0003 #include <linux/errno.h>
0004 #include <linux/gpio/consumer.h>
0005 #include <linux/spi/spi.h>
0006 #include "fbtft.h"
0007
0008 int fbtft_write_spi(struct fbtft_par *par, void *buf, size_t len)
0009 {
0010 struct spi_transfer t = {
0011 .tx_buf = buf,
0012 .len = len,
0013 };
0014 struct spi_message m;
0015
0016 fbtft_par_dbg_hex(DEBUG_WRITE, par, par->info->device, u8, buf, len,
0017 "%s(len=%zu): ", __func__, len);
0018
0019 if (!par->spi) {
0020 dev_err(par->info->device,
0021 "%s: par->spi is unexpectedly NULL\n", __func__);
0022 return -1;
0023 }
0024
0025 spi_message_init(&m);
0026 spi_message_add_tail(&t, &m);
0027 return spi_sync(par->spi, &m);
0028 }
0029 EXPORT_SYMBOL(fbtft_write_spi);
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040 int fbtft_write_spi_emulate_9(struct fbtft_par *par, void *buf, size_t len)
0041 {
0042 u16 *src = buf;
0043 u8 *dst = par->extra;
0044 size_t size = len / 2;
0045 size_t added = 0;
0046 int bits, i, j;
0047 u64 val, dc, tmp;
0048
0049 fbtft_par_dbg_hex(DEBUG_WRITE, par, par->info->device, u8, buf, len,
0050 "%s(len=%zu): ", __func__, len);
0051
0052 if (!par->extra) {
0053 dev_err(par->info->device, "%s: error: par->extra is NULL\n",
0054 __func__);
0055 return -EINVAL;
0056 }
0057 if ((len % 8) != 0) {
0058 dev_err(par->info->device,
0059 "error: len=%zu must be divisible by 8\n", len);
0060 return -EINVAL;
0061 }
0062
0063 for (i = 0; i < size; i += 8) {
0064 tmp = 0;
0065 bits = 63;
0066 for (j = 0; j < 7; j++) {
0067 dc = (*src & 0x0100) ? 1 : 0;
0068 val = *src & 0x00FF;
0069 tmp |= dc << bits;
0070 bits -= 8;
0071 tmp |= val << bits--;
0072 src++;
0073 }
0074 tmp |= ((*src & 0x0100) ? 1 : 0);
0075 *(__be64 *)dst = cpu_to_be64(tmp);
0076 dst += 8;
0077 *dst++ = (u8)(*src++ & 0x00FF);
0078 added++;
0079 }
0080
0081 return spi_write(par->spi, par->extra, size + added);
0082 }
0083 EXPORT_SYMBOL(fbtft_write_spi_emulate_9);
0084
0085 int fbtft_read_spi(struct fbtft_par *par, void *buf, size_t len)
0086 {
0087 int ret;
0088 u8 txbuf[32] = { 0, };
0089 struct spi_transfer t = {
0090 .speed_hz = 2000000,
0091 .rx_buf = buf,
0092 .len = len,
0093 };
0094 struct spi_message m;
0095
0096 if (!par->spi) {
0097 dev_err(par->info->device,
0098 "%s: par->spi is unexpectedly NULL\n", __func__);
0099 return -ENODEV;
0100 }
0101
0102 if (par->startbyte) {
0103 if (len > 32) {
0104 dev_err(par->info->device,
0105 "len=%zu can't be larger than 32 when using 'startbyte'\n",
0106 len);
0107 return -EINVAL;
0108 }
0109 txbuf[0] = par->startbyte | 0x3;
0110 t.tx_buf = txbuf;
0111 fbtft_par_dbg_hex(DEBUG_READ, par, par->info->device, u8,
0112 txbuf, len, "%s(len=%zu) txbuf => ",
0113 __func__, len);
0114 }
0115
0116 spi_message_init(&m);
0117 spi_message_add_tail(&t, &m);
0118 ret = spi_sync(par->spi, &m);
0119 fbtft_par_dbg_hex(DEBUG_READ, par, par->info->device, u8, buf, len,
0120 "%s(len=%zu) buf <= ", __func__, len);
0121
0122 return ret;
0123 }
0124 EXPORT_SYMBOL(fbtft_read_spi);
0125
0126
0127
0128
0129
0130 int fbtft_write_gpio8_wr(struct fbtft_par *par, void *buf, size_t len)
0131 {
0132 u8 data;
0133 int i;
0134 #ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO
0135 static u8 prev_data;
0136 #endif
0137
0138 fbtft_par_dbg_hex(DEBUG_WRITE, par, par->info->device, u8, buf, len,
0139 "%s(len=%zu): ", __func__, len);
0140
0141 while (len--) {
0142 data = *(u8 *)buf;
0143
0144
0145 gpiod_set_value(par->gpio.wr, 1);
0146
0147
0148 #ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO
0149 if (data == prev_data) {
0150 gpiod_set_value(par->gpio.wr, 1);
0151 } else {
0152 for (i = 0; i < 8; i++) {
0153 if ((data & 1) != (prev_data & 1))
0154 gpiod_set_value(par->gpio.db[i],
0155 data & 1);
0156 data >>= 1;
0157 prev_data >>= 1;
0158 }
0159 }
0160 #else
0161 for (i = 0; i < 8; i++) {
0162 gpiod_set_value(par->gpio.db[i], data & 1);
0163 data >>= 1;
0164 }
0165 #endif
0166
0167
0168 gpiod_set_value(par->gpio.wr, 0);
0169
0170 #ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO
0171 prev_data = *(u8 *)buf;
0172 #endif
0173 buf++;
0174 }
0175
0176 return 0;
0177 }
0178 EXPORT_SYMBOL(fbtft_write_gpio8_wr);
0179
0180 int fbtft_write_gpio16_wr(struct fbtft_par *par, void *buf, size_t len)
0181 {
0182 u16 data;
0183 int i;
0184 #ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO
0185 static u16 prev_data;
0186 #endif
0187
0188 fbtft_par_dbg_hex(DEBUG_WRITE, par, par->info->device, u8, buf, len,
0189 "%s(len=%zu): ", __func__, len);
0190
0191 while (len) {
0192 data = *(u16 *)buf;
0193
0194
0195 gpiod_set_value(par->gpio.wr, 1);
0196
0197
0198 #ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO
0199 if (data == prev_data) {
0200 gpiod_set_value(par->gpio.wr, 1);
0201 } else {
0202 for (i = 0; i < 16; i++) {
0203 if ((data & 1) != (prev_data & 1))
0204 gpiod_set_value(par->gpio.db[i],
0205 data & 1);
0206 data >>= 1;
0207 prev_data >>= 1;
0208 }
0209 }
0210 #else
0211 for (i = 0; i < 16; i++) {
0212 gpiod_set_value(par->gpio.db[i], data & 1);
0213 data >>= 1;
0214 }
0215 #endif
0216
0217
0218 gpiod_set_value(par->gpio.wr, 0);
0219
0220 #ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO
0221 prev_data = *(u16 *)buf;
0222 #endif
0223 buf += 2;
0224 len -= 2;
0225 }
0226
0227 return 0;
0228 }
0229 EXPORT_SYMBOL(fbtft_write_gpio16_wr);
0230
0231 int fbtft_write_gpio16_wr_latched(struct fbtft_par *par, void *buf, size_t len)
0232 {
0233 dev_err(par->info->device, "%s: function not implemented\n", __func__);
0234 return -1;
0235 }
0236 EXPORT_SYMBOL(fbtft_write_gpio16_wr_latched);