summaryrefslogtreecommitdiff
path: root/drivers/video/fbdev/metronomefb.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/fbdev/metronomefb.c')
-rw-r--r--drivers/video/fbdev/metronomefb.c121
1 files changed, 32 insertions, 89 deletions
diff --git a/drivers/video/fbdev/metronomefb.c b/drivers/video/fbdev/metronomefb.c
index bb4fee52e501..6f0942c6e5f1 100644
--- a/drivers/video/fbdev/metronomefb.c
+++ b/drivers/video/fbdev/metronomefb.c
@@ -10,7 +10,7 @@
* Layout is based on skeletonfb.c by James Simmons and Geert Uytterhoeven.
*
* This work was made possible by help and equipment support from E-Ink
- * Corporation. http://www.eink.com/
+ * Corporation. https://www.eink.com/
*
* This driver is written to be used with the Metronome display controller.
* It is intended to be architecture independent. A board specific driver
@@ -37,7 +37,7 @@
#include <video/metronomefb.h>
-#include <asm/unaligned.h>
+#include <linux/unaligned.h>
/* Display specific information */
#define DPY_W 832
@@ -181,7 +181,7 @@ static int load_waveform(u8 *mem, size_t size, int m, int t,
int mem_idx = 0;
struct waveform_hdr *wfm_hdr;
u8 *metromem = par->metromem_wfm;
- struct device *dev = par->info->dev;
+ struct device *dev = par->info->device;
if (user_wfm_size)
epd_frame_table[par->dt].wfm_size = user_wfm_size;
@@ -438,7 +438,7 @@ static void metronomefb_dpy_update(struct metronomefb_par *par)
{
int fbsize;
u16 cksum;
- unsigned char *buf = (unsigned char __force *)par->info->screen_base;
+ unsigned char *buf = par->info->screen_buffer;
fbsize = par->info->fix.smem_len;
/* copy from vm to metromem */
@@ -453,7 +453,7 @@ static u16 metronomefb_dpy_update_page(struct metronomefb_par *par, int index)
{
int i;
u16 csum = 0;
- u16 *buf = (u16 __force *)(par->info->screen_base + index);
+ u16 *buf = (u16 *)(par->info->screen_buffer + index);
u16 *img = (u16 *)(par->metromem_img + index);
/* swizzle from vm to metromem and recalc cksum at the same time*/
@@ -465,110 +465,52 @@ static u16 metronomefb_dpy_update_page(struct metronomefb_par *par, int index)
}
/* this is called back from the deferred io workqueue */
-static void metronomefb_dpy_deferred_io(struct fb_info *info,
- struct list_head *pagelist)
+static void metronomefb_dpy_deferred_io(struct fb_info *info, struct list_head *pagereflist)
{
u16 cksum;
- struct page *cur;
- struct fb_deferred_io *fbdefio = info->fbdefio;
+ struct fb_deferred_io_pageref *pageref;
struct metronomefb_par *par = info->par;
/* walk the written page list and swizzle the data */
- list_for_each_entry(cur, &fbdefio->pagelist, lru) {
- cksum = metronomefb_dpy_update_page(par,
- (cur->index << PAGE_SHIFT));
- par->metromem_img_csum -= par->csum_table[cur->index];
- par->csum_table[cur->index] = cksum;
+ list_for_each_entry(pageref, pagereflist, list) {
+ unsigned long pgoffset = pageref->offset >> PAGE_SHIFT;
+ cksum = metronomefb_dpy_update_page(par, pageref->offset);
+ par->metromem_img_csum -= par->csum_table[pgoffset];
+ par->csum_table[pgoffset] = cksum;
par->metromem_img_csum += cksum;
}
metronome_display_cmd(par);
}
-static void metronomefb_fillrect(struct fb_info *info,
- const struct fb_fillrect *rect)
+static void metronomefb_defio_damage_range(struct fb_info *info, off_t off, size_t len)
{
struct metronomefb_par *par = info->par;
- sys_fillrect(info, rect);
metronomefb_dpy_update(par);
}
-static void metronomefb_copyarea(struct fb_info *info,
- const struct fb_copyarea *area)
+static void metronomefb_defio_damage_area(struct fb_info *info, u32 x, u32 y,
+ u32 width, u32 height)
{
struct metronomefb_par *par = info->par;
- sys_copyarea(info, area);
metronomefb_dpy_update(par);
}
-static void metronomefb_imageblit(struct fb_info *info,
- const struct fb_image *image)
-{
- struct metronomefb_par *par = info->par;
-
- sys_imageblit(info, image);
- metronomefb_dpy_update(par);
-}
-
-/*
- * this is the slow path from userspace. they can seek and write to
- * the fb. it is based on fb_sys_write
- */
-static ssize_t metronomefb_write(struct fb_info *info, const char __user *buf,
- size_t count, loff_t *ppos)
-{
- struct metronomefb_par *par = info->par;
- unsigned long p = *ppos;
- void *dst;
- int err = 0;
- unsigned long total_size;
-
- if (info->state != FBINFO_STATE_RUNNING)
- return -EPERM;
+FB_GEN_DEFAULT_DEFERRED_SYSMEM_OPS(metronomefb,
+ metronomefb_defio_damage_range,
+ metronomefb_defio_damage_area)
- total_size = info->fix.smem_len;
-
- if (p > total_size)
- return -EFBIG;
-
- if (count > total_size) {
- err = -EFBIG;
- count = total_size;
- }
-
- if (count + p > total_size) {
- if (!err)
- err = -ENOSPC;
-
- count = total_size - p;
- }
-
- dst = (void __force *)(info->screen_base + p);
-
- if (copy_from_user(dst, buf, count))
- err = -EFAULT;
-
- if (!err)
- *ppos += count;
-
- metronomefb_dpy_update(par);
-
- return (err) ? err : count;
-}
-
-static struct fb_ops metronomefb_ops = {
- .owner = THIS_MODULE,
- .fb_write = metronomefb_write,
- .fb_fillrect = metronomefb_fillrect,
- .fb_copyarea = metronomefb_copyarea,
- .fb_imageblit = metronomefb_imageblit,
+static const struct fb_ops metronomefb_ops = {
+ .owner = THIS_MODULE,
+ FB_DEFAULT_DEFERRED_OPS(metronomefb),
};
static struct fb_deferred_io metronomefb_defio = {
- .delay = HZ,
- .deferred_io = metronomefb_dpy_deferred_io,
+ .delay = HZ,
+ .sort_pagereflist = true,
+ .deferred_io = metronomefb_dpy_deferred_io,
};
static int metronomefb_probe(struct platform_device *dev)
@@ -599,7 +541,7 @@ static int metronomefb_probe(struct platform_device *dev)
goto err;
/* we have two blocks of memory.
- info->screen_base which is vm, and is the fb used by apps.
+ info->screen_buffer which is vm, and is the fb used by apps.
par->metromem which is physically contiguous memory and
contains the display controller commands, waveform,
processed image data and padding. this is the data pulled
@@ -634,7 +576,7 @@ static int metronomefb_probe(struct platform_device *dev)
if (!videomemory)
goto err_fb_rel;
- info->screen_base = (char __force __iomem *)videomemory;
+ info->screen_buffer = videomemory;
info->fbops = &metronomefb_ops;
metronomefb_fix.line_length = fw;
@@ -700,7 +642,7 @@ static int metronomefb_probe(struct platform_device *dev)
if (retval < 0)
goto err_free_irq;
- info->flags = FBINFO_FLAG_DEFAULT | FBINFO_VIRTFB;
+ info->flags = FBINFO_VIRTFB;
info->fbdefio = &metronomefb_defio;
fb_deferred_io_init(info);
@@ -744,7 +686,7 @@ err:
return retval;
}
-static int metronomefb_remove(struct platform_device *dev)
+static void metronomefb_remove(struct platform_device *dev)
{
struct fb_info *info = platform_get_drvdata(dev);
@@ -756,17 +698,16 @@ static int metronomefb_remove(struct platform_device *dev)
fb_dealloc_cmap(&info->cmap);
par->board->cleanup(par);
vfree(par->csum_table);
- vfree((void __force *)info->screen_base);
+ vfree(info->screen_buffer);
module_put(par->board->owner);
dev_dbg(&dev->dev, "calling release\n");
framebuffer_release(info);
}
- return 0;
}
static struct platform_driver metronomefb_driver = {
.probe = metronomefb_probe,
- .remove = metronomefb_remove,
+ .remove = metronomefb_remove,
.driver = {
.name = "metronomefb",
},
@@ -779,3 +720,5 @@ MODULE_PARM_DESC(user_wfm_size, "Set custom waveform size");
MODULE_DESCRIPTION("fbdev driver for Metronome controller");
MODULE_AUTHOR("Jaya Kumar");
MODULE_LICENSE("GPL");
+
+MODULE_FIRMWARE("metronome.wbf");