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