radeon_base.c
来自「优龙2410linux2.6.8内核源代码」· C语言 代码 · 共 2,181 行 · 第 1/5 页
C
2,181 行
count = rinfo->mapped_vram - p; err = -ENOSPC; } radeonfb_sync(info); if (count) { char *base_addr; base_addr = info->screen_base; count -= copy_from_user(base_addr+p, buf, count); *ppos += count; err = -EFAULT; } if (count) return count; return err;}static struct fb_ops radeonfb_ops = { .owner = THIS_MODULE, .fb_check_var = radeonfb_check_var, .fb_set_par = radeonfb_set_par, .fb_setcolreg = radeonfb_setcolreg, .fb_pan_display = radeonfb_pan_display, .fb_blank = radeonfb_blank, .fb_ioctl = radeonfb_ioctl, .fb_sync = radeonfb_sync, .fb_fillrect = radeonfb_fillrect, .fb_copyarea = radeonfb_copyarea, .fb_imageblit = radeonfb_imageblit, .fb_read = radeonfb_read, .fb_write = radeonfb_write, .fb_cursor = soft_cursor,};static int __devinit radeon_set_fbinfo (struct radeonfb_info *rinfo){ struct fb_info *info = rinfo->info; info->currcon = -1; info->par = rinfo; info->pseudo_palette = rinfo->pseudo_palette; info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT | FBINFO_HWACCEL_XPAN | FBINFO_HWACCEL_YPAN; info->fbops = &radeonfb_ops; info->screen_base = (char *)rinfo->fb_base; /* Fill fix common fields */ strlcpy(info->fix.id, rinfo->name, sizeof(info->fix.id)); info->fix.smem_start = rinfo->fb_base_phys; info->fix.smem_len = rinfo->video_ram; info->fix.type = FB_TYPE_PACKED_PIXELS; info->fix.visual = FB_VISUAL_PSEUDOCOLOR; info->fix.xpanstep = 8; info->fix.ypanstep = 1; info->fix.ywrapstep = 0; info->fix.type_aux = 0; info->fix.mmio_start = rinfo->mmio_base_phys; info->fix.mmio_len = RADEON_REGSIZE; fb_alloc_cmap(&info->cmap, 256, 0); if (noaccel) info->flags |= FBINFO_HWACCEL_DISABLED; return 0;}#ifdef CONFIG_PMAC_BACKLIGHT/* TODO: Dbl check these tables, we don't go up to full ON backlight * in these, possibly because we noticed MacOS doesn't, but I'd prefer * having some more official numbers from ATI */static int backlight_conv_m6[] = { 0xff, 0xc0, 0xb5, 0xaa, 0x9f, 0x94, 0x89, 0x7e, 0x73, 0x68, 0x5d, 0x52, 0x47, 0x3c, 0x31, 0x24};static int backlight_conv_m7[] = { 0x00, 0x3f, 0x4a, 0x55, 0x60, 0x6b, 0x76, 0x81, 0x8c, 0x97, 0xa2, 0xad, 0xb8, 0xc3, 0xce, 0xd9};#define BACKLIGHT_LVDS_OFF#undef BACKLIGHT_DAC_OFF/* We turn off the LCD completely instead of just dimming the backlight. * This provides some greater power saving and the display is useless * without backlight anyway. */static int radeon_set_backlight_enable(int on, int level, void *data){ struct radeonfb_info *rinfo = (struct radeonfb_info *)data; unsigned int lvds_gen_cntl = INREG(LVDS_GEN_CNTL); unsigned long tmpPixclksCntl = INPLL(PIXCLKS_CNTL); int* conv_table; if (rinfo->mon1_type != MT_LCD) return 0; /* Pardon me for that hack... maybe some day we can figure * out in what direction backlight should work on a given * panel ? */ if ((rinfo->family == CHIP_FAMILY_RV200 || rinfo->family == CHIP_FAMILY_RV250 || rinfo->family == CHIP_FAMILY_RV280 || rinfo->family == CHIP_FAMILY_RV350) && !machine_is_compatible("PowerBook4,3") && !machine_is_compatible("PowerBook6,3") && !machine_is_compatible("PowerBook6,5")) conv_table = backlight_conv_m7; else conv_table = backlight_conv_m6; del_timer_sync(&rinfo->lvds_timer); lvds_gen_cntl |= (LVDS_BL_MOD_EN | LVDS_BLON); radeon_fifo_wait(3); if (on && (level > BACKLIGHT_OFF)) { lvds_gen_cntl |= LVDS_DIGON; if (!(lvds_gen_cntl & LVDS_ON)) { lvds_gen_cntl &= ~LVDS_BLON; OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl); (void)INREG(LVDS_GEN_CNTL); mdelay(rinfo->panel_info.pwr_delay);/* OUCH !!! FIXME */ lvds_gen_cntl |= LVDS_BLON; OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl); } lvds_gen_cntl &= ~LVDS_BL_MOD_LEVEL_MASK; lvds_gen_cntl |= (conv_table[level] << LVDS_BL_MOD_LEVEL_SHIFT); lvds_gen_cntl |= (LVDS_ON | LVDS_EN); lvds_gen_cntl &= ~LVDS_DISPLAY_DIS; } else { /* Asic bug, when turning off LVDS_ON, we have to make sure RADEON_PIXCLK_LVDS_ALWAYS_ON bit is off */ if (rinfo->is_mobility || rinfo->is_IGP) OUTPLLP(PIXCLKS_CNTL, 0, ~PIXCLK_LVDS_ALWAYS_ONb); lvds_gen_cntl &= ~LVDS_BL_MOD_LEVEL_MASK; lvds_gen_cntl |= (conv_table[0] << LVDS_BL_MOD_LEVEL_SHIFT); lvds_gen_cntl |= LVDS_DISPLAY_DIS | LVDS_BLON; OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl); mdelay(rinfo->panel_info.pwr_delay);/* OUCH !!! FIXME */ lvds_gen_cntl &= ~(LVDS_ON | LVDS_EN | LVDS_BLON | LVDS_DIGON); } OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl); if (rinfo->is_mobility || rinfo->is_IGP) OUTPLL(PIXCLKS_CNTL, tmpPixclksCntl); rinfo->init_state.lvds_gen_cntl &= ~LVDS_STATE_MASK; rinfo->init_state.lvds_gen_cntl |= (lvds_gen_cntl & LVDS_STATE_MASK); return 0;}static int radeon_set_backlight_level(int level, void *data){ return radeon_set_backlight_enable(1, level, data);}#endif /* CONFIG_PMAC_BACKLIGHT *//* * This reconfigure the card's internal memory map. In theory, we'd like * to setup the card's memory at the same address as it's PCI bus address, * and the AGP aperture right after that so that system RAM on 32 bits * machines at least, is directly accessible. However, doing so would * conflict with the current XFree drivers... * Ultimately, I hope XFree, GATOS and ATI binary drivers will all agree * on the proper way to set this up and duplicate this here. In the meantime, * I put the card's memory at 0 in card space and AGP at some random high * local (0xe0000000 for now) that will be changed by XFree/DRI anyway */#ifdef CONFIG_PPC_OF#undef SET_MC_FB_FROM_APERTUREstatic void fixup_memory_mappings(struct radeonfb_info *rinfo){ u32 save_crtc_gen_cntl, save_crtc2_gen_cntl; u32 save_crtc_ext_cntl; u32 aper_base, aper_size; u32 agp_base; /* First, we disable display to avoid interfering */ if (rinfo->has_CRTC2) { save_crtc2_gen_cntl = INREG(CRTC2_GEN_CNTL); OUTREG(CRTC2_GEN_CNTL, save_crtc2_gen_cntl | CRTC2_DISP_REQ_EN_B); } save_crtc_gen_cntl = INREG(CRTC_GEN_CNTL); save_crtc_ext_cntl = INREG(CRTC_EXT_CNTL); OUTREG(CRTC_EXT_CNTL, save_crtc_ext_cntl | CRTC_DISPLAY_DIS); OUTREG(CRTC_GEN_CNTL, save_crtc_gen_cntl | CRTC_DISP_REQ_EN_B); mdelay(100); aper_base = INREG(CONFIG_APER_0_BASE); aper_size = INREG(CONFIG_APER_SIZE);#ifdef SET_MC_FB_FROM_APERTURE /* Set framebuffer to be at the same address as set in PCI BAR */ OUTREG(MC_FB_LOCATION, ((aper_base + aper_size - 1) & 0xffff0000) | (aper_base >> 16)); rinfo->fb_local_base = aper_base;#else OUTREG(MC_FB_LOCATION, 0x7fff0000); rinfo->fb_local_base = 0;#endif agp_base = aper_base + aper_size; if (agp_base & 0xf0000000) agp_base = (aper_base | 0x0fffffff) + 1; /* Set AGP to be just after the framebuffer on a 256Mb boundary. This * assumes the FB isn't mapped to 0xf0000000 or above, but this is * always the case on PPCs afaik. */#ifdef SET_MC_FB_FROM_APERTURE OUTREG(MC_AGP_LOCATION, 0xffff0000 | (agp_base >> 16));#else OUTREG(MC_AGP_LOCATION, 0xffffe000);#endif /* Fixup the display base addresses & engine offsets while we * are at it as well */#ifdef SET_MC_FB_FROM_APERTURE OUTREG(DISPLAY_BASE_ADDR, aper_base); if (rinfo->has_CRTC2) OUTREG(CRTC2_DISPLAY_BASE_ADDR, aper_base);#else OUTREG(DISPLAY_BASE_ADDR, 0); if (rinfo->has_CRTC2) OUTREG(CRTC2_DISPLAY_BASE_ADDR, 0);#endif mdelay(100); /* Restore display settings */ OUTREG(CRTC_GEN_CNTL, save_crtc_gen_cntl); OUTREG(CRTC_EXT_CNTL, save_crtc_ext_cntl); if (rinfo->has_CRTC2) OUTREG(CRTC2_GEN_CNTL, save_crtc2_gen_cntl); RTRACE("aper_base: %08x MC_FB_LOC to: %08x, MC_AGP_LOC to: %08x\n", aper_base, ((aper_base + aper_size - 1) & 0xffff0000) | (aper_base >> 16), 0xffff0000 | (agp_base >> 16));}#endif /* CONFIG_PPC_OF *//* * Sysfs */static ssize_t radeon_show_one_edid(char *buf, loff_t off, size_t count, const u8 *edid){ if (off > EDID_LENGTH) return 0; if (off + count > EDID_LENGTH) count = EDID_LENGTH - off; memcpy(buf, edid + off, count); return count;}static ssize_t radeon_show_edid1(struct kobject *kobj, char *buf, loff_t off, size_t count){ struct device *dev = container_of(kobj, struct device, kobj); struct pci_dev *pdev = to_pci_dev(dev); struct fb_info *info = pci_get_drvdata(pdev); struct radeonfb_info *rinfo = info->par; return radeon_show_one_edid(buf, off, count, rinfo->mon1_EDID);}static ssize_t radeon_show_edid2(struct kobject *kobj, char *buf, loff_t off, size_t count){ struct device *dev = container_of(kobj, struct device, kobj); struct pci_dev *pdev = to_pci_dev(dev); struct fb_info *info = pci_get_drvdata(pdev); struct radeonfb_info *rinfo = info->par; return radeon_show_one_edid(buf, off, count, rinfo->mon2_EDID);}static struct bin_attribute edid1_attr = { .attr = { .name = "edid1", .owner = THIS_MODULE, .mode = 0444, }, .size = EDID_LENGTH, .read = radeon_show_edid1,};static struct bin_attribute edid2_attr = { .attr = { .name = "edid2", .owner = THIS_MODULE, .mode = 0444, }, .size = EDID_LENGTH, .read = radeon_show_edid2,};static int radeonfb_pci_register (struct pci_dev *pdev, const struct pci_device_id *ent){ struct fb_info *info; struct radeonfb_info *rinfo; u32 tmp; RTRACE("radeonfb_pci_register BEGIN\n"); /* Enable device in PCI config */ if (pci_enable_device(pdev) != 0) { printk(KERN_ERR "radeonfb: Cannot enable PCI device\n"); return -ENODEV; } info = framebuffer_alloc(sizeof(struct radeonfb_info), &pdev->dev); if (!info) { printk (KERN_ERR "radeonfb: could not allocate memory\n"); return -ENODEV; } rinfo = info->par; rinfo->info = info; rinfo->pdev = pdev; spin_lock_init(&rinfo->reg_lock); init_timer(&rinfo->lvds_timer); rinfo->lvds_timer.function = radeon_lvds_timer_func; rinfo->lvds_timer.data = (unsigned long)rinfo; strcpy(rinfo->name, "ATI Radeon XX "); rinfo->name[11] = ent->device >> 8; rinfo->name[12] = ent->device & 0xFF; rinfo->family = ent->driver_data & CHIP_FAMILY_MASK; rinfo->chipset = pdev->device; rinfo->has_CRTC2 = (ent->driver_data & CHIP_HAS_CRTC2) != 0; rinfo->is_mobility = (ent->driver_data & CHIP_IS_MOBILITY) != 0; rinfo->is_IGP = (ent->driver_data & CHIP_IS_IGP) != 0; /* Set base addrs */ rinfo->fb_base_phys = pci_resource_start (pdev, 0); rinfo->mmio_base_phys = pci_resource_start (pdev, 2); /* request the mem regions */ if (!request_mem_region (rinfo->fb_base_phys, pci_resource_len(pdev, 0), "radeonfb")) { printk (KERN_ERR "radeonfb: cannot reserve FB region\n"); goto free_rinfo; } if (!request_mem_region (rinfo->mmio_base_phys, pci_resource_len(pdev, 2), "radeonfb")) { printk (KERN_ERR "radeonfb: cannot reserve MMIO region\n"); goto release_fb; } /* map the regions */ rinfo->mmio_base = (unsigned long) ioremap (rinfo->mmio_base_phys, RADEON_REGSIZE); if (!rinfo->mmio_base) { printk (KERN_ERR "radeonfb: cannot map MMIO\n"); goto release_mmio; } /* On PPC, the firmware sets up a memory mapping that tends * to cause lockups when enabling the engine. We reconfigure * the card internal memory mappings properly */#ifdef CONFIG_PPC_OF fixup_memory_mappings(rinfo);#else rinfo->fb_local_base = INREG(MC_FB_LOCATION) << 16;#endif /* CONFIG_PPC_OF */ /* framebuffer size */ if ((rinfo->family == CHIP_FAMILY_RS100) || (rinfo->family == CHIP_FAMILY_RS200) || (rinfo->family == CHIP_FAMILY_RS300)) { u32 tom = INREG(NB_TOM); tmp = ((((tom >> 16) - (tom & 0xffff) + 1) << 6) * 1024); radeon_fifo_wait(6); OUTREG(MC_FB_LOCATION, tom); OUTREG(DISPLAY_BASE_ADDR, (tom & 0xffff) << 16); OUTREG(CRTC2_DISPLAY_BASE_ADDR, (tom & 0xffff) << 16); OUTREG(OV0_BASE_ADDR, (tom & 0xffff) << 16); /* This is supposed to fix the crtc2 noise problem. */ OUTREG(GRPH2_BUFFER_CNTL, INREG(GRPH2_BUFFER_CNTL) & ~0x7f0000); if ((rinfo->family == CHIP_FAMILY_RS100) || (rinfo->family == CHIP_FAMILY_RS200)) { /* This is to workaround the asic bug for RMX, some versions of BIOS dosen't have this register initialized correctly. */ OUTREGP(CRTC_MORE_CNTL, CRTC_H_CUTOFF_ACTIVE_EN, ~CRTC_H_CUTOFF_ACTIVE_EN); } } else { tmp = INREG(CONFIG_MEMSIZE); } /* mem size is bits [28:0], mask off the rest */ rinfo->video_ram = tmp & CONFIG_MEMSIZE_MASK; /* ram type */ tmp = INREG(MEM_SDRAM_MODE_REG); switch ((MEM_CFG_TYPE & tmp) >> 30) { case 0: /* SDR SGRAM (2:1) */ strcpy(rinfo->ram_type, "SDR SGRAM"); rinfo->ram.ml = 4; rinfo->ram.mb = 4; rinfo->ram.trcd = 1; rinfo->ram.trp = 2; rinfo->ram.twr = 1; rinfo->ram.cl = 2; rinfo->ram.loop_laten
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?