fbtft: experimental DMA support
A DMA capable SPI master driver is needed to use DMA. Tested-by: Derek Campbell
This commit is contained in:
parent
49d03f9634
commit
2c721932aa
3 changed files with 34 additions and 7 deletions
25
fbtft-core.c
25
fbtft-core.c
|
|
@ -36,6 +36,7 @@
|
|||
#include <linux/backlight.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
|
||||
#include "fbtft.h"
|
||||
|
||||
|
|
@ -49,6 +50,10 @@ static unsigned long debug;
|
|||
module_param(debug, ulong , 0);
|
||||
MODULE_PARM_DESC(debug, "override device debug level");
|
||||
|
||||
static bool dma;
|
||||
module_param(dma, bool, 0);
|
||||
MODULE_PARM_DESC(dma, "Use DMA buffer");
|
||||
|
||||
|
||||
void fbtft_dbg_hex(const struct device *dev, int groupsize,
|
||||
void *buf, size_t len, const char *fmt, ...)
|
||||
|
|
@ -788,7 +793,12 @@ struct fb_info *fbtft_framebuffer_alloc(struct fbtft_display *display,
|
|||
#endif
|
||||
|
||||
if (txbuflen > 0) {
|
||||
txbuf = vzalloc(txbuflen);
|
||||
if (dma) {
|
||||
dev->coherent_dma_mask = ~0;
|
||||
txbuf = dma_alloc_coherent(dev, txbuflen, &par->txbuf.dma, GFP_DMA);
|
||||
} else {
|
||||
txbuf = vzalloc(txbuflen);
|
||||
}
|
||||
if (!txbuf)
|
||||
goto alloc_fail;
|
||||
par->txbuf.buf = txbuf;
|
||||
|
|
@ -817,8 +827,6 @@ struct fb_info *fbtft_framebuffer_alloc(struct fbtft_display *display,
|
|||
alloc_fail:
|
||||
if (vmem)
|
||||
vfree(vmem);
|
||||
if (txbuf)
|
||||
vfree(txbuf);
|
||||
if (buf)
|
||||
vfree(buf);
|
||||
kfree(fbops);
|
||||
|
|
@ -841,8 +849,12 @@ void fbtft_framebuffer_release(struct fb_info *info)
|
|||
|
||||
fb_deferred_io_cleanup(info);
|
||||
vfree(info->screen_base);
|
||||
if (par->txbuf.buf)
|
||||
vfree(par->txbuf.buf);
|
||||
if (par->txbuf.buf) {
|
||||
if (par->txbuf.dma)
|
||||
dma_free_coherent(info->device, par->txbuf.len, par->txbuf.buf, par->txbuf.dma);
|
||||
else
|
||||
vfree(par->txbuf.buf);
|
||||
}
|
||||
vfree(par->buf);
|
||||
kfree(info->fbops);
|
||||
kfree(info->fbdefio);
|
||||
|
|
@ -921,7 +933,8 @@ int fbtft_register_framebuffer(struct fb_info *fb_info)
|
|||
fbtft_sysfs_init(par);
|
||||
|
||||
if (par->txbuf.buf)
|
||||
sprintf(text1, ", %d KiB buffer memory", par->txbuf.len >> 10);
|
||||
sprintf(text1, ", %d KiB %sbuffer memory",
|
||||
par->txbuf.len >> 10, par->txbuf.dma ? "DMA " : "");
|
||||
if (spi)
|
||||
sprintf(text2, ", spi%d.%d at %d MHz", spi->master->bus_num,
|
||||
spi->chip_select, spi->max_speed_hz/1000000);
|
||||
|
|
|
|||
15
fbtft-io.c
15
fbtft-io.c
|
|
@ -9,6 +9,12 @@
|
|||
|
||||
int fbtft_write_spi(struct fbtft_par *par, void *buf, size_t len)
|
||||
{
|
||||
struct spi_transfer t = {
|
||||
.tx_buf = buf,
|
||||
.len = len,
|
||||
};
|
||||
struct spi_message m;
|
||||
|
||||
fbtft_par_dbg_hex(DEBUG_WRITE, par, par->info->device, u8, buf, len,
|
||||
"%s(len=%d): ", __func__, len);
|
||||
|
||||
|
|
@ -17,7 +23,14 @@ int fbtft_write_spi(struct fbtft_par *par, void *buf, size_t len)
|
|||
"%s: par->spi is unexpectedly NULL\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
return spi_write(par->spi, buf, len);
|
||||
|
||||
spi_message_init(&m);
|
||||
if (par->txbuf.dma && buf == par->txbuf.buf) {
|
||||
t.tx_dma = par->txbuf.dma;
|
||||
m.is_dma_mapped = 1;
|
||||
}
|
||||
spi_message_add_tail(&t, &m);
|
||||
return spi_sync(par->spi, &m);
|
||||
}
|
||||
EXPORT_SYMBOL(fbtft_write_spi);
|
||||
|
||||
|
|
|
|||
1
fbtft.h
1
fbtft.h
|
|
@ -219,6 +219,7 @@ struct fbtft_par {
|
|||
u32 pseudo_palette[16];
|
||||
struct {
|
||||
void *buf;
|
||||
dma_addr_t dma;
|
||||
size_t len;
|
||||
} txbuf;
|
||||
u8 *buf;
|
||||
|
|
|
|||
Loading…
Reference in a new issue