1 #include <linux/export.h> 2 #include <linux/errno.h> 3 #include <linux/gpio.h> 4 #include <linux/spi/spi.h> 5 #include "fbtft.h" 6 7 int fbtft_write_spi(struct fbtft_par *par, void *buf, size_t len) 8 { 9 struct spi_transfer t = { 10 .tx_buf = buf, 11 .len = len, 12 }; 13 struct spi_message m; 14 15 fbtft_par_dbg_hex(DEBUG_WRITE, par, par->info->device, u8, buf, len, 16 "%s(len=%d): ", __func__, len); 17 18 if (!par->spi) { 19 dev_err(par->info->device, 20 "%s: par->spi is unexpectedly NULL\n", __func__); 21 return -1; 22 } 23 24 spi_message_init(&m); 25 spi_message_add_tail(&t, &m); 26 return spi_sync(par->spi, &m); 27 } 28 EXPORT_SYMBOL(fbtft_write_spi); 29 30 /** 31 * fbtft_write_spi_emulate_9() - write SPI emulating 9-bit 32 * @par: Driver data 33 * @buf: Buffer to write 34 * @len: Length of buffer (must be divisible by 8) 35 * 36 * When 9-bit SPI is not available, this function can be used to emulate that. 37 * par->extra must hold a transformation buffer used for transfer. 38 */ 39 int fbtft_write_spi_emulate_9(struct fbtft_par *par, void *buf, size_t len) 40 { 41 u16 *src = buf; 42 u8 *dst = par->extra; 43 size_t size = len / 2; 44 size_t added = 0; 45 int bits, i, j; 46 u64 val, dc, tmp; 47 48 fbtft_par_dbg_hex(DEBUG_WRITE, par, par->info->device, u8, buf, len, 49 "%s(len=%d): ", __func__, len); 50 51 if (!par->extra) { 52 dev_err(par->info->device, "%s: error: par->extra is NULL\n", 53 __func__); 54 return -EINVAL; 55 } 56 if ((len % 8) != 0) { 57 dev_err(par->info->device, 58 "error: len=%zu must be divisible by 8\n", len); 59 return -EINVAL; 60 } 61 62 for (i = 0; i < size; i += 8) { 63 tmp = 0; 64 bits = 63; 65 for (j = 0; j < 7; j++) { 66 dc = (*src & 0x0100) ? 1 : 0; 67 val = *src & 0x00FF; 68 tmp |= dc << bits; 69 bits -= 8; 70 tmp |= val << bits--; 71 src++; 72 } 73 tmp |= ((*src & 0x0100) ? 1 : 0); 74 *(__be64 *)dst = cpu_to_be64(tmp); 75 dst += 8; 76 *dst++ = (u8)(*src++ & 0x00FF); 77 added++; 78 } 79 80 return spi_write(par->spi, par->extra, size + added); 81 } 82 EXPORT_SYMBOL(fbtft_write_spi_emulate_9); 83 84 int fbtft_read_spi(struct fbtft_par *par, void *buf, size_t len) 85 { 86 int ret; 87 u8 txbuf[32] = { 0, }; 88 struct spi_transfer t = { 89 .speed_hz = 2000000, 90 .rx_buf = buf, 91 .len = len, 92 }; 93 struct spi_message m; 94 95 if (!par->spi) { 96 dev_err(par->info->device, 97 "%s: par->spi is unexpectedly NULL\n", __func__); 98 return -ENODEV; 99 } 100 101 if (par->startbyte) { 102 if (len > 32) { 103 dev_err(par->info->device, 104 "len=%zu can't be larger than 32 when using 'startbyte'\n", 105 len); 106 return -EINVAL; 107 } 108 txbuf[0] = par->startbyte | 0x3; 109 t.tx_buf = txbuf; 110 fbtft_par_dbg_hex(DEBUG_READ, par, par->info->device, u8, 111 txbuf, len, "%s(len=%d) txbuf => ", __func__, len); 112 } 113 114 spi_message_init(&m); 115 spi_message_add_tail(&t, &m); 116 ret = spi_sync(par->spi, &m); 117 fbtft_par_dbg_hex(DEBUG_READ, par, par->info->device, u8, buf, len, 118 "%s(len=%d) buf <= ", __func__, len); 119 120 return ret; 121 } 122 EXPORT_SYMBOL(fbtft_read_spi); 123 124 /* 125 * Optimized use of gpiolib is twice as fast as no optimization 126 * only one driver can use the optimized version at a time 127 */ 128 int fbtft_write_gpio8_wr(struct fbtft_par *par, void *buf, size_t len) 129 { 130 u8 data; 131 int i; 132 #ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO 133 static u8 prev_data; 134 #endif 135 136 fbtft_par_dbg_hex(DEBUG_WRITE, par, par->info->device, u8, buf, len, 137 "%s(len=%d): ", __func__, len); 138 139 while (len--) { 140 data = *(u8 *)buf; 141 142 /* Start writing by pulling down /WR */ 143 gpio_set_value(par->gpio.wr, 0); 144 145 /* Set data */ 146 #ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO 147 if (data == prev_data) { 148 gpio_set_value(par->gpio.wr, 0); /* used as delay */ 149 } else { 150 for (i = 0; i < 8; i++) { 151 if ((data & 1) != (prev_data & 1)) 152 gpio_set_value(par->gpio.db[i], 153 data & 1); 154 data >>= 1; 155 prev_data >>= 1; 156 } 157 } 158 #else 159 for (i = 0; i < 8; i++) { 160 gpio_set_value(par->gpio.db[i], data & 1); 161 data >>= 1; 162 } 163 #endif 164 165 /* Pullup /WR */ 166 gpio_set_value(par->gpio.wr, 1); 167 168 #ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO 169 prev_data = *(u8 *)buf; 170 #endif 171 buf++; 172 } 173 174 return 0; 175 } 176 EXPORT_SYMBOL(fbtft_write_gpio8_wr); 177 178 int fbtft_write_gpio16_wr(struct fbtft_par *par, void *buf, size_t len) 179 { 180 u16 data; 181 int i; 182 #ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO 183 static u16 prev_data; 184 #endif 185 186 fbtft_par_dbg_hex(DEBUG_WRITE, par, par->info->device, u8, buf, len, 187 "%s(len=%d): ", __func__, len); 188 189 while (len) { 190 data = *(u16 *)buf; 191 192 /* Start writing by pulling down /WR */ 193 gpio_set_value(par->gpio.wr, 0); 194 195 /* Set data */ 196 #ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO 197 if (data == prev_data) { 198 gpio_set_value(par->gpio.wr, 0); /* used as delay */ 199 } else { 200 for (i = 0; i < 16; i++) { 201 if ((data & 1) != (prev_data & 1)) 202 gpio_set_value(par->gpio.db[i], 203 data & 1); 204 data >>= 1; 205 prev_data >>= 1; 206 } 207 } 208 #else 209 for (i = 0; i < 16; i++) { 210 gpio_set_value(par->gpio.db[i], data & 1); 211 data >>= 1; 212 } 213 #endif 214 215 /* Pullup /WR */ 216 gpio_set_value(par->gpio.wr, 1); 217 218 #ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO 219 prev_data = *(u16 *)buf; 220 #endif 221 buf += 2; 222 len -= 2; 223 } 224 225 return 0; 226 } 227 EXPORT_SYMBOL(fbtft_write_gpio16_wr); 228 229 int fbtft_write_gpio16_wr_latched(struct fbtft_par *par, void *buf, size_t len) 230 { 231 dev_err(par->info->device, "%s: function not implemented\n", __func__); 232 return -1; 233 } 234 EXPORT_SYMBOL(fbtft_write_gpio16_wr_latched); 235