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 8 9 10/***************************************************************************** 11 * 12 * void (*write_reg)(struct fbtft_par *par, int len, ...); 13 * 14 *****************************************************************************/ 15 16#define define_fbtft_write_reg(func, type, modifier) \ 17void func(struct fbtft_par *par, int len, ...) \ 18{ \ 19 va_list args; \ 20 int i, ret; \ 21 int offset = 0; \ 22 type *buf = (type *)par->buf; \ 23 \ 24 if (unlikely(par->debug & DEBUG_WRITE_REGISTER)) { \ 25 va_start(args, len); \ 26 for (i = 0; i < len; i++) { \ 27 buf[i] = (type)va_arg(args, unsigned int); \ 28 } \ 29 va_end(args); \ 30 fbtft_par_dbg_hex(DEBUG_WRITE_REGISTER, par, par->info->device, type, buf, len, "%s: ", __func__); \ 31 } \ 32 \ 33 va_start(args, len); \ 34 \ 35 if (par->startbyte) { \ 36 *(u8 *)par->buf = par->startbyte; \ 37 buf = (type *)(par->buf + 1); \ 38 offset = 1; \ 39 } \ 40 \ 41 *buf = modifier((type)va_arg(args, unsigned int)); \ 42 if (par->gpio.dc != -1) \ 43 gpio_set_value(par->gpio.dc, 0); \ 44 ret = par->fbtftops.write(par, par->buf, sizeof(type)+offset); \ 45 if (ret < 0) { \ 46 va_end(args); \ 47 dev_err(par->info->device, "%s: write() failed and returned %d\n", __func__, ret); \ 48 return; \ 49 } \ 50 len--; \ 51 \ 52 if (par->startbyte) \ 53 *(u8 *)par->buf = par->startbyte | 0x2; \ 54 \ 55 if (len) { \ 56 i = len; \ 57 while (i--) { \ 58 *buf++ = modifier((type)va_arg(args, unsigned int)); \ 59 } \ 60 if (par->gpio.dc != -1) \ 61 gpio_set_value(par->gpio.dc, 1); \ 62 ret = par->fbtftops.write(par, par->buf, len * (sizeof(type)+offset)); \ 63 if (ret < 0) { \ 64 va_end(args); \ 65 dev_err(par->info->device, "%s: write() failed and returned %d\n", __func__, ret); \ 66 return; \ 67 } \ 68 } \ 69 va_end(args); \ 70} \ 71EXPORT_SYMBOL(func); 72 73define_fbtft_write_reg(fbtft_write_reg8_bus8, u8, ) 74define_fbtft_write_reg(fbtft_write_reg16_bus8, u16, cpu_to_be16) 75define_fbtft_write_reg(fbtft_write_reg16_bus16, u16, ) 76 77void fbtft_write_reg8_bus9(struct fbtft_par *par, int len, ...) 78{ 79 va_list args; 80 int i, ret; 81 int pad = 0; 82 u16 *buf = (u16 *)par->buf; 83 84 if (unlikely(par->debug & DEBUG_WRITE_REGISTER)) { 85 va_start(args, len); 86 for (i = 0; i < len; i++) 87 *(((u8 *)buf) + i) = (u8)va_arg(args, unsigned int); 88 va_end(args); 89 fbtft_par_dbg_hex(DEBUG_WRITE_REGISTER, par, 90 par->info->device, u8, buf, len, "%s: ", __func__); 91 } 92 if (len <= 0) 93 return; 94 95 if (par->spi && (par->spi->bits_per_word == 8)) { 96 /* we're emulating 9-bit, pad start of buffer with no-ops 97 (assuming here that zero is a no-op) */ 98 pad = (len % 4) ? 4 - (len % 4) : 0; 99 for (i = 0; i < pad; i++) 100 *buf++ = 0x000; 101 } 102 103 va_start(args, len); 104 *buf++ = (u8)va_arg(args, unsigned int); 105 i = len - 1; 106 while (i--) { 107 *buf = (u8)va_arg(args, unsigned int); 108 *buf++ |= 0x100; /* dc=1 */ 109 } 110 va_end(args); 111 ret = par->fbtftops.write(par, par->buf, (len + pad) * sizeof(u16)); 112 if (ret < 0) { 113 dev_err(par->info->device, 114 "write() failed and returned %d\n", ret); 115 return; 116 } 117} 118EXPORT_SYMBOL(fbtft_write_reg8_bus9); 119 120 121 122 123/***************************************************************************** 124 * 125 * int (*write_vmem)(struct fbtft_par *par); 126 * 127 *****************************************************************************/ 128 129/* 16 bit pixel over 8-bit databus */ 130int fbtft_write_vmem16_bus8(struct fbtft_par *par, size_t offset, size_t len) 131{ 132 u16 *vmem16; 133 u16 *txbuf16 = (u16 *)par->txbuf.buf; 134 size_t remain; 135 size_t to_copy; 136 size_t tx_array_size; 137 int i; 138 int ret = 0; 139 size_t startbyte_size = 0; 140 141 fbtft_par_dbg(DEBUG_WRITE_VMEM, par, "%s(offset=%zu, len=%zu)\n", 142 __func__, offset, len); 143 144 remain = len / 2; 145 vmem16 = (u16 *)(par->info->screen_base + offset); 146 147 if (par->gpio.dc != -1) 148 gpio_set_value(par->gpio.dc, 1); 149 150 /* non buffered write */ 151 if (!par->txbuf.buf) 152 return par->fbtftops.write(par, vmem16, len); 153 154 /* buffered write */ 155 tx_array_size = par->txbuf.len / 2; 156 157 if (par->startbyte) { 158 txbuf16 = (u16 *)(par->txbuf.buf + 1); 159 tx_array_size -= 2; 160 *(u8 *)(par->txbuf.buf) = par->startbyte | 0x2; 161 startbyte_size = 1; 162 } 163 164 while (remain) { 165 to_copy = remain > tx_array_size ? tx_array_size : remain; 166 dev_dbg(par->info->device, " to_copy=%zu, remain=%zu\n", 167 to_copy, remain - to_copy); 168 169 for (i = 0; i < to_copy; i++) 170 txbuf16[i] = cpu_to_be16(vmem16[i]); 171 172 vmem16 = vmem16 + to_copy; 173 ret = par->fbtftops.write(par, par->txbuf.buf, 174 startbyte_size + to_copy * 2); 175 if (ret < 0) 176 return ret; 177 remain -= to_copy; 178 } 179 180 return ret; 181} 182EXPORT_SYMBOL(fbtft_write_vmem16_bus8); 183 184/* 16 bit pixel over 9-bit SPI bus: dc + high byte, dc + low byte */ 185int fbtft_write_vmem16_bus9(struct fbtft_par *par, size_t offset, size_t len) 186{ 187 u8 *vmem8; 188 u16 *txbuf16 = par->txbuf.buf; 189 size_t remain; 190 size_t to_copy; 191 size_t tx_array_size; 192 int i; 193 int ret = 0; 194 195 fbtft_par_dbg(DEBUG_WRITE_VMEM, par, "%s(offset=%zu, len=%zu)\n", 196 __func__, offset, len); 197 198 if (!par->txbuf.buf) { 199 dev_err(par->info->device, "%s: txbuf.buf is NULL\n", __func__); 200 return -1; 201 } 202 203 remain = len; 204 vmem8 = par->info->screen_base + offset; 205 206 tx_array_size = par->txbuf.len / 2; 207 208 while (remain) { 209 to_copy = remain > tx_array_size ? tx_array_size : remain; 210 dev_dbg(par->info->device, " to_copy=%zu, remain=%zu\n", 211 to_copy, remain - to_copy); 212 213#ifdef __LITTLE_ENDIAN 214 for (i = 0; i < to_copy; i += 2) { 215 txbuf16[i] = 0x0100 | vmem8[i+1]; 216 txbuf16[i+1] = 0x0100 | vmem8[i]; 217 } 218#else 219 for (i = 0; i < to_copy; i++) 220 txbuf16[i] = 0x0100 | vmem8[i]; 221#endif 222 vmem8 = vmem8 + to_copy; 223 ret = par->fbtftops.write(par, par->txbuf.buf, to_copy*2); 224 if (ret < 0) 225 return ret; 226 remain -= to_copy; 227 } 228 229 return ret; 230} 231EXPORT_SYMBOL(fbtft_write_vmem16_bus9); 232 233int fbtft_write_vmem8_bus8(struct fbtft_par *par, size_t offset, size_t len) 234{ 235 dev_err(par->info->device, "%s: function not implemented\n", __func__); 236 return -1; 237} 238EXPORT_SYMBOL(fbtft_write_vmem8_bus8); 239 240/* 16 bit pixel over 16-bit databus */ 241int fbtft_write_vmem16_bus16(struct fbtft_par *par, size_t offset, size_t len) 242{ 243 u16 *vmem16; 244 245 fbtft_par_dbg(DEBUG_WRITE_VMEM, par, "%s(offset=%zu, len=%zu)\n", 246 __func__, offset, len); 247 248 vmem16 = (u16 *)(par->info->screen_base + offset); 249 250 if (par->gpio.dc != -1) 251 gpio_set_value(par->gpio.dc, 1); 252 253 /* no need for buffered write with 16-bit bus */ 254 return par->fbtftops.write(par, vmem16, len); 255} 256EXPORT_SYMBOL(fbtft_write_vmem16_bus16); 257