diff options
Diffstat (limited to 'drivers/video/offb.c')
| -rw-r--r-- | drivers/video/offb.c | 574 |
1 files changed, 0 insertions, 574 deletions
diff --git a/drivers/video/offb.c b/drivers/video/offb.c deleted file mode 100644 index ad1434e3f22..00000000000 --- a/drivers/video/offb.c +++ /dev/null @@ -1,574 +0,0 @@ -/* - * linux/drivers/video/offb.c -- Open Firmware based frame buffer device - * - * Copyright (C) 1997 Geert Uytterhoeven - * - * This driver is partly based on the PowerMac console driver: - * - * Copyright (C) 1996 Paul Mackerras - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of this archive for - * more details. - */ - -#include <linux/config.h> -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/string.h> -#include <linux/mm.h> -#include <linux/tty.h> -#include <linux/slab.h> -#include <linux/vmalloc.h> -#include <linux/delay.h> -#include <linux/interrupt.h> -#include <linux/fb.h> -#include <linux/init.h> -#include <linux/ioport.h> -#include <linux/pci.h> -#include <asm/io.h> -#include <asm/prom.h> - -#ifdef CONFIG_PPC64 -#include <asm/pci-bridge.h> -#endif - -#ifdef CONFIG_PPC32 -#include <asm/bootx.h> -#endif - -#include "macmodes.h" - -/* Supported palette hacks */ -enum { - cmap_unknown, - cmap_m64, /* ATI Mach64 */ - cmap_r128, /* ATI Rage128 */ - cmap_M3A, /* ATI Rage Mobility M3 Head A */ - cmap_M3B, /* ATI Rage Mobility M3 Head B */ - cmap_radeon, /* ATI Radeon */ - cmap_gxt2000, /* IBM GXT2000 */ -}; - -struct offb_par { - volatile void __iomem *cmap_adr; - volatile void __iomem *cmap_data; - int cmap_type; - int blanked; -}; - -struct offb_par default_par; - - /* - * Interface used by the world - */ - -int offb_init(void); - -static int offb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, - u_int transp, struct fb_info *info); -static int offb_blank(int blank, struct fb_info *info); - -#ifdef CONFIG_PPC32 -extern boot_infos_t *boot_infos; -#endif - -static void offb_init_nodriver(struct device_node *); -static void offb_init_fb(const char *name, const char *full_name, - int width, int height, int depth, int pitch, - unsigned long address, struct device_node *dp); - -static struct fb_ops offb_ops = { - .owner = THIS_MODULE, - .fb_setcolreg = offb_setcolreg, - .fb_blank = offb_blank, - .fb_fillrect = cfb_fillrect, - .fb_copyarea = cfb_copyarea, - .fb_imageblit = cfb_imageblit, -}; - - /* - * Set a single color register. The values supplied are already - * rounded down to the hardware's capabilities (according to the - * entries in the var structure). Return != 0 for invalid regno. - */ - -static int offb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, - u_int transp, struct fb_info *info) -{ - struct offb_par *par = (struct offb_par *) info->par; - - if (!par->cmap_adr || regno > 255) - return 1; - - red >>= 8; - green >>= 8; - blue >>= 8; - - switch (par->cmap_type) { - case cmap_m64: - writeb(regno, par->cmap_adr); - writeb(red, par->cmap_data); - writeb(green, par->cmap_data); - writeb(blue, par->cmap_data); - break; - case cmap_M3A: - /* Clear PALETTE_ACCESS_CNTL in DAC_CNTL */ - out_le32(par->cmap_adr + 0x58, - in_le32(par->cmap_adr + 0x58) & ~0x20); - case cmap_r128: - /* Set palette index & data */ - out_8(par->cmap_adr + 0xb0, regno); - out_le32(par->cmap_adr + 0xb4, - (red << 16 | green << 8 | blue)); - break; - case cmap_M3B: - /* Set PALETTE_ACCESS_CNTL in DAC_CNTL */ - out_le32(par->cmap_adr + 0x58, - in_le32(par->cmap_adr + 0x58) | 0x20); - /* Set palette index & data */ - out_8(par->cmap_adr + 0xb0, regno); - out_le32(par->cmap_adr + 0xb4, (red << 16 | green << 8 | blue)); - break; - case cmap_radeon: - /* Set palette index & data (could be smarter) */ - out_8(par->cmap_adr + 0xb0, regno); - out_le32(par->cmap_adr + 0xb4, (red << 16 | green << 8 | blue)); - break; - case cmap_gxt2000: - out_le32((unsigned __iomem *) par->cmap_adr + regno, - (red << 16 | green << 8 | blue)); - break; - } - - if (regno < 16) - switch (info->var.bits_per_pixel) { - case 16: - ((u16 *) (info->pseudo_palette))[regno] = - (regno << 10) | (regno << 5) | regno; - break; - case 32: - { - int i = (regno << 8) | regno; - ((u32 *) (info->pseudo_palette))[regno] = - (i << 16) | i; - break; - } - } - return 0; -} - - /* - * Blank the display. - */ - -static int offb_blank(int blank, struct fb_info *info) -{ - struct offb_par *par = (struct offb_par *) info->par; - int i, j; - - if (!par->cmap_adr) - return 0; - - if (!par->blanked) - if (!blank) - return 0; - - par->blanked = blank; - - if (blank) - for (i = 0; i < 256; i++) { - switch (par->cmap_type) { - case cmap_m64: - writeb(i, par->cmap_adr); - for (j = 0; j < 3; j++) - writeb(0, par->cmap_data); - break; - case cmap_M3A: - /* Clear PALETTE_ACCESS_CNTL in DAC_CNTL */ - out_le32(par->cmap_adr + 0x58, - in_le32(par->cmap_adr + 0x58) & ~0x20); - case cmap_r128: - /* Set palette index & data */ - out_8(par->cmap_adr + 0xb0, i); - out_le32(par->cmap_adr + 0xb4, 0); - break; - case cmap_M3B: - /* Set PALETTE_ACCESS_CNTL in DAC_CNTL */ - out_le32(par->cmap_adr + 0x58, - in_le32(par->cmap_adr + 0x58) | 0x20); - /* Set palette index & data */ - out_8(par->cmap_adr + 0xb0, i); - out_le32(par->cmap_adr + 0xb4, 0); - break; - case cmap_radeon: - out_8(par->cmap_adr + 0xb0, i); - out_le32(par->cmap_adr + 0xb4, 0); - break; - case cmap_gxt2000: - out_le32((unsigned __iomem *) par->cmap_adr + i, - 0); - break; - } - } else - fb_set_cmap(&info->cmap, info); - return 0; -} - - /* - * Initialisation - */ - -int __init offb_init(void) -{ - struct device_node *dp = NULL, *boot_disp = NULL; - -#if defined(CONFIG_BOOTX_TEXT) && defined(CONFIG_PPC32) - struct device_node *macos_display = NULL; -#endif - if (fb_get_options("offb", NULL)) - return -ENODEV; - -#if defined(CONFIG_BOOTX_TEXT) && defined(CONFIG_PPC32) - /* If we're booted from BootX... */ - if (boot_infos != 0) { - unsigned long addr = - (unsigned long) boot_infos->dispDeviceBase; - u32 *addrp; - u64 daddr, dsize; - unsigned int flags; - - /* find the device node corresponding to the macos display */ - while ((dp = of_find_node_by_type(dp, "display"))) { - int i; - - /* - * Look for an AAPL,address property first. - */ - unsigned int na; - unsigned int *ap = - (unsigned int *)get_property(dp, "AAPL,address", - &na); - if (ap != 0) { - for (na /= sizeof(unsigned int); na > 0; - --na, ++ap) - if (*ap <= addr && - addr < *ap + 0x1000000) { - macos_display = dp; - goto foundit; - } - } - - /* - * See if the display address is in one of the address - * ranges for this display. - */ - i = 0; - for (;;) { - addrp = of_get_address(dp, i++, &dsize, &flags); - if (addrp == NULL) - break; - if (!(flags & IORESOURCE_MEM)) - continue; - daddr = of_translate_address(dp, addrp); - if (daddr == OF_BAD_ADDR) - continue; - if (daddr <= addr && addr < (daddr + dsize)) { - macos_display = dp; - goto foundit; - } - } - foundit: - if (macos_display) { - printk(KERN_INFO "MacOS display is %s\n", - dp->full_name); - break; - } - } - - /* initialize it */ - offb_init_fb(macos_display ? macos_display-> - name : "MacOS display", - macos_display ? macos_display-> - full_name : "MacOS display", - boot_infos->dispDeviceRect[2], - boot_infos->dispDeviceRect[3], - boot_infos->dispDeviceDepth, - boot_infos->dispDeviceRowBytes, addr, NULL); - } -#endif /* defined(CONFIG_BOOTX_TEXT) && defined(CONFIG_PPC32) */ - - for (dp = NULL; (dp = of_find_node_by_type(dp, "display"));) { - if (get_property(dp, "linux,opened", NULL) && - get_property(dp, "linux,boot-display", NULL)) { - boot_disp = dp; - offb_init_nodriver(dp); - } - } - for (dp = NULL; (dp = of_find_node_by_type(dp, "display"));) { - if (get_property(dp, "linux,opened", NULL) && - dp != boot_disp) - offb_init_nodriver(dp); - } - - return 0; -} - - -static void __init offb_init_nodriver(struct device_node *dp) -{ - int *pp, i; - unsigned int len; - int width = 640, height = 480, depth = 8, pitch; - unsigned int flags, rsize, *up; - u64 address = OF_BAD_ADDR; - u32 *addrp; - u64 asize; - - if ((pp = (int *) get_property(dp, "depth", &len)) != NULL - && len == sizeof(int)) - depth = *pp; - if ((pp = (int *) get_property(dp, "width", &len)) != NULL - && len == sizeof(int)) - width = *pp; - if ((pp = (int *) get_property(dp, "height", &len)) != NULL - && len == sizeof(int)) - height = *pp; - if ((pp = (int *) get_property(dp, "linebytes", &len)) != NULL - && len == sizeof(int)) { - pitch = *pp; - if (pitch == 1) - pitch = 0x1000; - } else - pitch = width; - - rsize = (unsigned long)pitch * (unsigned long)height * - (unsigned long)(depth / 8); - - /* Try to match device to a PCI device in order to get a properly - * translated address rather then trying to decode the open firmware - * stuff in various incorrect ways - */ -#ifdef CONFIG_PCI - /* First try to locate the PCI device if any */ - { - struct pci_dev *pdev = NULL; - - for_each_pci_dev(pdev) { - if (dp == pci_device_to_OF_node(pdev)) - break; - } - if (pdev) { - for (i = 0; i < 6 && address == OF_BAD_ADDR; i++) { - if ((pci_resource_flags(pdev, i) & - IORESOURCE_MEM) && - (pci_resource_len(pdev, i) >= rsize)) - address = pci_resource_start(pdev, i); - } - pci_dev_put(pdev); - } - } -#endif /* CONFIG_PCI */ - - /* This one is dodgy, we may drop it ... */ - if (address == OF_BAD_ADDR && - (up = (unsigned *) get_property(dp, "address", &len)) != NULL && - len == sizeof(unsigned int)) - address = (u64) * up; - - if (address == OF_BAD_ADDR) { - for (i = 0; (addrp = of_get_address(dp, i, &asize, &flags)) - != NULL; i++) { - if (!(flags & IORESOURCE_MEM)) - continue; - if (asize >= pitch * height * depth / 8) - break; - } - if (addrp == NULL) { - printk(KERN_ERR - "no framebuffer address found for %s\n", - dp->full_name); - return; - } - address = of_translate_address(dp, addrp); - if (address == OF_BAD_ADDR) { - printk(KERN_ERR - "can't translate framebuffer address for %s\n", - dp->full_name); - return; - } - - /* kludge for valkyrie */ - if (strcmp(dp->name, "valkyrie") == 0) - address += 0x1000; - } - offb_init_fb(dp->name, dp->full_name, width, height, depth, - pitch, address, dp); - -} - -static void __init offb_init_fb(const char *name, const char *full_name, - int width, int height, int depth, - int pitch, unsigned long address, - struct device_node *dp) -{ - unsigned long res_size = pitch * height * depth / 8; - struct offb_par *par = &default_par; - unsigned long res_start = address; - struct fb_fix_screeninfo *fix; - struct fb_var_screeninfo *var; - struct fb_info *info; - int size; - - if (!request_mem_region(res_start, res_size, "offb")) - return; - - printk(KERN_INFO - "Using unsupported %dx%d %s at %lx, depth=%d, pitch=%d\n", - width, height, name, address, depth, pitch); - if (depth != 8 && depth != 16 && depth != 32) { - printk(KERN_ERR "%s: can't use depth = %d\n", full_name, - depth); - release_mem_region(res_start, res_size); - return; - } - - size = sizeof(struct fb_info) + sizeof(u32) * 17; - - info = kmalloc(size, GFP_ATOMIC); - - if (info == 0) { - release_mem_region(res_start, res_size); - return; - } - memset(info, 0, size); - - fix = &info->fix; - var = &info->var; - - strcpy(fix->id, "OFfb "); - strncat(fix->id, name, sizeof(fix->id) - sizeof("OFfb ")); - fix->id[sizeof(fix->id) - 1] = '\0'; - - var->xres = var->xres_virtual = width; - var->yres = var->yres_virtual = height; - fix->line_length = pitch; - - fix->smem_start = address; - fix->smem_len = pitch * height; - fix->type = FB_TYPE_PACKED_PIXELS; - fix->type_aux = 0; - - par->cmap_type = cmap_unknown; - if (depth == 8) { - - /* Palette hacks disabled for now */ -#if 0 - if (dp && !strncmp(name, "ATY,Rage128", 11)) { - unsigned long regbase = dp->addrs[2].address; - par->cmap_adr = ioremap(regbase, 0x1FFF); - par->cmap_type = cmap_r128; - } else if (dp && (!strncmp(name, "ATY,RageM3pA", 12) - || !strncmp(name, "ATY,RageM3p12A", 14))) { - unsigned long regbase = - dp->parent->addrs[2].address; - par->cmap_adr = ioremap(regbase, 0x1FFF); - par->cmap_type = cmap_M3A; - } else if (dp && !strncmp(name, "ATY,RageM3pB", 12)) { - unsigned long regbase = - dp->parent->addrs[2].address; - par->cmap_adr = ioremap(regbase, 0x1FFF); - par->cmap_type = cmap_M3B; - } else if (dp && !strncmp(name, "ATY,Rage6", 9)) { - unsigned long regbase = dp->addrs[1].address; - par->cmap_adr = ioremap(regbase, 0x1FFF); - par->cmap_type = cmap_radeon; - } else if (!strncmp(name, "ATY,", 4)) { - unsigned long base = address & 0xff000000UL; - par->cmap_adr = - ioremap(base + 0x7ff000, 0x1000) + 0xcc0; - par->cmap_data = par->cmap_adr + 1; - par->cmap_type = cmap_m64; - } else if (device_is_compatible(dp, "pci1014,b7")) { - unsigned long regbase = dp->addrs[0].address; - par->cmap_adr = ioremap(regbase + 0x6000, 0x1000); - par->cmap_type = cmap_gxt2000; - } -#endif - fix->visual = par->cmap_adr ? FB_VISUAL_PSEUDOCOLOR - : FB_VISUAL_STATIC_PSEUDOCOLOR; - } else - fix->visual = /* par->cmap_adr ? FB_VISUAL_DIRECTCOLOR - : */ FB_VISUAL_TRUECOLOR; - - var->xoffset = var->yoffset = 0; - var->bits_per_pixel = depth; - switch (depth) { - case 8: - var->bits_per_pixel = 8; - var->red.offset = 0; - var->red.length = 8; - var->green.offset = 0; - var->green.length = 8; - var->blue.offset = 0; - var->blue.length = 8; - var->transp.offset = 0; - var->transp.length = 0; - break; - case 16: /* RGB 555 */ - var->bits_per_pixel = 16; - var->red.offset = 10; - var->red.length = 5; - var->green.offset = 5; - var->green.length = 5; - var->blue.offset = 0; - var->blue.length = 5; - var->transp.offset = 0; - var->transp.length = 0; - break; - case 32: /* RGB 888 */ - var->bits_per_pixel = 32; - var->red.offset = 16; - var->red.length = 8; - var->green.offset = 8; - var->green.length = 8; - var->blue.offset = 0; - var->blue.length = 8; - var->transp.offset = 24; - var->transp.length = 8; - break; - } - var->red.msb_right = var->green.msb_right = var->blue.msb_right = - var->transp.msb_right = 0; - var->grayscale = 0; - var->nonstd = 0; - var->activate = 0; - var->height = var->width = -1; - var->pixclock = 10000; - var->left_margin = var->right_margin = 16; - var->upper_margin = var->lower_margin = 16; - var->hsync_len = var->vsync_len = 8; - var->sync = 0; - var->vmode = FB_VMODE_NONINTERLACED; - - info->fbops = &offb_ops; - info->screen_base = ioremap(address, fix->smem_len); - info->par = par; - info->pseudo_palette = (void *) (info + 1); - info->flags = FBINFO_DEFAULT; - - fb_alloc_cmap(&info->cmap, 256, 0); - - if (register_framebuffer(info) < 0) { - kfree(info); - release_mem_region(res_start, res_size); - return; - } - - printk(KERN_INFO "fb%d: Open Firmware frame buffer device on %s\n", - info->node, full_name); -} - -module_init(offb_init); -MODULE_LICENSE("GPL"); |
