diff options
Diffstat (limited to 'drivers/video')
-rw-r--r-- | drivers/video/Kconfig | 32 | ||||
-rw-r--r-- | drivers/video/Makefile | 1 | ||||
-rw-r--r-- | drivers/video/atmel_lcdfb.c | 2 | ||||
-rw-r--r-- | drivers/video/aty/radeon_accel.c | 24 | ||||
-rw-r--r-- | drivers/video/aty/radeon_base.c | 24 | ||||
-rw-r--r-- | drivers/video/aty/radeonfb.h | 2 | ||||
-rw-r--r-- | drivers/video/backlight/da903x.c | 2 | ||||
-rw-r--r-- | drivers/video/backlight/lcd.c | 11 | ||||
-rw-r--r-- | drivers/video/cirrusfb.c | 5 | ||||
-rw-r--r-- | drivers/video/console/fbcon.c | 15 | ||||
-rw-r--r-- | drivers/video/fbmem.c | 65 | ||||
-rw-r--r-- | drivers/video/macfb.c | 74 | ||||
-rw-r--r-- | drivers/video/mb862xx/Makefile | 5 | ||||
-rw-r--r-- | drivers/video/mb862xx/mb862xx_reg.h | 138 | ||||
-rw-r--r-- | drivers/video/mb862xx/mb862xxfb.c | 1061 | ||||
-rw-r--r-- | drivers/video/mb862xx/mb862xxfb.h | 83 | ||||
-rw-r--r-- | drivers/video/omap/Makefile | 1 | ||||
-rw-r--r-- | drivers/video/omap/lcd_sx1.c | 327 | ||||
-rw-r--r-- | drivers/video/omap/omapfb_main.c | 2 | ||||
-rw-r--r-- | drivers/video/pxafb.c | 5 | ||||
-rw-r--r-- | drivers/video/tmiofb.c | 10 | ||||
-rw-r--r-- | drivers/video/via/viafbdev.c | 17 | ||||
-rw-r--r-- | drivers/video/xen-fbfront.c | 6 | ||||
-rw-r--r-- | drivers/video/xilinxfb.c | 5 |
24 files changed, 1483 insertions, 434 deletions
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 0f13448c6f7..3f3ce13fef4 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -2083,6 +2083,38 @@ config FB_METRONOME controller. The pre-release name for this device was 8track and could also have been called by some vendors as PVI-nnnn. +config FB_MB862XX + tristate "Fujitsu MB862xx GDC support" + depends on FB + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + ---help--- + Frame buffer driver for Fujitsu Carmine/Coral-P(A)/Lime controllers. + +config FB_MB862XX_PCI_GDC + bool "Carmine/Coral-P(A) GDC" + depends on PCI && FB_MB862XX + ---help--- + This enables framebuffer support for Fujitsu Carmine/Coral-P(A) + PCI graphics controller devices. + +config FB_MB862XX_LIME + bool "Lime GDC" + depends on FB_MB862XX + depends on OF && !FB_MB862XX_PCI_GDC + select FB_FOREIGN_ENDIAN + select FB_LITTLE_ENDIAN + ---help--- + Framebuffer support for Fujitsu Lime GDC on host CPU bus. + +config FB_PRE_INIT_FB + bool "Don't reinitialize, use bootloader's GDC/Display configuration" + depends on FB_MB862XX_LIME + ---help--- + Select this option if display contents should be inherited as set by + the bootloader. + source "drivers/video/omap/Kconfig" source "drivers/video/backlight/Kconfig" diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 248bddc8d0b..e39e33e797d 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -122,6 +122,7 @@ obj-$(CONFIG_FB_SH_MOBILE_LCDC) += sh_mobile_lcdcfb.o obj-$(CONFIG_FB_OMAP) += omap/ obj-$(CONFIG_XEN_FBDEV_FRONTEND) += xen-fbfront.o obj-$(CONFIG_FB_CARMINE) += carminefb.o +obj-$(CONFIG_FB_MB862XX) += mb862xx/ # Platform or fallback drivers go here obj-$(CONFIG_FB_UVESA) += uvesafb.o diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c index f8d0a57a07c..9a577a800db 100644 --- a/drivers/video/atmel_lcdfb.c +++ b/drivers/video/atmel_lcdfb.c @@ -132,7 +132,7 @@ static void init_backlight(struct atmel_lcdfb_info *sinfo) bl = backlight_device_register("backlight", &sinfo->pdev->dev, sinfo, &atmel_lcdc_bl_ops); - if (IS_ERR(sinfo->backlight)) { + if (IS_ERR(bl)) { dev_err(&sinfo->pdev->dev, "error %ld on backlight register\n", PTR_ERR(bl)); return; diff --git a/drivers/video/aty/radeon_accel.c b/drivers/video/aty/radeon_accel.c index 8718f7349d6..8da5e5ab854 100644 --- a/drivers/video/aty/radeon_accel.c +++ b/drivers/video/aty/radeon_accel.c @@ -174,12 +174,12 @@ static void radeonfb_prim_imageblit(struct radeonfb_info *rinfo, const struct fb_image *image, u32 fg, u32 bg) { - unsigned int src_bytes, dwords; + unsigned int dwords; u32 *bits; radeonfb_set_creg(rinfo, DP_GUI_MASTER_CNTL, &rinfo->dp_gui_mc_cache, rinfo->dp_gui_mc_base | - GMC_BRUSH_NONE | + GMC_BRUSH_NONE | GMC_DST_CLIP_LEAVE | GMC_SRC_DATATYPE_MONO_FG_BG | ROP3_S | GMC_BYTE_ORDER_MSB_TO_LSB | @@ -189,9 +189,6 @@ static void radeonfb_prim_imageblit(struct radeonfb_info *rinfo, radeonfb_set_creg(rinfo, DP_SRC_FRGD_CLR, &rinfo->dp_src_fg_cache, fg); radeonfb_set_creg(rinfo, DP_SRC_BKGD_CLR, &rinfo->dp_src_bg_cache, bg); - radeon_fifo_wait(rinfo, 1); - OUTREG(DST_Y_X, (image->dy << 16) | image->dx); - /* Ensure the dst cache is flushed and the engine idle before * issuing the operation. * @@ -205,13 +202,19 @@ static void radeonfb_prim_imageblit(struct radeonfb_info *rinfo, /* X here pads width to a multiple of 32 and uses the clipper to * adjust the result. Is that really necessary ? Things seem to - * work ok for me without that and the doco doesn't seem to imply + * work ok for me without that and the doco doesn't seem to imply] * there is such a restriction. */ - OUTREG(DST_WIDTH_HEIGHT, (image->width << 16) | image->height); + radeon_fifo_wait(rinfo, 4); + OUTREG(SC_TOP_LEFT, (image->dy << 16) | image->dx); + OUTREG(SC_BOTTOM_RIGHT, ((image->dy + image->height) << 16) | + (image->dx + image->width)); + OUTREG(DST_Y_X, (image->dy << 16) | image->dx); + + OUTREG(DST_HEIGHT_WIDTH, (image->height << 16) | ((image->width + 31) & ~31)); - src_bytes = (((image->width * image->depth) + 7) / 8) * image->height; - dwords = (src_bytes + 3) / 4; + dwords = (image->width + 31) >> 5; + dwords *= image->height; bits = (u32*)(image->data); while(dwords >= 8) { @@ -253,7 +256,8 @@ void radeonfb_imageblit(struct fb_info *info, const struct fb_image *image) return; /* We only do 1 bpp color expansion for now */ - if (info->flags & FBINFO_HWACCEL_DISABLED || image->depth != 1) + if (!accel_cexp || + (info->flags & FBINFO_HWACCEL_DISABLED) || image->depth != 1) goto fallback; /* Fallback if running out of the screen. We may do clipping diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c index 9a5821c65eb..d5b27f9d374 100644 --- a/drivers/video/aty/radeon_base.c +++ b/drivers/video/aty/radeon_base.c @@ -282,6 +282,8 @@ static int backlight = 1; static int backlight = 0; #endif +int accel_cexp = 0; + /* * prototypes */ @@ -1875,6 +1877,7 @@ static int __devinit radeon_set_fbinfo (struct radeonfb_info *rinfo) info->fbops = &radeonfb_ops; info->screen_base = rinfo->fb_base; info->screen_size = rinfo->mapped_vram; + /* Fill fix common fields */ strlcpy(info->fix.id, rinfo->name, sizeof(info->fix.id)); info->fix.smem_start = rinfo->fb_base_phys; @@ -1889,8 +1892,25 @@ static int __devinit radeon_set_fbinfo (struct radeonfb_info *rinfo) info->fix.mmio_len = RADEON_REGSIZE; info->fix.accel = FB_ACCEL_ATI_RADEON; + /* Allocate colormap */ fb_alloc_cmap(&info->cmap, 256, 0); + /* Setup pixmap used for acceleration */ +#define PIXMAP_SIZE (2048 * 4) + + info->pixmap.addr = kmalloc(PIXMAP_SIZE, GFP_KERNEL); + if (!info->pixmap.addr) { + printk(KERN_ERR "radeonfb: Failed to allocate pixmap !\n"); + noaccel = 1; + goto bail; + } + info->pixmap.size = PIXMAP_SIZE; + info->pixmap.flags = FB_PIXMAP_SYSTEM; + info->pixmap.scan_align = 4; + info->pixmap.buf_align = 4; + info->pixmap.access_align = 32; + +bail: if (noaccel) info->flags |= FBINFO_HWACCEL_DISABLED; @@ -2502,6 +2522,8 @@ static int __init radeonfb_setup (char *options) } else if (!strncmp(this_opt, "ignore_devlist", 14)) { ignore_devlist = 1; #endif + } else if (!strncmp(this_opt, "accel_cexp", 12)) { + accel_cexp = 1; } else mode_option = this_opt; } @@ -2549,6 +2571,8 @@ module_param(monitor_layout, charp, 0); MODULE_PARM_DESC(monitor_layout, "Specify monitor mapping (like XFree86)"); module_param(force_measure_pll, bool, 0); MODULE_PARM_DESC(force_measure_pll, "Force measurement of PLL (debug)"); +module_param(accel_cexp, bool, 0); +MODULE_PARM_DESC(accel_cexp, "Use acceleration engine for color expansion"); #ifdef CONFIG_MTRR module_param(nomtrr, bool, 0); MODULE_PARM_DESC(nomtrr, "bool: disable use of MTRR registers"); diff --git a/drivers/video/aty/radeonfb.h b/drivers/video/aty/radeonfb.h index ea0b5b47aca..974ca6d8654 100644 --- a/drivers/video/aty/radeonfb.h +++ b/drivers/video/aty/radeonfb.h @@ -638,4 +638,6 @@ static inline void radeonfb_bl_init(struct radeonfb_info *rinfo) {} static inline void radeonfb_bl_exit(struct radeonfb_info *rinfo) {} #endif +extern int accel_cexp; + #endif /* __RADEONFB_H__ */ diff --git a/drivers/video/backlight/da903x.c b/drivers/video/backlight/da903x.c index 242c3825016..93bb4340cc6 100644 --- a/drivers/video/backlight/da903x.c +++ b/drivers/video/backlight/da903x.c @@ -119,6 +119,7 @@ static int da903x_backlight_probe(struct platform_device *pdev) default: dev_err(&pdev->dev, "invalid backlight device ID(%d)\n", pdev->id); + kfree(data); return -EINVAL; } @@ -130,6 +131,7 @@ static int da903x_backlight_probe(struct platform_device *pdev) data, &da903x_backlight_ops); if (IS_ERR(bl)) { dev_err(&pdev->dev, "failed to register backlight\n"); + kfree(data); return PTR_ERR(bl); } diff --git a/drivers/video/backlight/lcd.c b/drivers/video/backlight/lcd.c index 8e1731d3b22..680e57b616c 100644 --- a/drivers/video/backlight/lcd.c +++ b/drivers/video/backlight/lcd.c @@ -42,10 +42,13 @@ static int fb_notifier_callback(struct notifier_block *self, mutex_lock(&ld->ops_lock); if (!ld->ops->check_fb || ld->ops->check_fb(ld, evdata->info)) { - if (event == FB_EVENT_BLANK) - ld->ops->set_power(ld, *(int *)evdata->data); - else - ld->ops->set_mode(ld, evdata->data); + if (event == FB_EVENT_BLANK) { + if (ld->ops->set_power) + ld->ops->set_power(ld, *(int *)evdata->data); + } else { + if (ld->ops->set_mode) + ld->ops->set_mode(ld, evdata->data); + } } mutex_unlock(&ld->ops_lock); return 0; diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c index 048b139f0e5..a2aa6ddffbe 100644 --- a/drivers/video/cirrusfb.c +++ b/drivers/video/cirrusfb.c @@ -2049,7 +2049,7 @@ static void cirrusfb_pci_unmap(struct fb_info *info) #endif /* CONFIG_PCI */ #ifdef CONFIG_ZORRO -static void __devexit cirrusfb_zorro_unmap(struct fb_info *info) +static void cirrusfb_zorro_unmap(struct fb_info *info) { struct cirrusfb_info *cinfo = info->par; struct zorro_dev *zdev = to_zorro_dev(info->device); @@ -2462,8 +2462,7 @@ static int __init cirrusfb_init(void) #ifndef MODULE static int __init cirrusfb_setup(char *options) { - char *this_opt, s[32]; - int i; + char *this_opt; DPRINTK("ENTER\n"); diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index b92947d62ad..0b2adefe9e3 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c @@ -2389,16 +2389,13 @@ static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch) if (!fbcon_is_inactive(vc, info)) { if (ops->blank_state != blank) { - int ret = 1; - ops->blank_state = blank; fbcon_cursor(vc, blank ? CM_ERASE : CM_DRAW); ops->cursor_flash = (!blank); - if (info->fbops->fb_blank) - ret = info->fbops->fb_blank(blank, info); - if (ret) - fbcon_generic_blank(vc, info, blank); + if (!(info->flags & FBINFO_MISC_USEREVENT)) + if (fb_blank(info, blank)) + fbcon_generic_blank(vc, info, blank); } if (!blank) @@ -3534,12 +3531,18 @@ static void fbcon_exit(void) softback_buf = 0UL; for (i = 0; i < FB_MAX; i++) { + int pending; + mapped = 0; info = registered_fb[i]; if (info == NULL) continue; + pending = cancel_work_sync(&info->queue); + DPRINTK("fbcon: %s pending work\n", (pending ? "canceled" : + "no")); + for (j = first_fb_vc; j <= last_fb_vc; j++) { if (con2fb_map[j] == i) mapped = 1; diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 6048b55f287..3c65b0d6761 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -230,7 +230,7 @@ static void fb_set_logo_directpalette(struct fb_info *info, greenshift = info->var.green.offset; blueshift = info->var.blue.offset; - for (i = 32; i < logo->clutsize; i++) + for (i = 32; i < 32 + logo->clutsize; i++) palette[i] = i << redshift | i << greenshift | i << blueshift; } @@ -1002,13 +1002,9 @@ fb_blank(struct fb_info *info, int blank) return ret; } -static long -fb_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) +static long do_fb_ioctl(struct fb_info *info, unsigned int cmd, + unsigned long arg) { - struct inode *inode = file->f_path.dentry->d_inode; - int fbidx = iminor(inode); - struct fb_info *info; struct fb_ops *fb; struct fb_var_screeninfo var; struct fb_fix_screeninfo fix; @@ -1018,14 +1014,10 @@ fb_ioctl(struct file *file, unsigned int cmd, void __user *argp = (void __user *)arg; long ret = 0; - info = registered_fb[fbidx]; - mutex_lock(&info->lock); fb = info->fbops; - - if (!fb) { - mutex_unlock(&info->lock); + if (!fb) return -ENODEV; - } + switch (cmd) { case FBIOGET_VSCREENINFO: ret = copy_to_user(argp, &info->var, @@ -1126,6 +1118,21 @@ fb_ioctl(struct file *file, unsigned int cmd, else ret = fb->fb_ioctl(info, cmd, arg); } + return ret; +} + +static long fb_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +__acquires(&info->lock) +__releases(&info->lock) +{ + struct inode *inode = file->f_path.dentry->d_inode; + int fbidx = iminor(inode); + struct fb_info *info; + long ret; + + info = registered_fb[fbidx]; + mutex_lock(&info->lock); + ret = do_fb_ioctl(info, cmd, arg); mutex_unlock(&info->lock); return ret; } @@ -1157,8 +1164,8 @@ struct fb_cmap32 { compat_caddr_t transp; }; -static int fb_getput_cmap(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static int fb_getput_cmap(struct fb_info *info, unsigned int cmd, + unsigned long arg) { struct fb_cmap_user __user *cmap; struct fb_cmap32 __user *cmap32; @@ -1181,7 +1188,7 @@ static int fb_getput_cmap(struct inode *inode, struct file *file, put_user(compat_ptr(data), &cmap->transp)) return -EFAULT; - err = fb_ioctl(file, cmd, (unsigned long) cmap); + err = do_fb_ioctl(info, cmd, (unsigned long) cmap); if (!err) { if (copy_in_user(&cmap32->start, @@ -1223,8 +1230,8 @@ static int do_fscreeninfo_to_user(struct fb_fix_screeninfo *fix, return err; } -static int fb_get_fscreeninfo(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static int fb_get_fscreeninfo(struct fb_info *info, unsigned int cmd, + unsigned long arg) { mm_segment_t old_fs; struct fb_fix_screeninfo fix; @@ -1235,7 +1242,7 @@ static int fb_get_fscreeninfo(struct inode *inode, struct file *file, old_fs = get_fs(); set_fs(KERNEL_DS); - err = fb_ioctl(file, cmd, (unsigned long) &fix); + err = do_fb_ioctl(info, cmd, (unsigned long) &fix); set_fs(old_fs); if (!err) @@ -1244,8 +1251,10 @@ static int fb_get_fscreeninfo(struct inode *inode, struct file *file, return err; } -static long -fb_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +static long fb_compat_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +__acquires(&info->lock) +__releases(&info->lock) { struct inode *inode = file->f_path.dentry->d_inode; int fbidx = iminor(inode); @@ -1262,16 +1271,16 @@ fb_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case FBIOPUT_CON2FBMAP: arg = (unsigned long) compat_ptr(arg); case FBIOBLANK: - mutex_unlock(&info->lock); - return fb_ioctl(file, cmd, arg); + ret = do_fb_ioctl(info, cmd, arg); + break; case FBIOGET_FSCREENINFO: - ret = fb_get_fscreeninfo(inode, file, cmd, arg); + ret = fb_get_fscreeninfo(info, cmd, arg); break; case FBIOGETCMAP: case FBIOPUTCMAP: - ret = fb_getput_cmap(inode, file, cmd, arg); + ret = fb_getput_cmap(info, cmd, arg); break; default: @@ -1286,6 +1295,8 @@ fb_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) static int fb_mmap(struct file *file, struct vm_area_struct * vma) +__acquires(&info->lock) +__releases(&info->lock) { int fbidx = iminor(file->f_path.dentry->d_inode); struct fb_info *info = registered_fb[fbidx]; @@ -1339,6 +1350,8 @@ fb_mmap(struct file *file, struct vm_area_struct * vma) static int fb_open(struct inode *inode, struct file *file) +__acquires(&info->lock) +__releases(&info->lock) { int fbidx = iminor(inode); struct fb_info *info; @@ -1374,6 +1387,8 @@ out: static int fb_release(struct inode *inode, struct file *file) +__acquires(&info->lock) +__releases(&info->lock) { struct fb_info * const info = file->private_data; diff --git a/drivers/video/macfb.c b/drivers/video/macfb.c index b790ddff76f..ee380d5f341 100644 --- a/drivers/video/macfb.c +++ b/drivers/video/macfb.c @@ -164,7 +164,6 @@ static struct fb_var_screeninfo macfb_defined = { }; static struct fb_fix_screeninfo macfb_fix = { - .id = "Macintosh ", .type = FB_TYPE_PACKED_PIXELS, .accel = FB_ACCEL_NONE, }; @@ -760,22 +759,22 @@ static int __init macfb_init(void) switch(ndev->dr_hw) { case NUBUS_DRHW_APPLE_MDC: - strcat( macfb_fix.id, "Display Card" ); + strcpy(macfb_fix.id, "Mac Disp. Card"); macfb_setpalette = mdc_setpalette; macfb_defined.activate = FB_ACTIVATE_NOW; break; case NUBUS_DRHW_APPLE_TFB: - strcat( macfb_fix.id, "Toby" ); + strcpy(macfb_fix.id, "Toby"); macfb_setpalette = toby_setpalette; macfb_defined.activate = FB_ACTIVATE_NOW; break; case NUBUS_DRHW_APPLE_JET: - strcat( macfb_fix.id, "Jet"); + strcpy(macfb_fix.id, "Jet"); macfb_setpalette = jet_setpalette; macfb_defined.activate = FB_ACTIVATE_NOW; break; default: - strcat( macfb_fix.id, "Generic NuBus" ); + strcpy(macfb_fix.id, "Generic NuBus"); break; } } @@ -786,21 +785,11 @@ static int __init macfb_init(void) if (!video_is_nubus) switch( mac_bi_data.id ) { - /* These don't have onboard video. Eventually, we may - be able to write separate framebuffer drivers for - them (tobyfb.c, hiresfb.c, etc, etc) */ - case MAC_MODEL_II: - case MAC_MODEL_IIX: - case MAC_MODEL_IICX: - case MAC_MODEL_IIFX: - strcat( macfb_fix.id, "Generic NuBus" ); - break; - /* Valkyrie Quadras */ case MAC_MODEL_Q630: /* I'm not sure about this one */ case MAC_MODEL_P588: - strcat( macfb_fix.id, "Valkyrie built-in" ); + strcpy(macfb_fix.id, "Valkyrie"); macfb_setpalette = valkyrie_setpalette; macfb_defined.activate = FB_ACTIVATE_NOW; valkyrie_cmap_regs = ioremap(DAC_BASE, 0x1000); @@ -823,7 +812,7 @@ static int __init macfb_init(void) case MAC_MODEL_Q700: case MAC_MODEL_Q900: case MAC_MODEL_Q950: - strcat( macfb_fix.id, "DAFB built-in" ); + strcpy(macfb_fix.id, "DAFB"); macfb_setpalette = dafb_setpalette; macfb_defined.activate = FB_ACTIVATE_NOW; dafb_cmap_regs = ioremap(DAFB_BASE, 0x1000); @@ -831,7 +820,7 @@ static int __init macfb_init(void) /* LC II uses the V8 framebuffer */ case MAC_MODEL_LCII: - strcat( macfb_fix.id, "V8 built-in" ); + strcpy(macfb_fix.id, "V8"); macfb_setpalette = v8_brazil_setpalette; macfb_defined.activate = FB_ACTIVATE_NOW; v8_brazil_cmap_regs = ioremap(DAC_BASE, 0x1000); @@ -843,7 +832,7 @@ static int __init macfb_init(void) case MAC_MODEL_IIVI: case MAC_MODEL_IIVX: case MAC_MODEL_P600: - strcat( macfb_fix.id, "Brazil built-in" ); + strcpy(macfb_fix.id, "Brazil"); macfb_setpalette = v8_brazil_setpalette; macfb_defined.activate = FB_ACTIVATE_NOW; v8_brazil_cmap_regs = ioremap(DAC_BASE, 0x1000); @@ -860,7 +849,7 @@ static int __init macfb_init(void) case MAC_MODEL_P460: macfb_setpalette = v8_brazil_setpalette; macfb_defined.activate = FB_ACTIVATE_NOW; - strcat( macfb_fix.id, "Sonora built-in" ); + strcpy(macfb_fix.id, "Sonora"); v8_brazil_cmap_regs = ioremap(DAC_BASE, 0x1000); break; @@ -871,7 +860,7 @@ static int __init macfb_init(void) case MAC_MODEL_IISI: macfb_setpalette = rbv_setpalette; macfb_defined.activate = FB_ACTIVATE_NOW; - strcat( macfb_fix.id, "RBV built-in" ); + strcpy(macfb_fix.id, "RBV"); rbv_cmap_regs = ioremap(DAC_BASE, 0x1000); break; @@ -880,7 +869,7 @@ static int __init macfb_init(void) case MAC_MODEL_C660: macfb_setpalette = civic_setpalette; macfb_defined.activate = FB_ACTIVATE_NOW; - strcat( macfb_fix.id, "Civic built-in" ); + strcpy(macfb_fix.id, "Civic"); civic_cmap_regs = ioremap(CIVIC_BASE, 0x1000); break; @@ -901,7 +890,7 @@ static int __init macfb_init(void) v8_brazil_cmap_regs = ioremap(DAC_BASE, 0x1000); } - strcat( macfb_fix.id, "LC built-in" ); + strcpy(macfb_fix.id, "LC"); break; /* We think this may be like the LC II */ case MAC_MODEL_CCL: @@ -911,18 +900,18 @@ static int __init macfb_init(void) v8_brazil_cmap_regs = ioremap(DAC_BASE, 0x1000); } - strcat( macfb_fix.id, "Color Classic built-in" ); + strcpy(macfb_fix.id, "Color Classic"); break; /* And we *do* mean "weirdos" */ case MAC_MODEL_TV: - strcat( macfb_fix.id, "Mac TV built-in" ); + strcpy(macfb_fix.id, "Mac TV"); break; /* These don't have colour, so no need to worry */ case MAC_MODEL_SE30: case MAC_MODEL_CLII: - strcat( macfb_fix.id, "Monochrome built-in" ); + strcpy(macfb_fix.id, "Monochrome"); break; /* Powerbooks are particularly difficult. Many of @@ -935,7 +924,7 @@ static int __init macfb_init(void) case MAC_MODEL_PB140: case MAC_MODEL_PB145: case MAC_MODEL_PB170: - strcat( macfb_fix.id, "DDC built-in" ); + strcpy(macfb_fix.id, "DDC"); break; /* Internal is GSC, External (if present) is ViSC */ @@ -945,13 +934,13 @@ static int __init macfb_init(void) case MAC_MODEL_PB180: case MAC_MODEL_PB210: case MAC_MODEL_PB230: - strcat( macfb_fix.id, "GSC built-in" ); + strcpy(macfb_fix.id, "GSC"); break; /* Internal is TIM, External is ViSC */ case MAC_MODEL_PB165C: case MAC_MODEL_PB180C: - strcat( macfb_fix.id, "TIM built-in" ); + strcpy(macfb_fix.id, "TIM"); break; /* Internal is CSC, External is Keystone+Ariel. */ @@ -963,12 +952,12 @@ static int __init macfb_init(void) case MAC_MODEL_PB280C: macfb_setpalette = csc_setpalette; macfb_defined.activate = FB_ACTIVATE_NOW; - strcat( macfb_fix.id, "CSC built-in" ); + strcpy(macfb_fix.id, "CSC"); csc_cmap_regs = ioremap(CSC_BASE, 0x1000); break; default: - strcat( macfb_fix.id, "Unknown/Unsupported built-in" ); + strcpy(macfb_fix.id, "Unknown"); break; } @@ -978,16 +967,23 @@ static int __init macfb_init(void) fb_info.pseudo_palette = pseudo_palette; fb_info.flags = FBINFO_DEFAULT; - fb_alloc_cmap(&fb_info.cmap, video_cmap_len, 0); + err = fb_alloc_cmap(&fb_info.cmap, video_cmap_len, 0); + if (err) + goto fail_unmap; err = register_framebuffer(&fb_info); - if (!err) - printk("fb%d: %s frame buffer device\n", - fb_info.node, fb_info.fix.id); - else { - iounmap(fb_info.screen_base); - iounmap_macfb(); - } + if (err) + goto fail_dealloc; + + printk("fb%d: %s frame buffer device\n", + fb_info.node, fb_info.fix.id); + return 0; + +fail_dealloc: + fb_dealloc_cmap(&fb_info.cmap); +fail_unmap: + iounmap(fb_info.screen_base); + iounmap_macfb(); return err; } diff --git a/drivers/video/mb862xx/Makefile b/drivers/video/mb862xx/Makefile new file mode 100644 index 00000000000..07664814bb1 --- /dev/null +++ b/drivers/video/mb862xx/Makefile @@ -0,0 +1,5 @@ +# +# Makefile for the MB862xx framebuffer driver +# + +obj-$(CONFIG_FB_MB862XX) := mb862xxfb.o diff --git a/drivers/video/mb862xx/mb862xx_reg.h b/drivers/video/mb862xx/mb862xx_reg.h new file mode 100644 index 00000000000..2ba65e11850 --- /dev/null +++ b/drivers/video/mb862xx/mb862xx_reg.h @@ -0,0 +1,138 @@ +/* + * Fujitsu MB862xx Graphics Controller Registers/Bits + */ + +#ifndef _MB862XX_REG_H +#define _MB862XX_REG_H + +#ifdef MB862XX_MMIO_BOTTOM +#define MB862XX_MMIO_BASE 0x03fc0000 +#else +#define MB862XX_MMIO_BASE 0x01fc0000 +#endif +#define MB862XX_I2C_BASE 0x0000c000 +#define MB862XX_DISP_BASE 0x00010000 +#define MB862XX_CAP_BASE 0x00018000 +#define MB862XX_DRAW_BASE 0x00030000 +#define MB862XX_GEO_BASE 0x00038000 +#define MB862XX_PIO_BASE 0x00038000 +#define MB862XX_MMIO_SIZE 0x40000 + +/* Host interface/pio registers */ +#define GC_IST 0x00000020 +#define GC_IMASK 0x00000024 +#define GC_SRST 0x0000002c +#define GC_CCF 0x00000038 +#define GC_CID 0x000000f0 +#define GC_REVISION 0x00000084 + +#define GC_CCF_CGE_100 0x00000000 +#define GC_CCF_CGE_133 0x00040000 +#define GC_CCF_CGE_166 0x00080000 +#define GC_CCF_COT_100 0x00000000 +#define GC_CCF_COT_133 0x00010000 +#define GC_CID_CNAME_MSK 0x0000ff00 +#define GC_CID_VERSION_MSK 0x000000ff + +/* define enabled interrupts hereby */ +#define GC_INT_EN 0x00000000 + +/* Memory interface mode register */ +#define GC_MMR 0x0000fffc + +/* Display Controller registers */ +#define GC_DCM0 0x00000000 +#define GC_HTP 0x00000004 +#define GC_HDB_HDP 0x00000008 +#define GC_VSW_HSW_HSP 0x0000000c +#define GC_VTR 0x00000010 +#define GC_VDP_VSP 0x00000014 +#define GC_WY_WX 0x00000018 +#define GC_WH_WW 0x0000001c +#define GC_L0M 0x00000020 +#define GC_L0OA0 0x00000024 +#define GC_L0DA0 0x00000028 +#define GC_L0DY_L0DX 0x0000002c +#define GC_DCM1 0x00000100 +#define GC_L0EM 0x00000110 +#define GC_L0WY_L0WX 0x00000114 +#define GC_L0WH_L0WW 0x00000118 +#define GC_DCM2 0x00000104 +#define GC_DCM3 0x00000108 +#define GC_CPM_CUTC 0x000000a0 +#define GC_CUOA0 0x000000a4 +#define GC_CUY0_CUX0 0x000000a8 +#define GC_CUOA1 0x000000ac +#define GC_CUY1_CUX1 0x000000b0 +#define GC_L0PAL0 0x00000400 + +#define GC_CPM_CEN0 0x00100000 +#define GC_CPM_CEN1 0x00200000 + +#define GC_DCM01_ESY 0x00000004 +#define GC_DCM01_SC 0x00003f00 +#define GC_DCM01_RESV 0x00004000 +#define GC_DCM01_CKS 0x00008000 +#define GC_DCM01_L0E 0x00010000 +#define GC_DCM01_DEN 0x80000000 +#define GC_L0M_L0C_8 0x00000000 +#define GC_L0M_L0C_16 0x80000000 +#define GC_L0EM_L0EC_24 0x40000000 +#define GC_L0M_L0W_UNIT 64 + +#define GC_DISP_REFCLK_400 400 + +/* Carmine specific */ +#define MB86297_DRAW_BASE 0x00020000 +#define MB86297_DISP0_BASE 0x00100000 +#define MB86297_DISP1_BASE 0x00140000 +#define MB86297_WRBACK_BASE 0x00180000 +#define MB86297_CAP0_BASE 0x00200000 +#define MB86297_CAP1_BASE 0x00280000 +#define MB86297_DRAMCTRL_BASE 0x00300000 +#define MB86297_CTRL_BASE 0x00400000 +#define MB86297_I2C_BASE 0x00500000 + +#define GC_CTRL_STATUS 0x00000000 +#define GC_CTRL_INT_MASK 0x00000004 +#define GC_CTRL_CLK_ENABLE 0x0000000c +#define GC_CTRL_SOFT_RST 0x00000010 + +#define GC_CTRL_CLK_EN_DRAM 0x00000001 +#define GC_CTRL_CLK_EN_2D3D 0x00000002 +#define GC_CTRL_CLK_EN_DISP0 0x00000020 +#define GC_CTRL_CLK_EN_DISP1 0x00000040 + +#define GC_2D3D_REV 0x000004b4 +#define GC_RE_REVISION 0x24240200 + +/* define enabled interrupts hereby */ +#define GC_CARMINE_INT_EN 0x00000004 + +/* DRAM controller */ +#define GC_DCTL_MODE_ADD 0x00000000 +#define GC_DCTL_SETTIME1_EMODE 0x00000004 +#define GC_DCTL_REFRESH_SETTIME2 0x00000008 +#define GC_DCTL_RSV0_STATES 0x0000000C +#define GC_DCTL_RSV2_RSV1 0x00000010 +#define GC_DCTL_DDRIF2_DDRIF1 0x00000014 +#define GC_DCTL_IOCONT1_IOCONT0 0x00000024 + +#define GC_DCTL_STATES_MSK 0x0000000f +#define GC_DCTL_INIT_WAIT_CNT 3000 +#define GC_DCTL_INIT_WAIT_INTERVAL 1 + +/* DRAM ctrl values for Carmine PCI Eval. board */ +#define GC_EVB_DCTL_MODE_ADD 0x012105c3 +#define GC_EVB_DCTL_MODE_ADD_AFT_RST 0x002105c3 +#define GC_EVB_DCTL_SETTIME1_EMODE 0x47498000 +#define GC_EVB_DCTL_REFRESH_SETTIME2 0x00422a22 +#define GC_EVB_DCTL_RSV0_STATES 0x00200003 +#define GC_EVB_DCTL_RSV0_STATES_AFT_RST 0x00200002 +#define GC_EVB_DCTL_RSV2_RSV1 0x0000000f +#define GC_EVB_DCTL_DDRIF2_DDRIF1 0x00556646 +#define GC_EVB_DCTL_IOCONT1_IOCONT0 0x05550555 + +#define GC_DISP_REFCLK_533 533 + +#endif diff --git a/drivers/video/mb862xx/mb862xxfb.c b/drivers/video/mb862xx/mb862xxfb.c new file mode 100644 index 00000000000..fb64234a382 --- /dev/null +++ b/drivers/video/mb862xx/mb862xxfb.c @@ -0,0 +1,1061 @@ +/* + * drivers/mb862xx/mb862xxfb.c + * + * Fujitsu Carmine/Coral-P(A)/Lime framebuffer driver + * + * (C) 2008 Anatolij Gustschin <agust@denx.de> + * DENX Software Engineering + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#undef DEBUG + +#include <linux/fb.h> +#include <linux/delay.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/pci.h> +#if defined(CONFIG_PPC_OF) +#include <linux/of_platform.h> +#endif +#include "mb862xxfb.h" +#include "mb862xx_reg.h" + +#define NR_PALETTE 256 +#define MB862XX_MEM_SIZE 0x1000000 +#define CORALP_MEM_SIZE 0x4000000 +#define CARMINE_MEM_SIZE 0x8000000 +#define DRV_NAME "mb862xxfb" + +#if defined(CONFIG_LWMON5) +static struct mb862xx_gc_mode lwmon5_gc_mode = { + /* Mode for Sharp LQ104V1DG61 TFT LCD Panel */ + { "640x480", 60, 640, 480, 40000, 48, 16, 32, 11, 96, 2, 0, 0, 0 }, + /* 16 bits/pixel, 32MB, 100MHz, SDRAM memory mode value */ + 16, 0x2000000, GC_CCF_COT_100, 0x414fb7f2 +}; +#endif + +#if defined(CONFIG_SOCRATES) +static struct mb862xx_gc_mode socrates_gc_mode = { + /* Mode for Prime View PM070WL4 TFT LCD Panel */ + { "800x480", 45, 800, 480, 40000, 86, 42, 33, 10, 128, 2, 0, 0, 0 }, + /* 16 bits/pixel, 16MB, 133MHz, SDRAM memory mode value */ + 16, 0x1000000, GC_CCF_COT_133, 0x4157ba63 +}; +#endif + +/* Helpers */ +static inline int h_total(struct fb_var_screeninfo *var) +{ + return var->xres + var->left_margin + + var->right_margin + var->hsync_len; +} + +static inline int v_total(struct fb_var_screeninfo *var) +{ + return var->yres + var->upper_margin + + var->lower_margin + var->vsync_len; +} + +static inline int hsp(struct fb_var_screeninfo *var) +{ + return var->xres + var->right_margin - 1; +} + +static inline int vsp(struct fb_var_screeninfo *var) +{ + return var->yres + var->lower_margin - 1; +} + +static inline int d_pitch(struct fb_var_screeninfo *var) +{ + return var->xres * var->bits_per_pixel / 8; +} + +static inline unsigned int chan_to_field(unsigned int chan, + struct fb_bitfield *bf) +{ + chan &= 0xffff; + chan >>= 16 - bf->length; + return chan << bf->offset; +} + +static int mb862xxfb_setcolreg(unsigned regno, + unsigned red, unsigned green, unsigned blue, + unsigned transp, struct fb_info *info) +{ + struct mb862xxfb_par *par = info->par; + unsigned int val; + + switch (info->fix.visual) { + case FB_VISUAL_TRUECOLOR: + if (regno < 16) { + val = chan_to_field(red, &info->var.red); + val |= chan_to_field(green, &info->var.green); + val |= chan_to_field(blue, &info->var.blue); + par->pseudo_palette[regno] = val; + } + break; + case FB_VISUAL_PSEUDOCOLOR: + if (regno < 256) { + val = (red >> 8) << 16; + val |= (green >> 8) << 8; + val |= blue >> 8; + outreg(disp, GC_L0PAL0 + (regno * 4), val); + } + break; + default: + return 1; /* unsupported type */ + } + return 0; +} + +static int mb862xxfb_check_var(struct fb_var_screeninfo *var, + struct fb_info *fbi) +{ + unsigned long tmp; + + if (fbi->dev) + dev_dbg(fbi->dev, "%s\n", __func__); + + /* check if these values fit into the registers */ + if (var->hsync_len > 255 || var->vsync_len > 255) + return -EINVAL; + + if ((var->xres + var->right_margin) >= 4096) + return -EINVAL; + + if ((var->yres + var->lower_margin) > 4096) + return -EINVAL; + + if (h_total(var) > 4096 || v_total(var) > 4096) + return -EINVAL; + + if (var->xres_virtual > 4096 || var->yres_virtual > 4096) + return -EINVAL; + + 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 <= 32) + var->bits_per_pixel = 32; + + /* + * can cope with 8,16 or 24/32bpp if resulting + * pitch is divisible by 64 without remainder + */ + if (d_pitch(&fbi->var) % GC_L0M_L0W_UNIT) { + int r; + + var->bits_per_pixel = 0; + do { + var->bits_per_pixel += 8; + r = d_pitch(&fbi->var) % GC_L0M_L0W_UNIT; + } while (r && var->bits_per_pixel <= 32); + + if (d_pitch(&fbi->var) % GC_L0M_L0W_UNIT) + return -EINVAL; + } + + /* line length is going to be 128 bit aligned */ + tmp = (var->xres * var->bits_per_pixel) / 8; + if ((tmp & 15) != 0) + return -EINVAL; + + /* set r/g/b positions and validate bpp */ + switch (var->bits_per_pixel) { + case 8: + var->red.length = var->bits_per_pixel; + var->green.length = var->bits_per_pixel; + var->blue.length = var->bits_per_pixel; + var->red.offset = 0; + var->green.offset = 0; + var->blue.offset = 0; + var->transp.length = 0; + break; + case 16: + var->red.length = 5; + var->green.length = 5; + var->blue.length = 5; + var->red.offset = 10; + var->green.offset = 5; + var->blue.offset = 0; + var->transp.length = 0; + break; + case 24: + case 32: + var->transp.length = 8; + var->red.length = 8; + var->green.length = 8; + var->blue.length = 8; + var->transp.offset = 24; + var->red.offset = 16; + var->green.offset = 8; + var->blue.offset = 0; + break; + default: + return -EINVAL; + } + return 0; +} + +/* + * set display parameters + */ +static int mb862xxfb_set_par(struct fb_info *fbi) +{ + struct mb862xxfb_par *par = fbi->par; + unsigned long reg, sc; + + dev_dbg(par->dev, "%s\n", __func__); + + if (par->pre_init) + return 0; + + /* disp off */ + reg = inreg(disp, GC_DCM1); + reg &= ~GC_DCM01_DEN; + outreg(disp, GC_DCM1, reg); + + /* set display reference clock div. */ + sc = par->refclk / (1000000 / fbi->var.pixclock) - 1; + reg = inreg(disp, GC_DCM1); + reg &= ~(GC_DCM01_CKS | GC_DCM01_RESV | GC_DCM01_SC); + reg |= sc << 8; + outreg(disp, GC_DCM1, reg); + dev_dbg(par->dev, "SC 0x%lx\n", sc); + + /* disp dimension, format */ + reg = pack(d_pitch(&fbi->var) / GC_L0M_L0W_UNIT, + (fbi->var.yres - 1)); + if (fbi->var.bits_per_pixel == 16) + reg |= GC_L0M_L0C_16; + outreg(disp, GC_L0M, reg); + + if (fbi->var.bits_per_pixel == 32) { + reg = inreg(disp, GC_L0EM); + outreg(disp, GC_L0EM, reg | GC_L0EM_L0EC_24); + } + outreg(disp, GC_WY_WX, 0); + reg = pack(fbi->var.yres - 1, fbi->var.xres); + outreg(disp, GC_WH_WW, reg); + outreg(disp, GC_L0OA0, 0); + outreg(disp, GC_L0DA0, 0); + outreg(disp, GC_L0DY_L0DX, 0); + outreg(disp, GC_L0WY_L0WX, 0); + outreg(disp, GC_L0WH_L0WW, reg); + + /* both HW-cursors off */ + reg = inreg(disp, GC_CPM_CUTC); + reg &= ~(GC_CPM_CEN0 | GC_CPM_CEN1); + outreg(disp, GC_CPM_CUTC, reg); + + /* timings */ + reg = pack(fbi->var.xres - 1, fbi->var.xres - 1); + outreg(disp, GC_HDB_HDP, reg); + reg = pack((fbi->var.yres - 1), vsp(&fbi->var)); + outreg(disp, GC_VDP_VSP, reg); + reg = ((fbi->var.vsync_len - 1) << 24) | + pack((fbi->var.hsync_len - 1), hsp(&fbi->var)); + outreg(disp, GC_VSW_HSW_HSP, reg); + outreg(disp, GC_HTP, pack(h_total(&fbi->var) - 1, 0)); + outreg(disp, GC_VTR, pack(v_total(&fbi->var) - 1, 0)); + + /* display on */ + reg = inreg(disp, GC_DCM1); + reg |= GC_DCM01_DEN | GC_DCM01_L0E; + reg &= ~GC_DCM01_ESY; + outreg(disp, GC_DCM1, reg); + return 0; +} + +static int mb862xxfb_pan(struct fb_var_screeninfo *var, + struct fb_info *info) +{ + struct mb862xxfb_par *par = info->par; + unsigned long reg; + + reg = pack(var->yoffset, var->xoffset); + outreg(disp, GC_L0WY_L0WX, reg); + + reg = pack(var->yres_virtual, var->xres_virtual); + outreg(disp, GC_L0WH_L0WW, reg); + return 0; +} + +static int mb862xxfb_blank(int mode, struct fb_info *fbi) +{ + struct mb862xxfb_par *par = fbi->par; + unsigned long reg; + + dev_dbg(fbi->dev, "blank mode=%d\n", mode); + + switch (mode) { + case FB_BLANK_POWERDOWN: + reg = inreg(disp, GC_DCM1); + reg &= ~GC_DCM01_DEN; + outreg(disp, GC_DCM1, reg); + break; + case FB_BLANK_UNBLANK: + reg = inreg(disp, GC_DCM1); + reg |= GC_DCM01_DEN; + outreg(disp, GC_DCM1, reg); + break; + case FB_BLANK_NORMAL: + case FB_BLANK_VSYNC_SUSPEND: + case FB_BLANK_HSYNC_SUSPEND: + default: + return 1; + } + return 0; +} + +/* framebuffer ops */ +static struct fb_ops mb862xxfb_ops = { + .owner = THIS_MODULE, + .fb_check_var = mb862xxfb_check_var, + .fb_set_par = mb862xxfb_set_par, + .fb_setcolreg = mb862xxfb_setcolreg, + .fb_blank = mb862xxfb_blank, + .fb_pan_display = mb862xxfb_pan, + .fb_fillrect = cfb_fillrect, + .fb_copyarea = cfb_copyarea, + .fb_imageblit = cfb_imageblit, +}; + +/* initialize fb_info data */ +static int mb862xxfb_init_fbinfo(struct fb_info *fbi) +{ + struct mb862xxfb_par *par = fbi->par; + struct mb862xx_gc_mode *mode = par->gc_mode; + unsigned long reg; + + fbi->fbops = &mb862xxfb_ops; + fbi->pseudo_palette = par->pseudo_palette; + fbi->screen_base = par->fb_base; + fbi->screen_size = par->mapped_vram; + + strcpy(fbi->fix.id, DRV_NAME); + fbi->fix.smem_start = (unsigned long)par->fb_base_phys; + fbi->fix.smem_len = par->mapped_vram; + fbi->fix.mmio_start = (unsigned long)par->mmio_base_phys; + fbi->fix.mmio_len = par->mmio_len; + fbi->fix.accel = FB_ACCEL_NONE; + fbi->fix.type = FB_TYPE_PACKED_PIXELS; + fbi->fix.type_aux = 0; + fbi->fix.xpanstep = 1; + fbi->fix.ypanstep = 1; + fbi->fix.ywrapstep = 0; + + reg = inreg(disp, GC_DCM1); + if (reg & GC_DCM01_DEN && reg & GC_DCM01_L0E) { + /* get the disp mode from active display cfg */ + unsigned long sc = ((reg & GC_DCM01_SC) >> 8) + 1; + unsigned long hsp, vsp, ht, vt; + + dev_dbg(par->dev, "using bootloader's disp. mode\n"); + fbi->var.pixclock = (sc * 1000000) / par->refclk; + fbi->var.xres = (inreg(disp, GC_HDB_HDP) & 0x0fff) + 1; + reg = inreg(disp, GC_VDP_VSP); + fbi->var.yres = ((reg >> 16) & 0x0fff) + 1; + vsp = (reg & 0x0fff) + 1; + fbi->var.xres_virtual = fbi->var.xres; + fbi->var.yres_virtual = fbi->var.yres; + reg = inreg(disp, GC_L0EM); + if (reg & GC_L0EM_L0EC_24) { + fbi->var.bits_per_pixel = 32; + } else { + reg = inreg(disp, GC_L0M); + if (reg & GC_L0M_L0C_16) + fbi->var.bits_per_pixel = 16; + else + fbi->var.bits_per_pixel = 8; + } + reg = inreg(disp, GC_VSW_HSW_HSP); + fbi->var.hsync_len = ((reg & 0xff0000) >> 16) + 1; + fbi->var.vsync_len = ((reg & 0x3f000000) >> 24) + 1; + hsp = (reg & 0xffff) + 1; + ht = ((inreg(disp, GC_HTP) & 0xfff0000) >> 16) + 1; + fbi->var.right_margin = hsp - fbi->var.xres; + fbi->var.left_margin = ht - hsp - fbi->var.hsync_len; + vt = ((inreg(disp, GC_VTR) & 0xfff0000) >> 16) + 1; + fbi->var.lower_margin = vsp - fbi->var.yres; + fbi->var.upper_margin = vt - vsp - fbi->var.vsync_len; + } else if (mode) { + dev_dbg(par->dev, "using supplied mode\n"); + fb_videomode_to_var(&fbi->var, (struct fb_videomode *)mode); + fbi->var.bits_per_pixel = mode->def_bpp ? mode->def_bpp : 8; + } else { + int ret; + + ret = fb_find_mode(&fbi->var, fbi, "640x480-16@60", + NULL, 0, NULL, 16); + if (ret == 0 || ret == 4) { + dev_err(par->dev, + "failed to get initial mode\n"); + return -EINVAL; + } + } + + fbi->var.xoffset = 0; + fbi->var.yoffset = 0; + fbi->var.grayscale = 0; + fbi->var.nonstd = 0; + fbi->var.height = -1; + fbi->var.width = -1; + fbi->var.accel_flags = 0; + fbi->var.vmode = FB_VMODE_NONINTERLACED; + fbi->var.activate = FB_ACTIVATE_NOW; + fbi->flags = FBINFO_DEFAULT | +#ifdef __BIG_ENDIAN + FBINFO_FOREIGN_ENDIAN | +#endif + FBINFO_HWACCEL_XPAN | + FBINFO_HWACCEL_YPAN; + + /* check and possibly fix bpp */ + if ((fbi->fbops->fb_check_var)(&fbi->var, fbi)) + dev_err(par->dev, "check_var() failed on initial setup?\n"); + + fbi->fix.visual = fbi->var.bits_per_pixel == 8 ? + FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; + fbi->fix.line_length = (fbi->var.xres_virtual * + fbi->var.bits_per_pixel) / 8; + return 0; +} + +/* + * show some display controller and cursor registers + */ +static ssize_t mb862xxfb_show_dispregs(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct fb_info *fbi = dev_get_drvdata(dev); + struct mb862xxfb_par *par = fbi->par; + char *ptr = buf; + unsigned int reg; + + for (reg = GC_DCM0; reg <= GC_L0DY_L0DX; reg += 4) + ptr += sprintf(ptr, "%08x = %08x\n", + reg, inreg(disp, reg)); + + for (reg = GC_CPM_CUTC; reg <= GC_CUY1_CUX1; reg += 4) + ptr += sprintf(ptr, "%08x = %08x\n", + reg, inreg(disp, reg)); + + for (reg = GC_DCM1; reg <= GC_L0WH_L0WW; reg += 4) + ptr += sprintf(ptr, "%08x = %08x\n", + reg, inreg(disp, reg)); + + return ptr - buf; +} + +static DEVICE_ATTR(dispregs, 0444, mb862xxfb_show_dispregs, NULL); + +irqreturn_t mb862xx_intr(int irq, void *dev_id) +{ + struct mb862xxfb_par *par = (struct mb862xxfb_par *) dev_id; + unsigned long reg_ist, mask; + + if (!par) + return IRQ_NONE; + + if (par->type == BT_CARMINE) { + /* Get Interrupt Status */ + reg_ist = inreg(ctrl, GC_CTRL_STATUS); + mask = inreg(ctrl, GC_CTRL_INT_MASK); + if (reg_ist == 0) + return IRQ_HANDLED; + + reg_ist &= mask; + if (reg_ist == 0) + return IRQ_HANDLED; + + /* Clear interrupt status */ + outreg(ctrl, 0x0, reg_ist); + } else { + /* Get status */ + reg_ist = inreg(host, GC_IST); + mask = inreg(host, GC_IMASK); + + reg_ist &= mask; + if (reg_ist == 0) + return IRQ_HANDLED; + + /* Clear status */ + outreg(host, GC_IST, ~reg_ist); + } + return IRQ_HANDLED; +} + +#if defined(CONFIG_FB_MB862XX_LIME) +/* + * GDC (Lime, Coral(B/Q), Mint, ...) on host bus + */ +static int mb862xx_gdc_init(struct mb862xxfb_par *par) +{ + unsigned long ccf, mmr; + unsigned long ver, rev; + + if (!par) + return -ENODEV; + +#if defined(CONFIG_FB_PRE_INIT_FB) + par->pre_init = 1; +#endif + par->host = par->mmio_base; + par->i2c = par->mmio_base + MB862XX_I2C_BASE; + par->disp = par->mmio_base + MB862XX_DISP_BASE; + par->cap = par->mmio_base + MB862XX_CAP_BASE; + par->draw = par->mmio_base + MB862XX_DRAW_BASE; + par->geo = par->mmio_base + MB862XX_GEO_BASE; + par->pio = par->mmio_base + MB862XX_PIO_BASE; + + par->refclk = GC_DISP_REFCLK_400; + + ver = inreg(host, GC_CID); + rev = inreg(pio, GC_REVISION); + if ((ver == 0x303) && (rev & 0xffffff00) == 0x20050100) { + dev_info(par->dev, "Fujitsu Lime v1.%d found\n", + (int)rev & 0xff); + par->type = BT_LIME; + ccf = par->gc_mode ? par->gc_mode->ccf : GC_CCF_COT_100; + mmr = par->gc_mode ? par->gc_mode->mmr : 0x414fb7f2; + } else { + dev_info(par->dev, "? GDC, CID/Rev.: 0x%lx/0x%lx \n", ver, rev); + return -ENODEV; + } + + if (!par->pre_init) { + outreg(host, GC_CCF, ccf); + udelay(200); + outreg(host, GC_MMR, mmr); + udelay(10); + } + + /* interrupt status */ + outreg(host, GC_IST, 0); + outreg(host, GC_IMASK, GC_INT_EN); + return 0; +} + +static int __devinit of_platform_mb862xx_probe(struct of_device *ofdev, + const struct of_device_id *id) +{ + struct device_node *np = ofdev->node; + struct device *dev = &ofdev->dev; + struct mb862xxfb_par *par; + struct fb_info *info; + struct resource res; + resource_size_t res_size; + unsigned long ret = -ENODEV; + + if (of_address_to_resource(np, 0, &res)) { + dev_err(dev, "Invalid address\n"); + return -ENXIO; + } + + info = framebuffer_alloc(sizeof(struct mb862xxfb_par), dev); + if (info == NULL) { + dev_err(dev, "cannot allocate framebuffer\n"); + return -ENOMEM; + } + + par = info->par; + par->info = info; + par->dev = dev; + + par->irq = irq_of_parse_and_map(np, 0); + if (par->irq == NO_IRQ) { + dev_err(dev, "failed to map irq\n"); + ret = -ENODEV; + goto fbrel; + } + + res_size = 1 + res.end - res.start; + par->res = request_mem_region(res.start, res_size, DRV_NAME); + if (par->res == NULL) { + dev_err(dev, "Cannot claim framebuffer/mmio\n"); + ret = -ENXIO; + goto irqdisp; + } + +#if defined(CONFIG_LWMON5) + par->gc_mode = &lwmon5_gc_mode; +#endif + +#if defined(CONFIG_SOCRATES) + par->gc_mode = &socrates_gc_mode; +#endif + + par->fb_base_phys = res.start; + par->mmio_base_phys = res.start + MB862XX_MMIO_BASE; + par->mmio_len = MB862XX_MMIO_SIZE; + if (par->gc_mode) + par->mapped_vram = par->gc_mode->max_vram; + else + par->mapped_vram = MB862XX_MEM_SIZE; + + par->fb_base = ioremap(par->fb_base_phys, par->mapped_vram); + if (par->fb_base == NULL) { + dev_err(dev, "Cannot map framebuffer\n"); + goto rel_reg; + } + + par->mmio_base = ioremap(par->mmio_base_phys, par->mmio_len); + if (par->mmio_base == NULL) { + dev_err(dev, "Cannot map registers\n"); + goto fb_unmap; + } + + dev_dbg(dev, "fb phys 0x%llx 0x%lx\n", + (u64)par->fb_base_phys, (ulong)par->mapped_vram); + dev_dbg(dev, "mmio phys 0x%llx 0x%lx, (irq = %d)\n", + (u64)par->mmio_base_phys, (ulong)par->mmio_len, par->irq); + + if (mb862xx_gdc_init(par)) + goto io_unmap; + + if (request_irq(par->irq, mb862xx_intr, IRQF_DISABLED, + DRV_NAME, (void *)par)) { + dev_err(dev, "Cannot request irq\n"); + goto io_unmap; + } + + mb862xxfb_init_fbinfo(info); + + if (fb_alloc_cmap(&info->cmap, NR_PALETTE, 0) < 0) { + dev_err(dev, "Could not allocate cmap for fb_info.\n"); + goto free_irq; + } + + if ((info->fbops->fb_set_par)(info)) + dev_err(dev, "set_var() failed on initial setup?\n"); + + if (register_framebuffer(info)) { + dev_err(dev, "failed to register framebuffer\n"); + goto rel_cmap; + } + + dev_set_drvdata(dev, info); + + if (device_create_file(dev, &dev_attr_dispregs)) + dev_err(dev, "Can't create sysfs regdump file\n"); + return 0; + +rel_cmap: + fb_dealloc_cmap(&info->cmap); +free_irq: + outreg(host, GC_IMASK, 0); + free_irq(par->irq, (void *)par); +io_unmap: + iounmap(par->mmio_base); +fb_unmap: + iounmap(par->fb_base); +rel_reg: + release_mem_region(res.start, res_size); +irqdisp: + irq_dispose_mapping(par->irq); +fbrel: + dev_set_drvdata(dev, NULL); + framebuffer_release(info); + return ret; +} + +static int __devexit of_platform_mb862xx_remove(struct of_device *ofdev) +{ + struct fb_info *fbi = dev_get_drvdata(&ofdev->dev); + struct mb862xxfb_par *par = fbi->par; + resource_size_t res_size = 1 + par->res->end - par->res->start; + unsigned long reg; + + dev_dbg(fbi->dev, "%s release\n", fbi->fix.id); + + /* display off */ + reg = inreg(disp, GC_DCM1); + reg &= ~(GC_DCM01_DEN | GC_DCM01_L0E); + outreg(disp, GC_DCM1, reg); + + /* disable interrupts */ + outreg(host, GC_IMASK, 0); + + free_irq(par->irq, (void *)par); + irq_dispose_mapping(par->irq); + + device_remove_file(&ofdev->dev, &dev_attr_dispregs); + + unregister_framebuffer(fbi); + fb_dealloc_cmap(&fbi->cmap); + + iounmap(par->mmio_base); + iounmap(par->fb_base); + + dev_set_drvdata(&ofdev->dev, NULL); + release_mem_region(par->res->start, res_size); + framebuffer_release(fbi); + return 0; +} + +/* + * common types + */ +static struct of_device_id __devinitdata of_platform_mb862xx_tbl[] = { + { .compatible = "fujitsu,MB86276", }, + { .compatible = "fujitsu,lime", }, + { .compatible = "fujitsu,MB86277", }, + { .compatible = "fujitsu,mint", }, + { .compatible = "fujitsu,MB86293", }, + { .compatible = "fujitsu,MB86294", }, + { .compatible = "fujitsu,coral", }, + { /* end */ } +}; + +static struct of_platform_driver of_platform_mb862xxfb_driver = { + .owner = THIS_MODULE, + .name = DRV_NAME, + .match_table = of_platform_mb862xx_tbl, + .probe = of_platform_mb862xx_probe, + .remove = __devexit_p(of_platform_mb862xx_remove), +}; +#endif + +#if defined(CONFIG_FB_MB862XX_PCI_GDC) +static int coralp_init(struct mb862xxfb_par *par) +{ + int cn, ver; + + par->host = par->mmio_base; + par->i2c = par->mmio_base + MB862XX_I2C_BASE; + par->disp = par->mmio_base + MB862XX_DISP_BASE; + par->cap = par->mmio_base + MB862XX_CAP_BASE; + par->draw = par->mmio_base + MB862XX_DRAW_BASE; + par->geo = par->mmio_base + MB862XX_GEO_BASE; + par->pio = par->mmio_base + MB862XX_PIO_BASE; + + par->refclk = GC_DISP_REFCLK_400; + + ver = inreg(host, GC_CID); + cn = (ver & GC_CID_CNAME_MSK) >> 8; + ver = ver & GC_CID_VERSION_MSK; + if (cn == 3) { + dev_info(par->dev, "Fujitsu Coral-%s GDC Rev.%d found\n",\ + (ver == 6) ? "P" : (ver == 8) ? "PA" : "?", + par->pdev->revision); + outreg(host, GC_CCF, GC_CCF_CGE_166 | GC_CCF_COT_133); + udelay(200); + outreg(host, GC_MMR, GC_MMR_CORALP_EVB_VAL); + udelay(10); + /* Clear interrupt status */ + outreg(host, GC_IST, 0); + } else { + return -ENODEV; + } + return 0; +} + +static int init_dram_ctrl(struct mb862xxfb_par *par) +{ + unsigned long i = 0; + + /* + * Set io mode first! Spec. says IC may be destroyed + * if not set to SSTL2/LVCMOS before init. + */ + outreg(dram_ctrl, GC_DCTL_IOCONT1_IOCONT0, GC_EVB_DCTL_IOCONT1_IOCONT0); + + /* DRAM init */ + outreg(dram_ctrl, GC_DCTL_MODE_ADD, GC_EVB_DCTL_MODE_ADD); + outreg(dram_ctrl, GC_DCTL_SETTIME1_EMODE, GC_EVB_DCTL_SETTIME1_EMODE); + outreg(dram_ctrl, GC_DCTL_REFRESH_SETTIME2, + GC_EVB_DCTL_REFRESH_SETTIME2); + outreg(dram_ctrl, GC_DCTL_RSV2_RSV1, GC_EVB_DCTL_RSV2_RSV1); + outreg(dram_ctrl, GC_DCTL_DDRIF2_DDRIF1, GC_EVB_DCTL_DDRIF2_DDRIF1); + outreg(dram_ctrl, GC_DCTL_RSV0_STATES, GC_EVB_DCTL_RSV0_STATES); + + /* DLL reset done? */ + while ((inreg(dram_ctrl, GC_DCTL_RSV0_STATES) & GC_DCTL_STATES_MSK)) { + udelay(GC_DCTL_INIT_WAIT_INTERVAL); + if (i++ > GC_DCTL_INIT_WAIT_CNT) { + dev_err(par->dev, "VRAM init failed.\n"); + return -EINVAL; + } + } + outreg(dram_ctrl, GC_DCTL_MODE_ADD, GC_EVB_DCTL_MODE_ADD_AFT_RST); + outreg(dram_ctrl, GC_DCTL_RSV0_STATES, GC_EVB_DCTL_RSV0_STATES_AFT_RST); + return 0; +} + +static int carmine_init(struct mb862xxfb_par *par) +{ + unsigned long reg; + + par->ctrl = par->mmio_base + MB86297_CTRL_BASE; + par->i2c = par->mmio_base + MB86297_I2C_BASE; + par->disp = par->mmio_base + MB86297_DISP0_BASE; + par->disp1 = par->mmio_base + MB86297_DISP1_BASE; + par->cap = par->mmio_base + MB86297_CAP0_BASE; + par->cap1 = par->mmio_base + MB86297_CAP1_BASE; + par->draw = par->mmio_base + MB86297_DRAW_BASE; + par->dram_ctrl = par->mmio_base + MB86297_DRAMCTRL_BASE; + par->wrback = par->mmio_base + MB86297_WRBACK_BASE; + + par->refclk = GC_DISP_REFCLK_533; + + /* warm up */ + reg = GC_CTRL_CLK_EN_DRAM | GC_CTRL_CLK_EN_2D3D | GC_CTRL_CLK_EN_DISP0; + outreg(ctrl, GC_CTRL_CLK_ENABLE, reg); + + /* check for engine module revision */ + if (inreg(draw, GC_2D3D_REV) == GC_RE_REVISION) + dev_info(par->dev, "Fujitsu Carmine GDC Rev.%d found\n", + par->pdev->revision); + else + goto err_init; + + reg &= ~GC_CTRL_CLK_EN_2D3D; + outreg(ctrl, GC_CTRL_CLK_ENABLE, reg); + + /* set up vram */ + if (init_dram_ctrl(par) < 0) + goto err_init; + + outreg(ctrl, GC_CTRL_INT_MASK, 0); + return 0; + +err_init: + outreg(ctrl, GC_CTRL_CLK_ENABLE, 0); + return -EINVAL; +} + +static inline int mb862xx_pci_gdc_init(struct mb862xxfb_par *par) +{ + switch (par->type) { + case BT_CORALP: + return coralp_init(par); + case BT_CARMINE: + return carmine_init(par); + default: + return -ENODEV; + } +} + +#define CHIP_ID(id) \ + { PCI_DEVICE(PCI_VENDOR_ID_FUJITSU_LIMITED, id) } + +static struct pci_device_id mb862xx_pci_tbl[] __devinitdata = { + /* MB86295/MB86296 */ + CHIP_ID(PCI_DEVICE_ID_FUJITSU_CORALP), + CHIP_ID(PCI_DEVICE_ID_FUJITSU_CORALPA), + /* MB86297 */ + CHIP_ID(PCI_DEVICE_ID_FUJITSU_CARMINE), + { 0, } +}; + +MODULE_DEVICE_TABLE(pci, mb862xx_pci_tbl); + +static int __devinit mb862xx_pci_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + struct mb862xxfb_par *par; + struct fb_info *info; + struct device *dev = &pdev->dev; + int ret; + + ret = pci_enable_device(pdev); + if (ret < 0) { + dev_err(dev, "Cannot enable PCI device\n"); + goto out; + } + + info = framebuffer_alloc(sizeof(struct mb862xxfb_par), dev); + if (!info) { + dev_err(dev, "framebuffer alloc failed\n"); + ret = -ENOMEM; + goto dis_dev; + } + + par = info->par; + par->info = info; + par->dev = dev; + par->pdev = pdev; + par->irq = pdev->irq; + + ret = pci_request_regions(pdev, DRV_NAME); + if (ret < 0) { + dev_err(dev, "Cannot reserve region(s) for PCI device\n"); + goto rel_fb; + } + + switch (pdev->device) { + case PCI_DEVICE_ID_FUJITSU_CORALP: + case PCI_DEVICE_ID_FUJITSU_CORALPA: + par->fb_base_phys = pci_resource_start(par->pdev, 0); + par->mapped_vram = CORALP_MEM_SIZE; + par->mmio_base_phys = par->fb_base_phys + MB862XX_MMIO_BASE; + par->mmio_len = MB862XX_MMIO_SIZE; + par->type = BT_CORALP; + break; + case PCI_DEVICE_ID_FUJITSU_CARMINE: + par->fb_base_phys = pci_resource_start(par->pdev, 2); + par->mmio_base_phys = pci_resource_start(par->pdev, 3); + par->mmio_len = pci_resource_len(par->pdev, 3); + par->mapped_vram = CARMINE_MEM_SIZE; + par->type = BT_CARMINE; + break; + default: + /* should never occur */ + goto rel_reg; + } + + par->fb_base = ioremap(par->fb_base_phys, par->mapped_vram); + if (par->fb_base == NULL) { + dev_err(dev, "Cannot map framebuffer\n"); + goto rel_reg; + } + + par->mmio_base = ioremap(par->mmio_base_phys, par->mmio_len); + if (par->mmio_base == NULL) { + dev_err(dev, "Cannot map registers\n"); + ret = -EIO; + goto fb_unmap; + } + + dev_dbg(dev, "fb phys 0x%llx 0x%lx\n", + (unsigned long long)par->fb_base_phys, (ulong)par->mapped_vram); + dev_dbg(dev, "mmio phys 0x%llx 0x%lx\n", + (unsigned long long)par->mmio_base_phys, (ulong)par->mmio_len); + + if (mb862xx_pci_gdc_init(par)) + goto io_unmap; + + if (request_irq(par->irq, mb862xx_intr, IRQF_DISABLED | IRQF_SHARED, + DRV_NAME, (void *)par)) { + dev_err(dev, "Cannot request irq\n"); + goto io_unmap; + } + + mb862xxfb_init_fbinfo(info); + + if (fb_alloc_cmap(&info->cmap, NR_PALETTE, 0) < 0) { + dev_err(dev, "Could not allocate cmap for fb_info.\n"); + ret = -ENOMEM; + goto free_irq; + } + + if ((info->fbops->fb_set_par)(info)) + dev_err(dev, "set_var() failed on initial setup?\n"); + + ret = register_framebuffer(info); + if (ret < 0) { + dev_err(dev, "failed to register framebuffer\n"); + goto rel_cmap; + } + + pci_set_drvdata(pdev, info); + + if (device_create_file(dev, &dev_attr_dispregs)) + dev_err(dev, "Can't create sysfs regdump file\n"); + + if (par->type == BT_CARMINE) + outreg(ctrl, GC_CTRL_INT_MASK, GC_CARMINE_INT_EN); + else + outreg(host, GC_IMASK, GC_INT_EN); + + return 0; + +rel_cmap: + fb_dealloc_cmap(&info->cmap); +free_irq: + free_irq(par->irq, (void *)par); +io_unmap: + iounmap(par->mmio_base); +fb_unmap: + iounmap(par->fb_base); +rel_reg: + pci_release_regions(pdev); +rel_fb: + framebuffer_release(info); +dis_dev: + pci_disable_device(pdev); +out: + return ret; +} + +static void __devexit mb862xx_pci_remove(struct pci_dev *pdev) +{ + struct fb_info *fbi = pci_get_drvdata(pdev); + struct mb862xxfb_par *par = fbi->par; + unsigned long reg; + + dev_dbg(fbi->dev, "%s release\n", fbi->fix.id); + + /* display off */ + reg = inreg(disp, GC_DCM1); + reg &= ~(GC_DCM01_DEN | GC_DCM01_L0E); + outreg(disp, GC_DCM1, reg); + + if (par->type == BT_CARMINE) { + outreg(ctrl, GC_CTRL_INT_MASK, 0); + outreg(ctrl, GC_CTRL_CLK_ENABLE, 0); + } else { + outreg(host, GC_IMASK, 0); + } + + device_remove_file(&pdev->dev, &dev_attr_dispregs); + + pci_set_drvdata(pdev, NULL); + unregister_framebuffer(fbi); + fb_dealloc_cmap(&fbi->cmap); + + free_irq(par->irq, (void *)par); + iounmap(par->mmio_base); + iounmap(par->fb_base); + + pci_release_regions(pdev); + framebuffer_release(fbi); + pci_disable_device(pdev); +} + +static struct pci_driver mb862xxfb_pci_driver = { + .name = DRV_NAME, + .id_table = mb862xx_pci_tbl, + .probe = mb862xx_pci_probe, + .remove = __devexit_p(mb862xx_pci_remove), +}; +#endif + +static int __devinit mb862xxfb_init(void) +{ + int ret = -ENODEV; + +#if defined(CONFIG_FB_MB862XX_LIME) + ret = of_register_platform_driver(&of_platform_mb862xxfb_driver); +#endif +#if defined(CONFIG_FB_MB862XX_PCI_GDC) + ret = pci_register_driver(&mb862xxfb_pci_driver); +#endif + return ret; +} + +static void __exit mb862xxfb_exit(void) +{ +#if defined(CONFIG_FB_MB862XX_LIME) + of_unregister_platform_driver(&of_platform_mb862xxfb_driver); +#endif +#if defined(CONFIG_FB_MB862XX_PCI_GDC) + pci_unregister_driver(&mb862xxfb_pci_driver); +#endif +} + +module_init(mb862xxfb_init); +module_exit(mb862xxfb_exit); + +MODULE_DESCRIPTION("Fujitsu MB862xx Framebuffer driver"); +MODULE_AUTHOR("Anatolij Gustschin <agust@denx.de>"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/video/mb862xx/mb862xxfb.h b/drivers/video/mb862xx/mb862xxfb.h new file mode 100644 index 00000000000..c4c8f4dd221 --- /dev/null +++ b/drivers/video/mb862xx/mb862xxfb.h @@ -0,0 +1,83 @@ +#ifndef __MB862XX_H__ +#define __MB862XX_H__ + +#define PCI_VENDOR_ID_FUJITSU_LIMITED 0x10cf +#define PCI_DEVICE_ID_FUJITSU_CORALP 0x2019 +#define PCI_DEVICE_ID_FUJITSU_CORALPA 0x201e +#define PCI_DEVICE_ID_FUJITSU_CARMINE 0x202b + +#define GC_MMR_CORALP_EVB_VAL 0x11d7fa13 + +enum gdctype { + BT_NONE, + BT_LIME, + BT_MINT, + BT_CORAL, + BT_CORALP, + BT_CARMINE, +}; + +struct mb862xx_gc_mode { + struct fb_videomode def_mode; /* mode of connected display */ + unsigned int def_bpp; /* default depth */ + unsigned long max_vram; /* connected SDRAM size */ + unsigned long ccf; /* gdc clk */ + unsigned long mmr; /* memory mode for SDRAM */ +}; + +/* private data */ +struct mb862xxfb_par { + struct fb_info *info; /* fb info head */ + struct device *dev; + struct pci_dev *pdev; + struct resource *res; /* framebuffer/mmio resource */ + + resource_size_t fb_base_phys; /* fb base, 36-bit PPC440EPx */ + resource_size_t mmio_base_phys; /* io base addr */ + void __iomem *fb_base; /* remapped framebuffer */ + void __iomem *mmio_base; /* remapped registers */ + size_t mapped_vram; /* length of remapped vram */ + size_t mmio_len; /* length of register region */ + + void __iomem *host; /* relocatable reg. bases */ + void __iomem *i2c; + void __iomem *disp; + void __iomem *disp1; + void __iomem *cap; + void __iomem *cap1; + void __iomem *draw; + void __iomem *geo; + void __iomem *pio; + void __iomem *ctrl; + void __iomem *dram_ctrl; + void __iomem *wrback; + + unsigned int irq; + unsigned int type; /* GDC type */ + unsigned int refclk; /* disp. reference clock */ + struct mb862xx_gc_mode *gc_mode; /* GDC mode init data */ + int pre_init; /* don't init display if 1 */ + + u32 pseudo_palette[16]; +}; + +#if defined(CONFIG_FB_MB862XX_LIME) && defined(CONFIG_FB_MB862XX_PCI_GDC) +#error "Select Lime GDC or CoralP/Carmine support, but not both together" +#endif +#if defined(CONFIG_FB_MB862XX_LIME) +#define gdc_read __raw_readl +#define gdc_write __raw_writel +#else +#define gdc_read readl +#define gdc_write writel +#endif + +#define inreg(type, off) \ + gdc_read((par->type + (off))) + +#define outreg(type, off, val) \ + gdc_write((val), (par->type + (off))) + +#define pack(a, b) (((a) << 16) | (b)) + +#endif diff --git a/drivers/video/omap/Makefile b/drivers/video/omap/Makefile index 99da8b6d2c3..ed13889c116 100644 --- a/drivers/video/omap/Makefile +++ b/drivers/video/omap/Makefile @@ -23,7 +23,6 @@ objs-y$(CONFIG_MACH_OMAP_PALMZ71) += lcd_palmz71.o objs-$(CONFIG_ARCH_OMAP16XX)$(CONFIG_MACH_OMAP_INNOVATOR) += lcd_inn1610.o objs-$(CONFIG_ARCH_OMAP15XX)$(CONFIG_MACH_OMAP_INNOVATOR) += lcd_inn1510.o objs-y$(CONFIG_MACH_OMAP_OSK) += lcd_osk.o -objs-y$(CONFIG_MACH_SX1) += lcd_sx1.o omapfb-objs := $(objs-yy) diff --git a/drivers/video/omap/lcd_sx1.c b/drivers/video/omap/lcd_sx1.c deleted file mode 100644 index e55de201b8f..00000000000 --- a/drivers/video/omap/lcd_sx1.c +++ /dev/null @@ -1,327 +0,0 @@ -/* - * LCD panel support for the Siemens SX1 mobile phone - * - * Current version : Vovan888@gmail.com, great help from FCA00000 - * - * 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. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include <linux/module.h> -#include <linux/platform_device.h> -#include <linux/delay.h> -#include <linux/io.h> - -#include <mach/gpio.h> -#include <mach/omapfb.h> -#include <mach/mcbsp.h> -#include <mach/mux.h> - -/* - * OMAP310 GPIO registers - */ -#define GPIO_DATA_INPUT 0xfffce000 -#define GPIO_DATA_OUTPUT 0xfffce004 -#define GPIO_DIR_CONTROL 0xfffce008 -#define GPIO_INT_CONTROL 0xfffce00c -#define GPIO_INT_MASK 0xfffce010 -#define GPIO_INT_STATUS 0xfffce014 -#define GPIO_PIN_CONTROL 0xfffce018 - - -#define A_LCD_SSC_RD 3 -#define A_LCD_SSC_SD 7 -#define _A_LCD_RESET 9 -#define _A_LCD_SSC_CS 12 -#define _A_LCD_SSC_A0 13 - -#define DSP_REG 0xE1017024 - -const unsigned char INIT_1[12] = { - 0x1C, 0x02, 0x88, 0x00, 0x1E, 0xE0, 0x00, 0xDC, 0x00, 0x02, 0x00 -}; - -const unsigned char INIT_2[127] = { - 0x15, 0x00, 0x29, 0x00, 0x3E, 0x00, 0x51, 0x00, - 0x65, 0x00, 0x7A, 0x00, 0x8D, 0x00, 0xA1, 0x00, - 0xB6, 0x00, 0xC7, 0x00, 0xD8, 0x00, 0xEB, 0x00, - 0xFB, 0x00, 0x0B, 0x01, 0x1B, 0x01, 0x27, 0x01, - 0x34, 0x01, 0x41, 0x01, 0x4C, 0x01, 0x55, 0x01, - 0x5F, 0x01, 0x68, 0x01, 0x70, 0x01, 0x78, 0x01, - 0x7E, 0x01, 0x86, 0x01, 0x8C, 0x01, 0x94, 0x01, - 0x9B, 0x01, 0xA1, 0x01, 0xA4, 0x01, 0xA9, 0x01, - 0xAD, 0x01, 0xB2, 0x01, 0xB7, 0x01, 0xBC, 0x01, - 0xC0, 0x01, 0xC4, 0x01, 0xC8, 0x01, 0xCB, 0x01, - 0xCF, 0x01, 0xD2, 0x01, 0xD5, 0x01, 0xD8, 0x01, - 0xDB, 0x01, 0xE0, 0x01, 0xE3, 0x01, 0xE6, 0x01, - 0xE8, 0x01, 0xEB, 0x01, 0xEE, 0x01, 0xF1, 0x01, - 0xF3, 0x01, 0xF8, 0x01, 0xF9, 0x01, 0xFC, 0x01, - 0x00, 0x02, 0x03, 0x02, 0x07, 0x02, 0x09, 0x02, - 0x0E, 0x02, 0x13, 0x02, 0x1C, 0x02, 0x00 -}; - -const unsigned char INIT_3[15] = { - 0x14, 0x26, 0x33, 0x3D, 0x45, 0x4D, 0x53, 0x59, - 0x5E, 0x63, 0x67, 0x6D, 0x71, 0x78, 0xFF -}; - -static void epson_sendbyte(int flag, unsigned char byte) -{ - int i, shifter = 0x80; - - if (!flag) - gpio_set_value(_A_LCD_SSC_A0, 0); - mdelay(2); - gpio_set_value(A_LCD_SSC_RD, 1); - - gpio_set_value(A_LCD_SSC_SD, flag); - - OMAP_MCBSP_WRITE(OMAP1510_MCBSP3_BASE, PCR0, 0x2200); - OMAP_MCBSP_WRITE(OMAP1510_MCBSP3_BASE, PCR0, 0x2202); - for (i = 0; i < 8; i++) { - OMAP_MCBSP_WRITE(OMAP1510_MCBSP3_BASE, PCR0, 0x2200); - gpio_set_value(A_LCD_SSC_SD, shifter & byte); - OMAP_MCBSP_WRITE(OMAP1510_MCBSP3_BASE, PCR0, 0x2202); - shifter >>= 1; - } - gpio_set_value(_A_LCD_SSC_A0, 1); -} - -static void init_system(void) -{ - omap_mcbsp_request(OMAP_MCBSP3); - omap_mcbsp_stop(OMAP_MCBSP3); -} - -static void setup_GPIO(void) -{ - /* new wave */ - gpio_request(A_LCD_SSC_RD, "lcd_ssc_rd"); - gpio_request(A_LCD_SSC_SD, "lcd_ssc_sd"); - gpio_request(_A_LCD_RESET, "lcd_reset"); - gpio_request(_A_LCD_SSC_CS, "lcd_ssc_cs"); - gpio_request(_A_LCD_SSC_A0, "lcd_ssc_a0"); - - /* set GPIOs to output, with initial data */ - gpio_direction_output(A_LCD_SSC_RD, 1); - gpio_direction_output(A_LCD_SSC_SD, 0); - gpio_direction_output(_A_LCD_RESET, 0); - gpio_direction_output(_A_LCD_SSC_CS, 1); - gpio_direction_output(_A_LCD_SSC_A0, 1); -} - -static void display_init(void) -{ - int i; - - omap_cfg_reg(MCBSP3_CLKX); - - mdelay(2); - setup_GPIO(); - mdelay(2); - - /* reset LCD */ - gpio_set_value(A_LCD_SSC_SD, 1); - epson_sendbyte(0, 0x25); - - gpio_set_value(_A_LCD_RESET, 0); - mdelay(10); - gpio_set_value(_A_LCD_RESET, 1); - - gpio_set_value(_A_LCD_SSC_CS, 1); - mdelay(2); - gpio_set_value(_A_LCD_SSC_CS, 0); - - /* init LCD, phase 1 */ - epson_sendbyte(0, 0xCA); - for (i = 0; i < 10; i++) - epson_sendbyte(1, INIT_1[i]); - gpio_set_value(_A_LCD_SSC_CS, 1); - gpio_set_value(_A_LCD_SSC_CS, 0); - - /* init LCD phase 2 */ - epson_sendbyte(0, 0xCB); - for (i = 0; i < 125; i++) - epson_sendbyte(1, INIT_2[i]); - gpio_set_value(_A_LCD_SSC_CS, 1); - gpio_set_value(_A_LCD_SSC_CS, 0); - - /* init LCD phase 2a */ - epson_sendbyte(0, 0xCC); - for (i = 0; i < 14; i++) - epson_sendbyte(1, INIT_3[i]); - gpio_set_value(_A_LCD_SSC_CS, 1); - gpio_set_value(_A_LCD_SSC_CS, 0); - - /* init LCD phase 3 */ - epson_sendbyte(0, 0xBC); - epson_sendbyte(1, 0x08); - gpio_set_value(_A_LCD_SSC_CS, 1); - gpio_set_value(_A_LCD_SSC_CS, 0); - - /* init LCD phase 4 */ - epson_sendbyte(0, 0x07); - epson_sendbyte(1, 0x05); - gpio_set_value(_A_LCD_SSC_CS, 1); - gpio_set_value(_A_LCD_SSC_CS, 0); - - /* init LCD phase 5 */ - epson_sendbyte(0, 0x94); - gpio_set_value(_A_LCD_SSC_CS, 1); - gpio_set_value(_A_LCD_SSC_CS, 0); - - /* init LCD phase 6 */ - epson_sendbyte(0, 0xC6); - epson_sendbyte(1, 0x80); - gpio_set_value(_A_LCD_SSC_CS, 1); - mdelay(100); /* used to be 1000 */ - gpio_set_value(_A_LCD_SSC_CS, 0); - - /* init LCD phase 7 */ - epson_sendbyte(0, 0x16); - epson_sendbyte(1, 0x02); - epson_sendbyte(1, 0x00); - epson_sendbyte(1, 0xB1); - epson_sendbyte(1, 0x00); - gpio_set_value(_A_LCD_SSC_CS, 1); - gpio_set_value(_A_LCD_SSC_CS, 0); - - /* init LCD phase 8 */ - epson_sendbyte(0, 0x76); - epson_sendbyte(1, 0x00); - epson_sendbyte(1, 0x00); - epson_sendbyte(1, 0xDB); - epson_sendbyte(1, 0x00); - gpio_set_value(_A_LCD_SSC_CS, 1); - gpio_set_value(_A_LCD_SSC_CS, 0); - - /* init LCD phase 9 */ - epson_sendbyte(0, 0xAF); - gpio_set_value(_A_LCD_SSC_CS, 1); -} - -static int sx1_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev) -{ - return 0; -} - -static void sx1_panel_cleanup(struct lcd_panel *panel) -{ -} - -static void sx1_panel_disable(struct lcd_panel *panel) -{ - printk(KERN_INFO "SX1: LCD panel disable\n"); - sx1_setmmipower(0); - gpio_set_value(_A_LCD_SSC_CS, 1); - - epson_sendbyte(0, 0x25); - gpio_set_value(_A_LCD_SSC_CS, 0); - - epson_sendbyte(0, 0xAE); - gpio_set_value(_A_LCD_SSC_CS, 1); - mdelay(100); - gpio_set_value(_A_LCD_SSC_CS, 0); - - epson_sendbyte(0, 0x95); - gpio_set_value(_A_LCD_SSC_CS, 1); -} - -static int sx1_panel_enable(struct lcd_panel *panel) -{ - printk(KERN_INFO "lcd_sx1: LCD panel enable\n"); - init_system(); - display_init(); - - sx1_setmmipower(1); - sx1_setbacklight(0x18); - sx1_setkeylight (0x06); - return 0; -} - - -static unsigned long sx1_panel_get_caps(struct lcd_panel *panel) -{ - return 0; -} - -struct lcd_panel sx1_panel = { - .name = "sx1", - .config = OMAP_LCDC_PANEL_TFT | OMAP_LCDC_INV_VSYNC | - OMAP_LCDC_INV_HSYNC | OMAP_LCDC_INV_PIX_CLOCK | - OMAP_LCDC_INV_OUTPUT_EN, - - .x_res = 176, - .y_res = 220, - .data_lines = 16, - .bpp = 16, - .hsw = 5, - .hfp = 5, - .hbp = 5, - .vsw = 2, - .vfp = 1, - .vbp = 1, - .pixel_clock = 1500, - - .init = sx1_panel_init, - .cleanup = sx1_panel_cleanup, - .enable = sx1_panel_enable, - .disable = sx1_panel_disable, - .get_caps = sx1_panel_get_caps, -}; - -static int sx1_panel_probe(struct platform_device *pdev) -{ - omapfb_register_panel(&sx1_panel); - return 0; -} - -static int sx1_panel_remove(struct platform_device *pdev) -{ - return 0; -} - -static int sx1_panel_suspend(struct platform_device *pdev, pm_message_t mesg) -{ - return 0; -} - -static int sx1_panel_resume(struct platform_device *pdev) -{ - return 0; -} - -struct platform_driver sx1_panel_driver = { - .probe = sx1_panel_probe, - .remove = sx1_panel_remove, - .suspend = sx1_panel_suspend, - .resume = sx1_panel_resume, - .driver = { - .name = "lcd_sx1", - .owner = THIS_MODULE, - }, -}; - -static int sx1_panel_drv_init(void) -{ - return platform_driver_register(&sx1_panel_driver); -} - -static void sx1_panel_drv_cleanup(void) -{ - platform_driver_unregister(&sx1_panel_driver); -} - -module_init(sx1_panel_drv_init); -module_exit(sx1_panel_drv_cleanup); diff --git a/drivers/video/omap/omapfb_main.c b/drivers/video/omap/omapfb_main.c index 5a5e407dc45..1a49519dafa 100644 --- a/drivers/video/omap/omapfb_main.c +++ b/drivers/video/omap/omapfb_main.c @@ -392,7 +392,7 @@ static void set_fb_fix(struct fb_info *fbi) int bpp; rg = &plane->fbdev->mem_desc.region[plane->idx]; - fbi->screen_base = (char __iomem *)rg->vaddr; + fbi->screen_base = rg->vaddr; fix->smem_start = rg->paddr; fix->smem_len = rg->size; diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c index 97204497d9f..cc59c52e110 100644 --- a/drivers/video/pxafb.c +++ b/drivers/video/pxafb.c @@ -804,6 +804,9 @@ static int pxafb_smart_thread(void *arg) static int pxafb_smart_init(struct pxafb_info *fbi) { + if (!(fbi->lccr0 | LCCR0_LCDT)) + return 0; + fbi->smart_thread = kthread_run(pxafb_smart_thread, fbi, "lcd_refresh"); if (IS_ERR(fbi->smart_thread)) { @@ -1372,7 +1375,7 @@ static void pxafb_decode_mach_info(struct pxafb_info *fbi, fbi->cmap_inverse = inf->cmap_inverse; fbi->cmap_static = inf->cmap_static; - switch (lcd_conn & 0xf) { + switch (lcd_conn & LCD_TYPE_MASK) { case LCD_TYPE_MONO_STN: fbi->lccr0 = LCCR0_CMS; break; diff --git a/drivers/video/tmiofb.c b/drivers/video/tmiofb.c index 2a380011e9b..7baf2dd12d5 100644 --- a/drivers/video/tmiofb.c +++ b/drivers/video/tmiofb.c @@ -222,6 +222,9 @@ static irqreturn_t tmiofb_irq(int irq, void *__info) unsigned int bbisc = tmio_ioread16(par->lcr + LCR_BBISC); + tmio_iowrite16(bbisc, par->lcr + LCR_BBISC); + +#ifdef CONFIG_FB_TMIO_ACCELL /* * We were in polling mode and now we got correct irq. * Switch back to IRQ-based sync of command FIFO @@ -231,9 +234,6 @@ static irqreturn_t tmiofb_irq(int irq, void *__info) par->use_polling = false; } - tmio_iowrite16(bbisc, par->lcr + LCR_BBISC); - -#ifdef CONFIG_FB_TMIO_ACCELL if (bbisc & 1) wake_up(&par->wait_acc); #endif @@ -938,7 +938,9 @@ static void tmiofb_dump_regs(struct platform_device *dev) static int tmiofb_suspend(struct platform_device *dev, pm_message_t state) { struct fb_info *info = platform_get_drvdata(dev); +#ifdef CONFIG_FB_TMIO_ACCELL struct tmiofb_par *par = info->par; +#endif struct mfd_cell *cell = dev->dev.platform_data; int retval = 0; @@ -950,12 +952,14 @@ static int tmiofb_suspend(struct platform_device *dev, pm_message_t state) info->fbops->fb_sync(info); +#ifdef CONFIG_FB_TMIO_ACCELL /* * The fb should be usable even if interrupts are disabled (and they are * during suspend/resume). Switch temporary to forced polling. */ printk(KERN_INFO "tmiofb: switching to polling\n"); par->use_polling = true; +#endif tmiofb_hw_stop(dev); if (cell->suspend) diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c index 0132eae06f5..73ac754ad80 100644 --- a/drivers/video/via/viafbdev.c +++ b/drivers/video/via/viafbdev.c @@ -2036,30 +2036,30 @@ static int viafb_vt1636_proc_write(struct file *file, return count; } -static void viafb_init_proc(struct proc_dir_entry *viafb_entry) +static void viafb_init_proc(struct proc_dir_entry **viafb_entry) { struct proc_dir_entry *entry; - viafb_entry = proc_mkdir("viafb", NULL); + *viafb_entry = proc_mkdir("viafb", NULL); if (viafb_entry) { - entry = create_proc_entry("dvp0", 0, viafb_entry); + entry = create_proc_entry("dvp0", 0, *viafb_entry); if (entry) { entry->owner = THIS_MODULE; entry->read_proc = viafb_dvp0_proc_read; entry->write_proc = viafb_dvp0_proc_write; } - entry = create_proc_entry("dvp1", 0, viafb_entry); + entry = create_proc_entry("dvp1", 0, *viafb_entry); if (entry) { entry->owner = THIS_MODULE; entry->read_proc = viafb_dvp1_proc_read; entry->write_proc = viafb_dvp1_proc_write; } - entry = create_proc_entry("dfph", 0, viafb_entry); + entry = create_proc_entry("dfph", 0, *viafb_entry); if (entry) { entry->owner = THIS_MODULE; entry->read_proc = viafb_dfph_proc_read; entry->write_proc = viafb_dfph_proc_write; } - entry = create_proc_entry("dfpl", 0, viafb_entry); + entry = create_proc_entry("dfpl", 0, *viafb_entry); if (entry) { entry->owner = THIS_MODULE; entry->read_proc = viafb_dfpl_proc_read; @@ -2068,7 +2068,7 @@ static void viafb_init_proc(struct proc_dir_entry *viafb_entry) if (VT1636_LVDS == viaparinfo->chip_info->lvds_chip_info. lvds_chip_name || VT1636_LVDS == viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name) { - entry = create_proc_entry("vt1636", 0, viafb_entry); + entry = create_proc_entry("vt1636", 0, *viafb_entry); if (entry) { entry->owner = THIS_MODULE; entry->read_proc = viafb_vt1636_proc_read; @@ -2087,6 +2087,7 @@ static void viafb_remove_proc(struct proc_dir_entry *viafb_entry) remove_proc_entry("dfpl", viafb_entry); remove_proc_entry("vt1636", viafb_entry); remove_proc_entry("vt1625", viafb_entry); + remove_proc_entry("viafb", NULL); } static int __devinit via_pci_probe(void) @@ -2348,7 +2349,7 @@ static int __devinit via_pci_probe(void) viafbinfo->node, viafbinfo->fix.id, default_var.xres, default_var.yres, default_var.bits_per_pixel); - viafb_init_proc(viaparinfo->proc_entry); + viafb_init_proc(&viaparinfo->proc_entry); viafb_init_dac(IGA2); return 0; } diff --git a/drivers/video/xen-fbfront.c b/drivers/video/xen-fbfront.c index a463b3dd837..2493f05e9f6 100644 --- a/drivers/video/xen-fbfront.c +++ b/drivers/video/xen-fbfront.c @@ -668,7 +668,7 @@ static struct xenbus_device_id xenfb_ids[] = { { "" } }; -static struct xenbus_driver xenfb = { +static struct xenbus_driver xenfb_driver = { .name = "vfb", .owner = THIS_MODULE, .ids = xenfb_ids, @@ -687,12 +687,12 @@ static int __init xenfb_init(void) if (xen_initial_domain()) return -ENODEV; - return xenbus_register_frontend(&xenfb); + return xenbus_register_frontend(&xenfb_driver); } static void __exit xenfb_cleanup(void) { - xenbus_unregister_driver(&xenfb); + xenbus_unregister_driver(&xenfb_driver); } module_init(xenfb_init); diff --git a/drivers/video/xilinxfb.c b/drivers/video/xilinxfb.c index 5da3d2423cc..40a3a2afbfe 100644 --- a/drivers/video/xilinxfb.c +++ b/drivers/video/xilinxfb.c @@ -298,8 +298,9 @@ static int xilinxfb_assign(struct device *dev, unsigned long physaddr, /* Put a banner in the log (for DEBUG) */ dev_dbg(dev, "regs: phys=%lx, virt=%p\n", physaddr, drvdata->regs); - dev_dbg(dev, "fb: phys=%p, virt=%p, size=%x\n", - (void*)drvdata->fb_phys, drvdata->fb_virt, fbsize); + dev_dbg(dev, "fb: phys=%llx, virt=%p, size=%x\n", + (unsigned long long) drvdata->fb_phys, drvdata->fb_virt, + fbsize); return 0; /* success */ |