aboutsummaryrefslogtreecommitdiff
path: root/drivers/video/pxafb.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/pxafb.c')
-rw-r--r--drivers/video/pxafb.c103
1 files changed, 81 insertions, 22 deletions
diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c
index 3ee314beacc..d0746261c95 100644
--- a/drivers/video/pxafb.c
+++ b/drivers/video/pxafb.c
@@ -573,8 +573,8 @@ static int setup_frame_dma(struct pxafb_info *fbi, int dma, int pal,
dma_desc->fdadr = fbi->dma_buff_phys + dma_desc_off;
fbi->fdadr[dma] = fbi->dma_buff_phys + dma_desc_off;
} else {
- pal_desc = &fbi->dma_buff->pal_desc[dma];
- pal_desc_off = offsetof(struct pxafb_dma_buff, dma_desc[pal]);
+ pal_desc = &fbi->dma_buff->pal_desc[pal];
+ pal_desc_off = offsetof(struct pxafb_dma_buff, pal_desc[pal]);
pal_desc->fsadr = fbi->dma_buff_phys + pal * PALETTE_SIZE;
pal_desc->fidr = 0;
@@ -1246,7 +1246,7 @@ static int pxafb_resume(struct platform_device *dev)
* cache. Once this area is remapped, all virtual memory
* access to the video memory should occur at the new region.
*/
-static int __init pxafb_map_video_memory(struct pxafb_info *fbi)
+static int __devinit pxafb_map_video_memory(struct pxafb_info *fbi)
{
/*
* We reserve one page for the palette, plus the size
@@ -1276,6 +1276,8 @@ static int __init pxafb_map_video_memory(struct pxafb_info *fbi)
fbi->dma_buff_phys = fbi->map_dma;
fbi->palette_cpu = (u16 *) fbi->dma_buff->palette;
+ pr_debug("pxafb: palette_mem_size = 0x%08lx\n", fbi->palette_size*sizeof(u16));
+
#ifdef CONFIG_FB_PXA_SMARTPANEL
fbi->smart_cmds = (uint16_t *) fbi->dma_buff->cmd_buff;
fbi->n_smart_cmds = 0;
@@ -1346,12 +1348,11 @@ decode_mode:
pxafb_decode_mode_info(fbi, inf->modes, inf->num_modes);
}
-static struct pxafb_info * __init pxafb_init_fbinfo(struct device *dev)
+static struct pxafb_info * __devinit pxafb_init_fbinfo(struct device *dev)
{
struct pxafb_info *fbi;
void *addr;
struct pxafb_mach_info *inf = dev->platform_data;
- struct pxafb_mode_info *mode = inf->modes;
/* Alloc the pxafb_info and pseudo_palette in one step */
fbi = kmalloc(sizeof(struct pxafb_info) + sizeof(u32) * 16, GFP_KERNEL);
@@ -1409,7 +1410,7 @@ static struct pxafb_info * __init pxafb_init_fbinfo(struct device *dev)
}
#ifdef CONFIG_FB_PXA_PARAMETERS
-static int __init parse_opt_mode(struct device *dev, const char *this_opt)
+static int __devinit parse_opt_mode(struct device *dev, const char *this_opt)
{
struct pxafb_mach_info *inf = dev->platform_data;
@@ -1468,7 +1469,7 @@ done:
return 0;
}
-static int __init parse_opt(struct device *dev, char *this_opt)
+static int __devinit parse_opt(struct device *dev, char *this_opt)
{
struct pxafb_mach_info *inf = dev->platform_data;
struct pxafb_mode_info *mode = &inf->modes[0];
@@ -1566,7 +1567,7 @@ static int __init parse_opt(struct device *dev, char *this_opt)
return 0;
}
-static int __init pxafb_parse_options(struct device *dev, char *options)
+static int __devinit pxafb_parse_options(struct device *dev, char *options)
{
char *this_opt;
int ret;
@@ -1587,8 +1588,8 @@ static int __init pxafb_parse_options(struct device *dev, char *options)
static char g_options[256] __devinitdata = "";
-#ifndef CONFIG_MODULES
-static int __devinit pxafb_setup_options(void)
+#ifndef MODULE
+static int __init pxafb_setup_options(void)
{
char *options = NULL;
@@ -1612,7 +1613,7 @@ MODULE_PARM_DESC(options, "LCD parameters (see Documentation/fb/pxafb.txt)");
#define pxafb_setup_options() (0)
#endif
-static int __init pxafb_probe(struct platform_device *dev)
+static int __devinit pxafb_probe(struct platform_device *dev)
{
struct pxafb_info *fbi;
struct pxafb_mach_info *inf;
@@ -1684,14 +1685,14 @@ static int __init pxafb_probe(struct platform_device *dev)
if (r == NULL) {
dev_err(&dev->dev, "no I/O memory resource defined\n");
ret = -ENODEV;
- goto failed;
+ goto failed_fbi;
}
r = request_mem_region(r->start, r->end - r->start + 1, dev->name);
if (r == NULL) {
dev_err(&dev->dev, "failed to request I/O memory\n");
ret = -EBUSY;
- goto failed;
+ goto failed_fbi;
}
fbi->mmio_base = ioremap(r->start, r->end - r->start + 1);
@@ -1734,8 +1735,17 @@ static int __init pxafb_probe(struct platform_device *dev)
* This makes sure that our colour bitfield
* descriptors are correctly initialised.
*/
- pxafb_check_var(&fbi->fb.var, &fbi->fb);
- pxafb_set_par(&fbi->fb);
+ ret = pxafb_check_var(&fbi->fb.var, &fbi->fb);
+ if (ret) {
+ dev_err(&dev->dev, "failed to get suitable mode\n");
+ goto failed_free_irq;
+ }
+
+ ret = pxafb_set_par(&fbi->fb);
+ if (ret) {
+ dev_err(&dev->dev, "Failed to set parameters\n");
+ goto failed_free_irq;
+ }
platform_set_drvdata(dev, fbi);
@@ -1743,7 +1753,7 @@ static int __init pxafb_probe(struct platform_device *dev)
if (ret < 0) {
dev_err(&dev->dev,
"Failed to register framebuffer device: %d\n", ret);
- goto failed_free_irq;
+ goto failed_free_cmap;
}
#ifdef CONFIG_CPU_FREQ
@@ -1762,31 +1772,74 @@ static int __init pxafb_probe(struct platform_device *dev)
return 0;
+failed_free_cmap:
+ if (fbi->fb.cmap.len)
+ fb_dealloc_cmap(&fbi->fb.cmap);
failed_free_irq:
free_irq(irq, fbi);
-failed_free_res:
- release_mem_region(r->start, r->end - r->start + 1);
-failed_free_io:
- iounmap(fbi->mmio_base);
failed_free_mem:
dma_free_writecombine(&dev->dev, fbi->map_size,
fbi->map_cpu, fbi->map_dma);
-failed:
+failed_free_io:
+ iounmap(fbi->mmio_base);
+failed_free_res:
+ release_mem_region(r->start, r->end - r->start + 1);
+failed_fbi:
+ clk_put(fbi->clk);
platform_set_drvdata(dev, NULL);
kfree(fbi);
+failed:
return ret;
}
+static int __devexit pxafb_remove(struct platform_device *dev)
+{
+ struct pxafb_info *fbi = platform_get_drvdata(dev);
+ struct resource *r;
+ int irq;
+ struct fb_info *info;
+
+ if (!fbi)
+ return 0;
+
+ info = &fbi->fb;
+
+ unregister_framebuffer(info);
+
+ pxafb_disable_controller(fbi);
+
+ if (fbi->fb.cmap.len)
+ fb_dealloc_cmap(&fbi->fb.cmap);
+
+ irq = platform_get_irq(dev, 0);
+ free_irq(irq, fbi);
+
+ dma_free_writecombine(&dev->dev, fbi->map_size,
+ fbi->map_cpu, fbi->map_dma);
+
+ iounmap(fbi->mmio_base);
+
+ r = platform_get_resource(dev, IORESOURCE_MEM, 0);
+ release_mem_region(r->start, r->end - r->start + 1);
+
+ clk_put(fbi->clk);
+ kfree(fbi);
+
+ return 0;
+}
+
static struct platform_driver pxafb_driver = {
.probe = pxafb_probe,
+ .remove = pxafb_remove,
.suspend = pxafb_suspend,
.resume = pxafb_resume,
.driver = {
+ .owner = THIS_MODULE,
.name = "pxa2xx-fb",
},
};
-static int __devinit pxafb_init(void)
+static int __init pxafb_init(void)
{
if (pxafb_setup_options())
return -EINVAL;
@@ -1794,7 +1847,13 @@ static int __devinit pxafb_init(void)
return platform_driver_register(&pxafb_driver);
}
+static void __exit pxafb_exit(void)
+{
+ platform_driver_unregister(&pxafb_driver);
+}
+
module_init(pxafb_init);
+module_exit(pxafb_exit);
MODULE_DESCRIPTION("loadable framebuffer driver for PXA");
MODULE_LICENSE("GPL");