📄 radeonfb.c
字号:
{ struct fb_var_screeninfo *var = &radeonfb_default_var; /* * Update default var to match the lcd monitor's native resolution */ var->xres = rinfo->panel_xres; var->yres = rinfo->panel_yres; var->xres_virtual = rinfo->panel_xres; var->yres_virtual = rinfo->panel_yres; var->xoffset = var->yoffset = 0; var->bits_per_pixel = 8; var->pixclock = 100000000 / rinfo->clock; var->left_margin = (rinfo->hblank - rinfo->hOver_plus - rinfo->hSync_width); var->right_margin = rinfo->hOver_plus; var->upper_margin = (rinfo->vblank - rinfo->vOver_plus - rinfo->vSync_width); var->lower_margin = rinfo->vOver_plus; var->hsync_len = rinfo->hSync_width; var->vsync_len = rinfo->vSync_width; var->sync = 0; if (rinfo->hAct_high) var->sync |= FB_SYNC_HOR_HIGH_ACT; if (rinfo->vAct_high) var->sync |= FB_SYNC_VERT_HIGH_ACT; var->vmode = 0; if (rinfo->interlaced) var->vmode |= FB_VMODE_INTERLACED; rinfo->use_default_var = 1;}/* Copied from XFree86 4.3 --BenH */static intradeon_get_dfpinfo_BIOS(struct radeonfb_info *rinfo, unsigned char *fpbiosstart){ unsigned char *tmp; unsigned short offset; offset = readw(fpbiosstart + 0x34); if (offset != 0) offset = readw(rinfo->bios_seg + offset + 2); if (offset == 0) { printk("radeonfb: Failed to detect DFP panel info using BIOS\n"); return 0; } tmp = rinfo->bios_seg + offset; /* This is an EDID block */ rinfo->clock = readw(tmp); rinfo->panel_xres = (readb(tmp + 2) + ((readb(tmp + 4) & 0xf0) << 4)); rinfo->hblank = (readb(tmp + 3) + ((readb(tmp + 4) & 0x0f) << 8)); rinfo->panel_yres = (readb(tmp + 5) + ((readb(tmp + 7) & 0xf0) << 4)); rinfo->vblank = (readb(tmp + 6) + ((readb(tmp + 7) & 0x0f) << 8)); rinfo->hOver_plus = (readb(tmp + 8) + ((readb(tmp + 11) & 0xc0) << 2)); rinfo->hSync_width = (readb(tmp + 9) + ((readb(tmp + 11) & 0x30) << 4)); rinfo->vOver_plus = ((readb(tmp + 10) >> 4) + ((readb(tmp + 11) & 0x0c) << 2)); rinfo->vSync_width = ((readb(tmp + 10) & 0x0f) + ((readb(tmp + 11) & 0x03) << 4)); rinfo->interlaced = ((readb(tmp + 17) & 0x80) >> 7); rinfo->synct = ((readb(tmp + 17) & 0x18) >> 3); rinfo->misc = ((readb(tmp + 17) & 0x06) >> 1); rinfo->hAct_high = rinfo->vAct_high = 0; if (rinfo->synct == 3) { if (rinfo->misc & 2) rinfo->hAct_high = 1; if (rinfo->misc & 1) rinfo->vAct_high = 1; } printk("radeonfb: detected DFP panel size from BIOS: %dx%d\n", rinfo->panel_xres, rinfo->panel_yres); rinfo->got_dfpinfo = 1; return 1;}static intradeon_get_lcdinfo_BIOS(struct radeonfb_info *rinfo, unsigned char *fpbiosstart){ unsigned char *tmp, *tmp0; unsigned char stmp[30]; unsigned short offset; int i; offset = readw(fpbiosstart + 0x40); if (offset == 0) { printk("radeonfb: Failed to detect LCD panel info using BIOS\n"); return 0; } tmp = rinfo->bios_seg + offset; for(i=0; i<24; i++) stmp[i] = readb(tmp+i+1); stmp[24] = 0; printk("radeonfb: panel ID string: %s\n", stmp); rinfo->panel_xres = readw(tmp + 25); rinfo->panel_yres = readw(tmp + 27); printk("radeonfb: detected LCD panel size from BIOS: %dx%d\n", rinfo->panel_xres, rinfo->panel_yres); for(i=0; i<20; i++) { tmp0 = rinfo->bios_seg + readw(tmp+64+i*2); if (tmp0 == 0) break; if ((readw(tmp0) == rinfo->panel_xres) && (readw(tmp0+2) == rinfo->panel_yres)) { rinfo->hblank = (readw(tmp0+17) - readw(tmp0+19)) * 8; rinfo->hOver_plus = ((readw(tmp0+21) - readw(tmp0+19) -1) * 8) & 0x7fff; rinfo->hSync_width = readb(tmp0+23) * 8; rinfo->vblank = readw(tmp0+24) - readw(tmp0+26); rinfo->vOver_plus = (readw(tmp0+28) & 0x7ff) - readw(tmp0+26); rinfo->vSync_width = (readw(tmp0+28) & 0xf800) >> 11; rinfo->clock = readw(tmp0+9); /* We don't know that the H/V sync active level should be make the same assumptions as XFree does - High Active */ rinfo->vAct_high=1; rinfo->hAct_high=1; rinfo->got_dfpinfo = 1; return 1; } } return 0;}static int radeon_get_panelinfo_BIOS(struct radeonfb_info *rinfo){ unsigned char *fpbiosstart; if (!rinfo->bios_seg) return 0; if (!(fpbiosstart = rinfo->bios_seg + readw(rinfo->bios_seg + 0x48))) { printk("radeonfb: Failed to detect DFP panel info using BIOS\n"); return 0; } if (rinfo->dviDisp_type == MT_LCD) return radeon_get_lcdinfo_BIOS(rinfo, fpbiosstart); else if (rinfo->dviDisp_type == MT_DFP) return radeon_get_dfpinfo_BIOS(rinfo, fpbiosstart); return 0;}static int radeon_get_dfpinfo (struct radeonfb_info *rinfo){ unsigned int tmp; unsigned short a, b; if (radeon_get_panelinfo_BIOS(rinfo)) radeon_update_default_var(rinfo); if (radeon_dfp_parse_EDID(rinfo)) radeon_update_default_var(rinfo); if (!rinfo->got_dfpinfo) { /* * it seems all else has failed now and we * resort to probing registers for our DFP info */ if (panel_yres) { rinfo->panel_yres = panel_yres; } else { tmp = INREG(FP_VERT_STRETCH); tmp &= 0x00fff000; rinfo->panel_yres = (unsigned short)(tmp >> 0x0c) + 1; } switch (rinfo->panel_yres) { case 480: rinfo->panel_xres = 640; break; case 600: rinfo->panel_xres = 800; break; case 768: rinfo->panel_xres = 1024; break; case 1024: rinfo->panel_xres = 1280; break; case 1050: rinfo->panel_xres = 1400; break; case 1200: rinfo->panel_xres = 1600; break; default: printk("radeonfb: Failed to detect DFP panel size\n"); return 0; } printk("radeonfb: detected DFP panel size from registers: %dx%d\n", rinfo->panel_xres, rinfo->panel_yres); tmp = INREG(FP_CRTC_H_TOTAL_DISP); a = (tmp & FP_CRTC_H_TOTAL_MASK) + 4; b = (tmp & 0x01ff0000) >> FP_CRTC_H_DISP_SHIFT; rinfo->hblank = (a - b + 1) * 8; tmp = INREG(FP_H_SYNC_STRT_WID); rinfo->hOver_plus = (unsigned short) ((tmp & FP_H_SYNC_STRT_CHAR_MASK) >> FP_H_SYNC_STRT_CHAR_SHIFT) - b - 1; rinfo->hOver_plus *= 8; rinfo->hSync_width = (unsigned short) ((tmp & FP_H_SYNC_WID_MASK) >> FP_H_SYNC_WID_SHIFT); rinfo->hSync_width *= 8; tmp = INREG(FP_CRTC_V_TOTAL_DISP); a = (tmp & FP_CRTC_V_TOTAL_MASK) + 1; b = (tmp & FP_CRTC_V_DISP_MASK) >> FP_CRTC_V_DISP_SHIFT; rinfo->vblank = a - b /* + 24 */ ; tmp = INREG(FP_V_SYNC_STRT_WID); rinfo->vOver_plus = (unsigned short) (tmp & FP_V_SYNC_STRT_MASK) - b + 1; rinfo->vSync_width = (unsigned short) ((tmp & FP_V_SYNC_WID_MASK) >> FP_V_SYNC_WID_SHIFT); /* XXX */ /* We should calculate the pixclock as well here... --BenH. */ return 1; } return 1;}static int radeonfb_pci_register (struct pci_dev *pdev, const struct pci_device_id *ent){ struct radeonfb_info *rinfo; struct radeon_chip_info *rci = &radeon_chip_info[ent->driver_data]; u32 tmp; int i, j; RTRACE("radeonfb_pci_register BEGIN\n"); rinfo = kmalloc (sizeof (struct radeonfb_info), GFP_KERNEL); if (!rinfo) { printk ("radeonfb: could not allocate memory\n"); return -ENODEV; } memset (rinfo, 0, sizeof (struct radeonfb_info)); rinfo->pdev = pdev; strncpy(rinfo->name, rci->name, 16); rinfo->arch = rci->arch; /* enable device */ { int err; if ((err = pci_enable_device(pdev))) { printk("radeonfb: cannot enable device\n"); kfree (rinfo); return -ENODEV; } } /* 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 ("radeonfb: cannot reserve FB region\n"); kfree (rinfo); return -ENODEV; } if (!request_mem_region (rinfo->mmio_base_phys, pci_resource_len(pdev, 2), "radeonfb")) { printk ("radeonfb: cannot reserve MMIO region\n"); release_mem_region (rinfo->fb_base_phys, pci_resource_len(pdev, 0)); kfree (rinfo); return -ENODEV; } /* map the regions */ rinfo->mmio_base = (unsigned long) ioremap (rinfo->mmio_base_phys, RADEON_REGSIZE); if (!rinfo->mmio_base) { printk ("radeonfb: cannot map MMIO\n"); release_mem_region (rinfo->mmio_base_phys, pci_resource_len(pdev, 2)); release_mem_region (rinfo->fb_base_phys, pci_resource_len(pdev, 0)); kfree (rinfo); return -ENODEV; } rinfo->chipset = pdev->device; switch (rinfo->arch) { case RADEON_R100: rinfo->hasCRTC2 = 0; break; default: /* all the rest have it */ rinfo->hasCRTC2 = 1; break; } if (mirror) printk("radeonfb: mirroring display to CRT\n"); /* framebuffer size */ 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_latency = 16; rinfo->ram.rloop = 16; break; case 1: /* DDR SGRAM */ strcpy(rinfo->ram_type, "DDR SGRAM"); rinfo->ram.ml = 4; rinfo->ram.mb = 4; rinfo->ram.trcd = 3; rinfo->ram.trp = 3; rinfo->ram.twr = 2; rinfo->ram.cl = 3; rinfo->ram.tr2w = 1; rinfo->ram.loop_latency = 16; rinfo->ram.rloop = 16; break; default: /* 64-bit SDR SGRAM */ strcpy(rinfo->ram_type, "SDR SGRAM 64"); rinfo->ram.ml = 4; rinfo->ram.mb = 8; rinfo->ram.trcd = 3; rinfo->ram.trp = 3; rinfo->ram.twr = 1; rinfo->ram.cl = 3; rinfo->ram.tr2w = 1; rinfo->ram.loop_latency = 17; rinfo->ram.rloop = 17; break; } rinfo->bios_seg = radeon_find_rom(rinfo); radeon_get_pllinfo(rinfo, rinfo->bios_seg); /* * Hack to get around some busted production M6's * reporting no ram */ if (rinfo->video_ram == 0) { switch (pdev->device) { case PCI_DEVICE_ID_ATI_RADEON_LY: case PCI_DEVICE_ID_ATI_RADEON_LZ: rinfo->video_ram = 8192 * 1024; break; default: break; } } RTRACE("radeonfb: probed %s %dk videoram\n", (rinfo->ram_type), (rinfo->video_ram/1024)); RTRACE("BIOS 4 scratch = %x\n", INREG(RADEON_BIOS_4_SCRATCH)); RTRACE("FP_GEN_CNTL: %x, FP2_GEN_CNTL: %x\n", INREG(FP_GEN_CNTL), INREG(FP2_GEN_CNTL)); RTRACE("TMDS_TRANSMITTER_CNTL: %x, TMDS_CNTL: %x, LVDS_GEN_CNTL: %x\n", INREG(TMDS_TRANSMITTER_CNTL), INREG(TMDS_CNTL), INREG(LVDS_GEN_CNTL)); RTRACE("DAC_CNTL: %x, DAC_CNTL2: %x, CRTC_GEN_CNTL: %x\n", INREG(DAC_CNTL), INREG(DAC_CNTL2), INREG(CRTC_GEN_CNTL));#if !defined(__powerpc__) radeon_get_moninfo(rinfo);#else switch (rinfo->arch) { case RADEON_M6: case RADEON_M7: case RADEON_M9: /* If forced to no-LCD, we shut down the backlight */ if (force_nolcd) {#ifdef CONFIG_PMAC_BACKLIGHT radeon_set_backlight_enable(0, BACKLIGHT_OFF, rinfo);#endif } else { rinfo->dviDisp_type = MT_LCD; break; } /* Fall through */ default: radeon_get_moninfo(rinfo); break; }#endif radeon_get_EDID(rinfo); if ((rinfo->dviDisp_type == MT_DFP) || (rinfo->dviDisp_type == MT_LCD) || (rinfo->crtDisp_type == MT_DFP)) { if (!radeon_get_dfpinfo(rinfo)) { iounmap ((void*)rinfo->mmio_base); release_mem_region (rinfo->mmio_base_phys, pci_resource_len(pdev, 2)); release_mem_region (rinfo->fb_base_phys, pci_resource_len(pdev, 0)); kfree (rinfo); return -ENODEV; } } rinfo->fb_base = (unsigned long) ioremap (rinfo->fb_base_phys, rinfo->video_ram); if (!rinfo->fb_base) { printk ("radeonfb: cannot map FB\n"); iounmap ((void*)rinfo->mmio_base); release_mem_region (rinfo->mmio_base_phys, pci_resource_len(pdev, 2)); release_mem_region (rinfo->fb_base_phys, pci_resource_len(pdev, 0)); kfree (rinfo); return -ENODEV; } /* currcon not yet configured, will be set by first switch */ rinfo->currcon = -1; /* 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_ALL_PPC radeon_fixup_apertures(rinfo);#else rinfo->fb_local_base = INREG(MC_FB_LOCATION) << 16;#endif /* CONFIG_ALL_PPC */ /* save current mode regs before we switch into the new one * so we can restore this upon __exit */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -