📄 aty128fb.c
字号:
if (!info->pdev) printk(KERN_WARNING "aty128fb: Not a PCI card, can't enable power management\n"); else { info->pm_reg = pci_find_capability(info->pdev, PCI_CAP_ID_PM); pmu_register_sleep_notifier(&aty128_sleep_notifier); }#endif printk(KERN_INFO "fb%d: %s frame buffer device on %s\n", GET_FB_IDX(info->fb_info.node), aty128fb_name, name); return 1; /* success! */}/* add a new card to the list ++ajoshi */static structfb_info_aty128 *aty128_board_list_add(struct fb_info_aty128 *board_list, struct fb_info_aty128 *new_node){ struct fb_info_aty128 *i_p = board_list; new_node->next = NULL; if(board_list == NULL) return new_node; while(i_p->next != NULL) i_p = i_p->next; i_p->next = new_node; return board_list;}int __initaty128fb_init(void){#ifdef CONFIG_PCI struct pci_dev *pdev = NULL; const struct aty128_chip_info *aci = &aty128_pci_probe_list[0]; while (aci->name != NULL) { pdev = pci_find_device(PCI_VENDOR_ID_ATI, aci->device, pdev); while (pdev != NULL) { if (aty128_pci_register(pdev, aci) == 0) return 0; pdev = pci_find_device(PCI_VENDOR_ID_ATI, aci->device, pdev); } aci++; }#endif return 0;}#ifdef CONFIG_PCI/* register a card ++ajoshi */static int __initaty128_pci_register(struct pci_dev *pdev, const struct aty128_chip_info *aci){ struct fb_info_aty128 *info = NULL; unsigned long fb_addr, reg_addr; int err;#if !defined(CONFIG_PPC) && !defined(__sparc__) char *bios_seg = NULL;#endif /* Enable device in PCI config */ if ((err = pci_enable_device(pdev))) { printk(KERN_ERR "aty128fb: Cannot enable PCI device: %d\n", err); return -ENODEV; } fb_addr = pci_resource_start(pdev, 0); if (!request_mem_region(fb_addr, pci_resource_len(pdev, 0), "aty128fb FB")) { printk(KERN_ERR "aty128fb: cannot reserve frame " "buffer memory\n"); goto err_free_fb; } reg_addr = pci_resource_start(pdev, 2); if (!request_mem_region(reg_addr, pci_resource_len(pdev, 2), "aty128fb MMIO")) { printk(KERN_ERR "aty128fb: cannot reserve MMIO region\n"); goto err_free_mmio; } /* We have the resources. Now virtualize them */ if (!(info = kmalloc(sizeof(struct fb_info_aty128), GFP_ATOMIC))) { printk(KERN_ERR "aty128fb: can't alloc fb_info_aty128\n"); goto err_unmap_out; } memset(info, 0, sizeof(struct fb_info_aty128)); /* Copy PCI device info into info->pdev */ info->pdev = pdev; info->currcon = -1; /* Virtualize mmio region */ info->regbase_phys = reg_addr; info->regbase = ioremap(reg_addr, 0x1FFF); if (!info->regbase) goto err_free_info; /* Grab memory size from the card */ info->vram_size = aty_ld_le32(CONFIG_MEMSIZE) & 0x03FFFFFF; /* Virtualize the framebuffer */ info->frame_buffer_phys = fb_addr; info->frame_buffer = ioremap(fb_addr, info->vram_size); if (!info->frame_buffer) { iounmap((void *)info->regbase); goto err_free_info; } /* If we can't test scratch registers, something is seriously wrong */ if (!register_test(info)) { printk(KERN_ERR "aty128fb: Can't write to video register!\n"); goto err_out; }#if !defined(CONFIG_PPC) && !defined(__sparc__) if (!(bios_seg = aty128find_ROM(info))) printk(KERN_INFO "aty128fb: Rage128 BIOS not located. " "Guessing...\n"); else { printk(KERN_INFO "aty128fb: Rage128 BIOS located at " "segment %4.4X\n", (unsigned int)bios_seg); aty128_get_pllinfo(info, bios_seg); }#endif aty128_timings(info); if (!aty128_init(info, "PCI")) goto err_out;#ifdef CONFIG_MTRR if (mtrr) { info->mtrr.vram = mtrr_add(info->frame_buffer_phys, info->vram_size, MTRR_TYPE_WRCOMB, 1); info->mtrr.vram_valid = 1; /* let there be speed */ printk(KERN_INFO "aty128fb: Rage128 MTRR set to ON\n"); }#endif /* CONFIG_MTRR */#ifdef CONFIG_FB_COMPAT_XPMAC if (!console_fb_info) console_fb_info = &info->fb_info;#endif return 0;err_out: iounmap(info->frame_buffer); iounmap(info->regbase);err_free_info: kfree(info);err_unmap_out: release_mem_region(pci_resource_start(pdev, 2), pci_resource_len(pdev, 2));err_free_mmio: release_mem_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0));err_free_fb: release_mem_region(pci_resource_start(pdev, 1), pci_resource_len(pdev, 1)); return -ENODEV;}#endif /* CONFIG_PCI *//* PPC and Sparc cannot read video ROM */#if !defined(CONFIG_PPC) && !defined(__sparc__)static char __init*aty128find_ROM(struct fb_info_aty128 *info){ u32 segstart; char *rom_base; char *rom; int stage; int i; char aty_rom_sig[] = "761295520"; /* ATI ROM Signature */ char R128_sig[] = "R128"; /* Rage128 ROM identifier */ for (segstart=0x000c0000; segstart<0x000f0000; segstart+=0x00001000) { stage = 1; rom_base = (char *)ioremap(segstart, 0x1000); if ((*rom_base == 0x55) && (((*(rom_base + 1)) & 0xff) == 0xaa)) stage = 2; if (stage != 2) { iounmap(rom_base); continue; } rom = rom_base; for (i = 0; (i < 128 - strlen(aty_rom_sig)) && (stage != 3); i++) { if (aty_rom_sig[0] == *rom) if (strncmp(aty_rom_sig, rom, strlen(aty_rom_sig)) == 0) stage = 3; rom++; } if (stage != 3) { iounmap(rom_base); continue; } rom = rom_base; /* ATI signature found. Let's see if it's a Rage128 */ for (i = 0; (i < 512) && (stage != 4); i++) { if (R128_sig[0] == *rom) if (strncmp(R128_sig, rom, strlen(R128_sig)) == 0) stage = 4; rom++; } if (stage != 4) { iounmap(rom_base); continue; } return rom_base; } return NULL;}static void __initaty128_get_pllinfo(struct fb_info_aty128 *info, char *bios_seg){ void *bios_header; void *header_ptr; u16 bios_header_offset, pll_info_offset; PLL_BLOCK pll; bios_header = bios_seg + 0x48L; header_ptr = bios_header; bios_header_offset = readw(header_ptr); bios_header = bios_seg + bios_header_offset; bios_header += 0x30; header_ptr = bios_header; pll_info_offset = readw(header_ptr); header_ptr = bios_seg + pll_info_offset; memcpy_fromio(&pll, header_ptr, 50); info->constants.ppll_max = pll.PCLK_max_freq; info->constants.ppll_min = pll.PCLK_min_freq; info->constants.xclk = (u32)pll.XCLK; info->constants.ref_divider = (u32)pll.PCLK_ref_divider; info->constants.dotclock = (u32)pll.PCLK_ref_freq; DBG("ppll_max %d ppll_min %d xclk %d ref_divider %d dotclock %d\n", info->constants.ppll_max, info->constants.ppll_min, info->constants.xclk, info->constants.ref_divider, info->constants.dotclock);} #endif /* !CONFIG_PPC *//* fill in known card constants if pll_block is not available */static void __initaty128_timings(struct fb_info_aty128 *info){#ifdef CONFIG_PPC /* instead of a table lookup, assume OF has properly * setup the PLL registers and use their values * to set the XCLK values and reference divider values */ u32 x_mpll_ref_fb_div; u32 xclk_cntl; u32 Nx, M; unsigned PostDivSet[] = { 0, 1, 2, 4, 8, 3, 6, 12 };#endif if (!info->constants.dotclock) info->constants.dotclock = 2950;#ifdef CONFIG_PPC x_mpll_ref_fb_div = aty_ld_pll(X_MPLL_REF_FB_DIV); xclk_cntl = aty_ld_pll(XCLK_CNTL) & 0x7; Nx = (x_mpll_ref_fb_div & 0x00ff00) >> 8; M = x_mpll_ref_fb_div & 0x0000ff; info->constants.xclk = round_div((2 * Nx * info->constants.dotclock), (M * PostDivSet[xclk_cntl])); info->constants.ref_divider = aty_ld_pll(PPLL_REF_DIV) & PPLL_REF_DIV_MASK;#endif if (!info->constants.ref_divider) { info->constants.ref_divider = 0x3b; aty_st_pll(X_MPLL_REF_FB_DIV, 0x004c4c1e); aty_pll_writeupdate(info); } aty_st_pll(PPLL_REF_DIV, info->constants.ref_divider); aty_pll_writeupdate(info); /* from documentation */ if (!info->constants.ppll_min) info->constants.ppll_min = 12500; if (!info->constants.ppll_max) info->constants.ppll_max = 25000; /* 23000 on some cards? */ if (!info->constants.xclk) info->constants.xclk = 0x1d4d; /* same as mclk */ info->constants.fifo_width = 128; info->constants.fifo_depth = 32; switch (aty_ld_le32(MEM_CNTL) & 0x3) { case 0: info->mem = &sdr_128; break; case 1: info->mem = &sdr_sgram; break; case 2: info->mem = &ddr_sgram; break; default: info->mem = &sdr_sgram; }}static intaty128fbcon_switch(int con, struct fb_info *fb){ struct fb_info_aty128 *info = (struct fb_info_aty128 *)fb; struct aty128fb_par par; /* Do we have to save the colormap? */ if (fb_display[info->currcon].cmap.len) fb_get_cmap(&fb_display[info->currcon].cmap, 1, aty128_getcolreg, fb); /* set the current console */ info->currcon = con; aty128_decode_var(&fb_display[con].var, &par, info); aty128_set_par(&par, info); aty128_set_dispsw(&fb_display[con], info, par.crtc.bpp, par.accel_flags & FB_ACCELF_TEXT); do_install_cmap(con, fb); return 1;} /* * Blank the display. */static voidaty128fbcon_blank(int blank, struct fb_info *fb){ struct fb_info_aty128 *info = (struct fb_info_aty128 *)fb; u8 state = 0;#ifdef CONFIG_PMAC_BACKLIGHT if ((_machine == _MACH_Pmac) && blank) set_backlight_enable(0);#endif /* CONFIG_PMAC_BACKLIGHT */ if (blank & VESA_VSYNC_SUSPEND) state |= 2; if (blank & VESA_HSYNC_SUSPEND) state |= 1; if (blank & VESA_POWERDOWN) state |= 4; aty_st_8(CRTC_EXT_CNTL+1, state);#ifdef CONFIG_PMAC_PBOOK if (info->chip_gen == rage_M3) { aty128_set_crt_enable(info, info->crt_on && !blank); aty128_set_lcd_enable(info, info->lcd_on && !blank); }#endif #ifdef CONFIG_PMAC_BACKLIGHT if ((_machine == _MACH_Pmac) && !blank) set_backlight_enable(1);#endif /* CONFIG_PMAC_BACKLIGHT */} /* * Read a single color register and split it into * colors/transparent. Return != 0 for invalid regno. */static intaty128_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue, u_int *transp, struct fb_info *fb){ struct fb_info_aty128 *info = (struct fb_info_aty128 *) fb; if (regno > 255) return 1; *red = (info->palette[regno].red<<8) | info->palette[regno].red; *green = (info->palette[regno].green<<8) | info->palette[regno].green; *blue = (info->palette[regno].blue<<8) | info->palette[regno].blue; *transp = 0; return 0;} /* * 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 intaty128_setcolreg(u_int regno, u_int red, u_int green, u_int blue, u_int transp, struct fb_info *fb){ struct fb_info_aty128 *info = (struct fb_info_aty128 *)fb; u32 palreg; if (regno > 255) return 1; red >>= 8; green >>= 8; blue >>= 8; info->palette[regno].red = red; info->palette[regno].green = green; info->palette[regno].blue = blue; /* Note: For now, on M3, we set palette on both heads, which may * be useless. Can someone with a M3 check this ? */ /* initialize gamma ramp for hi-color+ */ if ((info->current_par.crtc.bpp > 8) && (regno == 0)) { int i; for (i=0; i<256; i++) aty128_st_pal(i, i, i, i, info); } /* initialize palette */ palreg = regno; if (info->current_par.crtc.bpp == 16) palreg = regno * 8; if (info->current_par.crtc.depth == 16) { aty128_st_pal(palreg/2, info->palette[regno/2].red, green, info->palette[regno/2].blue, info); green = info->palette[regno*2].green; } if (info->current_par.crtc.bpp == 8 || regno < 32) aty128_st_pal(palreg, red, green, blue, info); if (regno < 16) switch (info->current_par.crtc.depth) {#ifdef FBCON_HAS_CFB16 case 15: info->fbcon_cmap.cfb16[regno] = (regno << 10) | (regno << 5) | regno; break; case 16: info->fbcon_cmap.cfb16[regno] = (regno << 11) | (regno << 5) | regno;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -