platinumfb.c
来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 694 行 · 第 1/2 页
C
694 行
} if (default_vmode == VMODE_CHOOSE) { default_vmode = mac_map_monitor_sense(sense); } if (default_vmode <= 0 || default_vmode > VMODE_MAX) default_vmode = VMODE_640_480_60; if (default_cmode == CMODE_NVRAM) default_cmode = nvram_read_byte(NV_CMODE); if (default_cmode < CMODE_8 || default_cmode > CMODE_32) default_cmode = CMODE_8; /* * Reduce the pixel size if we don't have enough VRAM. */ while(default_cmode > CMODE_8 && platinum_vram_reqd(default_vmode, default_cmode) > pinfo->total_vram) default_cmode--; printk("platinumfb: Using video mode %d and color mode %d.\n", default_vmode, default_cmode); /* Setup default var */ if (mac_vmode_to_var(default_vmode, default_cmode, &var) < 0) { /* This shouldn't happen! */ printk("mac_vmode_to_var(%d, %d,) failed\n", default_vmode, default_cmode);try_again: default_vmode = VMODE_640_480_60; default_cmode = CMODE_8; if (mac_vmode_to_var(default_vmode, default_cmode, &var) < 0) { printk(KERN_ERR "platinumfb: mac_vmode_to_var() failed\n"); return -ENXIO; } } /* Initialize info structure */ platinum_init_info(info, pinfo); /* Apply default var */ info->var = var; var.activate = FB_ACTIVATE_NOW; rc = fb_set_var(info, &var); if (rc && (default_vmode != VMODE_640_480_60 || default_cmode != CMODE_8)) goto try_again; /* Register with fbdev layer */ rc = register_framebuffer(info); if (rc < 0) return rc; printk(KERN_INFO "fb%d: Apple Platinum frame buffer device\n", info->node); return 0;}/* * Get the monitor sense value. * Note that this can be called before calibrate_delay, * so we can't use udelay. */static int read_platinum_sense(struct fb_info_platinum *info){ volatile struct platinum_regs *platinum_regs = info->platinum_regs; int sense; out_be32(&platinum_regs->reg[23].r, 7); /* turn off drivers */ __delay(2000); sense = (~in_be32(&platinum_regs->reg[23].r) & 7) << 8; /* drive each sense line low in turn and collect the other 2 */ out_be32(&platinum_regs->reg[23].r, 3); /* drive A low */ __delay(2000); sense |= (~in_be32(&platinum_regs->reg[23].r) & 3) << 4; out_be32(&platinum_regs->reg[23].r, 5); /* drive B low */ __delay(2000); sense |= (~in_be32(&platinum_regs->reg[23].r) & 4) << 1; sense |= (~in_be32(&platinum_regs->reg[23].r) & 1) << 2; out_be32(&platinum_regs->reg[23].r, 6); /* drive C low */ __delay(2000); sense |= (~in_be32(&platinum_regs->reg[23].r) & 6) >> 1; out_be32(&platinum_regs->reg[23].r, 7); /* turn off drivers */ return sense;}/* * This routine takes a user-supplied var, and picks the best vmode/cmode from it. * It also updates the var structure to the actual mode data obtained */static int platinum_var_to_par(struct fb_var_screeninfo *var, struct fb_info_platinum *pinfo, int check_only){ int vmode, cmode; if (mac_var_to_vmode(var, &vmode, &cmode) != 0) { printk(KERN_ERR "platinum_var_to_par: mac_var_to_vmode unsuccessful.\n"); printk(KERN_ERR "platinum_var_to_par: var->xres = %d\n", var->xres); printk(KERN_ERR "platinum_var_to_par: var->yres = %d\n", var->yres); printk(KERN_ERR "platinum_var_to_par: var->xres_virtual = %d\n", var->xres_virtual); printk(KERN_ERR "platinum_var_to_par: var->yres_virtual = %d\n", var->yres_virtual); printk(KERN_ERR "platinum_var_to_par: var->bits_per_pixel = %d\n", var->bits_per_pixel); printk(KERN_ERR "platinum_var_to_par: var->pixclock = %d\n", var->pixclock); printk(KERN_ERR "platinum_var_to_par: var->vmode = %d\n", var->vmode); return -EINVAL; } if (!platinum_reg_init[vmode-1]) { printk(KERN_ERR "platinum_var_to_par, vmode %d not valid.\n", vmode); return -EINVAL; } if (platinum_vram_reqd(vmode, cmode) > pinfo->total_vram) { printk(KERN_ERR "platinum_var_to_par, not enough ram for vmode %d, cmode %d.\n", vmode, cmode); return -EINVAL; } if (mac_vmode_to_var(vmode, cmode, var)) return -EINVAL; if (check_only) return 0; pinfo->vmode = vmode; pinfo->cmode = cmode; pinfo->xres = vmode_attrs[vmode-1].hres; pinfo->yres = vmode_attrs[vmode-1].vres; pinfo->xoffset = 0; pinfo->yoffset = 0; pinfo->vxres = pinfo->xres; pinfo->vyres = pinfo->yres; return 0;}/* * Parse user speficied options (`video=platinumfb:') */int __init platinumfb_setup(char *options){ char *this_opt; if (!options || !*options) return 0; while ((this_opt = strsep(&options, ",")) != NULL) { if (!strncmp(this_opt, "vmode:", 6)) { int vmode = simple_strtoul(this_opt+6, NULL, 0); if (vmode > 0 && vmode <= VMODE_MAX) default_vmode = vmode; } else if (!strncmp(this_opt, "cmode:", 6)) { int depth = simple_strtoul(this_opt+6, NULL, 0); switch (depth) { case 0: case 8: default_cmode = CMODE_8; break; case 15: case 16: default_cmode = CMODE_16; break; case 24: case 32: default_cmode = CMODE_32; break; } } } return 0;}#ifdef __powerpc__#define invalidate_cache(addr) \ asm volatile("eieio; dcbf 0,%1" \ : "=m" (*(addr)) : "r" (addr) : "memory");#else#define invalidate_cache(addr)#endifstatic int __devinit platinumfb_probe(struct of_device* odev, const struct of_match *match){ struct device_node *dp = odev->node; struct fb_info *info; struct fb_info_platinum *pinfo; unsigned long addr, size; volatile __u8 *fbuffer; int i, bank0, bank1, bank2, bank3, rc; if (dp->n_addrs != 2) { printk(KERN_ERR "expecting 2 address for platinum (got %d)", dp->n_addrs); return -ENXIO; } printk(KERN_INFO "platinumfb: Found Apple Platinum video hardware\n"); info = framebuffer_alloc(sizeof(*pinfo), &odev->dev); if (info == NULL) return -ENOMEM; pinfo = info->par; /* Map in frame buffer and registers */ for (i = 0; i < dp->n_addrs; ++i) { addr = dp->addrs[i].address; size = dp->addrs[i].size; /* Let's assume we can request either all or nothing */ if (!request_mem_region(addr, size, "platinumfb")) { framebuffer_release(info); return -ENXIO; } if (size >= 0x400000) { /* frame buffer - map only 4MB */ pinfo->frame_buffer_phys = addr; pinfo->frame_buffer = __ioremap(addr, 0x400000, _PAGE_WRITETHRU); pinfo->base_frame_buffer = pinfo->frame_buffer; } else { /* registers */ pinfo->platinum_regs_phys = addr; pinfo->platinum_regs = ioremap(addr, size); } } pinfo->cmap_regs_phys = 0xf301b000; /* XXX not in prom? */ request_mem_region(pinfo->cmap_regs_phys, 0x1000, "platinumfb cmap"); pinfo->cmap_regs = ioremap(pinfo->cmap_regs_phys, 0x1000); /* Grok total video ram */ out_be32(&pinfo->platinum_regs->reg[16].r, (unsigned)pinfo->frame_buffer_phys); out_be32(&pinfo->platinum_regs->reg[20].r, 0x1011); /* select max vram */ out_be32(&pinfo->platinum_regs->reg[24].r, 0); /* switch in vram */ fbuffer = pinfo->base_frame_buffer; fbuffer[0x100000] = 0x34; fbuffer[0x100008] = 0x0; invalidate_cache(&fbuffer[0x100000]); fbuffer[0x200000] = 0x56; fbuffer[0x200008] = 0x0; invalidate_cache(&fbuffer[0x200000]); fbuffer[0x300000] = 0x78; fbuffer[0x300008] = 0x0; invalidate_cache(&fbuffer[0x300000]); bank0 = 1; /* builtin 1MB vram, always there */ bank1 = fbuffer[0x100000] == 0x34; bank2 = fbuffer[0x200000] == 0x56; bank3 = fbuffer[0x300000] == 0x78; pinfo->total_vram = (bank0 + bank1 + bank2 + bank3) * 0x100000; printk(KERN_INFO "platinumfb: Total VRAM = %dMB (%d%d%d%d)\n", (int) (pinfo->total_vram / 1024 / 1024), bank3, bank2, bank1, bank0); /* * Try to determine whether we have an old or a new DACula. */ out_8(&pinfo->cmap_regs->addr, 0x40); pinfo->dactype = in_8(&pinfo->cmap_regs->d2); switch (pinfo->dactype) { case 0x3c: pinfo->clktype = 1; printk(KERN_INFO "platinumfb: DACula type 0x3c\n"); break; case 0x84: pinfo->clktype = 0; printk(KERN_INFO "platinumfb: DACula type 0x84\n"); break; default: pinfo->clktype = 0; printk(KERN_INFO "platinumfb: Unknown DACula type: %x\n", pinfo->dactype); break; } dev_set_drvdata(&odev->dev, info); rc = platinum_init_fb(info); if (rc != 0) { dev_set_drvdata(&odev->dev, NULL); framebuffer_release(info); } return rc;}static int __devexit platinumfb_remove(struct of_device* odev){ struct fb_info *info = dev_get_drvdata(&odev->dev); struct fb_info_platinum *pinfo = info->par; struct device_node *dp = odev->node; unsigned long addr, size; int i; unregister_framebuffer (info); /* Unmap frame buffer and registers */ for (i = 0; i < dp->n_addrs; ++i) { addr = dp->addrs[i].address; size = dp->addrs[i].size; release_mem_region(addr, size); } iounmap((void *)pinfo->frame_buffer); iounmap((void *)pinfo->platinum_regs); release_mem_region(pinfo->cmap_regs_phys, 0x1000); iounmap((void *)pinfo->cmap_regs); framebuffer_release(info); return 0;}static struct of_match platinumfb_match[] = { { .name = "platinum", .type = OF_ANY_MATCH, .compatible = OF_ANY_MATCH, }, {},};static struct of_platform_driver platinum_driver = { .name = "platinumfb", .match_table = platinumfb_match, .probe = platinumfb_probe, .remove = platinumfb_remove,};int __init platinumfb_init(void){#ifndef MODULE char *option = NULL; if (fb_get_options("platinumfb", &option)) return -ENODEV; platinumfb_setup(option);#endif of_register_driver(&platinum_driver); return 0;}void __exit platinumfb_exit(void){ of_unregister_driver(&platinum_driver); }MODULE_LICENSE("GPL");MODULE_DESCRIPTION("framebuffer driver for Apple Platinum video");module_init(platinumfb_init);#ifdef MODULEmodule_exit(platinumfb_exit);#endif
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?