root/drivers/staging/fbtft/fbtft-bus.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. define_fbtft_write_reg
  2. fbtft_write_vmem16_bus8
  3. fbtft_write_vmem16_bus9
  4. fbtft_write_vmem8_bus8
  5. fbtft_write_vmem16_bus16

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

/* [<][>][^][v][top][bottom][index][help] */