diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2005-05-01 08:59:22 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-05-01 08:59:22 -0700 |
commit | 7149437669f79b497830e643a2b13d26a017b038 (patch) | |
tree | f5df8234c2e3cca1a335cf64b9f387c98c123fcf /drivers/video/fbcmap.c | |
parent | 5b052d8bb3ad9108489e7475868e14372774ca08 (diff) |
[PATCH] fbdev: Batch cmap changes at driver level
This patch adds to the fbdev interface a set_cmap callback that allow the
driver to "batch" palette changes. This is useful for drivers like
radeonfb which might require lenghtly workarounds on palette accesses, thus
allowing to factor out those workarounds efficiently.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/video/fbcmap.c')
-rw-r--r-- | drivers/video/fbcmap.c | 32 |
1 files changed, 30 insertions, 2 deletions
diff --git a/drivers/video/fbcmap.c b/drivers/video/fbcmap.c index c51f8fb5c1de..4e5ce8f7d65e 100644 --- a/drivers/video/fbcmap.c +++ b/drivers/video/fbcmap.c @@ -222,8 +222,11 @@ int fb_set_cmap(struct fb_cmap *cmap, struct fb_info *info) transp = cmap->transp; start = cmap->start; - if (start < 0 || !info->fbops->fb_setcolreg) + if (start < 0 || (!info->fbops->fb_setcolreg && + !info->fbops->fb_setcmap)) return -EINVAL; + if (info->fbops->fb_setcmap) + return info->fbops->fb_setcmap(cmap, info); for (i = 0; i < cmap->len; i++) { hred = *red++; hgreen = *green++; @@ -250,8 +253,33 @@ int fb_set_user_cmap(struct fb_cmap_user *cmap, struct fb_info *info) transp = cmap->transp; start = cmap->start; - if (start < 0 || !info->fbops->fb_setcolreg) + if (start < 0 || (!info->fbops->fb_setcolreg && + !info->fbops->fb_setcmap)) return -EINVAL; + + /* If we can batch, do it */ + if (info->fbops->fb_setcmap && cmap->len > 1) { + struct fb_cmap umap; + int size = cmap->len * sizeof(u16); + int rc; + + memset(&umap, 0, sizeof(struct fb_cmap)); + rc = fb_alloc_cmap(&umap, cmap->len, transp != NULL); + if (rc) + return rc; + if (copy_from_user(umap.red, red, size) || + copy_from_user(umap.green, green, size) || + copy_from_user(umap.blue, blue, size) || + (transp && copy_from_user(umap.transp, transp, size))) { + rc = -EFAULT; + } + umap.start = start; + if (rc == 0) + rc = info->fbops->fb_setcmap(&umap, info); + fb_dealloc_cmap(&umap); + return rc; + } + for (i = 0; i < cmap->len; i++, red++, blue++, green++) { if (get_user(hred, red) || get_user(hgreen, green) || |