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