X-Git-Url: http://pilppa.org/gitweb/gitweb.cgi?a=blobdiff_plain;f=drivers%2Fvideo%2Fleo.c;h=13fea61d6ae4cbf2bcdbca442eab84716e6e3499;hb=7ac9c1c24c0e68bdb89524e8c99e13fffcb2fcfb;hp=a23cfdb9d826391ff5d4007fb33f884da0d53f1c;hpb=21e2379b9ef705fcb3ba3be738decd3397fc30b7;p=linux-2.6-omap-h63xx.git diff --git a/drivers/video/leo.c b/drivers/video/leo.c index a23cfdb9d82..13fea61d6ae 100644 --- a/drivers/video/leo.c +++ b/drivers/video/leo.c @@ -1,6 +1,6 @@ /* leo.c: LEO frame buffer driver * - * Copyright (C) 2003 David S. Miller (davem@redhat.com) + * Copyright (C) 2003, 2006 David S. Miller (davem@davemloft.net) * Copyright (C) 1996-1999 Jakub Jelinek (jj@ultra.linux.cz) * Copyright (C) 1997 Michal Rehacek (Michal.Rehacek@st.mff.cuni.cz) * @@ -16,10 +16,9 @@ #include #include #include +#include +#include -#include -#include -#include #include #include "sbuslib.h" @@ -34,7 +33,6 @@ static int leo_blank(int, struct fb_info *); static int leo_mmap(struct fb_info *, struct vm_area_struct *); static int leo_ioctl(struct fb_info *, unsigned int, unsigned long); -static int leo_pan_display(struct fb_var_screeninfo *, struct fb_info *); /* * Frame buffer operations @@ -44,7 +42,6 @@ static struct fb_ops leo_ops = { .owner = THIS_MODULE, .fb_setcolreg = leo_setcolreg, .fb_blank = leo_blank, - .fb_pan_display = leo_pan_display, .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, @@ -79,11 +76,11 @@ static struct fb_ops leo_ops = { #define LEO_CUR_TYPE_CMAP 0x00000050 struct leo_cursor { - u8 xxx0[16]; - volatile u32 cur_type; - volatile u32 cur_misc; - volatile u32 cur_cursxy; - volatile u32 cur_data; + u8 xxx0[16]; + u32 cur_type; + u32 cur_misc; + u32 cur_cursxy; + u32 cur_data; }; #define LEO_KRN_TYPE_CLUT0 0x00001000 @@ -99,27 +96,27 @@ struct leo_cursor { #define LEO_KRN_CSR_UNK2 0x00000001 struct leo_lx_krn { - volatile u32 krn_type; - volatile u32 krn_csr; - volatile u32 krn_value; + u32 krn_type; + u32 krn_csr; + u32 krn_value; }; struct leo_lc_ss0_krn { - volatile u32 misc; - u8 xxx0[0x800-4]; - volatile u32 rev; + u32 misc; + u8 xxx0[0x800-4]; + u32 rev; }; struct leo_lc_ss0_usr { - volatile u32 csr; - volatile u32 addrspace; - volatile u32 fontmsk; - volatile u32 fontt; - volatile u32 extent; - volatile u32 src; - u32 dst; - volatile u32 copy; - volatile u32 fill; + u32 csr; + u32 addrspace; + u32 fontmsk; + u32 fontt; + u32 extent; + u32 src; + u32 dst; + u32 copy; + u32 fill; }; struct leo_lc_ss1_krn { @@ -130,49 +127,49 @@ struct leo_lc_ss1_usr { u8 unknown; }; -struct leo_ld { - u8 xxx0[0xe00]; - volatile u32 csr; - volatile u32 wid; - volatile u32 wmask; - volatile u32 widclip; - volatile u32 vclipmin; - volatile u32 vclipmax; - volatile u32 pickmin; /* SS1 only */ - volatile u32 pickmax; /* SS1 only */ - volatile u32 fg; - volatile u32 bg; - volatile u32 src; /* Copy/Scroll (SS0 only) */ - volatile u32 dst; /* Copy/Scroll/Fill (SS0 only) */ - volatile u32 extent; /* Copy/Scroll/Fill size (SS0 only) */ - u32 xxx1[3]; - volatile u32 setsem; /* SS1 only */ - volatile u32 clrsem; /* SS1 only */ - volatile u32 clrpick; /* SS1 only */ - volatile u32 clrdat; /* SS1 only */ - volatile u32 alpha; /* SS1 only */ - u8 xxx2[0x2c]; - volatile u32 winbg; - volatile u32 planemask; - volatile u32 rop; - volatile u32 z; - volatile u32 dczf; /* SS1 only */ - volatile u32 dczb; /* SS1 only */ - volatile u32 dcs; /* SS1 only */ - volatile u32 dczs; /* SS1 only */ - volatile u32 pickfb; /* SS1 only */ - volatile u32 pickbb; /* SS1 only */ - volatile u32 dcfc; /* SS1 only */ - volatile u32 forcecol; /* SS1 only */ - volatile u32 door[8]; /* SS1 only */ - volatile u32 pick[5]; /* SS1 only */ +struct leo_ld_ss0 { + u8 xxx0[0xe00]; + u32 csr; + u32 wid; + u32 wmask; + u32 widclip; + u32 vclipmin; + u32 vclipmax; + u32 pickmin; /* SS1 only */ + u32 pickmax; /* SS1 only */ + u32 fg; + u32 bg; + u32 src; /* Copy/Scroll (SS0 only) */ + u32 dst; /* Copy/Scroll/Fill (SS0 only) */ + u32 extent; /* Copy/Scroll/Fill size (SS0 only) */ + u32 xxx1[3]; + u32 setsem; /* SS1 only */ + u32 clrsem; /* SS1 only */ + u32 clrpick; /* SS1 only */ + u32 clrdat; /* SS1 only */ + u32 alpha; /* SS1 only */ + u8 xxx2[0x2c]; + u32 winbg; + u32 planemask; + u32 rop; + u32 z; + u32 dczf; /* SS1 only */ + u32 dczb; /* SS1 only */ + u32 dcs; /* SS1 only */ + u32 dczs; /* SS1 only */ + u32 pickfb; /* SS1 only */ + u32 pickbb; /* SS1 only */ + u32 dcfc; /* SS1 only */ + u32 forcecol; /* SS1 only */ + u32 door[8]; /* SS1 only */ + u32 pick[5]; /* SS1 only */ }; #define LEO_SS1_MISC_ENABLE 0x00000001 #define LEO_SS1_MISC_STEREO 0x00000002 struct leo_ld_ss1 { - u8 xxx0[0xef4]; - volatile u32 ss1_misc; + u8 xxx0[0xef4]; + u32 ss1_misc; }; struct leo_ld_gbl { @@ -193,19 +190,19 @@ struct leo_par { #define LEO_FLAG_BLANKED 0x00000001 unsigned long physbase; + unsigned long which_io; unsigned long fbsize; - - struct sbus_dev *sdev; }; static void leo_wait(struct leo_lx_krn __iomem *lx_krn) { int i; - + for (i = 0; - (sbus_readl(&lx_krn->krn_csr) & LEO_KRN_CSR_PROGRESS) && i < 300000; + (sbus_readl(&lx_krn->krn_csr) & LEO_KRN_CSR_PROGRESS) && + i < 300000; i++) - udelay (1); /* Busy wait at most 0.3 sec */ + udelay(1); /* Busy wait at most 0.3 sec */ return; } @@ -223,7 +220,7 @@ static int leo_setcolreg(unsigned regno, unsigned transp, struct fb_info *info) { struct leo_par *par = (struct leo_par *) info->par; - struct leo_lx_krn __iomem *lx_krn = par->lx_krn; + struct leo_lx_krn __iomem *lx_krn = par->lx_krn; unsigned long flags; u32 val; int i; @@ -368,8 +365,7 @@ static int leo_mmap(struct fb_info *info, struct vm_area_struct *vma) return sbusfb_mmap_helper(leo_mmap_map, par->physbase, par->fbsize, - par->sdev->reg_addrs[0].which_io, - vma); + par->which_io, vma); } static int leo_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) @@ -385,11 +381,9 @@ static int leo_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) */ static void -leo_init_fix(struct fb_info *info) +leo_init_fix(struct fb_info *info, struct device_node *dp) { - struct leo_par *par = (struct leo_par *)info->par; - - strlcpy(info->fix.id, par->sdev->prom_name, sizeof(info->fix.id)); + strlcpy(info->fix.id, dp->name, sizeof(info->fix.id)); info->fix.type = FB_TYPE_PACKED_PIXELS; info->fix.visual = FB_VISUAL_TRUECOLOR; @@ -413,7 +407,7 @@ static void leo_wid_put(struct fb_info *info, struct fb_wid_list *wl) leo_wait(lx_krn); for (i = 0, wi = wl->wl_list; i < wl->wl_count; i++, wi++) { - switch(wi->wi_type) { + switch (wi->wi_type) { case FB_WID_DBL_8: j = (wi->wi_index & 0xf) + 0x40; break; @@ -458,13 +452,12 @@ static void leo_init_wids(struct fb_info *info) wi.wi_index = 1; wi.wi_values [0] = 0x30; leo_wid_put(info, &wl); - } static void leo_switch_from_graph(struct fb_info *info) { struct leo_par *par = (struct leo_par *) info->par; - struct leo_ld __iomem *ss = (struct leo_ld __iomem *) par->ld_ss0; + struct leo_ld_ss0 __iomem *ss = par->ld_ss0; unsigned long flags; u32 val; @@ -490,19 +483,13 @@ static void leo_switch_from_graph(struct fb_info *info) val = sbus_readl(&par->lc_ss0_usr->csr); } while (val & 0x20000000); - spin_unlock_irqrestore(&par->lock, flags); -} - -static int leo_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) -{ - /* We just use this to catch switches out of - * graphics mode. - */ - leo_switch_from_graph(info); + /* setup screen buffer for cfb_* functions */ + sbus_writel(1, &ss->wid); + sbus_writel(0x00ffffff, &ss->planemask); + sbus_writel(0x310b90, &ss->rop); + sbus_writel(0, &par->lc_ss0_usr->addrspace); - if (var->xoffset || var->yoffset || var->vmode) - return -EINVAL; - return 0; + spin_unlock_irqrestore(&par->lock, flags); } static void leo_init_hw(struct fb_info *info) @@ -529,137 +516,163 @@ static void leo_fixup_var_rgb(struct fb_var_screeninfo *var) var->transp.length = 0; } -struct all_info { - struct fb_info info; - struct leo_par par; - struct list_head list; -}; -static LIST_HEAD(leo_list); +static void leo_unmap_regs(struct of_device *op, struct fb_info *info, + struct leo_par *par) +{ + if (par->lc_ss0_usr) + of_iounmap(&op->resource[0], par->lc_ss0_usr, 0x1000); + if (par->ld_ss0) + of_iounmap(&op->resource[0], par->ld_ss0, 0x1000); + if (par->ld_ss1) + of_iounmap(&op->resource[0], par->ld_ss1, 0x1000); + if (par->lx_krn) + of_iounmap(&op->resource[0], par->lx_krn, 0x1000); + if (par->cursor) + of_iounmap(&op->resource[0], + par->cursor, sizeof(struct leo_cursor)); + if (info->screen_base) + of_iounmap(&op->resource[0], info->screen_base, 0x800000); +} -static void leo_init_one(struct sbus_dev *sdev) +static int __devinit leo_probe(struct of_device *op, + const struct of_device_id *match) { - struct all_info *all; - int linebytes; + struct device_node *dp = op->node; + struct fb_info *info; + struct leo_par *par; + int linebytes, err; + + info = framebuffer_alloc(sizeof(struct leo_par), &op->dev); + + err = -ENOMEM; + if (!info) + goto out_err; + par = info->par; + + spin_lock_init(&par->lock); + + par->physbase = op->resource[0].start; + par->which_io = op->resource[0].flags & IORESOURCE_BITS; + + sbusfb_fill_var(&info->var, dp, 32); + leo_fixup_var_rgb(&info->var); + + linebytes = of_getintprop_default(dp, "linebytes", + info->var.xres); + par->fbsize = PAGE_ALIGN(linebytes * info->var.yres); + + par->lc_ss0_usr = + of_ioremap(&op->resource[0], LEO_OFF_LC_SS0_USR, + 0x1000, "leolc ss0usr"); + par->ld_ss0 = + of_ioremap(&op->resource[0], LEO_OFF_LD_SS0, + 0x1000, "leold ss0"); + par->ld_ss1 = + of_ioremap(&op->resource[0], LEO_OFF_LD_SS1, + 0x1000, "leold ss1"); + par->lx_krn = + of_ioremap(&op->resource[0], LEO_OFF_LX_KRN, + 0x1000, "leolx krn"); + par->cursor = + of_ioremap(&op->resource[0], LEO_OFF_LX_CURSOR, + sizeof(struct leo_cursor), "leolx cursor"); + info->screen_base = + of_ioremap(&op->resource[0], LEO_OFF_SS0, + 0x800000, "leo ram"); + if (!par->lc_ss0_usr || + !par->ld_ss0 || + !par->ld_ss1 || + !par->lx_krn || + !par->cursor || + !info->screen_base) + goto out_unmap_regs; + + info->flags = FBINFO_DEFAULT; + info->fbops = &leo_ops; + info->pseudo_palette = par->clut_data; + + leo_init_wids(info); + leo_init_hw(info); + + leo_blank(FB_BLANK_UNBLANK, info); + + if (fb_alloc_cmap(&info->cmap, 256, 0)) + goto out_unmap_regs; + + leo_init_fix(info, dp); + + err = register_framebuffer(info); + if (err < 0) + goto out_dealloc_cmap; + + dev_set_drvdata(&op->dev, info); + + printk(KERN_INFO "%s: leo at %lx:%lx\n", + dp->full_name, + par->which_io, par->physbase); - all = kmalloc(sizeof(*all), GFP_KERNEL); - if (!all) { - printk(KERN_ERR "leo: Cannot allocate memory.\n"); - return; - } - memset(all, 0, sizeof(*all)); + return 0; - INIT_LIST_HEAD(&all->list); +out_dealloc_cmap: + fb_dealloc_cmap(&info->cmap); - spin_lock_init(&all->par.lock); - all->par.sdev = sdev; +out_unmap_regs: + leo_unmap_regs(op, info, par); + framebuffer_release(info); - all->par.physbase = sdev->reg_addrs[0].phys_addr; +out_err: + return err; +} - sbusfb_fill_var(&all->info.var, sdev->prom_node, 32); - leo_fixup_var_rgb(&all->info.var); +static int __devexit leo_remove(struct of_device *op) +{ + struct fb_info *info = dev_get_drvdata(&op->dev); + struct leo_par *par = info->par; - linebytes = prom_getintdefault(sdev->prom_node, "linebytes", - all->info.var.xres); - all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres); + unregister_framebuffer(info); + fb_dealloc_cmap(&info->cmap); -#ifdef CONFIG_SPARC32 - all->info.screen_base = (char __iomem *) - prom_getintdefault(sdev->prom_node, "address", 0); -#endif - if (!all->info.screen_base) - all->info.screen_base = - sbus_ioremap(&sdev->resource[0], LEO_OFF_SS0, - 0x800000, "leo ram"); - - all->par.lc_ss0_usr = - sbus_ioremap(&sdev->resource[0], LEO_OFF_LC_SS0_USR, - 0x1000, "leolc ss0usr"); - all->par.ld_ss0 = - sbus_ioremap(&sdev->resource[0], LEO_OFF_LD_SS0, - 0x1000, "leold ss0"); - all->par.ld_ss1 = - sbus_ioremap(&sdev->resource[0], LEO_OFF_LD_SS1, - 0x1000, "leold ss1"); - all->par.lx_krn = - sbus_ioremap(&sdev->resource[0], LEO_OFF_LX_KRN, - 0x1000, "leolx krn"); - all->par.cursor = - sbus_ioremap(&sdev->resource[0], LEO_OFF_LX_CURSOR, - sizeof(struct leo_cursor), "leolx cursor"); - - all->info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN; - all->info.fbops = &leo_ops; - all->info.par = &all->par; - - leo_init_wids(&all->info); - leo_init_hw(&all->info); - - leo_blank(0, &all->info); - - if (fb_alloc_cmap(&all->info.cmap, 256, 0)) { - printk(KERN_ERR "leo: Could not allocate color map.\n"); - kfree(all); - return; - } + leo_unmap_regs(op, info, par); - leo_init_fix(&all->info); + framebuffer_release(info); - if (register_framebuffer(&all->info) < 0) { - printk(KERN_ERR "leo: Could not register framebuffer.\n"); - fb_dealloc_cmap(&all->info.cmap); - kfree(all); - return; - } - - list_add(&all->list, &leo_list); + dev_set_drvdata(&op->dev, NULL); - printk("leo: %s at %lx:%lx\n", - sdev->prom_name, - (long) sdev->reg_addrs[0].which_io, - (long) sdev->reg_addrs[0].phys_addr); + return 0; } -int __init leo_init(void) -{ - struct sbus_bus *sbus; - struct sbus_dev *sdev; - - if (fb_get_options("leofb", NULL)) - return -ENODEV; - - for_all_sbusdev(sdev, sbus) { - if (!strcmp(sdev->prom_name, "leo")) - leo_init_one(sdev); - } +static struct of_device_id leo_match[] = { + { + .name = "SUNW,leo", + }, + {}, +}; +MODULE_DEVICE_TABLE(of, leo_match); - return 0; -} +static struct of_platform_driver leo_driver = { + .name = "leo", + .match_table = leo_match, + .probe = leo_probe, + .remove = __devexit_p(leo_remove), +}; -void __exit leo_exit(void) +static int __init leo_init(void) { - struct list_head *pos, *tmp; - - list_for_each_safe(pos, tmp, &leo_list) { - struct all_info *all = list_entry(pos, typeof(*all), list); + if (fb_get_options("leofb", NULL)) + return -ENODEV; - unregister_framebuffer(&all->info); - fb_dealloc_cmap(&all->info.cmap); - kfree(all); - } + return of_register_driver(&leo_driver, &of_bus_type); } -int __init -leo_setup(char *arg) +static void __exit leo_exit(void) { - /* No cmdline options yet... */ - return 0; + of_unregister_driver(&leo_driver); } module_init(leo_init); -#ifdef MODULE module_exit(leo_exit); -#endif MODULE_DESCRIPTION("framebuffer driver for LEO chipsets"); -MODULE_AUTHOR("David S. Miller "); +MODULE_AUTHOR("David S. Miller "); +MODULE_VERSION("2.0"); MODULE_LICENSE("GPL");