📄 aty128fb.c
字号:
#endif aty_st_le32(CONFIG_CNTL, config); aty_st_8(CRTC_EXT_CNTL + 1, 0); /* turn the video back on */ info->fix.line_length = (par->crtc.vxres * par->crtc.bpp) >> 3; info->fix.visual = par->crtc.bpp == 8 ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR; if (par->chip_gen == rage_M3) { aty128_set_crt_enable(par, par->crt_on); aty128_set_lcd_enable(par, par->lcd_on); } if (par->accel_flags & FB_ACCELF_TEXT) aty128_init_engine(par);#ifdef CONFIG_BOOTX_TEXT btext_update_display(info->fix.smem_start, (((par->crtc.h_total>>16) & 0xff)+1)*8, ((par->crtc.v_total>>16) & 0x7ff)+1, par->crtc.bpp, par->crtc.vxres*par->crtc.bpp/8);#endif /* CONFIG_BOOTX_TEXT */ return 0;}/* * encode/decode the User Defined Part of the Display */static int aty128_decode_var(struct fb_var_screeninfo *var, struct aty128fb_par *par){ int err; struct aty128_crtc crtc; struct aty128_pll pll; struct aty128_ddafifo fifo_reg; if ((err = aty128_var_to_crtc(var, &crtc, par))) return err; if ((err = aty128_var_to_pll(var->pixclock, &pll, par))) return err; if ((err = aty128_ddafifo(&fifo_reg, &pll, crtc.depth, par))) return err; par->crtc = crtc; par->pll = pll; par->fifo_reg = fifo_reg; par->accel_flags = var->accel_flags; return 0;}static int aty128_encode_var(struct fb_var_screeninfo *var, const struct aty128fb_par *par){ int err; if ((err = aty128_crtc_to_var(&par->crtc, var))) return err; if ((err = aty128_pll_to_var(&par->pll, var))) return err; var->nonstd = 0; var->activate = 0; var->height = -1; var->width = -1; var->accel_flags = par->accel_flags; return 0;} static int aty128fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info){ struct aty128fb_par par; int err; par = *(struct aty128fb_par *)info->par; if ((err = aty128_decode_var(var, &par)) != 0) return err; aty128_encode_var(var, &par); return 0;}/* * Pan or Wrap the Display */static int aty128fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *fb) { struct aty128fb_par *par = fb->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 >> 3)) & ~7; if (par->crtc.bpp == 24) offset += 8 * (offset % 3); /* Must be multiple of 8 and 3 */ aty_st_le32(CRTC_OFFSET, offset); return 0;}/* * Helper function to store a single palette register */static void aty128_st_pal(u_int regno, u_int red, u_int green, u_int blue, struct aty128fb_par *par){ if (par->chip_gen == rage_M3) {#if 0 /* Note: For now, on M3, we set palette on both heads, which may * be useless. Can someone with a M3 check this ? * * This code would still be useful if using the second CRTC to * do mirroring */ aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) | DAC_PALETTE_ACCESS_CNTL); aty_st_8(PALETTE_INDEX, regno); aty_st_le32(PALETTE_DATA, (red<<16)|(green<<8)|blue);#endif aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) & ~DAC_PALETTE_ACCESS_CNTL); } aty_st_8(PALETTE_INDEX, regno); aty_st_le32(PALETTE_DATA, (red<<16)|(green<<8)|blue);}static int aty128fb_sync(struct fb_info *info){ struct aty128fb_par *par = info->par; if (par->blitter_may_be_busy) wait_for_idle(par); return 0;}#ifndef MODULEstatic int __init aty128fb_setup(char *options){ char *this_opt; if (!options || !*options) return 0; while ((this_opt = strsep(&options, ",")) != NULL) { if (!strncmp(this_opt, "lcd:", 4)) { default_lcd_on = simple_strtoul(this_opt+4, NULL, 0); continue; } else if (!strncmp(this_opt, "crt:", 4)) { default_crt_on = simple_strtoul(this_opt+4, NULL, 0); continue; }#ifdef CONFIG_MTRR if(!strncmp(this_opt, "nomtrr", 6)) { mtrr = 0; continue; }#endif#ifdef CONFIG_PPC_PMAC /* vmode and cmode deprecated */ 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; continue; } 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; } continue; }#endif /* CONFIG_PPC_PMAC */ mode_option = this_opt; } return 0;}#endif /* MODULE *//* * Initialisation */#ifdef CONFIG_PPC_PMACstatic void aty128_early_resume(void *data){ struct aty128fb_par *par = data; if (try_acquire_console_sem()) return; aty128_do_resume(par->pdev); release_console_sem();}#endif /* CONFIG_PPC_PMAC */static int __init aty128_init(struct pci_dev *pdev, const struct pci_device_id *ent){ struct fb_info *info = pci_get_drvdata(pdev); struct aty128fb_par *par = info->par; struct fb_var_screeninfo var; char video_card[DEVICE_NAME_SIZE]; u8 chip_rev; u32 dac; if (!par->vram_size) /* may have already been probed */ par->vram_size = aty_ld_le32(CONFIG_MEMSIZE) & 0x03FFFFFF; /* Get the chip revision */ chip_rev = (aty_ld_le32(CONFIG_CNTL) >> 16) & 0x1F; strcpy(video_card, "Rage128 XX "); video_card[8] = ent->device >> 8; video_card[9] = ent->device & 0xFF; /* range check to make sure */ if (ent->driver_data < (sizeof(r128_family)/sizeof(char *))) strncat(video_card, r128_family[ent->driver_data], sizeof(video_card)); printk(KERN_INFO "aty128fb: %s [chip rev 0x%x] ", video_card, chip_rev); if (par->vram_size % (1024 * 1024) == 0) printk("%dM %s\n", par->vram_size / (1024*1024), par->mem->name); else printk("%dk %s\n", par->vram_size / 1024, par->mem->name); par->chip_gen = ent->driver_data; /* fill in info */ info->fbops = &aty128fb_ops; info->flags = FBINFO_FLAG_DEFAULT; par->lcd_on = default_lcd_on; par->crt_on = default_crt_on; var = default_var;#ifdef CONFIG_PPC_PMAC if (_machine == _MACH_Pmac) { /* Indicate sleep capability */ if (par->chip_gen == rage_M3) { pmac_call_feature(PMAC_FTR_DEVICE_CAN_WAKE, NULL, 0, 1); pmac_set_early_video_resume(aty128_early_resume, par); } /* Find default mode */ if (mode_option) { if (!mac_find_mode(&var, info, mode_option, 8)) var = default_var; } else { if (default_vmode <= 0 || default_vmode > VMODE_MAX) default_vmode = VMODE_1024_768_60; /* iMacs need that resolution * PowerMac2,1 first r128 iMacs * PowerMac2,2 summer 2000 iMacs * PowerMac4,1 january 2001 iMacs "flower power" */ if (machine_is_compatible("PowerMac2,1") || machine_is_compatible("PowerMac2,2") || machine_is_compatible("PowerMac4,1")) default_vmode = VMODE_1024_768_75; /* iBook SE */ if (machine_is_compatible("PowerBook2,2")) default_vmode = VMODE_800_600_60; /* PowerBook Firewire (Pismo), iBook Dual USB */ if (machine_is_compatible("PowerBook3,1") || machine_is_compatible("PowerBook4,1")) default_vmode = VMODE_1024_768_60; /* PowerBook Titanium */ if (machine_is_compatible("PowerBook3,2")) default_vmode = VMODE_1152_768_60; if (default_cmode > 16) default_cmode = CMODE_32; else if (default_cmode > 8) default_cmode = CMODE_16; else default_cmode = CMODE_8; if (mac_vmode_to_var(default_vmode, default_cmode, &var)) var = default_var; } } else#endif /* CONFIG_PPC_PMAC */ { if (mode_option) if (fb_find_mode(&var, info, mode_option, NULL, 0, &defaultmode, 8) == 0) var = default_var; } var.accel_flags &= ~FB_ACCELF_TEXT;// var.accel_flags |= FB_ACCELF_TEXT;/* FIXME Will add accel later */ if (aty128fb_check_var(&var, info)) { printk(KERN_ERR "aty128fb: Cannot set default mode.\n"); return 0; } /* setup the DAC the way we like it */ dac = aty_ld_le32(DAC_CNTL); dac |= (DAC_8BIT_EN | DAC_RANGE_CNTL); dac |= DAC_MASK; if (par->chip_gen == rage_M3) dac |= DAC_PALETTE2_SNOOP_EN; 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); info->var = var; fb_alloc_cmap(&info->cmap, 256, 0); var.activate = FB_ACTIVATE_NOW; aty128_init_engine(par); if (register_framebuffer(info) < 0) return 0;#ifdef CONFIG_PMAC_BACKLIGHT /* Could be extended to Rage128Pro LVDS output too */ if (par->chip_gen == rage_M3) register_backlight_controller(&aty128_backlight_controller, par, "ati");#endif /* CONFIG_PMAC_BACKLIGHT */ par->pm_reg = pci_find_capability(pdev, PCI_CAP_ID_PM); par->pdev = pdev; par->asleep = 0; par->lock_blank = 0; printk(KERN_INFO "fb%d: %s frame buffer device on %s\n", info->node, info->fix.id, video_card); return 1; /* success! */}#ifdef CONFIG_PCI/* register a card ++ajoshi */static int __init aty128_probe(struct pci_dev *pdev, const struct pci_device_id *ent){ unsigned long fb_addr, reg_addr; struct aty128fb_par *par; struct fb_info *info; int err;#ifndef __sparc__ void __iomem *bios = 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"); return -ENODEV; } 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_fb; } /* We have the resources. Now virtualize them */ info = framebuffer_alloc(sizeof(struct aty128fb_par), &pdev->dev); if (info == NULL) { printk(KERN_ERR "aty128fb: can't alloc fb_info_aty128\n"); goto err_free_mmio; } par = info->par; info->pseudo_palette = par->pseudo_palette; info->fix = aty128fb_fix; /* Virtualize mmio region */ info->fix.mmio_start = reg_addr; par->regbase = ioremap(reg_addr, pci_resource_len(pdev, 2)); if (!par->regbase) goto err_free_info; /* Grab memory size from the card */ // How does this relate to the resource length from the PCI hardware? par->vram_size = aty_ld_le32(CONFIG_MEMSIZE) & 0x03FFFFFF; /* Virtualize the framebuffer */ info->screen_base = ioremap(fb_addr, par->vram_size); if (!info->screen_base) goto err_unmap_out; /* Set up info->fix */ info->fix = aty128fb_fix; info->fix.smem_start = fb_addr; info->fix.smem_len = par->vram_size; info->fix.mmio_start = reg_addr; /* If we can't test scratch registers, something is seriously wrong */ if (!register_test(par)) { printk(KERN_ERR "aty128fb: Can't write to video register!\n"); goto err_out; }#ifndef __sparc__ bios = aty128_map_ROM(par, pdev);#ifdef CONFIG_X86 if (bios == NULL) bios = aty128_find_mem_vbios(par);#endif if (bios == NULL) printk(KERN_INFO "aty128fb: BIOS not located, guessing timings.\n"); else { printk(KERN_INFO "aty128fb: Rage128 BIOS located\n"); aty128_get_pllinfo(par, bios); pci_unmap_rom(pdev, bios); }#endif /* __sparc__ */ aty128_timings(par); pci_set_drvdata(pdev, info); if (!aty128_init(pdev, ent)) goto err_out;#ifdef CONFIG_MTRR if (mtrr) { par->mtrr.vram = mtrr_add(info->fix.smem_start, par->vram_size, MTRR_TYPE_WRCOMB, 1); par->mtrr.vram_valid = 1; /* let there be speed */ printk(KERN_INFO "aty128fb: Rage128 MTRR set to ON\n"); }#endif /* CONFIG_MTRR */ return 0;err_out: iounmap(info->screen_base);err_unmap_out: iounmap(par->regbase);err_free_info: framebuffer_release(info);err_free_mmio: release_mem_region(pci_resource_start(pdev, 2), pci_resource_len(pdev, 2));err_free_fb: release_mem_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); return -ENODEV;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -