📄 radeon_base.c
字号:
rinfo->depth = depth; RTRACE("pixclock = %lu\n", (unsigned long)pixClock); RTRACE("freq = %lu\n", (unsigned long)freq); /* We use PPLL_DIV_3 */ newmode->clk_cntl_index = 0x300; /* Calculate PPLL value if necessary */ if (!nopllcalc) radeon_calc_pll_regs(rinfo, newmode, freq); newmode->vclk_ecp_cntl = rinfo->init_state.vclk_ecp_cntl; if ((primary_mon == MT_DFP) || (primary_mon == MT_LCD)) { unsigned int hRatio, vRatio; if (mode->xres > rinfo->panel_info.xres) mode->xres = rinfo->panel_info.xres; if (mode->yres > rinfo->panel_info.yres) mode->yres = rinfo->panel_info.yres; newmode->fp_horz_stretch = (((rinfo->panel_info.xres / 8) - 1) << HORZ_PANEL_SHIFT); newmode->fp_vert_stretch = ((rinfo->panel_info.yres - 1) << VERT_PANEL_SHIFT); if (mode->xres != rinfo->panel_info.xres) { hRatio = round_div(mode->xres * HORZ_STRETCH_RATIO_MAX, rinfo->panel_info.xres); newmode->fp_horz_stretch = (((((unsigned long)hRatio) & HORZ_STRETCH_RATIO_MASK)) | (newmode->fp_horz_stretch & (HORZ_PANEL_SIZE | HORZ_FP_LOOP_STRETCH | HORZ_AUTO_RATIO_INC))); newmode->fp_horz_stretch |= (HORZ_STRETCH_BLEND | HORZ_STRETCH_ENABLE); use_rmx = 1; } newmode->fp_horz_stretch &= ~HORZ_AUTO_RATIO; if (mode->yres != rinfo->panel_info.yres) { vRatio = round_div(mode->yres * VERT_STRETCH_RATIO_MAX, rinfo->panel_info.yres); newmode->fp_vert_stretch = (((((unsigned long)vRatio) & VERT_STRETCH_RATIO_MASK)) | (newmode->fp_vert_stretch & (VERT_PANEL_SIZE | VERT_STRETCH_RESERVED))); newmode->fp_vert_stretch |= (VERT_STRETCH_BLEND | VERT_STRETCH_ENABLE); use_rmx = 1; } newmode->fp_vert_stretch &= ~VERT_AUTO_RATIO_EN; newmode->fp_gen_cntl = (rinfo->init_state.fp_gen_cntl & (u32) ~(FP_SEL_CRTC2 | FP_RMX_HVSYNC_CONTROL_EN | FP_DFP_SYNC_SEL | FP_CRT_SYNC_SEL | FP_CRTC_LOCK_8DOT | FP_USE_SHADOW_EN | FP_CRTC_USE_SHADOW_VEND | FP_CRT_SYNC_ALT)); newmode->fp_gen_cntl |= (FP_CRTC_DONT_SHADOW_VPAR | FP_CRTC_DONT_SHADOW_HEND | FP_PANEL_FORMAT); if (IS_R300_VARIANT(rinfo) || (rinfo->family == CHIP_FAMILY_R200)) { newmode->fp_gen_cntl &= ~R200_FP_SOURCE_SEL_MASK; if (use_rmx) newmode->fp_gen_cntl |= R200_FP_SOURCE_SEL_RMX; else newmode->fp_gen_cntl |= R200_FP_SOURCE_SEL_CRTC1; } else newmode->fp_gen_cntl |= FP_SEL_CRTC1; newmode->lvds_gen_cntl = rinfo->init_state.lvds_gen_cntl; newmode->lvds_pll_cntl = rinfo->init_state.lvds_pll_cntl; newmode->tmds_crc = rinfo->init_state.tmds_crc; newmode->tmds_transmitter_cntl = rinfo->init_state.tmds_transmitter_cntl; if (primary_mon == MT_LCD) { newmode->lvds_gen_cntl |= (LVDS_ON | LVDS_BLON); newmode->fp_gen_cntl &= ~(FP_FPON | FP_TMDS_EN); } else { /* DFP */ newmode->fp_gen_cntl |= (FP_FPON | FP_TMDS_EN); newmode->tmds_transmitter_cntl &= ~(TMDS_PLLRST); /* TMDS_PLL_EN bit is reversed on RV (and mobility) chips */ if (IS_R300_VARIANT(rinfo) || (rinfo->family == CHIP_FAMILY_R200) || !rinfo->has_CRTC2) newmode->tmds_transmitter_cntl &= ~TMDS_PLL_EN; else newmode->tmds_transmitter_cntl |= TMDS_PLL_EN; newmode->crtc_ext_cntl &= ~CRTC_CRT_ON; } newmode->fp_crtc_h_total_disp = (((rinfo->panel_info.hblank / 8) & 0x3ff) | (((mode->xres / 8) - 1) << 16)); newmode->fp_crtc_v_total_disp = (rinfo->panel_info.vblank & 0xffff) | ((mode->yres - 1) << 16); newmode->fp_h_sync_strt_wid = ((rinfo->panel_info.hOver_plus & 0x1fff) | (hsync_wid << 16) | (h_sync_pol << 23)); newmode->fp_v_sync_strt_wid = ((rinfo->panel_info.vOver_plus & 0xfff) | (vsync_wid << 16) | (v_sync_pol << 23)); } /* do it! */ if (!rinfo->asleep) { memcpy(&rinfo->state, newmode, sizeof(*newmode)); radeon_write_mode (rinfo, newmode, 0); /* (re)initialize the engine */ if (!(info->flags & FBINFO_HWACCEL_DISABLED)) radeonfb_engine_init (rinfo); } /* Update fix */ if (!(info->flags & FBINFO_HWACCEL_DISABLED)) info->fix.line_length = rinfo->pitch*64; else info->fix.line_length = mode->xres_virtual * ((mode->bits_per_pixel + 1) / 8); info->fix.visual = rinfo->depth == 8 ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;#ifdef CONFIG_BOOTX_TEXT /* Update debug text engine */ btext_update_display(rinfo->fb_base_phys, mode->xres, mode->yres, rinfo->depth, info->fix.line_length);#endif kfree(newmode); return 0;}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_setcmap = radeonfb_setcmap, .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,};static int __devinit radeon_set_fbinfo (struct radeonfb_info *rinfo){ struct fb_info *info = rinfo->info; 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 = rinfo->fb_base; info->screen_size = rinfo->mapped_vram; /* 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; info->fix.accel = FB_ACCEL_ATI_RADEON; 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; u32 lvds_gen_cntl, tmpPixclksCntl; 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); radeon_engine_idle(); lvds_gen_cntl = INREG(LVDS_GEN_CNTL); if (on && (level > BACKLIGHT_OFF)) { lvds_gen_cntl &= ~LVDS_DISPLAY_DIS; if (!(lvds_gen_cntl & LVDS_BLON) || !(lvds_gen_cntl & LVDS_ON)) { lvds_gen_cntl |= (rinfo->init_state.lvds_gen_cntl & LVDS_DIGON); lvds_gen_cntl |= LVDS_BLON | LVDS_EN; 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_gen_cntl |= (rinfo->init_state.lvds_gen_cntl & LVDS_BL_MOD_EN); rinfo->pending_lvds_gen_cntl = lvds_gen_cntl; mod_timer(&rinfo->lvds_timer, jiffies + msecs_to_jiffies(rinfo->panel_info.pwr_delay)); } else { lvds_gen_cntl &= ~LVDS_BL_MOD_LEVEL_MASK; lvds_gen_cntl |= (conv_table[level] << LVDS_BL_MOD_LEVEL_SHIFT); OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl); } rinfo->init_state.lvds_gen_cntl &= ~LVDS_STATE_MASK; rinfo->init_state.lvds_gen_cntl |= rinfo->pending_lvds_gen_cntl & LVDS_STATE_MASK; } else { /* Asic bug, when turning off LVDS_ON, we have to make sure RADEON_PIXCLK_LVDS_ALWAYS_ON bit is off */ tmpPixclksCntl = INPLL(PIXCLKS_CNTL); if (rinfo->is_mobility || rinfo->is_IGP) OUTPLLP(PIXCLKS_CNTL, 0, ~PIXCLK_LVDS_ALWAYS_ONb); lvds_gen_cntl &= ~(LVDS_BL_MOD_LEVEL_MASK | LVDS_BL_MOD_EN); lvds_gen_cntl |= (conv_table[0] << LVDS_BL_MOD_LEVEL_SHIFT); lvds_gen_cntl |= LVDS_DISPLAY_DIS; OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl); udelay(100); lvds_gen_cntl &= ~(LVDS_ON | LVDS_EN); OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl); lvds_gen_cntl &= ~(LVDS_DIGON); rinfo->pending_lvds_gen_cntl = lvds_gen_cntl; mod_timer(&rinfo->lvds_timer, jiffies + msecs_to_jiffies(rinfo->panel_info.pwr_delay)); 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 = 0; 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); OUTREG(OV0_BASE_ADDR, aper_base);#else OUTREG(DISPLAY_BASE_ADDR, 0); if (rinfo->has_CRTC2) OUTREG(CRTC2_DISPLAY_BASE_ADDR, 0); OUTREG(OV0_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 */static void radeon_identify_vram(struct radeonfb_info *rinfo){ u32 tmp; /* 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; /* * Hack to get around some busted production M6's * reporting no ram */ if (rinfo->video_ram == 0) { switch (rinfo->pdev->device) { case PCI_CHIP_RADEON_LY: case PCI_CHIP_RADEON_LZ: rinfo->video_ram = 8192 * 1024;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -