Skip to content

Commit c296d5f

Browse files
tpetazzonigregkh
authored andcommitted
staging: fbtft: core support
This commit adds the core fbtft framework from https://github.com/notro/fbtft. Signed-off-by: Thomas Petazzoni <[email protected]> Signed-off-by: Noralf Tronnes <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent ab666bb commit c296d5f

10 files changed

Lines changed: 2897 additions & 0 deletions

File tree

drivers/staging/Kconfig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,4 +106,6 @@ source "drivers/staging/unisys/Kconfig"
106106

107107
source "drivers/staging/clocking-wizard/Kconfig"
108108

109+
source "drivers/staging/fbtft/Kconfig"
110+
109111
endif # STAGING

drivers/staging/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,4 @@ obj-$(CONFIG_GS_FPGABOOT) += gs_fpgaboot/
4545
obj-$(CONFIG_CRYPTO_SKEIN) += skein/
4646
obj-$(CONFIG_UNISYSSPAR) += unisys/
4747
obj-$(CONFIG_COMMON_CLK_XLNX_CLKWZRD) += clocking-wizard/
48+
obj-$(CONFIG_FB_TFT) += fbtft/

drivers/staging/fbtft/Kconfig

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
menuconfig FB_TFT
2+
tristate "Support for small TFT LCD display modules"
3+
depends on FB && SPI && GPIOLIB
4+
select FB_SYS_FILLRECT
5+
select FB_SYS_COPYAREA
6+
select FB_SYS_IMAGEBLIT
7+
select FB_SYS_FOPS
8+
select FB_DEFERRED_IO
9+
select FB_BACKLIGHT

drivers/staging/fbtft/Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Core module
2+
obj-$(CONFIG_FB_TFT) += fbtft.o
3+
fbtft-y += fbtft-core.o fbtft-sysfs.o fbtft-bus.o fbtft-io.o

drivers/staging/fbtft/README

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
FBTFT
2+
=========
3+
4+
Linux Framebuffer drivers for small TFT LCD display modules.
5+
The module 'fbtft' makes writing drivers for some of these displays very easy.
6+
7+
Development is done on a Raspberry Pi running the Raspbian "wheezy" distribution.
8+
9+
INSTALLATION
10+
Download kernel sources
11+
12+
From Linux 3.15
13+
cd drivers/video/fbdev/fbtft
14+
git clone https://github.com/notro/fbtft.git
15+
16+
Add to drivers/video/fbdev/Kconfig: source "drivers/video/fbdev/fbtft/Kconfig"
17+
Add to drivers/video/fbdev/Makefile: obj-y += fbtft/
18+
19+
Before Linux 3.15
20+
cd drivers/video
21+
git clone https://github.com/notro/fbtft.git
22+
23+
Add to drivers/video/Kconfig: source "drivers/video/fbtft/Kconfig"
24+
Add to drivers/video/Makefile: obj-y += fbtft/
25+
26+
Enable driver(s) in menuconfig and build the kernel
27+
28+
29+
See wiki for more information: https://github.com/notro/fbtft/wiki
30+
31+
32+
Source: https://github.com/notro/fbtft/

drivers/staging/fbtft/fbtft-bus.c

Lines changed: 256 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,256 @@
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) \
17+
void 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+
} \
71+
EXPORT_SYMBOL(func);
72+
73+
define_fbtft_write_reg(fbtft_write_reg8_bus8, u8, )
74+
define_fbtft_write_reg(fbtft_write_reg16_bus8, u16, cpu_to_be16)
75+
define_fbtft_write_reg(fbtft_write_reg16_bus16, u16, )
76+
77+
void 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+
"%s: write() failed and returned %d\n", __func__, ret);
115+
return;
116+
}
117+
}
118+
EXPORT_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 */
130+
int 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+
}
182+
EXPORT_SYMBOL(fbtft_write_vmem16_bus8);
183+
184+
/* 16 bit pixel over 9-bit SPI bus: dc + high byte, dc + low byte */
185+
int 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+
}
231+
EXPORT_SYMBOL(fbtft_write_vmem16_bus9);
232+
233+
int 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+
}
238+
EXPORT_SYMBOL(fbtft_write_vmem8_bus8);
239+
240+
/* 16 bit pixel over 16-bit databus */
241+
int 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+
}
256+
EXPORT_SYMBOL(fbtft_write_vmem16_bus16);

0 commit comments

Comments
 (0)