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

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

DEFINITIONS

This source file includes following definitions.
  1. fbtft_write_spi
  2. fbtft_write_spi_emulate_9
  3. fbtft_read_spi
  4. fbtft_write_gpio8_wr
  5. fbtft_write_gpio16_wr
  6. fbtft_write_gpio16_wr_latched

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

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