📄 aty128fb.c
字号:
aty128_decode_var(&fb_display[con].var, &par, info); aty128_encode_fix(fix, &par, info); return 0; } /* * Pan or Wrap the Display * * Not supported (yet!) */static intaty128fb_pan_display(struct fb_var_screeninfo *var, int con, struct fb_info *fb){ struct fb_info_aty128 *info = (struct fb_info_aty128 *)fb; struct aty128fb_par *par = &info->current_par; u32 xoffset, yoffset; u32 offset; u32 xres, yres; xres = (((par->crtc.h_total >> 16) & 0xff) + 1) << 3; yres = ((par->crtc.v_total >> 16) & 0x7ff) + 1; xoffset = (var->xoffset +7) & ~7; yoffset = var->yoffset; if (xoffset+xres > par->crtc.vxres || yoffset+yres > par->crtc.vyres) return -EINVAL; par->crtc.xoffset = xoffset; par->crtc.yoffset = yoffset; offset = ((yoffset * par->crtc.vxres + xoffset) * par->crtc.bpp) >> 6; aty_st_le32(CRTC_OFFSET, offset); return 0;} /* * Get the Colormap */static intaty128fb_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info){#if 1 fb_copy_cmap(&info->cmap, cmap, kspc ? 0 : 2);#else struct fb_info_aty128 fb = (struct fb_info_aty128 *)info; if (con == fb->currcon) /* current console? */ return fb_get_cmap(cmap, kspc, aty128_getcolreg, info); else if (fb_display[con].cmap.len) /* non default colormap? */ fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2); else { int size = (fb_display[con].var.bits_per_pixel <= 8) ? 256 : 32; fb_copy_cmap(fb_default_cmap(size), cmap, kspc ? 0 : 2); }#endif return 0;} /* * Set the Colormap */static intaty128fb_set_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info){ int err; struct fb_info_aty128 *fb = (struct fb_info_aty128 *)info; struct display *disp; if (con >= 0) disp = &fb_display[con]; else disp = info->disp; if (!disp->cmap.len) { /* no colormap allocated? */ int size = (disp->var.bits_per_pixel <= 8) ? 256 : 32; if ((err = fb_alloc_cmap(&disp->cmap, size, 0))) return err; } if (con == fb->currcon) /* current console? */ return fb_set_cmap(cmap, kspc, aty128_setcolreg, info); else fb_copy_cmap(cmap, &disp->cmap, kspc ? 0 : 1); return 0; }static intaty128fb_rasterimg(struct fb_info *info, int start){ struct fb_info_aty128 *fb = (struct fb_info_aty128 *)info; if (fb->blitter_may_be_busy) wait_for_idle(fb); return 0;}#ifndef MODULEint __initaty128fb_setup(char *options){ char *this_opt; if (!options || !*options) return 0; for (this_opt = strtok(options, ","); this_opt; this_opt = strtok(NULL, ",")) { if (!strncmp(this_opt, "font:", 5)) { char *p; int i; p = this_opt +5; for (i = 0; i < sizeof(fontname) - 1; i++) if (!*p || *p == ' ' || *p == ',') break; memcpy(fontname, this_opt + 5, i); fontname[i] = 0; } else if (!strncmp(this_opt, "noaccel", 7)) { noaccel = 1; }#ifdef CONFIG_MTRR else if(!strncmp(this_opt, "nomtrr", 6)) { mtrr = 0; }#endif#ifdef CONFIG_PPC /* vmode and cmode depreciated */ else if (!strncmp(this_opt, "vmode:", 6)) { unsigned 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)) { unsigned int cmode = simple_strtoul(this_opt+6, NULL, 0); switch (cmode) { 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; } }#endif /* CONFIG_PPC */ else mode_option = this_opt; } return 0;}#endif /* !MODULE */ /* * Initialisation */static int __initaty128_init(struct fb_info_aty128 *info, const char *name){ struct fb_var_screeninfo var; u32 dac; int j, k; u8 chip_rev; const struct aty128_chip_info *aci = &aty128_pci_probe_list[0]; char *video_card = "Rage128"; if (!info->vram_size) /* may have already been probed */ info->vram_size = aty_ld_le32(CONFIG_MEMSIZE) & 0x03FFFFFF; /* Get the chip revision */ chip_rev = (aty_ld_le32(CONFIG_CNTL) >> 16) & 0x1F; /* put a name with the face */ while (aci->name && info->pdev->device != aci->device) { aci++; } video_card = (char *)aci->name; info->chip_gen = aci->chip_gen; printk(KERN_INFO "aty128fb: %s [chip rev 0x%x] ", video_card, chip_rev); if (info->vram_size % (1024 * 1024) == 0) printk("%dM %s\n", info->vram_size / (1024*1024), info->mem->name); else printk("%dk %s\n", info->vram_size / 1024, info->mem->name); /* fill in info */ strcpy(info->fb_info.modename, aty128fb_name); info->fb_info.node = -1; info->fb_info.fbops = &aty128fb_ops; info->fb_info.disp = &info->disp; strcpy(info->fb_info.fontname, fontname); info->fb_info.changevar = NULL; info->fb_info.switch_con = &aty128fbcon_switch; info->fb_info.updatevar = NULL; info->fb_info.blank = &aty128fbcon_blank; info->fb_info.flags = FBINFO_FLAG_DEFAULT;#ifdef MODULE var = default_var;#else memset(&var, 0, sizeof(var));#ifdef CONFIG_PPC if (_machine == _MACH_Pmac) { if (mode_option) { if (!mac_find_mode(&var, &info->fb_info, mode_option, 8)) var = default_var; } else { if (default_vmode <= 0 || default_vmode > VMODE_MAX) default_vmode = VMODE_1024_768_60; if (default_cmode < CMODE_8 || default_cmode > CMODE_32) default_cmode = CMODE_8; if (mac_vmode_to_var(default_vmode, default_cmode, &var)) var = default_var; } } else#endif /* CONFIG_PPC */ { if (fb_find_mode(&var, &info->fb_info, mode_option, NULL, 0, &defaultmode, 8) == 0) var = default_var; }#endif /* MODULE */ if (noaccel) var.accel_flags &= ~FB_ACCELF_TEXT; else var.accel_flags |= FB_ACCELF_TEXT; if (aty128_decode_var(&var, &info->default_par, info)) { printk(KERN_ERR "aty128fb: Cannot set default mode.\n"); return 0; } /* load up the palette with default colors */ for (j = 0; j < 16; j++) { k = color_table[j]; info->palette[j].red = default_red[k]; info->palette[j].green = default_grn[k]; info->palette[j].blue = default_blu[k]; } /* setup the DAC the way we like it */ dac = aty_ld_le32(DAC_CNTL); dac |= (DAC_8BIT_EN | DAC_RANGE_CNTL); dac |= DAC_MASK; aty_st_le32(DAC_CNTL, dac); /* turn off bus mastering, just in case */ aty_st_le32(BUS_CNTL, aty_ld_le32(BUS_CNTL) | BUS_MASTER_DIS); aty128fb_set_var(&var, -1, &info->fb_info); aty128_init_engine(&info->default_par, info); board_list = aty128_board_list_add(board_list, info); if (register_framebuffer(&info->fb_info) < 0) return 0;#ifdef CONFIG_PMAC_BACKLIGHT /* Could be extended to Rage128Pro LVDS output too */ if (info->chip_gen == rage_M3) register_backlight_controller(&aty128_backlight_controller, info, "ati");#endif /* CONFIG_PMAC_BACKLIGHT */ 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; u32 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); goto err_out; } 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 = (u32)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((void *)info->frame_buffer); iounmap((void *)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 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -