Permalink
Browse files

fbtft: experimental DMA support

A DMA capable SPI master driver is needed to use DMA.

Tested-by: Derek Campbell
  • Loading branch information...
1 parent 49d03f9 commit 2c721932aa314e5119f07f63ffb78834344d5693 @notro committed Sep 10, 2013
Showing with 34 additions and 7 deletions.
  1. +19 −6 fbtft-core.c
  2. +14 −1 fbtft-io.c
  3. +1 −0 fbtft.h
View
@@ -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);
View
@@ -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);
View
@@ -219,6 +219,7 @@ struct fbtft_par {
u32 pseudo_palette[16];
struct {
void *buf;
+ dma_addr_t dma;
size_t len;
} txbuf;
u8 *buf;

0 comments on commit 2c72193

Please sign in to comment.