* Re: [PATCH] video: Add GRVGA framebuffer device driver
From: Konrad Rzeszutek Wilk @ 2011-06-15 14:56 UTC (permalink / raw)
To: linux-fbdev
In-Reply-To: <1308128180-14645-1-git-send-email-kristoffer@gaisler.com>
On Wed, Jun 15, 2011 at 10:56:20AM +0200, Kristoffer Glembo wrote:
> This patch adds support for the GRVGA framebuffer IP core from Aeroflex Gaisler.
> The device is used in LEON SPARCV8 based System on Chips. Documentation can
> be found here: www.gaisler.com/products/grlib/grip.pdf.
See comments below.
>
> Signed-off-by: Kristoffer Glembo <kristoffer@gaisler.com>
> ---
> drivers/video/Kconfig | 10 +
> drivers/video/Makefile | 1 +
> drivers/video/grvga.c | 559 ++++++++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 570 insertions(+), 0 deletions(-)
> create mode 100644 drivers/video/grvga.c
>
> diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
> index 549b960..18ee201 100644
> --- a/drivers/video/Kconfig
> +++ b/drivers/video/Kconfig
> @@ -259,6 +259,16 @@ config FB_TILEBLITTING
> comment "Frame buffer hardware drivers"
> depends on FB
>
> +config FB_GRVGA
> + tristate "Aeroflex Gaisler framebuffer support"
> + depends on FB && SPARC
> + select FB_CFB_FILLRECT
> + select FB_CFB_COPYAREA
> + select FB_CFB_IMAGEBLIT
> + ---help---
> + This enables support for the SVGACTRL framebuffer in the GRLIB IP library from Aeroflex Gaisler.
> +
> +
> config FB_CIRRUS
> tristate "Cirrus Logic support"
> depends on FB && (ZORRO || PCI)
> diff --git a/drivers/video/Makefile b/drivers/video/Makefile
> index 8b83129..4cff5ec 100644
> --- a/drivers/video/Makefile
> +++ b/drivers/video/Makefile
> @@ -29,6 +29,7 @@ obj-$(CONFIG_FB_DEFERRED_IO) += fb_defio.o
> obj-$(CONFIG_FB_WMT_GE_ROPS) += wmt_ge_rops.o
>
> # Hardware specific drivers go first
> +obj-$(CONFIG_FB_GRVGA) += grvga.o
> obj-$(CONFIG_FB_AMIGA) += amifb.o c2p_planar.o
> obj-$(CONFIG_FB_ARC) += arcfb.o
> obj-$(CONFIG_FB_CLPS711X) += clps711xfb.o
> diff --git a/drivers/video/grvga.c b/drivers/video/grvga.c
> new file mode 100644
> index 0000000..e1514f9
> --- /dev/null
> +++ b/drivers/video/grvga.c
> @@ -0,0 +1,559 @@
> +/*
> + * Driver for Aeroflex Gaisler SVGACTRL framebuffer device.
> + *
> + * 2011 (c) Aeroflex Gaisler AB
> + *
> + * Full documentation of the core can be found here:
> + * http://www.gaisler.com/products/grlib/grip.pdf
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License as published by the
> + * Free Software Foundation; either version 2 of the License, or (at your
> + * option) any later version.
> + *
> + * Contributors: Kristoffer Glembo <kristoffer@gaisler.com>
> + *
> + */
> +
> +#include <linux/platform_device.h>
> +#include <linux/of_platform.h>
> +#include <linux/of_device.h>
> +#include <linux/module.h>
> +#include <linux/kernel.h>
> +#include <linux/string.h>
> +#include <linux/delay.h>
> +#include <linux/errno.h>
> +#include <linux/init.h>
> +#include <linux/slab.h>
> +#include <linux/tty.h>
> +#include <linux/mm.h>
> +#include <linux/fb.h>
> +#include <linux/io.h>
> +
> +#define GRVGA_REGLOAD(a) (__raw_readl(&(a)))
> +#define GRVGA_REGSAVE(a, v) (__raw_writel(v, &(a)))
writel?
> +#define GRVGA_REGORIN(a, v) (GRVGA_REGSAVE(a, (GRVGA_REGLOAD(a) | (v))))
> +#define GRVGA_REGANDIN(a, v) (GRVGA_REGSAVE(a, (GRVGA_REGLOAD(a) & (v))))
> +
> +#define GRVGA_FBINFO_DEFAULT (FBINFO_DEFAULT \
> + | FBINFO_PARTIAL_PAN_OK \
> + | FBINFO_HWACCEL_YPAN)
> +
> +struct grvga_regs {
> + u32 status; /* 0x00 */
> + u32 video_length; /* 0x04 */
> + u32 front_porch; /* 0x08 */
> + u32 sync_length; /* 0x0C */
> + u32 line_length; /* 0x10 */
> + u32 fb_pos; /* 0x14 */
> + u32 clk_vector[4]; /* 0x18 */
> + u32 clut; /* 0x20 */
> +};
Would it make sense to add __packed__ here? It seems that you
really depend on this ordering.
> +
> +struct grvga_par {
> + struct grvga_regs *regs;
> + u32 color_palette[16]; /* 16 entry pseudo palette used by fbcon in true color mode */
> + int clk_sel;
> +};
> +
> +
> +static const struct fb_videomode grvga_modedb[] = {
> + {
> + /* 640x480 @ 60 Hz */
> + NULL, 60, 640, 480, 40000, 48, 16, 39, 11, 96, 2,
> + 0, FB_VMODE_NONINTERLACED
> + }, {
> + /* 800x600 @ 60 Hz */
> + NULL, 60, 800, 600, 25000, 88, 40, 23, 1, 128, 4,
> + 0, FB_VMODE_NONINTERLACED
> + }, {
> + /* 800x600 @ 72 Hz */
> + NULL, 72, 800, 600, 20000, 64, 56, 23, 37, 120, 6,
> + 0, FB_VMODE_NONINTERLACED
> + }, {
> + /* 1024x768 @ 60 Hz */
> + NULL, 60, 1024, 768, 15385, 160, 24, 29, 3, 136, 6,
> + 0, FB_VMODE_NONINTERLACED
> + }
> + };
> +
> +static struct fb_fix_screeninfo grvga_fix __initdata = {
> + .id = "AG SVGACTRL",
> + .type = FB_TYPE_PACKED_PIXELS,
> + .visual = FB_VISUAL_PSEUDOCOLOR,
> + .xpanstep = 0,
> + .ypanstep = 1,
> + .ywrapstep = 0,
> + .accel = FB_ACCEL_NONE,
> +};
> +
> +
> +static int grvga_check_var(struct fb_var_screeninfo *var,
> + struct fb_info *info);
> +static int grvga_set_par(struct fb_info *info);
> +static int grvga_setcolreg(unsigned regno,
> + unsigned red, unsigned green, unsigned blue, unsigned transp,
> + struct fb_info *info);
> +static int grvga_pan_display(struct fb_var_screeninfo *var, struct fb_info *info);
> +
> +static struct fb_ops grvga_ops = {
> + .owner = THIS_MODULE,
> + .fb_check_var = grvga_check_var,
> + .fb_set_par = grvga_set_par,
> + .fb_setcolreg = grvga_setcolreg,
> + .fb_pan_display = grvga_pan_display,
> + .fb_fillrect = cfb_fillrect,
> + .fb_copyarea = cfb_copyarea,
> + .fb_imageblit = cfb_imageblit
> +};
Could you move this struct down and remove the declarations earlier?
> +
> +static int grvga_check_var(struct fb_var_screeninfo *var,
> + struct fb_info *info)
> +{
> + struct grvga_par *par = info->par;
> + int i;
> +
> + if (!var->xres)
> + var->xres = 1;
> + if (!var->yres)
> + var->yres = 1;
> + if (var->bits_per_pixel <= 8)
> + var->bits_per_pixel = 8;
> + else if (var->bits_per_pixel <= 16)
> + var->bits_per_pixel = 16;
> + else if (var->bits_per_pixel <= 24)
> + var->bits_per_pixel = 24;
> + else if (var->bits_per_pixel <= 32)
> + var->bits_per_pixel = 32;
> + else
> + return -EINVAL;
> +
> + var->xres_virtual = var->xres;
> + var->yres_virtual = 2*var->yres;
> +
> + if (info->fix.smem_len) {
> + if ((var->yres_virtual*var->xres_virtual*var->bits_per_pixel/8) > info->fix.smem_len)
> + return -ENOMEM;
> + }
> +
> + /* Which clocks that are available can be read out in these registers */
> + for (i = 0; i <= 3 ; i++) {
> + if (var->pixclock = par->regs->clk_vector[i])
> + break;
> + }
> + if (i != -1)
> + par->clk_sel = i;
How would i possibly become -1?
> + else
> + return -EINVAL;
> +
> + switch (info->var.bits_per_pixel) {
> + case 8:
> + var->red = (struct fb_bitfield) {0, 8, 0}; /* offset, length, msb-right */
> + var->green = (struct fb_bitfield) {0, 8, 0};
> + var->blue = (struct fb_bitfield) {0, 8, 0};
> + var->transp = (struct fb_bitfield) {0, 0, 0};
> + break;
> + case 16:
> + var->red = (struct fb_bitfield) {11, 5, 0};
> + var->green = (struct fb_bitfield) {5, 6, 0};
> + var->blue = (struct fb_bitfield) {0, 5, 0};
> + var->transp = (struct fb_bitfield) {0, 0, 0};
> + break;
> + case 24:
> + case 32:
> + var->red = (struct fb_bitfield) {16, 8, 0};
> + var->green = (struct fb_bitfield) {8, 8, 0};
> + var->blue = (struct fb_bitfield) {0, 8, 0};
> + var->transp = (struct fb_bitfield) {24, 8, 0};
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + return 0;
> +}
> +
> +static int grvga_set_par(struct fb_info *info)
> +{
> +
> + int func = 0;
You probably want that to be u32.
> + struct grvga_par *par = info->par;
> +
> + GRVGA_REGSAVE(par->regs->video_length,
> + ((info->var.yres - 1) << 16) | (info->var.xres - 1));
> + GRVGA_REGSAVE(par->regs->front_porch,
> + (info->var.lower_margin << 16) | (info->var.right_margin));
> + GRVGA_REGSAVE(par->regs->sync_length,
> + (info->var.vsync_len << 16) | (info->var.hsync_len));
> + GRVGA_REGSAVE(par->regs->line_length,
> + ((info->var.yres + info->var.lower_margin + info->var.upper_margin + info->var.vsync_len - 1) << 16) |
> + (info->var.xres + info->var.right_margin + info->var.left_margin + info->var.hsync_len - 1));
> +
> + switch (info->var.bits_per_pixel) {
> + case 8:
> + info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
> + func = 1;
> + break;
> + case 16:
> + info->fix.visual = FB_VISUAL_TRUECOLOR;
> + func = 2;
> + break;
> + case 24:
> + case 32:
> + info->fix.visual = FB_VISUAL_TRUECOLOR;
> + func = 3;
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + GRVGA_REGSAVE(par->regs->status, ((par->clk_sel << 6) | (func << 4)) | 1);
Just in case in the future you modify the code and bitshift func more than you thought
and end up with a signed value in an unsigned register.
> +
> + info->fix.line_length = (info->var.xres_virtual*info->var.bits_per_pixel)/8;
> + return 0;
> +}
> +
> +static int grvga_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *info)
> +{
> + struct grvga_par *par;
> + par = info->par;
> +
> + if (regno >= 256) /* Size of CLUT */
> + return -EINVAL;
> +
> + if (info->var.grayscale) {
> + /* grayscale = 0.30*R + 0.59*G + 0.11*B */
> + red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
> + }
> +
> +
> +
> +#define CNVT_TOHW(val, width) ((((val)<<(width))+0x7FFF-(val))>>16)
> +
> + red = CNVT_TOHW(red, info->var.red.length);
> + green = CNVT_TOHW(green, info->var.green.length);
> + blue = CNVT_TOHW(blue, info->var.blue.length);
> + transp = CNVT_TOHW(transp, info->var.transp.length);
> +
> +#undef CNVT_TOHW
> +
> + /* In PSEUDOCOLOR we use the hardware CLUT */
> + if (info->fix.visual = FB_VISUAL_PSEUDOCOLOR)
> + GRVGA_REGSAVE(par->regs->clut,
> + (regno << 24) | (red << 16) | (green << 8) | blue);
> +
> + /* Truecolor uses the pseudo palette */
> + else if (info->fix.visual = FB_VISUAL_TRUECOLOR) {
> + u32 v;
> + if (regno >= 16)
> + return -EINVAL;
> +
> +
> + v = (red << info->var.red.offset) |
> + (green << info->var.green.offset) |
> + (blue << info->var.blue.offset) |
> + (transp << info->var.transp.offset);
> +
> + ((u32 *) (info->pseudo_palette))[regno] = v;
> + }
> + return 0;
> +}
> +
> +static int grvga_pan_display(struct fb_var_screeninfo *var,
> + struct fb_info *info)
> +{
> + struct grvga_par *par = info->par;
> + struct fb_fix_screeninfo *fix = &info->fix;
> + u32 base_addr;
> +
> + if (var->xoffset != 0)
> + return -EINVAL;
> +
> + base_addr = fix->smem_start + (var->yoffset * fix->line_length);
> + base_addr &= ~3UL;
> +
> + /* Set framebuffer base address */
> + GRVGA_REGSAVE(par->regs->fb_pos, base_addr);
> +
> + return 0;
> +}
> +
> +static int __init grvga_parse_custom(char *options,
> + struct fb_var_screeninfo *screendata)
> +{
> + char *this_opt;
> + int count = 0;
> + if (!options || !*options)
> + return -1;
> +
> + while ((this_opt = strsep(&options, " ")) != NULL) {
> + if (!*this_opt)
> + continue;
> +
> + switch (count) {
> + case 0:
> + screendata->pixclock = simple_strtoul(this_opt, NULL, 0);
> + count++;
> + break;
> + case 1:
> + screendata->xres = screendata->xres_virtual = simple_strtoul(this_opt, NULL, 0);
> + count++;
> + break;
> + case 2:
> + screendata->right_margin = simple_strtoul(this_opt, NULL, 0);
> + count++;
> + break;
> + case 3:
> + screendata->hsync_len = simple_strtoul(this_opt, NULL, 0);
> + count++;
> + break;
> + case 4:
> + screendata->left_margin = simple_strtoul(this_opt, NULL, 0);
> + count++;
> + break;
> + case 5:
> + screendata->yres = screendata->yres_virtual = simple_strtoul(this_opt, NULL, 0);
> + count++;
> + break;
> + case 6:
> + screendata->lower_margin = simple_strtoul(this_opt, NULL, 0);
> + count++;
> + break;
> + case 7:
> + screendata->vsync_len = simple_strtoul(this_opt, NULL, 0);
> + count++;
> + break;
> + case 8:
> + screendata->upper_margin = simple_strtoul(this_opt, NULL, 0);
> + count++;
> + break;
> + case 9:
> + screendata->bits_per_pixel = simple_strtoul(this_opt, NULL, 0);
> + count++;
> + break;
No default case?
> + }
> + }
> + screendata->activate = FB_ACTIVATE_NOW;
> + screendata->vmode = FB_VMODE_NONINTERLACED;
> + return 0;
> +}
> +
> +static int __devinit grvga_probe(struct platform_device *dev)
> +{
> + struct fb_info *info;
> + int retval = -ENOMEM;
> + unsigned long virtual_start;
> + unsigned long grvga_fix_addr = 0;
> + unsigned long physical_start = 0;
> + unsigned long grvga_mem_size = 0;
> + struct grvga_par *par;
> + char *options = NULL, *mode_opt = NULL;
> +
> + info = framebuffer_alloc(sizeof(struct grvga_par), &dev->dev);
> + if (!info) {
> + dev_err(&dev->dev, "framebuffer_alloc failed\n");
> + return -ENOMEM;
> + }
> +
> + /* Expecting: "grvga: modestring, [addr:<framebuffer physical address>], [size:<framebuffer size>]
> + *
> + * If modestring is custom:<custom mode string> we parse the string which then contains all videoparameters
> + * If address is left out, we allocate memory,
> + * if size is left out we only allocate enough to support the given mode.
> + */
> + if (fb_get_options("grvga", &options)) {
> + retval = -ENODEV;
> + goto err;
> + }
> +
> + if (!options || !*options)
> + options = "640x480-8@60";
> +
> + while (1) {
> + char *this_opt = strsep(&options, ",");
> +
> + if (!this_opt)
> + break;
> +
> + if (!strncmp(this_opt, "custom", 6))
> + grvga_parse_custom(this_opt, &info->var);
> + else if (!strncmp(this_opt, "addr:", 5))
> + grvga_fix_addr = simple_strtoul(this_opt + 5, NULL, 16);
> + else if (!strncmp(this_opt, "size:", 5))
> + grvga_mem_size = simple_strtoul(this_opt + 5, NULL, 0);
> + else
> + mode_opt = this_opt;
> + }
> +
> + par = info->par;
> + info->fbops = &grvga_ops;
> + info->fix = grvga_fix;
> + info->pseudo_palette = par->color_palette;
> + info->flags = GRVGA_FBINFO_DEFAULT;
> + info->fix.smem_len = grvga_mem_size;
> +
> + par->regs = of_ioremap(&dev->resource[0], 0,
> + resource_size(&dev->resource[0]),
> + "grlib-svgactrl regs");
> +
> + retval = fb_alloc_cmap(&info->cmap, 256, 0);
> + if (retval < 0) {
> + dev_err(&dev->dev, "failed to allocate mem with fb_alloc_cmap\n");
> + retval = -ENOMEM;
> + goto err1;
> + }
> +
> + if (mode_opt) {
> + retval = fb_find_mode(&info->var, info, mode_opt,
> + grvga_modedb, sizeof(grvga_modedb), &grvga_modedb[0], 8);
> + if (!retval || retval = 4) {
> + retval = -EINVAL;
> + goto err2;
> + }
> + }
> +
> + if (!grvga_mem_size)
> + grvga_mem_size = info->var.xres_virtual * info->var.yres_virtual * info->var.bits_per_pixel/8;
Should you update the info->fix.smem_len ?
> +
> + if (grvga_fix_addr) {
> + /* Got framebuffer base address from argument list */
> +
> + physical_start = grvga_fix_addr;
> +
> + if (!request_mem_region(physical_start, grvga_mem_size, dev->name)) {
> + dev_err(&dev->dev, "request mem region failed\n");
requested..
> + retval = -ENOMEM;
> + goto err2;
> + }
> +
> + virtual_start = (unsigned long) ioremap(physical_start, grvga_mem_size);
> +
> + if (!virtual_start) {
> + dev_err(&dev->dev, "error mapping memory\n");
> + retval = -ENOMEM;
> + goto err3;
> + }
> + } else { /* Allocate frambuffer memory */
> +
> + unsigned long page;
> +
> + virtual_start = (unsigned long) __get_free_pages(GFP_ATOMIC | GFP_DMA,
> + get_order(grvga_mem_size));
> + if (!virtual_start) {
> + dev_err(&dev->dev,
> + "unable to allocate framebuffer memory (%lu bytes)\n",
> + grvga_mem_size);
> + retval = -ENOMEM;
> + goto err2;
> + }
> +
> +
> + physical_start = __pa(virtual_start);
Yikes. That is one big assumption. You don't want to use the PCI/DMA API
to map it? I thought that on SPARCs the Bus addresses are different
from the physical addresses?
> +
> + /* Set page reserved so that mmap will work. This is necessary
> + * since we'll be remapping normal memory.
> + */
> + for (page = virtual_start;
> + page < PAGE_ALIGN(virtual_start + grvga_mem_size);
> + page += PAGE_SIZE) {
> + SetPageReserved(virt_to_page(page));
> + }
> + }
> +
> + memset((unsigned long *) virtual_start, 0, grvga_mem_size);
> +
> + info->screen_base = (char __iomem *) virtual_start;
> + info->fix.smem_start = physical_start;
> + info->fix.smem_len = grvga_mem_size;
Ah, you update it here. OK.
> +
> + dev_set_drvdata(&dev->dev, info);
> +
> + dev_info(&dev->dev,
> + "Aeroflex Gaisler framebuffer device (fb%d), %dx%d-%d, using %luK of video memory @ 0x%x\n",
> + info->node, info->var.xres, info->var.yres, info->var.bits_per_pixel,
> + grvga_mem_size >> 10, (unsigned int) info->screen_base);
> +
> + retval = register_framebuffer(info);
> + if (retval < 0) {
> + dev_err(&dev->dev, "failed to register framebuffer\n");
> + if (grvga_fix_addr)
> + goto err3;
> + else {
> + kfree((void *)virtual_start);
> + goto err2;
> + }
> + }
> +
> + GRVGA_REGSAVE(par->regs->fb_pos, physical_start);
> + GRVGA_REGORIN(par->regs->status, 1); /* Enable framebuffer */
> +
> + return 0;
> +
> +err3:
> + release_mem_region(physical_start, grvga_mem_size);
> +err2:
> + fb_dealloc_cmap(&info->cmap);
> +err1:
> + of_iounmap(&dev->resource[0], par->regs,
> + resource_size(&dev->resource[0]));
> +err:
> + framebuffer_release(info);
> +
> + return retval;
> +}
> +
> +static int __devexit grvga_remove(struct platform_device *device)
> +{
> + struct fb_info *info = dev_get_drvdata(&device->dev);
> + struct grvga_par *par = info->par;
> +
> + if (info) {
> + unregister_framebuffer(info);
> + fb_dealloc_cmap(&info->cmap);
> + of_iounmap(&device->resource[0], par->regs,
> + resource_size(&device->resource[0]));
> + framebuffer_release(info);
> + dev_set_drvdata(&device->dev, NULL);
Shouldn't that be much earlier? Like right after unregister_framebuffer?
> + }
> +
> + return 0;
> +}
> +
> +static struct of_device_id svgactrl_of_match[] = {
> + {
> + .name = "GAISLER_SVGACTRL",
> + },
> + {
> + .name = "01_063",
> + },
> + {},
> +};
> +MODULE_DEVICE_TABLE(of, svgactrl_of_match);
> +
> +static struct platform_driver grvga_driver = {
> + .driver = {
> + .name = "grlib-svgactrl",
> + .owner = THIS_MODULE,
> + .of_match_table = svgactrl_of_match,
> + },
> + .probe = grvga_probe,
> + .remove = __devexit_p(grvga_remove),
> +};
> +
> +
> +int __init grvga_init(void)
> +{
> + return platform_driver_register(&grvga_driver);
> +}
> +
> +static void __exit grvga_exit(void)
> +{
> + platform_driver_unregister(&grvga_driver);
> +}
> +
> +module_init(grvga_init);
> +module_exit(grvga_exit);
> +
> +MODULE_LICENSE("GPL");
> +MODULE_AUTHOR("Aeroflex Gaisler");
> +MODULE_DESCRIPTION("Aeroflex Gaisler framebuffer device driver");
> --
> 1.6.4.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH V2] video: Add GRVGA framebuffer device driver
From: Paul Mundt @ 2011-06-16 6:34 UTC (permalink / raw)
To: linux-fbdev
In-Reply-To: <1308139443-15661-1-git-send-email-kristoffer@gaisler.com>
On Wed, Jun 15, 2011 at 02:04:03PM +0200, Kristoffer Glembo wrote:
> +#define GRVGA_REGLOAD(a) (__raw_readl(&(a)))
> +#define GRVGA_REGSAVE(a, v) (__raw_writel(v, &(a)))
> +#define GRVGA_REGORIN(a, v) (GRVGA_REGSAVE(a, (GRVGA_REGLOAD(a) | (v))))
> +#define GRVGA_REGANDIN(a, v) (GRVGA_REGSAVE(a, (GRVGA_REGLOAD(a) & (v))))
> +
I would recommend just getting rid of these completely, they don't really
buy you much of anything, other than forcing people to scroll to the top
to figure out what exactly it's supposed to be doing.
> +#define GRVGA_FBINFO_DEFAULT (FBINFO_DEFAULT \
> + | FBINFO_PARTIAL_PAN_OK \
> + | FBINFO_HWACCEL_YPAN)
> +
Same with this.
> + switch (info->var.bits_per_pixel) {
> + case 8:
> + var->red = (struct fb_bitfield) {0, 8, 0}; /* offset, length, msb-right */
> + var->green = (struct fb_bitfield) {0, 8, 0};
> + var->blue = (struct fb_bitfield) {0, 8, 0};
> + var->transp = (struct fb_bitfield) {0, 0, 0};
> + break;
> + case 16:
> + var->red = (struct fb_bitfield) {11, 5, 0};
> + var->green = (struct fb_bitfield) {5, 6, 0};
> + var->blue = (struct fb_bitfield) {0, 5, 0};
> + var->transp = (struct fb_bitfield) {0, 0, 0};
> + break;
> + case 24:
> + case 32:
> + var->red = (struct fb_bitfield) {16, 8, 0};
> + var->green = (struct fb_bitfield) {8, 8, 0};
> + var->blue = (struct fb_bitfield) {0, 8, 0};
> + var->transp = (struct fb_bitfield) {24, 8, 0};
> + break;
This is also a bit unconventional. var should already be zeroed out, so
you can just establish the .length values for each one as necessary.
> +static int __init grvga_parse_custom(char *options,
> + struct fb_var_screeninfo *screendata)
> +{
> + char *this_opt;
> + int count = 0;
> + if (!options || !*options)
> + return -1;
> +
> + while ((this_opt = strsep(&options, " ")) != NULL) {
> + if (!*this_opt)
> + continue;
> +
> + switch (count) {
> + case 0:
> + screendata->pixclock = simple_strtoul(this_opt, NULL, 0);
> + count++;
> + break;
> + case 1:
> + screendata->xres = screendata->xres_virtual = simple_strtoul(this_opt, NULL, 0);
> + count++;
> + break;
If you have open firmware available then why do you have a need to have
this bizarre "custom" command line option for parsing all of the geometry
information?
> +static int __devinit grvga_probe(struct platform_device *dev)
> +{
> + struct fb_info *info;
> + int retval = -ENOMEM;
> + unsigned long virtual_start;
> + unsigned long grvga_fix_addr = 0;
> + unsigned long physical_start = 0;
> + unsigned long grvga_mem_size = 0;
> + struct grvga_par *par;
> + char *options = NULL, *mode_opt = NULL;
> +
> + info = framebuffer_alloc(sizeof(struct grvga_par), &dev->dev);
> + if (!info) {
> + dev_err(&dev->dev, "framebuffer_alloc failed\n");
> + return -ENOMEM;
> + }
> +
> + /* Expecting: "grvga: modestring, [addr:<framebuffer physical address>], [size:<framebuffer size>]
> + *
> + * If modestring is custom:<custom mode string> we parse the string which then contains all videoparameters
> + * If address is left out, we allocate memory,
> + * if size is left out we only allocate enough to support the given mode.
> + */
> + if (fb_get_options("grvga", &options)) {
> + retval = -ENODEV;
> + goto err;
> + }
> +
> + if (!options || !*options)
> + options = "640x480-8@60";
> +
> + while (1) {
> + char *this_opt = strsep(&options, ",");
> +
> + if (!this_opt)
> + break;
> +
> + if (!strncmp(this_opt, "custom", 6))
> + grvga_parse_custom(this_opt, &info->var);
> + else if (!strncmp(this_opt, "addr:", 5))
> + grvga_fix_addr = simple_strtoul(this_opt + 5, NULL, 16);
> + else if (!strncmp(this_opt, "size:", 5))
> + grvga_mem_size = simple_strtoul(this_opt + 5, NULL, 0);
> + else
> + mode_opt = this_opt;
> + }
> +
You would probably benefit from ripping all of this out and stashing it
in a grvga_setup() function.
> + par = info->par;
> + info->fbops = &grvga_ops;
> + info->fix = grvga_fix;
> + info->pseudo_palette = par->color_palette;
> + info->flags = GRVGA_FBINFO_DEFAULT;
> + info->fix.smem_len = grvga_mem_size;
> +
> + par->regs = of_ioremap(&dev->resource[0], 0,
> + resource_size(&dev->resource[0]),
> + "grlib-svgactrl regs");
> +
> + retval = fb_alloc_cmap(&info->cmap, 256, 0);
> + if (retval < 0) {
> + dev_err(&dev->dev, "failed to allocate mem with fb_alloc_cmap\n");
> + retval = -ENOMEM;
> + goto err1;
> + }
> +
Can of_ioremap() fail?
> + if (mode_opt) {
> + retval = fb_find_mode(&info->var, info, mode_opt,
> + grvga_modedb, sizeof(grvga_modedb), &grvga_modedb[0], 8);
> + if (!retval || retval = 4) {
> + retval = -EINVAL;
> + goto err2;
> + }
> + }
> +
> + if (!grvga_mem_size)
> + grvga_mem_size = info->var.xres_virtual * info->var.yres_virtual * info->var.bits_per_pixel/8;
> +
> + if (grvga_fix_addr) {
> + /* Got framebuffer base address from argument list */
> +
> + physical_start = grvga_fix_addr;
> +
> + if (!request_mem_region(physical_start, grvga_mem_size, dev->name)) {
> + dev_err(&dev->dev, "request mem region failed\n");
> + retval = -ENOMEM;
> + goto err2;
> + }
> +
> + virtual_start = (unsigned long) ioremap(physical_start, grvga_mem_size);
> +
> + if (!virtual_start) {
> + dev_err(&dev->dev, "error mapping memory\n");
> + retval = -ENOMEM;
> + goto err3;
> + }
> + } else { /* Allocate frambuffer memory */
> +
> + unsigned long page;
> +
> + virtual_start = (unsigned long) __get_free_pages(GFP_ATOMIC | GFP_DMA,
> + get_order(grvga_mem_size));
GFP_ATOMIC?
> + if (!virtual_start) {
> + dev_err(&dev->dev,
> + "unable to allocate framebuffer memory (%lu bytes)\n",
> + grvga_mem_size);
> + retval = -ENOMEM;
> + goto err2;
> + }
> +
> +
> + physical_start = __pa(virtual_start);
> +
> + /* Set page reserved so that mmap will work. This is necessary
> + * since we'll be remapping normal memory.
> + */
> + for (page = virtual_start;
> + page < PAGE_ALIGN(virtual_start + grvga_mem_size);
> + page += PAGE_SIZE) {
> + SetPageReserved(virt_to_page(page));
> + }
> + }
> +
This all looks like a good candidate for dma_alloc_coherent().
> +static int __devexit grvga_remove(struct platform_device *device)
> +{
> + struct fb_info *info = dev_get_drvdata(&device->dev);
> + struct grvga_par *par = info->par;
> +
> + if (info) {
> + unregister_framebuffer(info);
> + fb_dealloc_cmap(&info->cmap);
> + of_iounmap(&device->resource[0], par->regs,
> + resource_size(&device->resource[0]));
> + framebuffer_release(info);
> + dev_set_drvdata(&device->dev, NULL);
> + }
> +
You seem to be missing a release_mem_region() in here.
> + return 0;
> +}
> +
> +static struct of_device_id svgactrl_of_match[] = {
> + {
> + .name = "GAISLER_SVGACTRL",
> + },
> + {
> + .name = "01_063",
> + },
> + {},
> +};
> +MODULE_DEVICE_TABLE(of, svgactrl_of_match);
> +
> +static struct platform_driver grvga_driver = {
> + .driver = {
> + .name = "grlib-svgactrl",
> + .owner = THIS_MODULE,
> + .of_match_table = svgactrl_of_match,
> + },
> + .probe = grvga_probe,
> + .remove = __devexit_p(grvga_remove),
> +};
> +
> +
> +int __init grvga_init(void)
> +{
> + return platform_driver_register(&grvga_driver);
> +}
> +
static?
^ permalink raw reply
* [GIT PULL] fbdev fixes for 3.0-rc4
From: Paul Mundt @ 2011-06-16 6:53 UTC (permalink / raw)
To: Linus Torvalds; +Cc: linux-fbdev, linux-kernel
This is just a pretty straightforward set of fixes. It doesn't yet
address the console locking / suspend/resume issue as that's still
pending feedback.
Please pull from:
master.kernel.org:/pub/scm/linux/kernel/git/lethal/fbdev-3.x.git fbdev-fixes-for-linus
Which contains:
Geert Uytterhoeven (1):
fbdev/atyfb: Fix 2 defined-but-not-used warnings
Guennadi Liakhovetski (1):
fbdev: sh_mobile_hdmi: fix regression: statically enable RTPM
Jingoo Han (3):
video: s3c-fb: fix misleading kfree in remove function
video: s3c-fb: fix virtual resolution checking
video: s3c-fb: move enabling channel for window
Wanlong Gao (1):
efifb: Fix call to wrong unregister function
drivers/video/aty/atyfb_base.c | 10 ++++------
drivers/video/efifb.c | 2 +-
drivers/video/s3c-fb.c | 22 ++++++++++------------
drivers/video/sh_mobile_hdmi.c | 18 +++++-------------
4 files changed, 20 insertions(+), 32 deletions(-)
^ permalink raw reply
* Re: [PATCH] video: Add GRVGA framebuffer device driver
From: Kristoffer Glembo @ 2011-06-16 7:20 UTC (permalink / raw)
To: linux-fbdev
In-Reply-To: <1308128180-14645-1-git-send-email-kristoffer@gaisler.com>
Hi Konrad,
Konrad Rzeszutek Wilk wrote:
>> +#define GRVGA_REGLOAD(a) (__raw_readl(&(a)))
>> +#define GRVGA_REGSAVE(a, v) (__raw_writel(v, &(a)))
>
> writel?
>
I use __raw since I want native endianess. On a big endian system
writel/readl byte swap since they are for little endian (PCI).
>> +struct grvga_regs {
>> + u32 status; /* 0x00 */
>> + u32 video_length; /* 0x04 */
>> + u32 front_porch; /* 0x08 */
>> + u32 sync_length; /* 0x0C */
>> + u32 line_length; /* 0x10 */
>> + u32 fb_pos; /* 0x14 */
>> + u32 clk_vector[4]; /* 0x18 */
>> + u32 clut; /* 0x20 */
>> +};
>
> Would it make sense to add __packed__ here? It seems that you
> really depend on this ordering.
>
I depend on the ordering, but that is guaranteed by the compiler without __packed__.
Attribute __packed__ is dangerous here since it tells the compiler that it is ok
to do byte accesses.
>> +static struct fb_ops grvga_ops = {
>> + .owner = THIS_MODULE,
>> + .fb_check_var = grvga_check_var,
>> + .fb_set_par = grvga_set_par,
>> + .fb_setcolreg = grvga_setcolreg,
>> + .fb_pan_display = grvga_pan_display,
>> + .fb_fillrect = cfb_fillrect,
>> + .fb_copyarea = cfb_copyarea,
>> + .fb_imageblit = cfb_imageblit
>> +};
>
> Could you move this struct down and remove the declarations earlier?
Yes sure.
>> + }
>> + if (i != -1)
>> + par->clk_sel = i;
>
> How would i possibly become -1?
Refactoring error .. thanks!
>> +static int grvga_set_par(struct fb_info *info)
>> +{
>> +
>> + int func = 0;
>
> You probably want that to be u32.
Sure why not.
> No default case?
Will add ...
>> + physical_start = __pa(virtual_start);
>
> Yikes. That is one big assumption. You don't want to use the PCI/DMA API
> to map it? I thought that on SPARCs the Bus addresses are different
> from the physical addresses?
Yeah I should map it for cleanliness sake. It does not matter on this architecture (LEON) though.
>> +
>> + if (info) {
>> + unregister_framebuffer(info);
>> + fb_dealloc_cmap(&info->cmap);
>> + of_iounmap(&device->resource[0], par->regs,
>> + resource_size(&device->resource[0]));
>> + framebuffer_release(info);
>> + dev_set_drvdata(&device->dev, NULL);
>
> Shouldn't that be much earlier? Like right after unregister_framebuffer?
>
You mean I should set driver_data = NULL ASAP after unregistering the framebuffer?
Does it really matter? Please enlighten me.
Thanks a lot for your feedback.
Best regards,
Kristoffer Glembo
^ permalink raw reply
* Re: [PATCH V2] video: Add GRVGA framebuffer device driver
From: Kristoffer Glembo @ 2011-06-16 8:55 UTC (permalink / raw)
To: linux-fbdev
In-Reply-To: <1308139443-15661-1-git-send-email-kristoffer@gaisler.com>
Hi Paul,
Paul Mundt wrote:
> On Wed, Jun 15, 2011 at 02:04:03PM +0200, Kristoffer Glembo wrote:
>> +#define GRVGA_REGLOAD(a) (__raw_readl(&(a)))
>> +#define GRVGA_REGSAVE(a, v) (__raw_writel(v, &(a)))
>> +#define GRVGA_REGORIN(a, v) (GRVGA_REGSAVE(a, (GRVGA_REGLOAD(a) | (v))))
>> +#define GRVGA_REGANDIN(a, v) (GRVGA_REGSAVE(a, (GRVGA_REGLOAD(a) & (v))))
>> +
> I would recommend just getting rid of these completely, they don't really
> buy you much of anything, other than forcing people to scroll to the top
> to figure out what exactly it's supposed to be doing.
I find it quite convenient when doing a lot of register accesses and especially
a lot of ORing and ANDing (this driver is simple enough to not benefit a lot).
It also makes it very clear that we are accessing a register which I think is good.
Anyway, it should be readable to other people as well and since this driver is
so simple I can remove it.
>
>> +#define GRVGA_FBINFO_DEFAULT (FBINFO_DEFAULT \
>> + | FBINFO_PARTIAL_PAN_OK \
>> + | FBINFO_HWACCEL_YPAN)
>> +
> Same with this.
Ok.
>
>> + var->red = (struct fb_bitfield) {16, 8, 0};
>> + var->green = (struct fb_bitfield) {8, 8, 0};
>> + var->blue = (struct fb_bitfield) {0, 8, 0};
>> + var->transp = (struct fb_bitfield) {24, 8, 0};
>> + break;
>
> This is also a bit unconventional. var should already be zeroed out, so
> you can just establish the .length values for each one as necessary.
I think this looks better than setting length and offset for each one.
> If you have open firmware available then why do you have a need to have
> this bizarre "custom" command line option for parsing all of the geometry
> information?
Our OF typically only contains the address and interrupt of each device (it
is automatically generated in the boot loader from a ROM area in the chip).
> You would probably benefit from ripping all of this out and stashing it
> in a grvga_setup() function.
Ok.
>> + par->regs = of_ioremap(&dev->resource[0], 0,
>> + resource_size(&dev->resource[0]),
>> + "grlib-svgactrl regs");
>> +
>> + retval = fb_alloc_cmap(&info->cmap, 256, 0);
>> + if (retval < 0) {
>> + dev_err(&dev->dev, "failed to allocate mem with fb_alloc_cmap\n");
>> + retval = -ENOMEM;
>> + goto err1;
>> + }
>> +
> Can of_ioremap() fail?
I will add error checking.
>> +
>> + virtual_start = (unsigned long) __get_free_pages(GFP_ATOMIC | GFP_DMA,
>> + get_order(grvga_mem_size));
>
> GFP_ATOMIC?
Hmm yes that seems very unnecessary, will remove.
>> + physical_start = __pa(virtual_start);
>> +
>> + /* Set page reserved so that mmap will work. This is necessary
>> + * since we'll be remapping normal memory.
>> + */
>> + for (page = virtual_start;
>> + page < PAGE_ALIGN(virtual_start + grvga_mem_size);
>> + page += PAGE_SIZE) {
>> + SetPageReserved(virt_to_page(page));
>> + }
>> + }
>> +
> This all looks like a good candidate for dma_alloc_coherent().
That would make the whole framebuffer uncachable and won't reserve the page?
>> + if (info) {
>> + unregister_framebuffer(info);
>> + fb_dealloc_cmap(&info->cmap);
>> + of_iounmap(&device->resource[0], par->regs,
>> + resource_size(&device->resource[0]));
>> + framebuffer_release(info);
>> + dev_set_drvdata(&device->dev, NULL);
>> + }
>> +
> You seem to be missing a release_mem_region() in here.
Indeed.
>> +int __init grvga_init(void)
>> +{
>> + return platform_driver_register(&grvga_driver);
>> +}
>> +
> static?
It should be, yes.
Thanks,
Kristoffer Glembo
^ permalink raw reply
* [PATCH] gx1fb: Fix section mismatch warnings
From: Randy Dunlap @ 2011-06-16 19:31 UTC (permalink / raw)
To: Paul Mundt
Cc: Sedat Dilek, linux-geode, linux-fbdev, linux-kernel, Sedat Dilek
In-Reply-To: <20110106063906.GB15340@linux-sh.org>
On Thu, 6 Jan 2011 15:39:07 +0900 Paul Mundt wrote:
> The problem seems to be because gx1fb_probe is annotated __init. In the
> PCI case you want it to be __devinit, and you're also going to want to
> annotate the remove function as __devexit and wrap it up with a
> __devexit_p().
> --
From: Randy Dunlap <randy.dunlap@oracle.com>
Fix a chain of section mismatches in geode driver, beginning with:
WARNING: drivers/video/geode/gx1fb.o(.data+0x70): Section mismatch in reference from the variable gx1fb_driver to the function .init.text:gx1fb_probe()
The variable gx1fb_driver references
the function __init gx1fb_probe()
If the reference is valid then annotate the
variable with __init* or __refdata (see linux/init.h) or name the variable:
*_template, *_timer, *_sht, *_ops, *_probe, *_probe_one, *_console
Making the changes that Paul pointed out resulted in a few more
changes being needed, so they are all included here.
Signed-off-by: Randy Dunlap <randy.dunlap@oracle.com>
---
drivers/video/geode/gx1fb_core.c | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
--- lnx-30-rc3.orig/drivers/video/geode/gx1fb_core.c
+++ lnx-30-rc3/drivers/video/geode/gx1fb_core.c
@@ -29,7 +29,7 @@ static int crt_option = 1;
static char panel_option[32] = "";
/* Modes relevant to the GX1 (taken from modedb.c) */
-static const struct fb_videomode __initdata gx1_modedb[] = {
+static const struct fb_videomode __devinitdata gx1_modedb[] = {
/* 640x480-60 VESA */
{ NULL, 60, 640, 480, 39682, 48, 16, 33, 10, 96, 2,
0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
@@ -195,7 +195,7 @@ static int gx1fb_blank(int blank_mode, s
return par->vid_ops->blank_display(info, blank_mode);
}
-static int __init gx1fb_map_video_memory(struct fb_info *info, struct pci_dev *dev)
+static int __devinit gx1fb_map_video_memory(struct fb_info *info, struct pci_dev *dev)
{
struct geodefb_par *par = info->par;
unsigned gx_base;
@@ -268,7 +268,7 @@ static struct fb_ops gx1fb_ops = {
.fb_imageblit = cfb_imageblit,
};
-static struct fb_info * __init gx1fb_init_fbinfo(struct device *dev)
+static struct fb_info * __devinit gx1fb_init_fbinfo(struct device *dev)
{
struct geodefb_par *par;
struct fb_info *info;
@@ -318,7 +318,7 @@ static struct fb_info * __init gx1fb_ini
return info;
}
-static int __init gx1fb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+static int __devinit gx1fb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
struct geodefb_par *par;
struct fb_info *info;
@@ -382,7 +382,7 @@ static int __init gx1fb_probe(struct pci
return ret;
}
-static void gx1fb_remove(struct pci_dev *pdev)
+static void __devexit gx1fb_remove(struct pci_dev *pdev)
{
struct fb_info *info = pci_get_drvdata(pdev);
struct geodefb_par *par = info->par;
@@ -441,7 +441,7 @@ static struct pci_driver gx1fb_driver =
.name = "gx1fb",
.id_table = gx1fb_id_table,
.probe = gx1fb_probe,
- .remove = gx1fb_remove,
+ .remove = __devexit_p(gx1fb_remove),
};
static int __init gx1fb_init(void)
@@ -456,7 +456,7 @@ static int __init gx1fb_init(void)
return pci_register_driver(&gx1fb_driver);
}
-static void __exit gx1fb_cleanup(void)
+static void __devexit gx1fb_cleanup(void)
{
pci_unregister_driver(&gx1fb_driver);
}
^ permalink raw reply
* [PATCH] sm501fb: fix section mismatch warning
From: Randy Dunlap @ 2011-06-16 19:32 UTC (permalink / raw)
To: linux-fbdev
From: Randy Dunlap <randy.dunlap@oracle.com>
Fix section mismatch warning in sm501fb:
WARNING: drivers/video/sm501fb.o(.text+0x21d6): Section mismatch in reference from the function sm501fb_init_fb() to the variable .devinit.data:sm501_default_mode
The function sm501fb_init_fb() references
the variable __devinitdata sm501_default_mode.
This is often because sm501fb_init_fb lacks a __devinitdata
annotation or the annotation of sm501_default_mode is wrong.
Signed-off-by: Randy Dunlap <randy.dunlap@oracle.com>
---
drivers/video/sm501fb.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- lnx-30-rc3.orig/drivers/video/sm501fb.c
+++ lnx-30-rc3/drivers/video/sm501fb.c
@@ -1664,7 +1664,7 @@ static void sm501fb_stop(struct sm501fb_
resource_size(info->regs_res));
}
-static int sm501fb_init_fb(struct fb_info *fb,
+static int __devinit sm501fb_init_fb(struct fb_info *fb,
enum sm501_controller head,
const char *fbname)
{
^ permalink raw reply
* Re: [PATCH] gx1fb: Fix section mismatch warnings
From: Sedat Dilek @ 2011-06-17 7:15 UTC (permalink / raw)
To: Randy Dunlap; +Cc: Paul Mundt, linux-geode, linux-fbdev, linux-kernel
In-Reply-To: <20110616123119.6ca873fa.randy.dunlap@oracle.com>
On Thu, Jun 16, 2011 at 9:31 PM, Randy Dunlap <randy.dunlap@oracle.com> wrote:
> On Thu, 6 Jan 2011 15:39:07 +0900 Paul Mundt wrote:
>
>> The problem seems to be because gx1fb_probe is annotated __init. In the
>> PCI case you want it to be __devinit, and you're also going to want to
>> annotate the remove function as __devexit and wrap it up with a
>> __devexit_p().
>> --
>
> From: Randy Dunlap <randy.dunlap@oracle.com>
>
> Fix a chain of section mismatches in geode driver, beginning with:
>
> WARNING: drivers/video/geode/gx1fb.o(.data+0x70): Section mismatch in reference from the variable gx1fb_driver to the function .init.text:gx1fb_probe()
> The variable gx1fb_driver references
> the function __init gx1fb_probe()
> If the reference is valid then annotate the
> variable with __init* or __refdata (see linux/init.h) or name the variable:
> *_template, *_timer, *_sht, *_ops, *_probe, *_probe_one, *_console
>
> Making the changes that Paul pointed out resulted in a few more
> changes being needed, so they are all included here.
>
> Signed-off-by: Randy Dunlap <randy.dunlap@oracle.com>
> ---
Hi Randy,
thanks for taking care of this old issue!
It's around a week I did not compile a linux-next kernel.
I should again enable full section mismatch in my setup.
Regards,
- Sedat -
^ permalink raw reply
* [PATCH] hecubafb: add module_put on error path in hecubafb_probe()
From: Pavel Shved @ 2011-06-17 16:25 UTC (permalink / raw)
To: Paul Mundt; +Cc: Pavel Shved, linux-fbdev, linux-kernel, ldv-project
In-Reply-To: <1308327913-23220-1-git-send-email-shved@ispras.ru>
In hecubafb_probe(), after a successful try_module_get, vzalloc may
fail and make the hecubafb_probe return, but the module is not put on
this error path.
This patch adds an exit point that calls module_put in such situation.
Found by Linux Driver Verification project (linuxtesting.org).
Signed-off-by: Pavel Shved <shved@ispras.ru>
---
drivers/video/hecubafb.c | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/drivers/video/hecubafb.c b/drivers/video/hecubafb.c
index fbef15f..614251a 100644
--- a/drivers/video/hecubafb.c
+++ b/drivers/video/hecubafb.c
@@ -233,7 +233,7 @@ static int __devinit hecubafb_probe(struct platform_device *dev)
videomemory = vzalloc(videomemorysize);
if (!videomemory)
- return retval;
+ goto err_videomem_alloc;
info = framebuffer_alloc(sizeof(struct hecubafb_par), &dev->dev);
if (!info)
@@ -275,6 +275,7 @@ err_fbreg:
framebuffer_release(info);
err_fballoc:
vfree(videomemory);
+err_videomem_alloc:
module_put(board->owner);
return retval;
}
--
1.7.0.2
^ permalink raw reply related
* [PATCH] fb: avoid possible deadlock caused by fb_set_suspend
From: Florian Tobias Schandinat @ 2011-06-17 18:46 UTC (permalink / raw)
To: lethal, linux-fbdev
Cc: francis.moro, torvalds, bonbons, linux-kernel,
Herton Ronaldo Krzesinski, Florian Tobias Schandinat, stable
In-Reply-To: <4DF7B0B4.4060002@gmx.de>
From: Herton Ronaldo Krzesinski <herton@mandriva.com.br>
A lock ordering issue can cause deadlocks: in framebuffer/console code,
all needed struct fb_info locks are taken before acquire_console_sem(),
in places which need to take console semaphore.
But fb_set_suspend is always called with console semaphore held, and
inside it we call lock_fb_info which gets the fb_info lock, inverse
locking order of what the rest of the code does. This causes a real
deadlock issue, when we write to state fb sysfs attribute (which calls
fb_set_suspend) while a framebuffer is being unregistered by
remove_conflicting_framebuffers, as can be shown by following show
blocked state trace on a test program which loads i915 and runs another
forked processes writing to state attribute:
Test process with semaphore held and trying to get fb_info lock:
..
fb-test2 D 0000000000000000 0 237 228 0x00000000
ffff8800774f3d68 0000000000000082 00000000000135c0 00000000000135c0
ffff880000000000 ffff8800774f3fd8 ffff8800774f3fd8 ffff880076ee4530
00000000000135c0 ffff8800774f3fd8 ffff8800774f2000 00000000000135c0
Call Trace:
[<ffffffff8141287a>] __mutex_lock_slowpath+0x11a/0x1e0
[<ffffffff814142f2>] ? _raw_spin_lock_irq+0x22/0x40
[<ffffffff814123d3>] mutex_lock+0x23/0x50
[<ffffffff8125dfc5>] lock_fb_info+0x25/0x60
[<ffffffff8125e3f0>] fb_set_suspend+0x20/0x80
[<ffffffff81263e2f>] store_fbstate+0x4f/0x70
[<ffffffff812e7f70>] dev_attr_store+0x20/0x30
[<ffffffff811c46b4>] sysfs_write_file+0xd4/0x160
[<ffffffff81155a26>] vfs_write+0xc6/0x190
[<ffffffff81155d51>] sys_write+0x51/0x90
[<ffffffff8100c012>] system_call_fastpath+0x16/0x1b
..
modprobe process stalled because has the fb_info lock (got inside
unregister_framebuffer) but waiting for the semaphore held by the
test process which is waiting to get the fb_info lock:
..
modprobe D 0000000000000000 0 230 218 0x00000000
ffff880077a4d618 0000000000000082 0000000000000001 0000000000000001
ffff880000000000 ffff880077a4dfd8 ffff880077a4dfd8 ffff8800775a2e20
00000000000135c0 ffff880077a4dfd8 ffff880077a4c000 00000000000135c0
Call Trace:
[<ffffffff81411fe5>] schedule_timeout+0x215/0x310
[<ffffffff81058051>] ? get_parent_ip+0x11/0x50
[<ffffffff814130dd>] __down+0x6d/0xb0
[<ffffffff81089f71>] down+0x41/0x50
[<ffffffff810629ac>] acquire_console_sem+0x2c/0x50
[<ffffffff812ca53d>] unbind_con_driver+0xad/0x2d0
[<ffffffff8126f5f7>] fbcon_event_notify+0x457/0x890
[<ffffffff814144ff>] ? _raw_spin_unlock_irqrestore+0x1f/0x50
[<ffffffff81058051>] ? get_parent_ip+0x11/0x50
[<ffffffff8141836d>] notifier_call_chain+0x4d/0x70
[<ffffffff8108a3b8>] __blocking_notifier_call_chain+0x58/0x80
[<ffffffff8108a3f6>] blocking_notifier_call_chain+0x16/0x20
[<ffffffff8125dabb>] fb_notifier_call_chain+0x1b/0x20
[<ffffffff8125e6ac>] unregister_framebuffer+0x7c/0x130
[<ffffffff8125e8b3>] remove_conflicting_framebuffers+0x153/0x180
[<ffffffff8125eef3>] register_framebuffer+0x93/0x2c0
[<ffffffffa0331112>] drm_fb_helper_single_fb_probe+0x252/0x2f0 [drm_kms_helper]
[<ffffffffa03314a3>] drm_fb_helper_initial_config+0x2f3/0x6d0 [drm_kms_helper]
[<ffffffffa03318dd>] ? drm_fb_helper_single_add_all_connectors+0x5d/0x1c0 [drm_kms_helper]
[<ffffffffa037b588>] intel_fbdev_init+0xa8/0x160 [i915]
[<ffffffffa0343d74>] i915_driver_load+0x854/0x12b0 [i915]
[<ffffffffa02f0e7e>] drm_get_pci_dev+0x19e/0x360 [drm]
[<ffffffff8141821d>] ? sub_preempt_count+0x9d/0xd0
[<ffffffffa0386f91>] i915_pci_probe+0x15/0x17 [i915]
[<ffffffff8124481f>] local_pci_probe+0x5f/0xd0
[<ffffffff81244f89>] pci_device_probe+0x119/0x120
[<ffffffff812eccaa>] ? driver_sysfs_add+0x7a/0xb0
[<ffffffff812ed003>] driver_probe_device+0xa3/0x290
[<ffffffff812ed1f0>] ? __driver_attach+0x0/0xb0
[<ffffffff812ed29b>] __driver_attach+0xab/0xb0
[<ffffffff812ed1f0>] ? __driver_attach+0x0/0xb0
[<ffffffff812ebd3e>] bus_for_each_dev+0x5e/0x90
[<ffffffff812ecc2e>] driver_attach+0x1e/0x20
[<ffffffff812ec6f2>] bus_add_driver+0xe2/0x320
[<ffffffffa03aa000>] ? i915_init+0x0/0x96 [i915]
[<ffffffff812ed536>] driver_register+0x76/0x140
[<ffffffffa03aa000>] ? i915_init+0x0/0x96 [i915]
[<ffffffff81245216>] __pci_register_driver+0x56/0xd0
[<ffffffffa02f1264>] drm_pci_init+0xe4/0xf0 [drm]
[<ffffffffa03aa000>] ? i915_init+0x0/0x96 [i915]
[<ffffffffa02e84a8>] drm_init+0x58/0x70 [drm]
[<ffffffffa03aa094>] i915_init+0x94/0x96 [i915]
[<ffffffff81002194>] do_one_initcall+0x44/0x190
[<ffffffff810a066b>] sys_init_module+0xcb/0x210
[<ffffffff8100c012>] system_call_fastpath+0x16/0x1b
..
fb-test2 which reproduces above is available on kernel.org bug #26232.
To solve this issue, avoid calling lock_fb_info inside fb_set_suspend,
and move it out to where needed (callers of fb_set_suspend must call
lock_fb_info before if needed). So far, the only place which needs to
call lock_fb_info is store_fbstate, all other places which calls
fb_set_suspend are suspend/resume hooks that should not need the lock as
they should be run only when processes are already frozen in
suspend/resume.
References: https://bugzilla.kernel.org/show_bug.cgi?id&232
Signed-off-by: Herton Ronaldo Krzesinski <herton@mandriva.com.br>
Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
Cc: stable@kernel.org
---
drivers/video/fbmem.c | 3 ---
drivers/video/fbsysfs.c | 3 +++
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 5aac00e..ad93629 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -1738,8 +1738,6 @@ void fb_set_suspend(struct fb_info *info, int state)
{
struct fb_event event;
- if (!lock_fb_info(info))
- return;
event.info = info;
if (state) {
fb_notifier_call_chain(FB_EVENT_SUSPEND, &event);
@@ -1748,7 +1746,6 @@ void fb_set_suspend(struct fb_info *info, int state)
info->state = FBINFO_STATE_RUNNING;
fb_notifier_call_chain(FB_EVENT_RESUME, &event);
}
- unlock_fb_info(info);
}
/**
diff --git a/drivers/video/fbsysfs.c b/drivers/video/fbsysfs.c
index 04251ce..67afa9c 100644
--- a/drivers/video/fbsysfs.c
+++ b/drivers/video/fbsysfs.c
@@ -399,9 +399,12 @@ static ssize_t store_fbstate(struct device *device,
state = simple_strtoul(buf, &last, 0);
+ if (!lock_fb_info(fb_info))
+ return -ENODEV;
console_lock();
fb_set_suspend(fb_info, (int)state);
console_unlock();
+ unlock_fb_info(fb_info);
return count;
}
--
1.6.3.2
^ permalink raw reply related
* Framebuffer driver for controller with indirect addressing?
From: Steve Strobel @ 2011-06-17 23:10 UTC (permalink / raw)
To: linux-fbdev
I am trying to support a Tianma TM023KDH18 QVGA LCD display (1) via a
16-bit parallel bus interface on a BF537 Blackfin running the
distribution from blackfin.uclinux.org. Built into the display is a
ILITEK ILI9342 controller (2). The controller has built-in memory
for the framebuffer and handles refreshing the display
automatically. Changing the contents of the framebuffer is done by
sending commands to set the starting pixel position, then writing
repeatedly to the same address with the data for each successive
pixel. It does not have address lines, so the framebuffer memory is
not directly accessible as with the S1D13XXX chips. A single D/CX
pin, which we plan to treat like an address line, controls whether
each bus read/write operation is treated as a command or data.
I am wondering if there is an existing driver for something that
works in a similar way that I could use as a model. I think I am
going to need to create a shadow framebuffer in system memory (maybe
using the virtual framebuffer) and DMA it to the graphics controller
whenever the displayed information changes (or maybe on the
double-buffer flip). Ultimately I would like to use Qt, so building
on the existing framebuffer API seems like a good idea.
If someone could point me to a driver that works in a similar way, it
would help me out a lot. Thanks.
Steve
(1) Datasheet at
http://www.tianma-usa.com/web/uploads/spec/0906123532_TM023KDH18%20V1.0.pdf
(2) Datasheet at http://linkcomm.com/temp/ILI9342.pdf
---
Steve Strobel
Link Communications, Inc.
1035 Cerise Rd
Billings, MT 59101-7378
(406) 245-5002 ext 102
(406) 245-4889 (fax)
WWW: http://www.link-comm.com
MailTo:steve.strobel@link-comm.com
^ permalink raw reply
* Re: Framebuffer driver for controller with indirect addressing?
From: Bernie Thompson @ 2011-06-18 0:18 UTC (permalink / raw)
To: linux-fbdev
In-Reply-To: <0LlUqt-1Pye1R36EZ-00bCDF@mrelay.perfora.net>
On Fri, Jun 17, 2011 at 4:10 PM, Steve Strobel
<steve.strobel@link-comm.com> wrote:
> It does not have address lines, so the framebuffer memory
> is not directly accessible
>
> If someone could point me to a driver that works in a similar way, it would
> help me out a lot. Â Thanks.
Hi Steve - there are several drivers that handle this kind of case,
including the udlfb driver for DisplayLink USB graphics chips (in the
kernel tree /drivers/video/udlfb.c)
The main unsolved challenge is fbdev (in the memory mapped framebuffer
case) assumes writes to the framebuffer take effect immediately. For
hardware in which this isn't true (e.g. USB, eink controllers, etc.),
there are two common solutions. However both have problems:
1) Use of /driver/video/fb_defio.c to use the MMU to trigger fault
handlers on framebuffer writes, and transmit to hardware via delayed
processing of the dirty pages. However, this implementation still
appears to have some race conditions which can result in difficult to
debug problems. It's also a bit of MMU/cache load.
2) Use of an ioctl to allow the user mode client to inform the
framebuffer of changed pixels (usually xorg forwarding X DAMAGE
notifications, which are well matched for this purpose). This works
well and is simple, however we don't yet have a standardized ioctl, so
several drivers have different ioctls and thus custom x servers,
instead of being supported by the standard xf86-video-fbdev driver.
#2 would be the quickest way to give Linux a clean way of handling
remote (non-directly-addressable) framebuffers.
Others may have some additional suggestions.
Hope that helps. Best wishes,
Bernie
http://plugable.com/
^ permalink raw reply
* Re: [PATCH] fb: avoid possible deadlock caused by fb_set_suspend
From: Bruno Prémont @ 2011-06-18 8:43 UTC (permalink / raw)
To: Florian Tobias Schandinat
Cc: lethal, linux-fbdev, francis.moro, torvalds, linux-kernel,
Herton Ronaldo Krzesinski, stable
In-Reply-To: <1308337359-3480-1-git-send-email-FlorianSchandinat@gmx.de>
On Fri, 17 June 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de> wrote:
> From: Herton Ronaldo Krzesinski <herton@mandriva.com.br>
>
> A lock ordering issue can cause deadlocks: in framebuffer/console code,
> all needed struct fb_info locks are taken before acquire_console_sem(),
> in places which need to take console semaphore.
>
> But fb_set_suspend is always called with console semaphore held, and
> inside it we call lock_fb_info which gets the fb_info lock, inverse
> locking order of what the rest of the code does. This causes a real
> deadlock issue, when we write to state fb sysfs attribute (which calls
> fb_set_suspend) while a framebuffer is being unregistered by
> remove_conflicting_framebuffers, as can be shown by following show
> blocked state trace on a test program which loads i915 and runs another
> forked processes writing to state attribute:
>
> Test process with semaphore held and trying to get fb_info lock:
...
> fb-test2 which reproduces above is available on kernel.org bug #26232.
> To solve this issue, avoid calling lock_fb_info inside fb_set_suspend,
> and move it out to where needed (callers of fb_set_suspend must call
> lock_fb_info before if needed). So far, the only place which needs to
> call lock_fb_info is store_fbstate, all other places which calls
> fb_set_suspend are suspend/resume hooks that should not need the lock as
> they should be run only when processes are already frozen in
> suspend/resume.
From a quick look through FB drivers in 2.6.39 I've found one that would need
more work:
- drivers/video/sh_mobile_hdmi.c: sh_hdmi_edid_work_fn()
Should get changed to
a) right locking order in case (hdmi->hp_state = HDMI_HOTPLUG_CONNECTED)
b) lock fb_info in the other case
For this one fb_set_suspend() does get call in a hotplug worker,
thus independently on suspend/resume process.
The rest does match the suspend/resume hook pattern mentioned.
Bruno
> References: https://bugzilla.kernel.org/show_bug.cgi?id&232
> Signed-off-by: Herton Ronaldo Krzesinski <herton@mandriva.com.br>
> Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
> Cc: stable@kernel.org
> ---
> drivers/video/fbmem.c | 3 ---
> drivers/video/fbsysfs.c | 3 +++
> 2 files changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
> index 5aac00e..ad93629 100644
> --- a/drivers/video/fbmem.c
> +++ b/drivers/video/fbmem.c
> @@ -1738,8 +1738,6 @@ void fb_set_suspend(struct fb_info *info, int state)
> {
> struct fb_event event;
>
> - if (!lock_fb_info(info))
> - return;
> event.info = info;
> if (state) {
> fb_notifier_call_chain(FB_EVENT_SUSPEND, &event);
> @@ -1748,7 +1746,6 @@ void fb_set_suspend(struct fb_info *info, int state)
> info->state = FBINFO_STATE_RUNNING;
> fb_notifier_call_chain(FB_EVENT_RESUME, &event);
> }
> - unlock_fb_info(info);
> }
>
> /**
> diff --git a/drivers/video/fbsysfs.c b/drivers/video/fbsysfs.c
> index 04251ce..67afa9c 100644
> --- a/drivers/video/fbsysfs.c
> +++ b/drivers/video/fbsysfs.c
> @@ -399,9 +399,12 @@ static ssize_t store_fbstate(struct device *device,
>
> state = simple_strtoul(buf, &last, 0);
>
> + if (!lock_fb_info(fb_info))
> + return -ENODEV;
> console_lock();
> fb_set_suspend(fb_info, (int)state);
> console_unlock();
> + unlock_fb_info(fb_info);
>
> return count;
> }
^ permalink raw reply
* Re: [PATCH] fb: avoid possible deadlock caused by fb_set_suspend
From: Bruno Prémont @ 2011-06-18 9:19 UTC (permalink / raw)
To: Guennadi Liakhovetski
Cc: Florian Tobias Schandinat, lethal, linux-fbdev, francis.moro,
torvalds, linux-kernel, Herton Ronaldo Krzesinski, stable
In-Reply-To: <20110618104311.6d80ba50@neptune.home>
Guennadi, could you have a look at (completely untested) patch which avoids
possible deadlock due to inverted lock taking order on hotplug as well
as "readding" lock_fb_info() for fb_set_suspend() call after Herton's
patch to fb_set_suspend().
Thanks,
Bruno
On Sat, 18 June 2011 Bruno Prémont <bonbons@linux-vserver.org> wrote:
> On Fri, 17 June 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de> wrote:
> > From: Herton Ronaldo Krzesinski <herton@mandriva.com.br>
> >
> > A lock ordering issue can cause deadlocks: in framebuffer/console code,
> > all needed struct fb_info locks are taken before acquire_console_sem(),
> > in places which need to take console semaphore.
> >
> > But fb_set_suspend is always called with console semaphore held, and
> > inside it we call lock_fb_info which gets the fb_info lock, inverse
> > locking order of what the rest of the code does. This causes a real
> > deadlock issue, when we write to state fb sysfs attribute (which calls
> > fb_set_suspend) while a framebuffer is being unregistered by
> > remove_conflicting_framebuffers, as can be shown by following show
> > blocked state trace on a test program which loads i915 and runs another
> > forked processes writing to state attribute:
> >
> > Test process with semaphore held and trying to get fb_info lock:
>
> ...
>
> > fb-test2 which reproduces above is available on kernel.org bug #26232.
> > To solve this issue, avoid calling lock_fb_info inside fb_set_suspend,
> > and move it out to where needed (callers of fb_set_suspend must call
> > lock_fb_info before if needed). So far, the only place which needs to
> > call lock_fb_info is store_fbstate, all other places which calls
> > fb_set_suspend are suspend/resume hooks that should not need the lock as
> > they should be run only when processes are already frozen in
> > suspend/resume.
>
> From a quick look through FB drivers in 2.6.39 I've found one that would need
> more work:
> - drivers/video/sh_mobile_hdmi.c: sh_hdmi_edid_work_fn()
> Should get changed to
> a) right locking order in case (hdmi->hp_state = HDMI_HOTPLUG_CONNECTED)
> b) lock fb_info in the other case
> For this one fb_set_suspend() does get call in a hotplug worker,
> thus independently on suspend/resume process.
>
> The rest does match the suspend/resume hook pattern mentioned.
>
> Bruno
>
>
> > References: https://bugzilla.kernel.org/show_bug.cgi?id&232
> > Signed-off-by: Herton Ronaldo Krzesinski <herton@mandriva.com.br>
> > Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
> > Cc: stable@kernel.org
> > ---
> > drivers/video/fbmem.c | 3 ---
> > drivers/video/fbsysfs.c | 3 +++
> > 2 files changed, 3 insertions(+), 3 deletions(-)
> >
> > diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
> > index 5aac00e..ad93629 100644
> > --- a/drivers/video/fbmem.c
> > +++ b/drivers/video/fbmem.c
> > @@ -1738,8 +1738,6 @@ void fb_set_suspend(struct fb_info *info, int state)
> > {
> > struct fb_event event;
> >
> > - if (!lock_fb_info(info))
> > - return;
> > event.info = info;
> > if (state) {
> > fb_notifier_call_chain(FB_EVENT_SUSPEND, &event);
> > @@ -1748,7 +1746,6 @@ void fb_set_suspend(struct fb_info *info, int state)
> > info->state = FBINFO_STATE_RUNNING;
> > fb_notifier_call_chain(FB_EVENT_RESUME, &event);
> > }
> > - unlock_fb_info(info);
> > }
> >
> > /**
> > diff --git a/drivers/video/fbsysfs.c b/drivers/video/fbsysfs.c
> > index 04251ce..67afa9c 100644
> > --- a/drivers/video/fbsysfs.c
> > +++ b/drivers/video/fbsysfs.c
> > @@ -399,9 +399,12 @@ static ssize_t store_fbstate(struct device *device,
> >
> > state = simple_strtoul(buf, &last, 0);
> >
> > + if (!lock_fb_info(fb_info))
> > + return -ENODEV;
> > console_lock();
> > fb_set_suspend(fb_info, (int)state);
> > console_unlock();
> > + unlock_fb_info(fb_info);
> >
> > return count;
> > }
diff --git a/drivers/video/sh_mobile_hdmi.c b/drivers/video/sh_mobile_hdmi.c
index 2b9e56a..b1a13ab 100644
--- a/drivers/video/sh_mobile_hdmi.c
+++ b/drivers/video/sh_mobile_hdmi.c
@@ -1151,27 +1151,27 @@ static void sh_hdmi_edid_work_fn(struct work_struct *work)
ch = info->par;
- console_lock();
+ if (lock_fb_info(info)) {
+ console_lock();
- /* HDMI plug in */
- if (!sh_hdmi_must_reconfigure(hdmi) &&
- info->state = FBINFO_STATE_RUNNING) {
- /*
- * First activation with the default monitor - just turn
- * on, if we run a resume here, the logo disappears
- */
- if (lock_fb_info(info)) {
+ /* HDMI plug in */
+ if (!sh_hdmi_must_reconfigure(hdmi) &&
+ info->state = FBINFO_STATE_RUNNING) {
+ /*
+ * First activation with the default monitor - just turn
+ * on, if we run a resume here, the logo disappears
+ */
info->var.width = hdmi->var.width;
info->var.height = hdmi->var.height;
sh_hdmi_display_on(hdmi, info);
- unlock_fb_info(info);
+ } else {
+ /* New monitor or have to wake up */
+ fb_set_suspend(info, 0);
}
- } else {
- /* New monitor or have to wake up */
- fb_set_suspend(info, 0);
- }
- console_unlock();
+ console_unlock();
+ unlock_fb_info(info);
+ }
} else {
ret = 0;
if (!hdmi->info)
@@ -1181,12 +1181,15 @@ static void sh_hdmi_edid_work_fn(struct work_struct *work)
fb_destroy_modedb(hdmi->monspec.modedb);
hdmi->monspec.modedb = NULL;
- console_lock();
+ if (lock_fb_info(info)) {
+ console_lock();
- /* HDMI disconnect */
- fb_set_suspend(hdmi->info, 1);
+ /* HDMI disconnect */
+ fb_set_suspend(hdmi->info, 1);
- console_unlock();
+ console_unlock();
+ unlock_fb_info(info);
+ }
pm_runtime_put(hdmi->dev);
}
^ permalink raw reply related
* [PATCH 0/2] video: Make omap2 support conditional
From: Tushar Behera @ 2011-06-20 10:57 UTC (permalink / raw)
To: linux-arm-kernel
Currently drivers/video/omap2 is built by default with every configuration
of the kernel. Current patchset makes the omap2 video support conditional
on appropriate config option.
[Patch 2/2] was first generated, but that resulted in a build error.
[Patch 1/2] was created to fix that build error.
These patches have only been tested for build consistency and have not been
tested on any related hardware.
Tushar Behera (2):
config: omap2+: force fb and dss support as built-in
video: omap2: Compile omap2 support only when needed
arch/arm/configs/omap2plus_defconfig | 4 ++--
drivers/video/Makefile | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
--
1.7.4.1
^ permalink raw reply
* [PATCH 1/2] config: omap2+: force fb and dss support as built-in
From: Tushar Behera @ 2011-06-20 10:58 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1308566761-2850-1-git-send-email-tushar.behera@linaro.org>
In certain board files, there are references to vram related functions
which are defined in drivers/video/omap2/vram.c. Because of this direct
dependency, CONFIG_FB_OMAP2 should be a built-in feature.
As per the current architecture, CONFIG_FB_OMAP2 is dependent on
CONFIG_OMAP2_DSS. Hence CONFIG_OMAP2_DSS support should also be selected
by default.
Cc: Tony Lindgren <tony@atomide.com>
Cc: Samreen <samreen@ti.com>
Signed-off-by: Tushar Behera <tushar.behera@linaro.org>
---
arch/arm/mach-omap2/built-in.o: In function `rx51_video_mem_init':
linux-linaro-2.6.39/arch/arm/mach-omap2/board-rx51-video.c:97: undefined reference to `omap_vram_set_sdram_vram'
arch/arm/plat-omap/built-in.o: In function `omap_reserve':
linux-linaro-2.6.39/arch/arm/plat-omap/common.c:66: undefined reference to `omap_vram_reserve_sdram_memblock'
arch/arm/plat-omap/built-in.o: In function `omap_detect_sram':
linux-linaro-2.6.39/arch/arm/plat-omap/sram.c:179: undefined reference to `omap_vram_reserve_sram'
make[1]: *** [.tmp_vmlinux1] Error 1
make: *** [sub-make] Error 2
arch/arm/configs/omap2plus_defconfig | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/arm/configs/omap2plus_defconfig b/arch/arm/configs/omap2plus_defconfig
index d5f00d7..c3ffff2 100644
--- a/arch/arm/configs/omap2plus_defconfig
+++ b/arch/arm/configs/omap2plus_defconfig
@@ -138,11 +138,11 @@ CONFIG_FIRMWARE_EDID=y
CONFIG_FB_MODE_HELPERS=y
CONFIG_FB_TILEBLITTING=y
CONFIG_FB_OMAP_LCD_VGA=y
-CONFIG_OMAP2_DSS=m
+CONFIG_OMAP2_DSS=y
CONFIG_OMAP2_DSS_RFBI=y
CONFIG_OMAP2_DSS_SDI=y
CONFIG_OMAP2_DSS_DSI=y
-CONFIG_FB_OMAP2=m
+CONFIG_FB_OMAP2=y
CONFIG_PANEL_GENERIC_DPI=m
CONFIG_PANEL_SHARP_LS037V7DW01=m
CONFIG_PANEL_NEC_NL8048HL11_01B=m
--
1.7.4.1
^ permalink raw reply related
* [PATCH 2/2] video: omap2: Compile omap2 support only when needed
From: Tushar Behera @ 2011-06-20 10:58 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1308566761-2850-1-git-send-email-tushar.behera@linaro.org>
Currently display support for omap2 is selected by default and
it gets built for all the configurations.
Instead of it being a built-in feature, it's compilation should
depend on the config option CONFIG_FB_OMAP2.
Cc: Paul Mundt <lethal@linux-sh.org>
Cc: Tomi Valkeinen <tomi.valkeinen@nokia.com>
Cc: Tony Lindgren <tony@atomide.com>
Signed-off-by: Tushar Behera <tushar.behera@linaro.org>
---
drivers/video/Makefile | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 8b83129..a19e44e 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -133,7 +133,7 @@ obj-$(CONFIG_FB_SH_MOBILE_HDMI) += sh_mobile_hdmi.o
obj-$(CONFIG_FB_SH_MOBILE_MERAM) += sh_mobile_meram.o
obj-$(CONFIG_FB_SH_MOBILE_LCDC) += sh_mobile_lcdcfb.o
obj-$(CONFIG_FB_OMAP) += omap/
-obj-y += omap2/
+obj-$(CONFIG_FB_OMAP2) += omap2/
obj-$(CONFIG_XEN_FBDEV_FRONTEND) += xen-fbfront.o
obj-$(CONFIG_FB_CARMINE) += carminefb.o
obj-$(CONFIG_FB_MB862XX) += mb862xx/
--
1.7.4.1
^ permalink raw reply related
* RE: [PATCH 1/2] config: omap2+: force fb and dss support as built-in
From: Premi, Sanjeev @ 2011-06-20 12:19 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1308566761-2850-2-git-send-email-tushar.behera@linaro.org>
> -----Original Message-----
> From: linux-omap-owner@vger.kernel.org
> [mailto:linux-omap-owner@vger.kernel.org] On Behalf Of Tushar Behera
> Sent: Monday, June 20, 2011 4:16 PM
> To: linux-kernel@vger.kernel.org;
> linux-arm-kernel@lists.infradead.org;
> linux-fbdev@vger.kernel.org; linux-omap@vger.kernel.org
> Cc: linux@arm.linux.org.uk; tony@atomide.com;
> lethal@linux-sh.org; linaro-dev@lists.linaro.org;
> patches@linaro.org; Nilofer, Samreen
> Subject: [PATCH 1/2] config: omap2+: force fb and dss support
> as built-in
>
> In certain board files, there are references to vram related functions
> which are defined in drivers/video/omap2/vram.c. Because of
> this direct
> dependency, CONFIG_FB_OMAP2 should be a built-in feature.
>
> As per the current architecture, CONFIG_FB_OMAP2 is dependent on
> CONFIG_OMAP2_DSS. Hence CONFIG_OMAP2_DSS support should also
> be selected
> by default.
>
> Cc: Tony Lindgren <tony@atomide.com>
> Cc: Samreen <samreen@ti.com>
> Signed-off-by: Tushar Behera <tushar.behera@linaro.org>
> ---
> arch/arm/mach-omap2/built-in.o: In function `rx51_video_mem_init':
> linux-linaro-2.6.39/arch/arm/mach-omap2/board-rx51-video.c:97:
> undefined reference to `omap_vram_set_sdram_vram'
> arch/arm/plat-omap/built-in.o: In function `omap_reserve':
> linux-linaro-2.6.39/arch/arm/plat-omap/common.c:66: undefined
> reference to `omap_vram_reserve_sdram_memblock'
> arch/arm/plat-omap/built-in.o: In function `omap_detect_sram':
> linux-linaro-2.6.39/arch/arm/plat-omap/sram.c:179: undefined
> reference to `omap_vram_reserve_sram'
> make[1]: *** [.tmp_vmlinux1] Error 1
> make: *** [sub-make] Error 2
>
> arch/arm/configs/omap2plus_defconfig | 4 ++--
> 1 files changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/arch/arm/configs/omap2plus_defconfig
> b/arch/arm/configs/omap2plus_defconfig
> index d5f00d7..c3ffff2 100644
> --- a/arch/arm/configs/omap2plus_defconfig
> +++ b/arch/arm/configs/omap2plus_defconfig
> @@ -138,11 +138,11 @@ CONFIG_FIRMWARE_EDID=y
> CONFIG_FB_MODE_HELPERS=y
> CONFIG_FB_TILEBLITTING=y
> CONFIG_FB_OMAP_LCD_VGA=y
> -CONFIG_OMAP2_DSS=m
> +CONFIG_OMAP2_DSS=y
> CONFIG_OMAP2_DSS_RFBI=y
> CONFIG_OMAP2_DSS_SDI=y
> CONFIG_OMAP2_DSS_DSI=y
> -CONFIG_FB_OMAP2=m
> +CONFIG_FB_OMAP2=y
> CONFIG_PANEL_GENERIC_DPI=m
> CONFIG_PANEL_SHARP_LS037V7DW01=m
> CONFIG_PANEL_NEC_NL8048HL11_01B=m
[sp] Instead of changing the omap2plus_defconfig, shouldn't the
board specific file be fixed instead?
~sanjeev
> --
> 1.7.4.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe
> linux-omap" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
^ permalink raw reply
* Re: [PATCH 1/2] config: omap2+: force fb and dss support as
From: Russell King - ARM Linux @ 2011-06-20 12:20 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <B85A65D85D7EB246BE421B3FB0FBB593024D625A5C@dbde02.ent.ti.com>
On Mon, Jun 20, 2011 at 05:37:07PM +0530, Premi, Sanjeev wrote:
> [sp] Instead of changing the omap2plus_defconfig, shouldn't the
> board specific file be fixed instead?
The board specific configuration files in the mainline kernel are
deprecated and are gradually being removed.
^ permalink raw reply
* RE: [PATCH 1/2] config: omap2+: force fb and dss support as built-in
From: Premi, Sanjeev @ 2011-06-20 12:36 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20110620122032.GJ2082@n2100.arm.linux.org.uk>
> -----Original Message-----
> From: Russell King - ARM Linux [mailto:linux@arm.linux.org.uk]
> Sent: Monday, June 20, 2011 5:51 PM
> To: Premi, Sanjeev
> Cc: Tushar Behera; linux-kernel@vger.kernel.org;
> linux-arm-kernel@lists.infradead.org;
> linux-fbdev@vger.kernel.org; linux-omap@vger.kernel.org;
> tony@atomide.com; lethal@linux-sh.org;
> linaro-dev@lists.linaro.org; patches@linaro.org; Nilofer, Samreen
> Subject: Re: [PATCH 1/2] config: omap2+: force fb and dss
> support as built-in
>
> On Mon, Jun 20, 2011 at 05:37:07PM +0530, Premi, Sanjeev wrote:
> > [sp] Instead of changing the omap2plus_defconfig, shouldn't the
> > board specific file be fixed instead?
>
> The board specific configuration files in the mainline kernel are
> deprecated and are gradually being removed.
>
[sp] I didn't mean board specific config file, but:
linux-linaro-2.6.39/arch/arm/mach-omap2/board-rx51-video.c
~sanjeev
^ permalink raw reply
* Re: [PATCH 1/2] config: omap2+: force fb and dss support as
From: Tomi Valkeinen @ 2011-06-20 13:04 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1308566761-2850-2-git-send-email-tushar.behera@linaro.org>
On Mon, 2011-06-20 at 16:16 +0530, Tushar Behera wrote:
> In certain board files, there are references to vram related functions
> which are defined in drivers/video/omap2/vram.c. Because of this direct
> dependency, CONFIG_FB_OMAP2 should be a built-in feature.
arch/arm/plat-omap/include/plat/vram.h defines dummy inline function in
case vram.c is not compiled in, so the board files should compile fine.
> As per the current architecture, CONFIG_FB_OMAP2 is dependent on
> CONFIG_OMAP2_DSS. Hence CONFIG_OMAP2_DSS support should also be selected
> by default.
The configuration is fine as it is. And anyway, if things do not compile
when something is configured as a module, the correct fix is hardly just
changing the feature to be compiled built-in =).
> Cc: Tony Lindgren <tony@atomide.com>
> Cc: Samreen <samreen@ti.com>
> Signed-off-by: Tushar Behera <tushar.behera@linaro.org>
> ---
> arch/arm/mach-omap2/built-in.o: In function `rx51_video_mem_init':
> linux-linaro-2.6.39/arch/arm/mach-omap2/board-rx51-video.c:97: undefined reference to `omap_vram_set_sdram_vram'
> arch/arm/plat-omap/built-in.o: In function `omap_reserve':
> linux-linaro-2.6.39/arch/arm/plat-omap/common.c:66: undefined reference to `omap_vram_reserve_sdram_memblock'
> arch/arm/plat-omap/built-in.o: In function `omap_detect_sram':
> linux-linaro-2.6.39/arch/arm/plat-omap/sram.c:179: undefined reference to `omap_vram_reserve_sram'
> make[1]: *** [.tmp_vmlinux1] Error 1
> make: *** [sub-make] Error 2
Compiles fine for me. Perhaps you are using some old kernel?
Tomi
^ permalink raw reply
* Re: [PATCH 2/2] video: omap2: Compile omap2 support only when
From: Tomi Valkeinen @ 2011-06-20 13:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1308566761-2850-3-git-send-email-tushar.behera@linaro.org>
On Mon, 2011-06-20 at 16:16 +0530, Tushar Behera wrote:
> Currently display support for omap2 is selected by default and
> it gets built for all the configurations.
>
> Instead of it being a built-in feature, it's compilation should
> depend on the config option CONFIG_FB_OMAP2.
No, I don't think so. omap2 directory contains vram, vrfb and omapdss,
all of which can be used without omapfb driver. vram and vrfb can be
even used without omapdss driver.
Is this patch fixing some real problem?
Tomi
^ permalink raw reply
* [PATCH] ARM: amba: Link fb device to its parent
From: Loïc Minier @ 2011-06-20 20:44 UTC (permalink / raw)
To: linux-arm-kernel
Some pieces of userspace like debian-installer expect to find the fb0
driver name by readlink-ing /sys/class/graphics/fb0/device/driver but
this was broken with amba-clcd as it sets up fb_info manually and missed
the .device parent pointer.
Signed-off-by: Loïc Minier <loic.minier@linaro.org>
Cc: Russell King <linux@arm.linux.org.uk>
Cc: Paul Mundt <lethal@linux-sh.org>
---
drivers/video/amba-clcd.c | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/drivers/video/amba-clcd.c b/drivers/video/amba-clcd.c
index 5fc983c..cf03ad0 100644
--- a/drivers/video/amba-clcd.c
+++ b/drivers/video/amba-clcd.c
@@ -447,6 +447,8 @@ static int clcdfb_register(struct clcd_fb *fb)
goto out;
}
+ fb->fb.device = &fb->dev->dev;
+
fb->fb.fix.mmio_start = fb->dev->res.start;
fb->fb.fix.mmio_len = resource_size(&fb->dev->res);
--
1.7.5.4
^ permalink raw reply related
* Re: Framebuffer driver for controller with indirect addressing?
From: Steve Strobel @ 2011-06-20 21:02 UTC (permalink / raw)
To: linux-fbdev
In-Reply-To: <0LlUqt-1Pye1R36EZ-00bCDF@mrelay.perfora.net>
At 06:18 PM 6/17/2011, Bernie Thompson wrote:
>On Fri, Jun 17, 2011 at 4:10 PM, Steve Strobel
><steve.strobel@link-comm.com> wrote:
> > It does not have address lines, so the framebuffer memory
> > is not directly accessible
> >
> > If someone could point me to a driver that works in a similar way, it would
> > help me out a lot. Â Thanks.
>
>Hi Steve - there are several drivers that handle this kind of case,
>including the udlfb driver for DisplayLink USB graphics chips (in the
>kernel tree /drivers/video/udlfb.c)
That helps a lot. I will check it out. Is there
something other than the source code that I
should read to get up to speed on it?
>The main unsolved challenge is fbdev (in the memory mapped framebuffer
>case) assumes writes to the framebuffer take effect immediately. [snip]
If I am understanding you right, the challenge is
knowing when to flush the changed framebuffer memory to the graphics hardware.
>1) Use of /driver/video/fb_defio.c to use the MMU to trigger...
I don't know if a Blackfin system could support
that method or not. It doesn't have a full MMU
with virtual memory (it runs uClinux), but it
does have a memory protection unit. I suppose
all that would be needed is to be notified when
the framebuffer memory is written to; I think it could do that.
>2) Use of an ioctl to allow the user mode client to inform the
>framebuffer of changed pixels (usually xorg forwarding X DAMAGE
>notifications, which are well matched for this purpose). This works
>well and is simple, however we don't yet have a standardized ioctl, so
>several drivers have different ioctls and thus custom x servers,
>instead of being supported by the standard xf86-video-fbdev driver.
Since this is a custom embedded system, we are in
control of all of the software on it. So we can
just make sure that everything included is set up for the same ioctl.
>#2 would be the quickest way to give Linux a clean way of handling
>remote (non-directly-addressable) framebuffers.
>
>Others may have some additional suggestions.
Someone suggested to me using the double-buffer
flipping logic. Does it get flipped on every
screen refresh, or just when the contents of one buffer have been changed?
>Hope that helps. Best wishes,
>Bernie
>http://plugable.com/
Thanks a bunch,
Steve
---
Steve Strobel
Link Communications, Inc.
1035 Cerise Rd
Billings, MT 59101-7378
(406) 245-5002 ext 102
(406) 245-4889 (fax)
WWW: http://www.link-comm.com
MailTo:steve.strobel@link-comm.com
^ permalink raw reply
* [PATCH] locomo: drop special locomo_{read/write}l in favor of io{read/write}16
From: H Hartley Sweeten @ 2011-06-20 21:54 UTC (permalink / raw)
To: linux-arm-kernel
All the locomo registers are 16-bit ioremap'ed memory addresses.
Make the locomo drivers use generic purpose io routines: ioread16
and iowrite16 instead of directly accessing memory.
There are still a couple checkpatch warnings about lines exceeding
79 characters.
Signed-off-by: H Hartley Sweeten <hsweeten@visionengravers.com>
Cc: Russell King <linux@arm.linux.org.uk>
Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Cc: Richard Purdie <rpurdie@rpsys.net>
Cc: Paul Mundt <lethal@linux-sh.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Lennert Buytenhek <buytenh@secretlab.ca>
---
diff --git a/arch/arm/common/locomo.c b/arch/arm/common/locomo.c
index b55c362..3ced960 100644
--- a/arch/arm/common/locomo.c
+++ b/arch/arm/common/locomo.c
@@ -141,13 +141,14 @@ static struct locomo_dev_info locomo_devices[] = {
static void locomo_handler(unsigned int irq, struct irq_desc *desc)
{
struct locomo *lchip = irq_get_chip_data(irq);
- int req, i;
+ u16 req;
+ int i;
/* Acknowledge the parent IRQ */
desc->irq_data.chip->irq_ack(&desc->irq_data);
/* check why this interrupt was generated */
- req = locomo_readl(lchip->base + LOCOMO_ICR) & 0x0f00;
+ req = ioread16(lchip->base + LOCOMO_ICR) & 0x0f00;
if (req) {
/* generate the next interrupt(s) */
@@ -168,19 +169,21 @@ static void locomo_ack_irq(struct irq_data *d)
static void locomo_mask_irq(struct irq_data *d)
{
struct locomo *lchip = irq_data_get_irq_chip_data(d);
- unsigned int r;
- r = locomo_readl(lchip->base + LOCOMO_ICR);
+ u16 r;
+
+ r = ioread16(lchip->base + LOCOMO_ICR);
r &= ~(0x0010 << (d->irq - lchip->irq_base));
- locomo_writel(r, lchip->base + LOCOMO_ICR);
+ iowrite16(r, lchip->base + LOCOMO_ICR);
}
static void locomo_unmask_irq(struct irq_data *d)
{
struct locomo *lchip = irq_data_get_irq_chip_data(d);
- unsigned int r;
- r = locomo_readl(lchip->base + LOCOMO_ICR);
+ u16 r;
+
+ r = ioread16(lchip->base + LOCOMO_ICR);
r |= (0x0010 << (d->irq - lchip->irq_base));
- locomo_writel(r, lchip->base + LOCOMO_ICR);
+ iowrite16(r, lchip->base + LOCOMO_ICR);
}
static struct irq_chip locomo_chip = {
@@ -265,11 +268,11 @@ locomo_init_one_child(struct locomo *lchip, struct locomo_dev_info *info)
#ifdef CONFIG_PM
struct locomo_save_data {
- u16 LCM_GPO;
- u16 LCM_SPICT;
- u16 LCM_GPE;
- u16 LCM_ASD;
- u16 LCM_SPIMD;
+ u16 LCM_GPO; /* GPIO */
+ u16 LCM_SPICT; /* SPI */
+ u16 LCM_GPE; /* GPIO */
+ u16 LCM_ASD; /* ADSTART */
+ u16 LCM_SPIMD; /* SPI */
};
static int locomo_suspend(struct platform_device *dev, pm_message_t state)
@@ -286,30 +289,31 @@ static int locomo_suspend(struct platform_device *dev, pm_message_t state)
spin_lock_irqsave(&lchip->lock, flags);
- save->LCM_GPO = locomo_readl(lchip->base + LOCOMO_GPO); /* GPIO */
- locomo_writel(0x00, lchip->base + LOCOMO_GPO);
- save->LCM_SPICT = locomo_readl(lchip->base + LOCOMO_SPI + LOCOMO_SPICT); /* SPI */
- locomo_writel(0x40, lchip->base + LOCOMO_SPI + LOCOMO_SPICT);
- save->LCM_GPE = locomo_readl(lchip->base + LOCOMO_GPE); /* GPIO */
- locomo_writel(0x00, lchip->base + LOCOMO_GPE);
- save->LCM_ASD = locomo_readl(lchip->base + LOCOMO_ASD); /* ADSTART */
- locomo_writel(0x00, lchip->base + LOCOMO_ASD);
- save->LCM_SPIMD = locomo_readl(lchip->base + LOCOMO_SPI + LOCOMO_SPIMD); /* SPI */
- locomo_writel(0x3C14, lchip->base + LOCOMO_SPI + LOCOMO_SPIMD);
-
- locomo_writel(0x00, lchip->base + LOCOMO_PAIF);
- locomo_writel(0x00, lchip->base + LOCOMO_DAC);
- locomo_writel(0x00, lchip->base + LOCOMO_BACKLIGHT + LOCOMO_TC);
-
- if ((locomo_readl(lchip->base + LOCOMO_LED + LOCOMO_LPT0) & 0x88) && (locomo_readl(lchip->base + LOCOMO_LED + LOCOMO_LPT1) & 0x88))
- locomo_writel(0x00, lchip->base + LOCOMO_C32K); /* CLK32 off */
+ save->LCM_GPO = ioread16(lchip->base + LOCOMO_GPO);
+ save->LCM_SPICT = ioread16(lchip->base + LOCOMO_SPI + LOCOMO_SPICT);
+ save->LCM_GPE = ioread16(lchip->base + LOCOMO_GPE);
+ save->LCM_ASD = ioread16(lchip->base + LOCOMO_ASD);
+ save->LCM_SPIMD = ioread16(lchip->base + LOCOMO_SPI + LOCOMO_SPIMD);
+ iowrite16(0x00, lchip->base + LOCOMO_GPO);
+ iowrite16(0x40, lchip->base + LOCOMO_SPI + LOCOMO_SPICT);
+ iowrite16(0x00, lchip->base + LOCOMO_GPE);
+ iowrite16(0x00, lchip->base + LOCOMO_ASD);
+ iowrite16(0x3C14, lchip->base + LOCOMO_SPI + LOCOMO_SPIMD);
+
+ iowrite16(0x00, lchip->base + LOCOMO_PAIF);
+ iowrite16(0x00, lchip->base + LOCOMO_DAC);
+ iowrite16(0x00, lchip->base + LOCOMO_BACKLIGHT + LOCOMO_TC);
+
+ if ((ioread16(lchip->base + LOCOMO_LED + LOCOMO_LPT0) & 0x88) &&
+ (ioread16(lchip->base + LOCOMO_LED + LOCOMO_LPT1) & 0x88))
+ iowrite16(0x00, lchip->base + LOCOMO_C32K); /* CLK32 off */
else
/* 18MHz already enabled, so no wait */
- locomo_writel(0xc1, lchip->base + LOCOMO_C32K); /* CLK32 on */
+ iowrite16(0xc1, lchip->base + LOCOMO_C32K); /* CLK32 on */
- locomo_writel(0x00, lchip->base + LOCOMO_TADC); /* 18MHz clock off*/
- locomo_writel(0x00, lchip->base + LOCOMO_AUDIO + LOCOMO_ACC); /* 22MHz/24MHz clock off */
- locomo_writel(0x00, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALS); /* FL */
+ iowrite16(0x00, lchip->base + LOCOMO_TADC); /* 18MHz clock off*/
+ iowrite16(0x00, lchip->base + LOCOMO_AUDIO + LOCOMO_ACC); /* 22MHz/24MHz clock off */
+ iowrite16(0x00, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALS); /* FL */
spin_unlock_irqrestore(&lchip->lock, flags);
@@ -320,7 +324,7 @@ static int locomo_resume(struct platform_device *dev)
{
struct locomo *lchip = platform_get_drvdata(dev);
struct locomo_save_data *save;
- unsigned long r;
+ u16 r;
unsigned long flags;
save = lchip->saved_state;
@@ -329,20 +333,20 @@ static int locomo_resume(struct platform_device *dev)
spin_lock_irqsave(&lchip->lock, flags);
- locomo_writel(save->LCM_GPO, lchip->base + LOCOMO_GPO);
- locomo_writel(save->LCM_SPICT, lchip->base + LOCOMO_SPI + LOCOMO_SPICT);
- locomo_writel(save->LCM_GPE, lchip->base + LOCOMO_GPE);
- locomo_writel(save->LCM_ASD, lchip->base + LOCOMO_ASD);
- locomo_writel(save->LCM_SPIMD, lchip->base + LOCOMO_SPI + LOCOMO_SPIMD);
+ iowrite16(save->LCM_GPO, lchip->base + LOCOMO_GPO);
+ iowrite16(save->LCM_SPICT, lchip->base + LOCOMO_SPI + LOCOMO_SPICT);
+ iowrite16(save->LCM_GPE, lchip->base + LOCOMO_GPE);
+ iowrite16(save->LCM_ASD, lchip->base + LOCOMO_ASD);
+ iowrite16(save->LCM_SPIMD, lchip->base + LOCOMO_SPI + LOCOMO_SPIMD);
- locomo_writel(0x00, lchip->base + LOCOMO_C32K);
- locomo_writel(0x90, lchip->base + LOCOMO_TADC);
+ iowrite16(0x00, lchip->base + LOCOMO_C32K);
+ iowrite16(0x90, lchip->base + LOCOMO_TADC);
- locomo_writel(0, lchip->base + LOCOMO_KEYBOARD + LOCOMO_KSC);
- r = locomo_readl(lchip->base + LOCOMO_KEYBOARD + LOCOMO_KIC);
+ iowrite16(0, lchip->base + LOCOMO_KEYBOARD + LOCOMO_KSC);
+ r = ioread16(lchip->base + LOCOMO_KEYBOARD + LOCOMO_KIC);
r &= 0xFEFF;
- locomo_writel(r, lchip->base + LOCOMO_KEYBOARD + LOCOMO_KIC);
- locomo_writel(0x1, lchip->base + LOCOMO_KEYBOARD + LOCOMO_KCMD);
+ iowrite16(r, lchip->base + LOCOMO_KEYBOARD + LOCOMO_KIC);
+ iowrite16(0x1, lchip->base + LOCOMO_KEYBOARD + LOCOMO_KCMD);
spin_unlock_irqrestore(&lchip->lock, flags);
@@ -371,7 +375,7 @@ __locomo_probe(struct device *me, struct resource *mem, int irq)
{
struct locomo_platform_data *pdata = me->platform_data;
struct locomo *lchip;
- unsigned long r;
+ u16 r;
int i, ret = -ENODEV;
lchip = kzalloc(sizeof(struct locomo), GFP_KERNEL);
@@ -398,54 +402,53 @@ __locomo_probe(struct device *me, struct resource *mem, int irq)
}
/* locomo initialize */
- locomo_writel(0, lchip->base + LOCOMO_ICR);
+ iowrite16(0, lchip->base + LOCOMO_ICR);
/* KEYBOARD */
- locomo_writel(0, lchip->base + LOCOMO_KEYBOARD + LOCOMO_KIC);
+ iowrite16(0, lchip->base + LOCOMO_KEYBOARD + LOCOMO_KIC);
/* GPIO */
- locomo_writel(0, lchip->base + LOCOMO_GPO);
- locomo_writel((LOCOMO_GPIO(1) | LOCOMO_GPIO(2) | LOCOMO_GPIO(13) | LOCOMO_GPIO(14))
- , lchip->base + LOCOMO_GPE);
- locomo_writel((LOCOMO_GPIO(1) | LOCOMO_GPIO(2) | LOCOMO_GPIO(13) | LOCOMO_GPIO(14))
- , lchip->base + LOCOMO_GPD);
- locomo_writel(0, lchip->base + LOCOMO_GIE);
+ iowrite16(0, lchip->base + LOCOMO_GPO);
+ r = LOCOMO_GPIO(1) | LOCOMO_GPIO(2) | LOCOMO_GPIO(13) | LOCOMO_GPIO(14);
+ iowrite16(r, lchip->base + LOCOMO_GPE);
+ iowrite16(r, lchip->base + LOCOMO_GPD);
+ iowrite16(0, lchip->base + LOCOMO_GIE);
/* Frontlight */
- locomo_writel(0, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALS);
- locomo_writel(0, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALD);
+ iowrite16(0, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALS);
+ iowrite16(0, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALD);
/* Longtime timer */
- locomo_writel(0, lchip->base + LOCOMO_LTINT);
+ iowrite16(0, lchip->base + LOCOMO_LTINT);
/* SPI */
- locomo_writel(0, lchip->base + LOCOMO_SPI + LOCOMO_SPIIE);
+ iowrite16(0, lchip->base + LOCOMO_SPI + LOCOMO_SPIIE);
- locomo_writel(6 + 8 + 320 + 30 - 10, lchip->base + LOCOMO_ASD);
- r = locomo_readl(lchip->base + LOCOMO_ASD);
+ iowrite16(6 + 8 + 320 + 30 - 10, lchip->base + LOCOMO_ASD);
+ r = ioread16(lchip->base + LOCOMO_ASD);
r |= 0x8000;
- locomo_writel(r, lchip->base + LOCOMO_ASD);
+ iowrite16(r, lchip->base + LOCOMO_ASD);
- locomo_writel(6 + 8 + 320 + 30 - 10 - 128 + 4, lchip->base + LOCOMO_HSD);
- r = locomo_readl(lchip->base + LOCOMO_HSD);
+ iowrite16(6 + 8 + 320 + 30 - 10 - 128 + 4, lchip->base + LOCOMO_HSD);
+ r = ioread16(lchip->base + LOCOMO_HSD);
r |= 0x8000;
- locomo_writel(r, lchip->base + LOCOMO_HSD);
+ iowrite16(r, lchip->base + LOCOMO_HSD);
- locomo_writel(128 / 8, lchip->base + LOCOMO_HSC);
+ iowrite16(128 / 8, lchip->base + LOCOMO_HSC);
/* XON */
- locomo_writel(0x80, lchip->base + LOCOMO_TADC);
+ iowrite16(0x80, lchip->base + LOCOMO_TADC);
udelay(1000);
/* CLK9MEN */
- r = locomo_readl(lchip->base + LOCOMO_TADC);
+ r = ioread16(lchip->base + LOCOMO_TADC);
r |= 0x10;
- locomo_writel(r, lchip->base + LOCOMO_TADC);
+ iowrite16(r, lchip->base + LOCOMO_TADC);
udelay(100);
/* init DAC */
- r = locomo_readl(lchip->base + LOCOMO_DAC);
+ r = ioread16(lchip->base + LOCOMO_DAC);
r |= LOCOMO_DAC_SCLOEB | LOCOMO_DAC_SDAOEB;
- locomo_writel(r, lchip->base + LOCOMO_DAC);
+ iowrite16(r, lchip->base + LOCOMO_DAC);
- r = locomo_readl(lchip->base + LOCOMO_VER);
+ r = ioread16(lchip->base + LOCOMO_VER);
printk(KERN_INFO "LoCoMo Chip: %lu%lu\n", (r >> 8), (r & 0xff));
/*
@@ -541,26 +544,26 @@ void locomo_gpio_set_dir(struct device *dev, unsigned int bits, unsigned int dir
{
struct locomo *lchip = dev_get_drvdata(dev);
unsigned long flags;
- unsigned int r;
+ u16 r;
if (!lchip)
return;
spin_lock_irqsave(&lchip->lock, flags);
- r = locomo_readl(lchip->base + LOCOMO_GPD);
+ r = ioread16(lchip->base + LOCOMO_GPD);
if (dir)
r |= bits;
else
r &= ~bits;
- locomo_writel(r, lchip->base + LOCOMO_GPD);
+ iowrite16(r, lchip->base + LOCOMO_GPD);
- r = locomo_readl(lchip->base + LOCOMO_GPE);
+ r = ioread16(lchip->base + LOCOMO_GPE);
if (dir)
r |= bits;
else
r &= ~bits;
- locomo_writel(r, lchip->base + LOCOMO_GPE);
+ iowrite16(r, lchip->base + LOCOMO_GPE);
spin_unlock_irqrestore(&lchip->lock, flags);
}
@@ -570,13 +573,13 @@ int locomo_gpio_read_level(struct device *dev, unsigned int bits)
{
struct locomo *lchip = dev_get_drvdata(dev);
unsigned long flags;
- unsigned int ret;
+ u16 ret;
if (!lchip)
return -ENODEV;
spin_lock_irqsave(&lchip->lock, flags);
- ret = locomo_readl(lchip->base + LOCOMO_GPL);
+ ret = ioread16(lchip->base + LOCOMO_GPL);
spin_unlock_irqrestore(&lchip->lock, flags);
ret &= bits;
@@ -588,13 +591,13 @@ int locomo_gpio_read_output(struct device *dev, unsigned int bits)
{
struct locomo *lchip = dev_get_drvdata(dev);
unsigned long flags;
- unsigned int ret;
+ u16 ret;
if (!lchip)
return -ENODEV;
spin_lock_irqsave(&lchip->lock, flags);
- ret = locomo_readl(lchip->base + LOCOMO_GPO);
+ ret = ioread16(lchip->base + LOCOMO_GPO);
spin_unlock_irqrestore(&lchip->lock, flags);
ret &= bits;
@@ -606,19 +609,19 @@ void locomo_gpio_write(struct device *dev, unsigned int bits, unsigned int set)
{
struct locomo *lchip = dev_get_drvdata(dev);
unsigned long flags;
- unsigned int r;
+ u16 r;
if (!lchip)
return;
spin_lock_irqsave(&lchip->lock, flags);
- r = locomo_readl(lchip->base + LOCOMO_GPO);
+ r = ioread16(lchip->base + LOCOMO_GPO);
if (set)
r |= bits;
else
r &= ~bits;
- locomo_writel(r, lchip->base + LOCOMO_GPO);
+ iowrite16(r, lchip->base + LOCOMO_GPO);
spin_unlock_irqrestore(&lchip->lock, flags);
}
@@ -626,35 +629,35 @@ EXPORT_SYMBOL(locomo_gpio_write);
static void locomo_m62332_sendbit(void *mapbase, int bit)
{
- unsigned int r;
+ u16 r;
- r = locomo_readl(mapbase + LOCOMO_DAC);
+ r = ioread16(mapbase + LOCOMO_DAC);
r &= ~(LOCOMO_DAC_SCLOEB);
- locomo_writel(r, mapbase + LOCOMO_DAC);
+ iowrite16(r, mapbase + LOCOMO_DAC);
udelay(DAC_LOW_SETUP_TIME); /* 300 nsec */
udelay(DAC_DATA_HOLD_TIME); /* 300 nsec */
- r = locomo_readl(mapbase + LOCOMO_DAC);
+ r = ioread16(mapbase + LOCOMO_DAC);
r &= ~(LOCOMO_DAC_SCLOEB);
- locomo_writel(r, mapbase + LOCOMO_DAC);
+ iowrite16(r, mapbase + LOCOMO_DAC);
udelay(DAC_LOW_SETUP_TIME); /* 300 nsec */
udelay(DAC_SCL_LOW_HOLD_TIME); /* 4.7 usec */
if (bit & 1) {
- r = locomo_readl(mapbase + LOCOMO_DAC);
+ r = ioread16(mapbase + LOCOMO_DAC);
r |= LOCOMO_DAC_SDAOEB;
- locomo_writel(r, mapbase + LOCOMO_DAC);
+ iowrite16(r, mapbase + LOCOMO_DAC);
udelay(DAC_HIGH_SETUP_TIME); /* 1000 nsec */
} else {
- r = locomo_readl(mapbase + LOCOMO_DAC);
+ r = ioread16(mapbase + LOCOMO_DAC);
r &= ~(LOCOMO_DAC_SDAOEB);
- locomo_writel(r, mapbase + LOCOMO_DAC);
+ iowrite16(r, mapbase + LOCOMO_DAC);
udelay(DAC_LOW_SETUP_TIME); /* 300 nsec */
}
udelay(DAC_DATA_SETUP_TIME); /* 250 nsec */
- r = locomo_readl(mapbase + LOCOMO_DAC);
+ r = ioread16(mapbase + LOCOMO_DAC);
r |= LOCOMO_DAC_SCLOEB;
- locomo_writel(r, mapbase + LOCOMO_DAC);
+ iowrite16(r, mapbase + LOCOMO_DAC);
udelay(DAC_HIGH_SETUP_TIME); /* 1000 nsec */
udelay(DAC_SCL_HIGH_HOLD_TIME); /* 4.0 usec */
}
@@ -664,7 +667,7 @@ void locomo_m62332_senddata(struct locomo_dev *ldev, unsigned int dac_data, int
struct locomo *lchip = locomo_chip_driver(ldev);
int i;
unsigned char data;
- unsigned int r;
+ u16 r;
void *mapbase = lchip->base;
unsigned long flags;
@@ -672,14 +675,14 @@ void locomo_m62332_senddata(struct locomo_dev *ldev, unsigned int dac_data, int
/* Start */
udelay(DAC_BUS_FREE_TIME); /* 5.0 usec */
- r = locomo_readl(mapbase + LOCOMO_DAC);
+ r = ioread16(mapbase + LOCOMO_DAC);
r |= LOCOMO_DAC_SCLOEB | LOCOMO_DAC_SDAOEB;
- locomo_writel(r, mapbase + LOCOMO_DAC);
+ iowrite16(r, mapbase + LOCOMO_DAC);
udelay(DAC_HIGH_SETUP_TIME); /* 1000 nsec */
udelay(DAC_SCL_HIGH_HOLD_TIME); /* 4.0 usec */
- r = locomo_readl(mapbase + LOCOMO_DAC);
+ r = ioread16(mapbase + LOCOMO_DAC);
r &= ~(LOCOMO_DAC_SDAOEB);
- locomo_writel(r, mapbase + LOCOMO_DAC);
+ iowrite16(r, mapbase + LOCOMO_DAC);
udelay(DAC_START_HOLD_TIME); /* 5.0 usec */
udelay(DAC_DATA_HOLD_TIME); /* 300 nsec */
@@ -690,21 +693,21 @@ void locomo_m62332_senddata(struct locomo_dev *ldev, unsigned int dac_data, int
}
/* Check A bit */
- r = locomo_readl(mapbase + LOCOMO_DAC);
+ r = ioread16(mapbase + LOCOMO_DAC);
r &= ~(LOCOMO_DAC_SCLOEB);
- locomo_writel(r, mapbase + LOCOMO_DAC);
+ iowrite16(r, mapbase + LOCOMO_DAC);
udelay(DAC_LOW_SETUP_TIME); /* 300 nsec */
udelay(DAC_SCL_LOW_HOLD_TIME); /* 4.7 usec */
- r = locomo_readl(mapbase + LOCOMO_DAC);
+ r = ioread16(mapbase + LOCOMO_DAC);
r &= ~(LOCOMO_DAC_SDAOEB);
- locomo_writel(r, mapbase + LOCOMO_DAC);
+ iowrite16(r, mapbase + LOCOMO_DAC);
udelay(DAC_LOW_SETUP_TIME); /* 300 nsec */
- r = locomo_readl(mapbase + LOCOMO_DAC);
+ r = ioread16(mapbase + LOCOMO_DAC);
r |= LOCOMO_DAC_SCLOEB;
- locomo_writel(r, mapbase + LOCOMO_DAC);
+ iowrite16(r, mapbase + LOCOMO_DAC);
udelay(DAC_HIGH_SETUP_TIME); /* 1000 nsec */
udelay(DAC_SCL_HIGH_HOLD_TIME); /* 4.7 usec */
- if (locomo_readl(mapbase + LOCOMO_DAC) & LOCOMO_DAC_SDAOEB) { /* High is error */
+ if (ioread16(mapbase + LOCOMO_DAC) & LOCOMO_DAC_SDAOEB) { /* High is error */
printk(KERN_WARNING "locomo: m62332_senddata Error 1\n");
goto out;
}
@@ -718,21 +721,21 @@ void locomo_m62332_senddata(struct locomo_dev *ldev, unsigned int dac_data, int
}
/* Check A bit */
- r = locomo_readl(mapbase + LOCOMO_DAC);
+ r = ioread16(mapbase + LOCOMO_DAC);
r &= ~(LOCOMO_DAC_SCLOEB);
- locomo_writel(r, mapbase + LOCOMO_DAC);
+ iowrite16(r, mapbase + LOCOMO_DAC);
udelay(DAC_LOW_SETUP_TIME); /* 300 nsec */
udelay(DAC_SCL_LOW_HOLD_TIME); /* 4.7 usec */
- r = locomo_readl(mapbase + LOCOMO_DAC);
+ r = ioread16(mapbase + LOCOMO_DAC);
r &= ~(LOCOMO_DAC_SDAOEB);
- locomo_writel(r, mapbase + LOCOMO_DAC);
+ iowrite16(r, mapbase + LOCOMO_DAC);
udelay(DAC_LOW_SETUP_TIME); /* 300 nsec */
- r = locomo_readl(mapbase + LOCOMO_DAC);
+ r = ioread16(mapbase + LOCOMO_DAC);
r |= LOCOMO_DAC_SCLOEB;
- locomo_writel(r, mapbase + LOCOMO_DAC);
+ iowrite16(r, mapbase + LOCOMO_DAC);
udelay(DAC_HIGH_SETUP_TIME); /* 1000 nsec */
udelay(DAC_SCL_HIGH_HOLD_TIME); /* 4.7 usec */
- if (locomo_readl(mapbase + LOCOMO_DAC) & LOCOMO_DAC_SDAOEB) { /* High is error */
+ if (ioread16(mapbase + LOCOMO_DAC) & LOCOMO_DAC_SDAOEB) { /* High is error */
printk(KERN_WARNING "locomo: m62332_senddata Error 2\n");
goto out;
}
@@ -743,45 +746,45 @@ void locomo_m62332_senddata(struct locomo_dev *ldev, unsigned int dac_data, int
}
/* Check A bit */
- r = locomo_readl(mapbase + LOCOMO_DAC);
+ r = ioread16(mapbase + LOCOMO_DAC);
r &= ~(LOCOMO_DAC_SCLOEB);
- locomo_writel(r, mapbase + LOCOMO_DAC);
+ iowrite16(r, mapbase + LOCOMO_DAC);
udelay(DAC_LOW_SETUP_TIME); /* 300 nsec */
udelay(DAC_SCL_LOW_HOLD_TIME); /* 4.7 usec */
- r = locomo_readl(mapbase + LOCOMO_DAC);
+ r = ioread16(mapbase + LOCOMO_DAC);
r &= ~(LOCOMO_DAC_SDAOEB);
- locomo_writel(r, mapbase + LOCOMO_DAC);
+ iowrite16(r, mapbase + LOCOMO_DAC);
udelay(DAC_LOW_SETUP_TIME); /* 300 nsec */
- r = locomo_readl(mapbase + LOCOMO_DAC);
+ r = ioread16(mapbase + LOCOMO_DAC);
r |= LOCOMO_DAC_SCLOEB;
- locomo_writel(r, mapbase + LOCOMO_DAC);
+ iowrite16(r, mapbase + LOCOMO_DAC);
udelay(DAC_HIGH_SETUP_TIME); /* 1000 nsec */
udelay(DAC_SCL_HIGH_HOLD_TIME); /* 4.7 usec */
- if (locomo_readl(mapbase + LOCOMO_DAC) & LOCOMO_DAC_SDAOEB) { /* High is error */
+ if (ioread16(mapbase + LOCOMO_DAC) & LOCOMO_DAC_SDAOEB) { /* High is error */
printk(KERN_WARNING "locomo: m62332_senddata Error 3\n");
}
out:
/* stop */
- r = locomo_readl(mapbase + LOCOMO_DAC);
+ r = ioread16(mapbase + LOCOMO_DAC);
r &= ~(LOCOMO_DAC_SCLOEB);
- locomo_writel(r, mapbase + LOCOMO_DAC);
+ iowrite16(r, mapbase + LOCOMO_DAC);
udelay(DAC_LOW_SETUP_TIME); /* 300 nsec */
udelay(DAC_SCL_LOW_HOLD_TIME); /* 4.7 usec */
- r = locomo_readl(mapbase + LOCOMO_DAC);
+ r = ioread16(mapbase + LOCOMO_DAC);
r |= LOCOMO_DAC_SCLOEB;
- locomo_writel(r, mapbase + LOCOMO_DAC);
+ iowrite16(r, mapbase + LOCOMO_DAC);
udelay(DAC_HIGH_SETUP_TIME); /* 1000 nsec */
udelay(DAC_SCL_HIGH_HOLD_TIME); /* 4 usec */
- r = locomo_readl(mapbase + LOCOMO_DAC);
+ r = ioread16(mapbase + LOCOMO_DAC);
r |= LOCOMO_DAC_SDAOEB;
- locomo_writel(r, mapbase + LOCOMO_DAC);
+ iowrite16(r, mapbase + LOCOMO_DAC);
udelay(DAC_HIGH_SETUP_TIME); /* 1000 nsec */
udelay(DAC_SCL_HIGH_HOLD_TIME); /* 4 usec */
- r = locomo_readl(mapbase + LOCOMO_DAC);
+ r = ioread16(mapbase + LOCOMO_DAC);
r |= LOCOMO_DAC_SCLOEB | LOCOMO_DAC_SDAOEB;
- locomo_writel(r, mapbase + LOCOMO_DAC);
+ iowrite16(r, mapbase + LOCOMO_DAC);
udelay(DAC_LOW_SETUP_TIME); /* 1000 nsec */
udelay(DAC_SCL_LOW_HOLD_TIME); /* 4.7 usec */
@@ -804,10 +807,10 @@ void locomo_frontlight_set(struct locomo_dev *dev, int duty, int vr, int bpwf)
locomo_gpio_write(dev->dev.parent, LOCOMO_GPIO_FL_VR, 0);
spin_lock_irqsave(&lchip->lock, flags);
- locomo_writel(bpwf, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALS);
+ iowrite16(bpwf, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALS);
udelay(100);
- locomo_writel(duty, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALD);
- locomo_writel(bpwf | LOCOMO_ALC_EN, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALS);
+ iowrite16(duty, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALD);
+ iowrite16(bpwf | LOCOMO_ALC_EN, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALS);
spin_unlock_irqrestore(&lchip->lock, flags);
}
EXPORT_SYMBOL(locomo_frontlight_set);
diff --git a/arch/arm/include/asm/hardware/locomo.h b/arch/arm/include/asm/hardware/locomo.h
index 74e51d6..dc90c21 100644
--- a/arch/arm/include/asm/hardware/locomo.h
+++ b/arch/arm/include/asm/hardware/locomo.h
@@ -13,9 +13,6 @@
#ifndef _ASM_ARCH_LOCOMO
#define _ASM_ARCH_LOCOMO
-#define locomo_writel(val,addr) ({ *(volatile u16 *)(addr) = (val); })
-#define locomo_readl(addr) (*(volatile u16 *)(addr))
-
/* LOCOMO version */
#define LOCOMO_VER 0x00
diff --git a/drivers/input/keyboard/locomokbd.c b/drivers/input/keyboard/locomokbd.c
index b1ab298..ddb9595 100644
--- a/drivers/input/keyboard/locomokbd.c
+++ b/drivers/input/keyboard/locomokbd.c
@@ -31,6 +31,7 @@
#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
+#include <linux/io.h>
#include <asm/hardware/locomo.h>
#include <asm/irq.h>
@@ -86,35 +87,35 @@ struct locomokbd {
/* helper functions for reading the keyboard matrix */
static inline void locomokbd_charge_all(unsigned long membase)
{
- locomo_writel(0x00FF, membase + LOCOMO_KSC);
+ iowrite16(0x00FF, membase + LOCOMO_KSC);
}
static inline void locomokbd_activate_all(unsigned long membase)
{
- unsigned long r;
+ u16 r;
- locomo_writel(0, membase + LOCOMO_KSC);
- r = locomo_readl(membase + LOCOMO_KIC);
+ iowrite16(0, membase + LOCOMO_KSC);
+ r = ioread16(membase + LOCOMO_KIC);
r &= 0xFEFF;
- locomo_writel(r, membase + LOCOMO_KIC);
+ iowrite16(r, membase + LOCOMO_KIC);
}
static inline void locomokbd_activate_col(unsigned long membase, int col)
{
- unsigned short nset;
- unsigned short nbset;
+ u16 nset;
+ u16 nbset;
nset = 0xFF & ~(1 << col);
nbset = (nset << 8) + nset;
- locomo_writel(nbset, membase + LOCOMO_KSC);
+ iowrite16(nbset, membase + LOCOMO_KSC);
}
static inline void locomokbd_reset_col(unsigned long membase, int col)
{
- unsigned short nbset;
+ u16 nbset;
nbset = ((0xFF & ~(1 << col)) << 8) + 0xFF;
- locomo_writel(nbset, membase + LOCOMO_KSC);
+ iowrite16(nbset, membase + LOCOMO_KSC);
}
/*
@@ -126,7 +127,7 @@ static inline void locomokbd_reset_col(unsigned long membase, int col)
/* Scan the hardware keyboard and push any changes up through the input layer */
static void locomokbd_scankeyboard(struct locomokbd *locomokbd)
{
- unsigned int row, col, rowd;
+ u16 row, col, rowd;
unsigned long flags;
unsigned int num_pressed;
unsigned long membase = locomokbd->base;
@@ -141,7 +142,7 @@ static void locomokbd_scankeyboard(struct locomokbd *locomokbd)
locomokbd_activate_col(membase, col);
udelay(KB_DELAY);
- rowd = ~locomo_readl(membase + LOCOMO_KIB);
+ rowd = ~ioread16(membase + LOCOMO_KIB);
for (row = 0; row < KB_ROWS; row++) {
unsigned int scancode, pressed, key;
@@ -194,11 +195,11 @@ static irqreturn_t locomokbd_interrupt(int irq, void *dev_id)
struct locomokbd *locomokbd = dev_id;
u16 r;
- r = locomo_readl(locomokbd->base + LOCOMO_KIC);
+ r = ioread16(locomokbd->base + LOCOMO_KIC);
if ((r & 0x0001) = 0)
return IRQ_HANDLED;
- locomo_writel(r & ~0x0100, locomokbd->base + LOCOMO_KIC); /* Ack */
+ iowrite16(r & ~0x0100, locomokbd->base + LOCOMO_KIC); /* Ack */
/** wait chattering delay **/
udelay(100);
@@ -222,8 +223,8 @@ static int locomokbd_open(struct input_dev *dev)
struct locomokbd *locomokbd = input_get_drvdata(dev);
u16 r;
- r = locomo_readl(locomokbd->base + LOCOMO_KIC) | 0x0010;
- locomo_writel(r, locomokbd->base + LOCOMO_KIC);
+ r = ioread16(locomokbd->base + LOCOMO_KIC) | 0x0010;
+ iowrite16(r, locomokbd->base + LOCOMO_KIC);
return 0;
}
@@ -232,8 +233,8 @@ static void locomokbd_close(struct input_dev *dev)
struct locomokbd *locomokbd = input_get_drvdata(dev);
u16 r;
- r = locomo_readl(locomokbd->base + LOCOMO_KIC) & ~0x0010;
- locomo_writel(r, locomokbd->base + LOCOMO_KIC);
+ r = ioread16(locomokbd->base + LOCOMO_KIC) & ~0x0010;
+ iowrite16(r, locomokbd->base + LOCOMO_KIC);
}
static int __devinit locomokbd_probe(struct locomo_dev *dev)
diff --git a/drivers/leds/leds-locomo.c b/drivers/leds/leds-locomo.c
index 1f7c10f..6cc6b69 100644
--- a/drivers/leds/leds-locomo.c
+++ b/drivers/leds/leds-locomo.c
@@ -12,6 +12,7 @@
#include <linux/init.h>
#include <linux/device.h>
#include <linux/leds.h>
+#include <linux/io.h>
#include <mach/hardware.h>
#include <asm/hardware/locomo.h>
@@ -24,9 +25,9 @@ static void locomoled_brightness_set(struct led_classdev *led_cdev,
local_irq_save(flags);
if (value)
- locomo_writel(LOCOMO_LPT_TOFH, locomo_dev->mapbase + offset);
+ iowrite16(LOCOMO_LPT_TOFH, locomo_dev->mapbase + offset);
else
- locomo_writel(LOCOMO_LPT_TOFL, locomo_dev->mapbase + offset);
+ iowrite16(LOCOMO_LPT_TOFL, locomo_dev->mapbase + offset);
local_irq_restore(flags);
}
diff --git a/drivers/video/backlight/locomolcd.c b/drivers/video/backlight/locomolcd.c
index be20b5c..37f325c 100644
--- a/drivers/video/backlight/locomolcd.c
+++ b/drivers/video/backlight/locomolcd.c
@@ -18,6 +18,7 @@
#include <linux/interrupt.h>
#include <linux/fb.h>
#include <linux/backlight.h>
+#include <linux/io.h>
#include <asm/hardware/locomo.h>
#include <asm/irq.h>
@@ -49,13 +50,13 @@ static void locomolcd_on(int comadj)
mdelay(10);
/* TFTCRST | CPSOUT=0 | CPSEN */
- locomo_writel(0x01, locomolcd_dev->mapbase + LOCOMO_TC);
+ iowrite16(0x01, locomolcd_dev->mapbase + LOCOMO_TC);
/* Set CPSD */
- locomo_writel(6, locomolcd_dev->mapbase + LOCOMO_CPSD);
+ iowrite16(6, locomolcd_dev->mapbase + LOCOMO_CPSD);
/* TFTCRST | CPSOUT=0 | CPSEN */
- locomo_writel((0x04 | 0x01), locomolcd_dev->mapbase + LOCOMO_TC);
+ iowrite16((0x04 | 0x01), locomolcd_dev->mapbase + LOCOMO_TC);
mdelay(10);
locomo_gpio_set_dir(locomolcd_dev->dev.parent, LOCOMO_GPIO_LCD_MOD, 0);
@@ -65,7 +66,7 @@ static void locomolcd_on(int comadj)
static void locomolcd_off(int comadj)
{
/* TFTCRST=1 | CPSOUT=1 | CPSEN = 0 */
- locomo_writel(0x06, locomolcd_dev->mapbase + LOCOMO_TC);
+ iowrite16(0x06, locomolcd_dev->mapbase + LOCOMO_TC);
mdelay(1);
locomo_gpio_write(locomolcd_dev->dev.parent, LOCOMO_GPIO_LCD_VSHA_ON, 0);
@@ -75,7 +76,7 @@ static void locomolcd_off(int comadj)
mdelay(700);
/* TFTCRST=0 | CPSOUT=0 | CPSEN = 0 */
- locomo_writel(0, locomolcd_dev->mapbase + LOCOMO_TC);
+ iowrite16(0, locomolcd_dev->mapbase + LOCOMO_TC);
locomo_gpio_write(locomolcd_dev->dev.parent, LOCOMO_GPIO_LCD_MOD, 0);
locomo_gpio_write(locomolcd_dev->dev.parent, LOCOMO_GPIO_LCD_VSHD_ON, 0);
}
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox