There is no need for enabling 'Matrox multihead support' if you have
only one Matrox card in the box.
+config FB_RADEON_OLD
+ tristate "ATI Radeon display support (Old driver)"
+ depends on FB && PCI
+ help
+ Choose this option if you want to use an ATI Radeon graphics card as
+ a framebuffer device. There are both PCI and AGP versions. You
+ don't need to choose this to run the Radeon in plain VGA mode.
+ There is a product page at
+ <http://www.ati.com/na/pages/products/pc/radeon32/index.html>.
+
config FB_RADEON
tristate "ATI Radeon display support"
depends on FB && PCI
Choose this option if you want to use an ATI Radeon graphics card as
a framebuffer device. There are both PCI and AGP versions. You
don't need to choose this to run the Radeon in plain VGA mode.
+
+ If you say Y here and want DDC/I2C support you must first say Y to
+ "I2C support" and "I2C bit-banging support" in the character devices
+ section.
+
+ If you say M here then "I2C support" and "I2C bit-banging support"
+ can be build either as modules or built-in.
+
There is a product page at
<http://www.ati.com/na/pages/products/pc/radeon32/index.html>.
+config FB_RADEON_I2C
+ bool "DDC/I2C for ATI Radeon support"
+ depends on FB_RADEON && (I2C_ALGOBIT=FB_RADEON || I2C_ALGOBIT=y)
+ default y
+ help
+ Say Y here if you want DDC/I2C support for your Radeon board.
+
config FB_ATY128
tristate "ATI Rage128 display support"
depends on FB && PCI
obj-$(CONFIG_FB_Q40) += q40fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
obj-$(CONFIG_FB_ATARI) += atafb.o
obj-$(CONFIG_FB_68328) += 68328fb.o
-obj-$(CONFIG_FB_RADEON) += radeonfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
+obj-$(CONFIG_FB_RADEON_OLD) += radeonfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
obj-$(CONFIG_FB_NEOMAGIC) += neofb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
obj-$(CONFIG_FB_IGA) += igafb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
obj-$(CONFIG_FB_CONTROL) += controlfb.o macmodes.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
obj-$(CONFIG_FB_SIS) += sis/ cfbcopyarea.o cfbfillrect.o cfbimgblt.o
obj-$(CONFIG_FB_ATY) += aty/ cfbcopyarea.o cfbfillrect.o cfbimgblt.o
obj-$(CONFIG_FB_ATY128) += aty/ cfbcopyarea.o cfbfillrect.o cfbimgblt.o
+obj-$(CONFIG_FB_RADEON) += aty/ cfbcopyarea.o cfbfillrect.o cfbimgblt.o
obj-$(CONFIG_FB_I810) += i810/ cfbfillrect.o cfbcopyarea.o \
cfbimgblt.o vgastate.o
obj-$(CONFIG_FB_ATY) += atyfb.o
obj-$(CONFIG_FB_ATY128) += aty128fb.o
+obj-$(CONFIG_FB_RADEON) += radeonfb.o
atyfb-y := atyfb_base.o mach64_accel.o
atyfb-$(CONFIG_FB_ATY_GX) += mach64_gx.o
atyfb-$(CONFIG_FB_ATY_CT) += mach64_ct.o mach64_cursor.o
atyfb-objs := $(atyfb-y)
+
+radeonfb-y := radeon_base.o radeon_pm.o radeon_monitor.o radeon_accel.o
+radeonfb-$(CONFIG_FB_RADEON_I2C) += radeon_i2c.o
+radeonfb-objs := $(radeonfb-y)
+
--- /dev/null
+/*
+ * ATI PCI IDs from XFree86, kept here to make sync'ing with
+ * XFree much simpler. Currently, this list is only used by
+ * radeonfb
+ */
+
+#define PCI_CHIP_RS100_4136 0x4136
+#define PCI_CHIP_RS200_4137 0x4137
+#define PCI_CHIP_R300_AD 0x4144
+#define PCI_CHIP_R300_AE 0x4145
+#define PCI_CHIP_R300_AF 0x4146
+#define PCI_CHIP_R300_AG 0x4147
+#define PCI_CHIP_R350_AH 0x4148
+#define PCI_CHIP_R350_AI 0x4149
+#define PCI_CHIP_R350_AJ 0x414A
+#define PCI_CHIP_R350_AK 0x414B
+#define PCI_CHIP_RV350_AP 0x4150
+#define PCI_CHIP_RV350_AQ 0x4151
+#define PCI_CHIP_RV360_AR 0x4152
+#define PCI_CHIP_RV350_AS 0x4153
+#define PCI_CHIP_RV350_AT 0x4154
+#define PCI_CHIP_RV350_AV 0x4156
+#define PCI_CHIP_MACH32 0x4158
+#define PCI_CHIP_RS250_4237 0x4237
+#define PCI_CHIP_R200_BB 0x4242
+#define PCI_CHIP_R200_BC 0x4243
+#define PCI_CHIP_RS100_4336 0x4336
+#define PCI_CHIP_RS200_4337 0x4337
+#define PCI_CHIP_MACH64CT 0x4354
+#define PCI_CHIP_MACH64CX 0x4358
+#define PCI_CHIP_RS250_4437 0x4437
+#define PCI_CHIP_MACH64ET 0x4554
+#define PCI_CHIP_MACH64GB 0x4742
+#define PCI_CHIP_MACH64GD 0x4744
+#define PCI_CHIP_MACH64GI 0x4749
+#define PCI_CHIP_MACH64GL 0x474C
+#define PCI_CHIP_MACH64GM 0x474D
+#define PCI_CHIP_MACH64GN 0x474E
+#define PCI_CHIP_MACH64GO 0x474F
+#define PCI_CHIP_MACH64GP 0x4750
+#define PCI_CHIP_MACH64GQ 0x4751
+#define PCI_CHIP_MACH64GR 0x4752
+#define PCI_CHIP_MACH64GS 0x4753
+#define PCI_CHIP_MACH64GT 0x4754
+#define PCI_CHIP_MACH64GU 0x4755
+#define PCI_CHIP_MACH64GV 0x4756
+#define PCI_CHIP_MACH64GW 0x4757
+#define PCI_CHIP_MACH64GX 0x4758
+#define PCI_CHIP_MACH64GY 0x4759
+#define PCI_CHIP_MACH64GZ 0x475A
+#define PCI_CHIP_RV250_Id 0x4964
+#define PCI_CHIP_RV250_Ie 0x4965
+#define PCI_CHIP_RV250_If 0x4966
+#define PCI_CHIP_RV250_Ig 0x4967
+#define PCI_CHIP_MACH64LB 0x4C42
+#define PCI_CHIP_MACH64LD 0x4C44
+#define PCI_CHIP_RAGE128LE 0x4C45
+#define PCI_CHIP_RAGE128LF 0x4C46
+#define PCI_CHIP_MACH64LG 0x4C47
+#define PCI_CHIP_MACH64LI 0x4C49
+#define PCI_CHIP_MACH64LM 0x4C4D
+#define PCI_CHIP_MACH64LN 0x4C4E
+#define PCI_CHIP_MACH64LP 0x4C50
+#define PCI_CHIP_MACH64LQ 0x4C51
+#define PCI_CHIP_MACH64LR 0x4C52
+#define PCI_CHIP_MACH64LS 0x4C53
+#define PCI_CHIP_RADEON_LW 0x4C57
+#define PCI_CHIP_RADEON_LX 0x4C58
+#define PCI_CHIP_RADEON_LY 0x4C59
+#define PCI_CHIP_RADEON_LZ 0x4C5A
+#define PCI_CHIP_RV250_Ld 0x4C64
+#define PCI_CHIP_RV250_Le 0x4C65
+#define PCI_CHIP_RV250_Lf 0x4C66
+#define PCI_CHIP_RV250_Lg 0x4C67
+#define PCI_CHIP_RAGE128MF 0x4D46
+#define PCI_CHIP_RAGE128ML 0x4D4C
+#define PCI_CHIP_R300_ND 0x4E44
+#define PCI_CHIP_R300_NE 0x4E45
+#define PCI_CHIP_R300_NF 0x4E46
+#define PCI_CHIP_R300_NG 0x4E47
+#define PCI_CHIP_R350_NH 0x4E48
+#define PCI_CHIP_R350_NI 0x4E49
+#define PCI_CHIP_R360_NJ 0x4E4A
+#define PCI_CHIP_R350_NK 0x4E4B
+#define PCI_CHIP_RV350_NP 0x4E50
+#define PCI_CHIP_RV350_NQ 0x4E51
+#define PCI_CHIP_RV350_NR 0x4E52
+#define PCI_CHIP_RV350_NS 0x4E53
+#define PCI_CHIP_RV350_NT 0x4E54
+#define PCI_CHIP_RV350_NV 0x4E56
+#define PCI_CHIP_RAGE128PA 0x5041
+#define PCI_CHIP_RAGE128PB 0x5042
+#define PCI_CHIP_RAGE128PC 0x5043
+#define PCI_CHIP_RAGE128PD 0x5044
+#define PCI_CHIP_RAGE128PE 0x5045
+#define PCI_CHIP_RAGE128PF 0x5046
+#define PCI_CHIP_RAGE128PG 0x5047
+#define PCI_CHIP_RAGE128PH 0x5048
+#define PCI_CHIP_RAGE128PI 0x5049
+#define PCI_CHIP_RAGE128PJ 0x504A
+#define PCI_CHIP_RAGE128PK 0x504B
+#define PCI_CHIP_RAGE128PL 0x504C
+#define PCI_CHIP_RAGE128PM 0x504D
+#define PCI_CHIP_RAGE128PN 0x504E
+#define PCI_CHIP_RAGE128PO 0x504F
+#define PCI_CHIP_RAGE128PP 0x5050
+#define PCI_CHIP_RAGE128PQ 0x5051
+#define PCI_CHIP_RAGE128PR 0x5052
+#define PCI_CHIP_RAGE128PS 0x5053
+#define PCI_CHIP_RAGE128PT 0x5054
+#define PCI_CHIP_RAGE128PU 0x5055
+#define PCI_CHIP_RAGE128PV 0x5056
+#define PCI_CHIP_RAGE128PW 0x5057
+#define PCI_CHIP_RAGE128PX 0x5058
+#define PCI_CHIP_RADEON_QD 0x5144
+#define PCI_CHIP_RADEON_QE 0x5145
+#define PCI_CHIP_RADEON_QF 0x5146
+#define PCI_CHIP_RADEON_QG 0x5147
+#define PCI_CHIP_R200_QH 0x5148
+#define PCI_CHIP_R200_QI 0x5149
+#define PCI_CHIP_R200_QJ 0x514A
+#define PCI_CHIP_R200_QK 0x514B
+#define PCI_CHIP_R200_QL 0x514C
+#define PCI_CHIP_R200_QM 0x514D
+#define PCI_CHIP_R200_QN 0x514E
+#define PCI_CHIP_R200_QO 0x514F
+#define PCI_CHIP_RV200_QW 0x5157
+#define PCI_CHIP_RV200_QX 0x5158
+#define PCI_CHIP_RV100_QY 0x5159
+#define PCI_CHIP_RV100_QZ 0x515A
+#define PCI_CHIP_RAGE128RE 0x5245
+#define PCI_CHIP_RAGE128RF 0x5246
+#define PCI_CHIP_RAGE128RG 0x5247
+#define PCI_CHIP_RAGE128RK 0x524B
+#define PCI_CHIP_RAGE128RL 0x524C
+#define PCI_CHIP_RAGE128SE 0x5345
+#define PCI_CHIP_RAGE128SF 0x5346
+#define PCI_CHIP_RAGE128SG 0x5347
+#define PCI_CHIP_RAGE128SH 0x5348
+#define PCI_CHIP_RAGE128SK 0x534B
+#define PCI_CHIP_RAGE128SL 0x534C
+#define PCI_CHIP_RAGE128SM 0x534D
+#define PCI_CHIP_RAGE128SN 0x534E
+#define PCI_CHIP_RAGE128TF 0x5446
+#define PCI_CHIP_RAGE128TL 0x544C
+#define PCI_CHIP_RAGE128TR 0x5452
+#define PCI_CHIP_RAGE128TS 0x5453
+#define PCI_CHIP_RAGE128TT 0x5454
+#define PCI_CHIP_RAGE128TU 0x5455
+#define PCI_CHIP_MACH64VT 0x5654
+#define PCI_CHIP_MACH64VU 0x5655
+#define PCI_CHIP_MACH64VV 0x5656
+#define PCI_CHIP_RS300_5834 0x5834
+#define PCI_CHIP_RS300_5835 0x5835
+#define PCI_CHIP_RS300_5836 0x5836
+#define PCI_CHIP_RS300_5837 0x5837
+#define PCI_CHIP_RV280_5960 0x5960
+#define PCI_CHIP_RV280_5961 0x5961
+#define PCI_CHIP_RV280_5962 0x5962
+#define PCI_CHIP_RV280_5963 0x5963
+#define PCI_CHIP_RV280_5964 0x5964
+#define PCI_CHIP_RV280_5968 0x5968
+#define PCI_CHIP_RV280_5969 0x5969
+#define PCI_CHIP_RV280_596A 0x596A
+#define PCI_CHIP_RV280_596B 0x596B
+#define PCI_CHIP_RV280_5C61 0x5C61
+#define PCI_CHIP_RV280_5C63 0x5C63
--- /dev/null
+#include "radeonfb.h"
+
+/* the accelerated functions here are patterned after the
+ * "ACCEL_MMIO" ifdef branches in XFree86
+ * --dte
+ */
+static void radeonfb_prim_fillrect(struct radeonfb_info *rinfo,
+ const struct fb_fillrect *region)
+{
+ radeon_fifo_wait(4);
+
+ OUTREG(DP_GUI_MASTER_CNTL,
+ rinfo->dp_gui_master_cntl /* contains, like GMC_DST_32BPP */
+ | GMC_BRUSH_SOLID_COLOR
+ | ROP3_P);
+ OUTREG(DP_BRUSH_FRGD_CLR, region->color);
+ OUTREG(DP_WRITE_MSK, 0xffffffff);
+ OUTREG(DP_CNTL, (DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM));
+
+ radeon_fifo_wait(2);
+ OUTREG(DST_Y_X, (region->dy << 16) | region->dx);
+ OUTREG(DST_WIDTH_HEIGHT, (region->width << 16) | region->height);
+}
+
+void radeonfb_fillrect(struct fb_info *info, const struct fb_fillrect *region)
+{
+ struct radeonfb_info *rinfo = info->par;
+ struct fb_fillrect modded;
+ int vxres, vyres;
+
+ if (rinfo->asleep)
+ return;
+ if (radeon_accel_disabled()) {
+ cfb_fillrect(info, region);
+ return;
+ }
+
+ vxres = info->var.xres;
+ vyres = info->var.yres;
+
+ memcpy(&modded, region, sizeof(struct fb_fillrect));
+
+ if(!modded.width || !modded.height ||
+ modded.dx >= vxres || modded.dy >= vyres)
+ return;
+
+ if(modded.dx + modded.width > vxres) modded.width = vxres - modded.dx;
+ if(modded.dy + modded.height > vyres) modded.height = vyres - modded.dy;
+
+ radeonfb_prim_fillrect(rinfo, &modded);
+}
+
+static void radeonfb_prim_copyarea(struct radeonfb_info *rinfo,
+ const struct fb_copyarea *area)
+{
+ radeon_fifo_wait(3);
+ OUTREG(DP_GUI_MASTER_CNTL,
+ rinfo->dp_gui_master_cntl /* i.e. GMC_DST_32BPP */
+ | GMC_SRC_DSTCOLOR
+ | ROP3_S
+ | DP_SRC_RECT );
+ OUTREG(DP_WRITE_MSK, 0xffffffff);
+ OUTREG(DP_CNTL, (DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM));
+
+ radeon_fifo_wait(3);
+ OUTREG(SRC_Y_X, (area->sy << 16) | area->sx);
+ OUTREG(DST_Y_X, (area->dy << 16) | area->dx);
+ OUTREG(DST_HEIGHT_WIDTH, (area->height << 16) | area->width);
+}
+
+
+void radeonfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
+{
+ struct radeonfb_info *rinfo = info->par;
+ struct fb_copyarea modded;
+ u32 vxres, vyres;
+ modded.sx = area->sx;
+ modded.sy = area->sy;
+ modded.dx = area->dx;
+ modded.dy = area->dy;
+ modded.width = area->width;
+ modded.height = area->height;
+
+ if (rinfo->asleep)
+ return;
+ if (radeon_accel_disabled()) {
+ cfb_copyarea(info, area);
+ return;
+ }
+
+ vxres = info->var.xres;
+ vyres = info->var.yres;
+
+ if(!modded.width || !modded.height ||
+ modded.sx >= vxres || modded.sy >= vyres ||
+ modded.dx >= vxres || modded.dy >= vyres)
+ return;
+
+ if(modded.sx + modded.width > vxres) modded.width = vxres - modded.sx;
+ if(modded.dx + modded.width > vxres) modded.width = vxres - modded.dx;
+ if(modded.sy + modded.height > vyres) modded.height = vyres - modded.sy;
+ if(modded.dy + modded.height > vyres) modded.height = vyres - modded.dy;
+
+ radeonfb_prim_copyarea(rinfo, &modded);
+}
+
+void radeonfb_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+ struct radeonfb_info *rinfo = info->par;
+
+ if (rinfo->asleep)
+ return;
+ radeon_engine_idle();
+
+ cfb_imageblit(info, image);
+}
+
+int radeonfb_sync(struct fb_info *info)
+{
+ struct radeonfb_info *rinfo = info->par;
+
+ if (rinfo->asleep)
+ return 0;
+ radeon_engine_idle();
+
+ return 0;
+}
+
+void radeon_engine_reset(struct radeonfb_info *rinfo)
+{
+ u32 clock_cntl_index, mclk_cntl, rbbm_soft_reset;
+ u32 host_path_cntl;
+
+ radeon_engine_flush (rinfo);
+
+ /* Some ASICs have bugs with dynamic-on feature, which are
+ * ASIC-version dependent, so we force all blocks on for now
+ * -- from XFree86
+ * We don't do that on macs, things just work here with dynamic
+ * clocking... --BenH
+ */
+#ifdef CONFIG_ALL_PPC
+ if (_machine != _MACH_Pmac && rinfo->hasCRTC2)
+#else
+ if (rinfo->has_CRTC2)
+#endif
+ {
+ u32 tmp;
+
+ tmp = INPLL(SCLK_CNTL);
+ OUTPLL(SCLK_CNTL, ((tmp & ~DYN_STOP_LAT_MASK) |
+ CP_MAX_DYN_STOP_LAT |
+ SCLK_FORCEON_MASK));
+
+ if (rinfo->family == CHIP_FAMILY_RV200)
+ {
+ tmp = INPLL(SCLK_MORE_CNTL);
+ OUTPLL(SCLK_MORE_CNTL, tmp | SCLK_MORE_FORCEON);
+ }
+ }
+
+ clock_cntl_index = INREG(CLOCK_CNTL_INDEX);
+ mclk_cntl = INPLL(MCLK_CNTL);
+
+ OUTPLL(MCLK_CNTL, (mclk_cntl |
+ FORCEON_MCLKA |
+ FORCEON_MCLKB |
+ FORCEON_YCLKA |
+ FORCEON_YCLKB |
+ FORCEON_MC |
+ FORCEON_AIC));
+
+ host_path_cntl = INREG(HOST_PATH_CNTL);
+ rbbm_soft_reset = INREG(RBBM_SOFT_RESET);
+
+ if (rinfo->family == CHIP_FAMILY_R300 ||
+ rinfo->family == CHIP_FAMILY_R350 ||
+ rinfo->family == CHIP_FAMILY_RV350) {
+ u32 tmp;
+
+ OUTREG(RBBM_SOFT_RESET, (rbbm_soft_reset |
+ SOFT_RESET_CP |
+ SOFT_RESET_HI |
+ SOFT_RESET_E2));
+ INREG(RBBM_SOFT_RESET);
+ OUTREG(RBBM_SOFT_RESET, 0);
+ tmp = INREG(RB2D_DSTCACHE_MODE);
+ OUTREG(RB2D_DSTCACHE_MODE, tmp | (1 << 17)); /* FIXME */
+ } else {
+ OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset |
+ SOFT_RESET_CP |
+ SOFT_RESET_HI |
+ SOFT_RESET_SE |
+ SOFT_RESET_RE |
+ SOFT_RESET_PP |
+ SOFT_RESET_E2 |
+ SOFT_RESET_RB);
+ INREG(RBBM_SOFT_RESET);
+ OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset & (u32)
+ ~(SOFT_RESET_CP |
+ SOFT_RESET_HI |
+ SOFT_RESET_SE |
+ SOFT_RESET_RE |
+ SOFT_RESET_PP |
+ SOFT_RESET_E2 |
+ SOFT_RESET_RB));
+ INREG(RBBM_SOFT_RESET);
+ }
+
+ OUTREG(HOST_PATH_CNTL, host_path_cntl | HDP_SOFT_RESET);
+ INREG(HOST_PATH_CNTL);
+ OUTREG(HOST_PATH_CNTL, host_path_cntl);
+
+ if (rinfo->family != CHIP_FAMILY_R300 ||
+ rinfo->family != CHIP_FAMILY_R350 ||
+ rinfo->family != CHIP_FAMILY_RV350)
+ OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset);
+
+ OUTREG(CLOCK_CNTL_INDEX, clock_cntl_index);
+ OUTPLL(MCLK_CNTL, mclk_cntl);
+ if (rinfo->R300_cg_workaround)
+ R300_cg_workardound(rinfo);
+}
+
+void radeon_engine_init (struct radeonfb_info *rinfo)
+{
+ unsigned long temp;
+
+ /* disable 3D engine */
+ OUTREG(RB3D_CNTL, 0);
+
+ radeon_engine_reset(rinfo);
+
+ radeon_fifo_wait (1);
+ if ((rinfo->family != CHIP_FAMILY_R300) &&
+ (rinfo->family != CHIP_FAMILY_R350) &&
+ (rinfo->family != CHIP_FAMILY_RV350))
+ OUTREG(RB2D_DSTCACHE_MODE, 0);
+
+ radeon_fifo_wait (3);
+ /* We re-read MC_FB_LOCATION from card as it can have been
+ * modified by XFree drivers (ouch !)
+ */
+ rinfo->fb_local_base = INREG(MC_FB_LOCATION) << 16;
+
+ OUTREG(DEFAULT_PITCH_OFFSET, (rinfo->pitch << 0x16) |
+ (rinfo->fb_local_base >> 10));
+ OUTREG(DST_PITCH_OFFSET, (rinfo->pitch << 0x16) | (rinfo->fb_local_base >> 10));
+ OUTREG(SRC_PITCH_OFFSET, (rinfo->pitch << 0x16) | (rinfo->fb_local_base >> 10));
+
+ radeon_fifo_wait (1);
+#if defined(__BIG_ENDIAN)
+ OUTREGP(DP_DATATYPE, HOST_BIG_ENDIAN_EN, ~HOST_BIG_ENDIAN_EN);
+#else
+ OUTREGP(DP_DATATYPE, 0, ~HOST_BIG_ENDIAN_EN);
+#endif
+ radeon_fifo_wait (2);
+ OUTREG(DEFAULT_SC_TOP_LEFT, 0);
+ OUTREG(DEFAULT_SC_BOTTOM_RIGHT, (DEFAULT_SC_RIGHT_MAX |
+ DEFAULT_SC_BOTTOM_MAX));
+
+ temp = radeon_get_dstbpp(rinfo->depth);
+ rinfo->dp_gui_master_cntl = ((temp << 8) | GMC_CLR_CMP_CNTL_DIS);
+
+ radeon_fifo_wait (1);
+ OUTREG(DP_GUI_MASTER_CNTL, (rinfo->dp_gui_master_cntl |
+ GMC_BRUSH_SOLID_COLOR |
+ GMC_SRC_DATATYPE_COLOR));
+
+ radeon_fifo_wait (7);
+
+ /* clear line drawing regs */
+ OUTREG(DST_LINE_START, 0);
+ OUTREG(DST_LINE_END, 0);
+
+ /* set brush color regs */
+ OUTREG(DP_BRUSH_FRGD_CLR, 0xffffffff);
+ OUTREG(DP_BRUSH_BKGD_CLR, 0x00000000);
+
+ /* set source color regs */
+ OUTREG(DP_SRC_FRGD_CLR, 0xffffffff);
+ OUTREG(DP_SRC_BKGD_CLR, 0x00000000);
+
+ /* default write mask */
+ OUTREG(DP_WRITE_MSK, 0xffffffff);
+
+ radeon_engine_idle ();
+}
--- /dev/null
+/*
+ * drivers/video/radeonfb.c
+ * framebuffer driver for ATI Radeon chipset video boards
+ *
+ * Copyright 2003 Ben. Herrenschmidt <benh@kernel.crashing.org>
+ * Copyright 2000 Ani Joshi <ajoshi@kernel.crashing.org>
+ *
+ * i2c bits from Luca Tettamanti <kronos@kronoz.cjb.net>
+ *
+ * Special thanks to ATI DevRel team for their hardware donations.
+ *
+ * ...Insert GPL boilerplate here...
+ *
+ * Significant portions of this driver apdated from XFree86 Radeon
+ * driver which has the following copyright notice:
+ *
+ * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and
+ * VA Linux Systems Inc., Fremont, California.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation on the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT. IN NO EVENT SHALL ATI, VA LINUX SYSTEMS AND/OR
+ * THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * XFree86 driver authors:
+ *
+ * Kevin E. Martin <martin@xfree86.org>
+ * Rickard E. Faith <faith@valinux.com>
+ * Alan Hourihane <alanh@fairlite.demon.co.uk>
+ *
+ */
+
+
+#define RADEON_VERSION "0.2.0"
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/vmalloc.h>
+#include <linux/device.h>
+#include <linux/i2c.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+
+#ifdef CONFIG_PPC_OF
+
+#include <asm/prom.h>
+#include <asm/pci-bridge.h>
+#include "../macmodes.h"
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+#include <asm/backlight.h>
+#endif
+
+#ifdef CONFIG_BOOTX_TEXT
+#include <asm/btext.h>
+#endif
+
+#endif /* CONFIG_PPC_OF */
+
+#ifdef CONFIG_MTRR
+#include <asm/mtrr.h>
+#endif
+
+#include <video/radeon.h>
+#include <linux/radeonfb.h>
+
+#include "../edid.h" // MOVE THAT TO include/video
+#include "ati_ids.h"
+#include "radeonfb.h"
+
+
+#define CHIP_DEF(id, family, flags) \
+ { PCI_VENDOR_ID_ATI, id, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (flags) | (CHIP_FAMILY_##family) }
+
+static struct pci_device_id radeonfb_pci_table[] = {
+ /* Mobility M6 */
+ CHIP_DEF(PCI_CHIP_RADEON_LY, RV100, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+ CHIP_DEF(PCI_CHIP_RADEON_LZ, RV100, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+ /* Radeon VE/7000 */
+ CHIP_DEF(PCI_CHIP_RV100_QY, RV100, CHIP_HAS_CRTC2),
+ CHIP_DEF(PCI_CHIP_RV100_QZ, RV100, CHIP_HAS_CRTC2),
+ /* Radeon IGP320M (U1) */
+ CHIP_DEF(PCI_CHIP_RS100_4336, RS100, CHIP_HAS_CRTC2 | CHIP_IS_IGP | CHIP_IS_MOBILITY),
+ /* Radeon IGP320 (A3) */
+ CHIP_DEF(PCI_CHIP_RS100_4136, RS100, CHIP_HAS_CRTC2 | CHIP_IS_IGP),
+ /* IGP330M/340M/350M (U2) */
+ CHIP_DEF(PCI_CHIP_RS200_4337, RS200, CHIP_HAS_CRTC2 | CHIP_IS_IGP | CHIP_IS_MOBILITY),
+ /* IGP330/340/350 (A4) */
+ CHIP_DEF(PCI_CHIP_RS200_4137, RS200, CHIP_HAS_CRTC2 | CHIP_IS_IGP),
+ /* Mobility 7000 IGP */
+ CHIP_DEF(PCI_CHIP_RS250_4437, RS200, CHIP_HAS_CRTC2 | CHIP_IS_IGP | CHIP_IS_MOBILITY),
+ /* 7000 IGP (A4+) */
+ CHIP_DEF(PCI_CHIP_RS250_4237, RS200, CHIP_HAS_CRTC2 | CHIP_IS_IGP),
+ /* 8500 AIW */
+ CHIP_DEF(PCI_CHIP_R200_BB, R200, CHIP_HAS_CRTC2),
+ CHIP_DEF(PCI_CHIP_R200_BC, R200, CHIP_HAS_CRTC2),
+ /* 8700/8800 */
+ CHIP_DEF(PCI_CHIP_R200_QH, R200, CHIP_HAS_CRTC2),
+ /* 8500 */
+ CHIP_DEF(PCI_CHIP_R200_QL, R200, CHIP_HAS_CRTC2),
+ /* 9100 */
+ CHIP_DEF(PCI_CHIP_R200_QM, R200, CHIP_HAS_CRTC2),
+ /* Mobility M7 */
+ CHIP_DEF(PCI_CHIP_RADEON_LW, RV200, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+ CHIP_DEF(PCI_CHIP_RADEON_LW, RV200, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+ /* 7500 */
+ CHIP_DEF(PCI_CHIP_RV200_QW, RV200, CHIP_HAS_CRTC2),
+ CHIP_DEF(PCI_CHIP_RV200_QX, RV200, CHIP_HAS_CRTC2),
+ /* Mobility M9 */
+ CHIP_DEF(PCI_CHIP_RV250_Ld, RV250, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+ CHIP_DEF(PCI_CHIP_RV250_Le, RV250, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+ CHIP_DEF(PCI_CHIP_RV250_Lf, RV250, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+ CHIP_DEF(PCI_CHIP_RV250_Lg, RV250, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+ /* 9000/Pro */
+ CHIP_DEF(PCI_CHIP_RV250_If, RV250, CHIP_HAS_CRTC2),
+ CHIP_DEF(PCI_CHIP_RV250_Ig, RV250, CHIP_HAS_CRTC2),
+ /* Mobility 9100 IGP (U3) */
+ CHIP_DEF(PCI_CHIP_RS300_5835, RS300, CHIP_HAS_CRTC2 | CHIP_IS_IGP | CHIP_IS_MOBILITY),
+ /* 9100 IGP (A5) */
+ CHIP_DEF(PCI_CHIP_RS300_5834, RS300, CHIP_HAS_CRTC2 | CHIP_IS_IGP),
+ /* Mobility 9200 (M9+) */
+ CHIP_DEF(PCI_CHIP_RV280_5C61, RV280, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+ CHIP_DEF(PCI_CHIP_RV280_5C63, RV280, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+ /* 9200 */
+ CHIP_DEF(PCI_CHIP_RV280_5960, RV280, CHIP_HAS_CRTC2),
+ CHIP_DEF(PCI_CHIP_RV280_5961, RV280, CHIP_HAS_CRTC2),
+ CHIP_DEF(PCI_CHIP_RV280_5962, RV280, CHIP_HAS_CRTC2),
+ CHIP_DEF(PCI_CHIP_RV280_5964, RV280, CHIP_HAS_CRTC2),
+ /* 9500 */
+ CHIP_DEF(PCI_CHIP_R300_AD, R300, CHIP_HAS_CRTC2),
+ CHIP_DEF(PCI_CHIP_R300_AE, R300, CHIP_HAS_CRTC2),
+ /* 9600TX / FireGL Z1 */
+ CHIP_DEF(PCI_CHIP_R300_AF, R300, CHIP_HAS_CRTC2),
+ CHIP_DEF(PCI_CHIP_R300_AG, R300, CHIP_HAS_CRTC2),
+ /* 9700/9500/Pro/FireGL X1 */
+ CHIP_DEF(PCI_CHIP_R300_ND, R300, CHIP_HAS_CRTC2),
+ CHIP_DEF(PCI_CHIP_R300_NE, R300, CHIP_HAS_CRTC2),
+ CHIP_DEF(PCI_CHIP_R300_NF, R300, CHIP_HAS_CRTC2),
+ CHIP_DEF(PCI_CHIP_R300_NG, R300, CHIP_HAS_CRTC2),
+ /* Mobility M10/M11 */
+ CHIP_DEF(PCI_CHIP_RV350_NP, RV350, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+ CHIP_DEF(PCI_CHIP_RV350_NQ, RV350, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+ CHIP_DEF(PCI_CHIP_RV350_NR, RV350, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+ CHIP_DEF(PCI_CHIP_RV350_NS, RV350, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+ CHIP_DEF(PCI_CHIP_RV350_NT, RV350, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+ CHIP_DEF(PCI_CHIP_RV350_NV, RV350, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+ /* 9600/FireGL T2 */
+ CHIP_DEF(PCI_CHIP_RV350_AP, RV350, CHIP_HAS_CRTC2),
+ CHIP_DEF(PCI_CHIP_RV350_AQ, RV350, CHIP_HAS_CRTC2),
+ CHIP_DEF(PCI_CHIP_RV360_AR, RV350, CHIP_HAS_CRTC2),
+ CHIP_DEF(PCI_CHIP_RV350_AS, RV350, CHIP_HAS_CRTC2),
+ CHIP_DEF(PCI_CHIP_RV350_AT, RV350, CHIP_HAS_CRTC2),
+ CHIP_DEF(PCI_CHIP_RV350_AV, RV350, CHIP_HAS_CRTC2),
+ /* 9800/Pro/FileGL X2 */
+ CHIP_DEF(PCI_CHIP_R350_AH, R350, CHIP_HAS_CRTC2),
+ CHIP_DEF(PCI_CHIP_R350_AI, R350, CHIP_HAS_CRTC2),
+ CHIP_DEF(PCI_CHIP_R350_AJ, R350, CHIP_HAS_CRTC2),
+ CHIP_DEF(PCI_CHIP_R350_AK, R350, CHIP_HAS_CRTC2),
+ CHIP_DEF(PCI_CHIP_R350_NH, R350, CHIP_HAS_CRTC2),
+ CHIP_DEF(PCI_CHIP_R350_NI, R350, CHIP_HAS_CRTC2),
+ CHIP_DEF(PCI_CHIP_R360_NJ, R350, CHIP_HAS_CRTC2),
+ CHIP_DEF(PCI_CHIP_R350_NK, R350, CHIP_HAS_CRTC2),
+ /* Original Radeon/7200 */
+ CHIP_DEF(PCI_CHIP_RADEON_QD, RADEON, 0),
+ CHIP_DEF(PCI_CHIP_RADEON_QE, RADEON, 0),
+ CHIP_DEF(PCI_CHIP_RADEON_QF, RADEON, 0),
+ CHIP_DEF(PCI_CHIP_RADEON_QG, RADEON, 0),
+ { 0, }
+};
+MODULE_DEVICE_TABLE(pci, radeonfb_pci_table);
+
+
+typedef struct {
+ u16 reg;
+ u32 val;
+} reg_val;
+
+
+/* these common regs are cleared before mode setting so they do not
+ * interfere with anything
+ */
+reg_val common_regs[] = {
+ { OVR_CLR, 0 },
+ { OVR_WID_LEFT_RIGHT, 0 },
+ { OVR_WID_TOP_BOTTOM, 0 },
+ { OV0_SCALE_CNTL, 0 },
+ { SUBPIC_CNTL, 0 },
+ { VIPH_CONTROL, 0 },
+ { I2C_CNTL_1, 0 },
+ { GEN_INT_CNTL, 0 },
+ { CAP0_TRIG_CNTL, 0 },
+};
+
+reg_val common_regs_m6[] = {
+ { OVR_CLR, 0 },
+ { OVR_WID_LEFT_RIGHT, 0 },
+ { OVR_WID_TOP_BOTTOM, 0 },
+ { OV0_SCALE_CNTL, 0 },
+ { SUBPIC_CNTL, 0 },
+ { GEN_INT_CNTL, 0 },
+ { CAP0_TRIG_CNTL, 0 }
+};
+
+/*
+ * globals
+ */
+
+static char *mode_option;
+static char *monitor_layout;
+static int noaccel = 0;
+static int nomodeset = 0;
+static int ignore_edid = 0;
+static int mirror = 0;
+static int panel_yres = 0;
+static int force_dfp = 0;
+static int force_measure_pll = 0;
+#ifdef CONFIG_MTRR
+static int nomtrr = 0;
+#endif
+
+int radeonfb_noaccel = 0;
+
+/*
+ * prototypes
+ */
+
+
+#ifdef CONFIG_PPC_OF
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+static int radeon_set_backlight_enable(int on, int level, void *data);
+static int radeon_set_backlight_level(int level, void *data);
+static struct backlight_controller radeon_backlight_controller = {
+ radeon_set_backlight_enable,
+ radeon_set_backlight_level
+};
+#endif /* CONFIG_PMAC_BACKLIGHT */
+
+#endif /* CONFIG_PPC_OF */
+
+static void __devexit radeon_unmap_ROM(struct radeonfb_info *rinfo, struct pci_dev *dev)
+{
+ // leave it disabled and unassigned
+ struct resource *r = &dev->resource[PCI_ROM_RESOURCE];
+
+ if (!rinfo->bios_seg)
+ return;
+ iounmap(rinfo->bios_seg);
+
+ /* Release the ROM resource if we used it in the first place */
+ if (r->parent && r->flags & PCI_ROM_ADDRESS_ENABLE) {
+ release_resource(r);
+ r->flags &= ~PCI_ROM_ADDRESS_ENABLE;
+ r->end -= r->start;
+ r->start = 0;
+ }
+ /* This will disable and set address to unassigned */
+ pci_write_config_dword(dev, dev->rom_base_reg, 0);
+}
+
+static int __devinit radeon_map_ROM(struct radeonfb_info *rinfo, struct pci_dev *dev)
+{
+ void *rom;
+ struct resource *r;
+ u16 dptr;
+ u8 rom_type;
+
+ /* If this is a primary card, there is a shadow copy of the
+ * ROM somewhere in the first meg. We will just ignore the copy
+ * and use the ROM directly.
+ */
+
+ /* Fix from ATI for problem with Radeon hardware not leaving ROM enabled */
+ unsigned int temp;
+ temp = INREG(MPP_TB_CONFIG);
+ temp &= 0x00ffffffu;
+ temp |= 0x04 << 24;
+ OUTREG(MPP_TB_CONFIG, temp);
+ temp = INREG(MPP_TB_CONFIG);
+
+ /* no need to search for the ROM, just ask the card where it is. */
+ r = &dev->resource[PCI_ROM_RESOURCE];
+
+ /* assign the ROM an address if it doesn't have one */
+ if (r->parent == NULL)
+ pci_assign_resource(dev, PCI_ROM_RESOURCE);
+
+ /* enable if needed */
+ if (!(r->flags & PCI_ROM_ADDRESS_ENABLE)) {
+ pci_write_config_dword(dev, dev->rom_base_reg,
+ r->start | PCI_ROM_ADDRESS_ENABLE);
+ r->flags |= PCI_ROM_ADDRESS_ENABLE;
+ }
+
+ rom = ioremap(r->start, r->end - r->start + 1);
+ if (!rom) {
+ printk(KERN_ERR "radeonfb: ROM failed to map\n");
+ return -ENOMEM;
+ }
+
+ rinfo->bios_seg = rom;
+
+ /* Very simple test to make sure it appeared */
+ if (BIOS_IN16(0) != 0xaa55) {
+ printk(KERN_ERR "radeonfb: Invalid ROM signature %x should be 0xaa55\n",
+ BIOS_IN16(0));
+ goto failed;
+ }
+ /* Look for the PCI data to check the ROM type */
+ dptr = BIOS_IN16(0x18);
+
+ /* Check the PCI data signature. If it's wrong, we still assume a normal x86 ROM
+ * for now, until I've verified this works everywhere. The goal here is more
+ * to phase out Open Firmware images.
+ *
+ * Currently, we only look at the first PCI data, we could iteratre and deal with
+ * them all, and we should use fb_bios_start relative to start of image and not
+ * relative start of ROM, but so far, I never found a dual-image ATI card
+ *
+ * typedef struct {
+ * u32 signature; + 0x00
+ * u16 vendor; + 0x04
+ * u16 device; + 0x06
+ * u16 reserved_1; + 0x08
+ * u16 dlen; + 0x0a
+ * u8 drevision; + 0x0c
+ * u8 class_hi; + 0x0d
+ * u16 class_lo; + 0x0e
+ * u16 ilen; + 0x10
+ * u16 irevision; + 0x12
+ * u8 type; + 0x14
+ * u8 indicator; + 0x15
+ * u16 reserved_2; + 0x16
+ * } pci_data_t;
+ */
+ if (BIOS_IN32(dptr) != (('R' << 24) | ('I' << 16) | ('C' << 8) | 'P')) {
+ printk(KERN_WARNING "radeonfb: PCI DATA signature in ROM incorrect: %08x\n",
+ BIOS_IN32(dptr));
+ goto anyway;
+ }
+ rom_type = BIOS_IN8(dptr + 0x14);
+ switch(rom_type) {
+ case 0:
+ printk(KERN_INFO "radeonfb: Found Intel x86 BIOS ROM Image\n");
+ break;
+ case 1:
+ printk(KERN_INFO "radeonfb: Found Open Firmware ROM Image\n");
+ goto failed;
+ case 2:
+ printk(KERN_INFO "radeonfb: Found HP PA-RISC ROM Image\n");
+ goto failed;
+ default:
+ printk(KERN_INFO "radeonfb: Found unknown type %d ROM Image\n", rom_type);
+ goto failed;
+ }
+ anyway:
+ /* Locate the flat panel infos, do some sanity checking !!! */
+ rinfo->fp_bios_start = BIOS_IN16(0x48);
+ return 0;
+
+ failed:
+ rinfo->bios_seg = NULL;
+ radeon_unmap_ROM(rinfo, dev);
+ return -ENXIO;
+}
+
+#ifdef __i386__
+static int __devinit radeon_find_mem_vbios(struct radeonfb_info *rinfo)
+{
+ /* I simplified this code as we used to miss the signatures in
+ * a lot of case. It's now closer to XFree, we just don't check
+ * for signatures at all... Something better will have to be done
+ * if we end up having conflicts
+ */
+ u32 segstart;
+ unsigned char *rom_base = NULL;
+
+ for(segstart=0x000c0000; segstart<0x000f0000; segstart+=0x00001000) {
+ rom_base = (char *)ioremap(segstart, 0x10000);
+ if (rom_base == NULL)
+ return -ENOMEM;
+ if ((*rom_base == 0x55) && (((*(rom_base + 1)) & 0xff) == 0xaa))
+ break;
+ iounmap(rom_base);
+ rom_base = NULL;
+ }
+ if (rom_base == NULL)
+ return -ENXIO;
+
+ /* Locate the flat panel infos, do some sanity checking !!! */
+ rinfo->bios_seg = rom_base;
+ rinfo->fp_bios_start = BIOS_IN16(0x48);
+
+ return 0;
+}
+#endif /* __i386__ */
+
+#ifdef CONFIG_PPC_OF
+/*
+ * Read XTAL (ref clock), SCLK and MCLK from Open Firmware device
+ * tree. Hopefully, ATI OF driver is kind enough to fill these
+ */
+static int __devinit radeon_read_xtal_OF (struct radeonfb_info *rinfo)
+{
+ struct device_node *dp;
+ u32 *val;
+
+ dp = pci_device_to_OF_node(rinfo->pdev);
+ if (dp == NULL) {
+ printk(KERN_WARNING "radeonfb: Cannot match card to OF node !\n");
+ return -ENODEV;
+ }
+ val = (u32 *) get_property(dp, "ATY,RefCLK", 0);
+ if (!val || !*val) {
+ printk(KERN_WARNING "radeonfb: No ATY,RefCLK property !\n");
+ return -EINVAL;
+ }
+
+ rinfo->pll.ref_clk = (*val) / 10;
+
+ val = (u32 *) get_property(dp, "ATY,SCLK", 0);
+ if (val && *val)
+ rinfo->pll.sclk = (*val) / 10;
+
+ val = (u32 *) get_property(dp, "ATY,MCLK", 0);
+ if (val && *val)
+ rinfo->pll.mclk = (*val) / 10;
+
+ return 0;
+}
+#endif /* CONFIG_PPC_OF */
+
+/*
+ * Read PLL infos from chip registers
+ */
+static int __devinit radeon_probe_pll_params(struct radeonfb_info *rinfo)
+{
+ unsigned char ppll_div_sel;
+ unsigned Ns, Nm, M;
+ unsigned sclk, mclk, tmp, ref_div;
+ int hTotal, vTotal, num, denom, m, n;
+ unsigned long long hz, vclk;
+ long xtal;
+ struct timeval start_tv, stop_tv;
+ long total_secs, total_usecs;
+ int i;
+
+ /* Ugh, we cut interrupts, bad bad bad, but we want some precision
+ * here, so... --BenH
+ */
+
+ /* Flush PCI buffers ? */
+ tmp = INREG(DEVICE_ID);
+
+ local_irq_disable();
+
+ for(i=0; i<1000000; i++)
+ if (((INREG(CRTC_VLINE_CRNT_VLINE) >> 16) & 0x3ff) == 0)
+ break;
+
+ do_gettimeofday(&start_tv);
+
+ for(i=0; i<1000000; i++)
+ if (((INREG(CRTC_VLINE_CRNT_VLINE) >> 16) & 0x3ff) != 0)
+ break;
+
+ for(i=0; i<1000000; i++)
+ if (((INREG(CRTC_VLINE_CRNT_VLINE) >> 16) & 0x3ff) == 0)
+ break;
+
+ do_gettimeofday(&stop_tv);
+
+ local_irq_enable();
+
+ total_secs = stop_tv.tv_sec - start_tv.tv_sec;
+ if (total_secs > 10)
+ return -1;
+ total_usecs = stop_tv.tv_usec - start_tv.tv_usec;
+ total_usecs += total_secs * 1000000;
+ if (total_usecs < 0)
+ total_usecs = -total_usecs;
+ hz = 1000000/total_usecs;
+
+ hTotal = ((INREG(CRTC_H_TOTAL_DISP) & 0x1ff) + 1) * 8;
+ vTotal = ((INREG(CRTC_V_TOTAL_DISP) & 0x3ff) + 1);
+ vclk = (long long)hTotal * (long long)vTotal * hz;
+
+ switch((INPLL(PPLL_REF_DIV) & 0x30000) >> 16) {
+ case 0:
+ default:
+ num = 1;
+ denom = 1;
+ break;
+ case 1:
+ n = ((INPLL(X_MPLL_REF_FB_DIV) >> 16) & 0xff);
+ m = (INPLL(X_MPLL_REF_FB_DIV) & 0xff);
+ num = 2*n;
+ denom = 2*m;
+ break;
+ case 2:
+ n = ((INPLL(X_MPLL_REF_FB_DIV) >> 8) & 0xff);
+ m = (INPLL(X_MPLL_REF_FB_DIV) & 0xff);
+ num = 2*n;
+ denom = 2*m;
+ break;
+ }
+
+ OUTREG8(CLOCK_CNTL_INDEX, 1);
+ ppll_div_sel = INREG8(CLOCK_CNTL_DATA + 1) & 0x3;
+
+ n = (INPLL(PPLL_DIV_0 + ppll_div_sel) & 0x7ff);
+ m = (INPLL(PPLL_REF_DIV) & 0x3ff);
+
+ num *= n;
+ denom *= m;
+
+ switch ((INPLL(PPLL_DIV_0 + ppll_div_sel) >> 16) & 0x7) {
+ case 1:
+ denom *= 2;
+ break;
+ case 2:
+ denom *= 4;
+ break;
+ case 3:
+ denom *= 8;
+ break;
+ case 4:
+ denom *= 3;
+ break;
+ case 6:
+ denom *= 6;
+ break;
+ case 7:
+ denom *= 12;
+ break;
+ }
+
+ do_div(vclk, 1000);
+ xtal = (xtal * denom) / num;
+
+ if ((xtal > 26900) && (xtal < 27100))
+ xtal = 2700;
+ else if ((xtal > 14200) && (xtal < 14400))
+ xtal = 1432;
+ else if ((xtal > 29400) && (xtal < 29600))
+ xtal = 2950;
+ else {
+ printk(KERN_WARNING "xtal calculation failed: %ld\n", xtal);
+ return -1;
+ }
+
+ tmp = INPLL(X_MPLL_REF_FB_DIV);
+ ref_div = INPLL(PPLL_REF_DIV) & 0x3ff;
+
+ Ns = (tmp & 0xff0000) >> 16;
+ Nm = (tmp & 0xff00) >> 8;
+ M = (tmp & 0xff);
+ sclk = round_div((2 * Ns * xtal), (2 * M));
+ mclk = round_div((2 * Nm * xtal), (2 * M));
+
+ /* we're done, hopefully these are sane values */
+ rinfo->pll.ref_clk = xtal;
+ rinfo->pll.ref_div = ref_div;
+ rinfo->pll.sclk = sclk;
+ rinfo->pll.mclk = mclk;
+
+ return 0;
+}
+
+/*
+ * Retreive PLL infos by different means (BIOS, Open Firmware, register probing...)
+ */
+static void __devinit radeon_get_pllinfo(struct radeonfb_info *rinfo)
+{
+#ifdef CONFIG_PPC_OF
+ /*
+ * Retreive PLL infos from Open Firmware first
+ */
+ if (!force_measure_pll && radeon_read_xtal_OF(rinfo) == 0) {
+ printk(KERN_INFO "radeonfb: Retreived PLL infos from Open Firmware\n");
+ rinfo->pll.ref_div = INPLL(PPLL_REF_DIV) & 0x3ff;
+ /* FIXME: Max clock may be higher on newer chips */
+ rinfo->pll.ppll_min = 12000;
+ rinfo->pll.ppll_max = 35000;
+ goto found;
+ }
+#endif /* CONFIG_PPC_OF */
+
+ /*
+ * Check out if we have an X86 which gave us some PLL informations
+ * and if yes, retreive them
+ */
+ if (!force_measure_pll && rinfo->bios_seg) {
+ u16 pll_info_block = BIOS_IN16(rinfo->fp_bios_start + 0x30);
+
+ rinfo->pll.sclk = BIOS_IN16(pll_info_block + 0x08);
+ rinfo->pll.mclk = BIOS_IN16(pll_info_block + 0x0a);
+ rinfo->pll.ref_clk = BIOS_IN16(pll_info_block + 0x0e);
+ rinfo->pll.ref_div = BIOS_IN16(pll_info_block + 0x10);
+ rinfo->pll.ppll_min = BIOS_IN32(pll_info_block + 0x12);
+ rinfo->pll.ppll_max = BIOS_IN32(pll_info_block + 0x16);
+
+ printk(KERN_INFO "radeonfb: Retreived PLL infos from BIOS\n");
+ goto found;
+ }
+
+ /*
+ * We didn't get PLL parameters from either OF or BIOS, we try to
+ * probe them
+ */
+ if (radeon_probe_pll_params(rinfo) == 0) {
+ printk(KERN_INFO "radeonfb: Retreived PLL infos from registers\n");
+ /* FIXME: Max clock may be higher on newer chips */
+ rinfo->pll.ppll_min = 12000;
+ rinfo->pll.ppll_max = 35000;
+ goto found;
+ }
+
+ /*
+ * Neither of the above worked, we have a few default values, though
+ * that's mostly incomplete
+ */
+ switch (rinfo->chipset) {
+ case PCI_DEVICE_ID_ATI_RADEON_QW:
+ case PCI_DEVICE_ID_ATI_RADEON_QX:
+ rinfo->pll.ppll_max = 35000;
+ rinfo->pll.ppll_min = 12000;
+ rinfo->pll.mclk = 23000;
+ rinfo->pll.sclk = 23000;
+ rinfo->pll.ref_clk = 2700;
+ break;
+ case PCI_DEVICE_ID_ATI_RADEON_QL:
+ case PCI_DEVICE_ID_ATI_RADEON_QN:
+ case PCI_DEVICE_ID_ATI_RADEON_QO:
+ case PCI_DEVICE_ID_ATI_RADEON_Ql:
+ case PCI_DEVICE_ID_ATI_RADEON_BB:
+ rinfo->pll.ppll_max = 35000;
+ rinfo->pll.ppll_min = 12000;
+ rinfo->pll.mclk = 27500;
+ rinfo->pll.sclk = 27500;
+ rinfo->pll.ref_clk = 2700;
+ break;
+ case PCI_DEVICE_ID_ATI_RADEON_Id:
+ case PCI_DEVICE_ID_ATI_RADEON_Ie:
+ case PCI_DEVICE_ID_ATI_RADEON_If:
+ case PCI_DEVICE_ID_ATI_RADEON_Ig:
+ rinfo->pll.ppll_max = 35000;
+ rinfo->pll.ppll_min = 12000;
+ rinfo->pll.mclk = 25000;
+ rinfo->pll.sclk = 25000;
+ rinfo->pll.ref_clk = 2700;
+ break;
+ case PCI_DEVICE_ID_ATI_RADEON_ND:
+ case PCI_DEVICE_ID_ATI_RADEON_NE:
+ case PCI_DEVICE_ID_ATI_RADEON_NF:
+ case PCI_DEVICE_ID_ATI_RADEON_NG:
+ rinfo->pll.ppll_max = 40000;
+ rinfo->pll.ppll_min = 20000;
+ rinfo->pll.mclk = 27000;
+ rinfo->pll.sclk = 27000;
+ rinfo->pll.ref_clk = 2700;
+ break;
+ case PCI_DEVICE_ID_ATI_RADEON_QD:
+ case PCI_DEVICE_ID_ATI_RADEON_QE:
+ case PCI_DEVICE_ID_ATI_RADEON_QF:
+ case PCI_DEVICE_ID_ATI_RADEON_QG:
+ default:
+ rinfo->pll.ppll_max = 35000;
+ rinfo->pll.ppll_min = 12000;
+ rinfo->pll.mclk = 16600;
+ rinfo->pll.sclk = 16600;
+ rinfo->pll.ref_clk = 2700;
+ break;
+ }
+ rinfo->pll.ref_div = INPLL(PPLL_REF_DIV) & 0x3ff;
+
+ printk(KERN_INFO "radeonfb: Used default PLL infos\n");
+
+found:
+ /*
+ * Some methods fail to retreive SCLK and MCLK values, we apply default
+ * settings in this case (200Mhz). If that really happne often, we could
+ * fetch from registers instead...
+ */
+ if (rinfo->pll.mclk == 0)
+ rinfo->pll.mclk = 20000;
+ if (rinfo->pll.sclk == 0)
+ rinfo->pll.sclk = 20000;
+
+ printk("radeonfb: Reference=%d.%02d MHz (RefDiv=%d) Memory=%d.%02d Mhz, System=%d.%02d MHz\n",
+ rinfo->pll.ref_clk / 100, rinfo->pll.ref_clk % 100,
+ rinfo->pll.ref_div,
+ rinfo->pll.mclk / 100, rinfo->pll.mclk % 100,
+ rinfo->pll.sclk / 100, rinfo->pll.sclk % 100);
+}
+
+static int radeonfb_check_var (struct fb_var_screeninfo *var, struct fb_info *info)
+{
+ struct radeonfb_info *rinfo = info->par;
+ struct fb_var_screeninfo v;
+ int nom, den;
+ unsigned int pitch;
+
+ if (radeon_match_mode(rinfo, &v, var))
+ return -EINVAL;
+
+ switch (v.bits_per_pixel) {
+ case 0 ... 8:
+ v.bits_per_pixel = 8;
+ break;
+ case 9 ... 16:
+ v.bits_per_pixel = 16;
+ break;
+ case 17 ... 24:
+#if 0 /* Doesn't seem to work */
+ v.bits_per_pixel = 24;
+ break;
+#endif
+ return -EINVAL;
+ case 25 ... 32:
+ v.bits_per_pixel = 32;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (var_to_depth(&v)) {
+ case 8:
+ nom = den = 1;
+ v.red.offset = v.green.offset = v.blue.offset = 0;
+ v.red.length = v.green.length = v.blue.length = 8;
+ v.transp.offset = v.transp.length = 0;
+ break;
+ case 15:
+ nom = 2;
+ den = 1;
+ v.red.offset = 10;
+ v.green.offset = 5;
+ v.blue.offset = 0;
+ v.red.length = v.green.length = v.blue.length = 5;
+ v.transp.offset = v.transp.length = 0;
+ break;
+ case 16:
+ nom = 2;
+ den = 1;
+ v.red.offset = 11;
+ v.green.offset = 5;
+ v.blue.offset = 0;
+ v.red.length = 5;
+ v.green.length = 6;
+ v.blue.length = 5;
+ v.transp.offset = v.transp.length = 0;
+ break;
+ case 24:
+ nom = 4;
+ den = 1;
+ v.red.offset = 16;
+ v.green.offset = 8;
+ v.blue.offset = 0;
+ v.red.length = v.blue.length = v.green.length = 8;
+ v.transp.offset = v.transp.length = 0;
+ break;
+ case 32:
+ nom = 4;
+ den = 1;
+ v.red.offset = 16;
+ v.green.offset = 8;
+ v.blue.offset = 0;
+ v.red.length = v.blue.length = v.green.length = 8;
+ v.transp.offset = 24;
+ v.transp.length = 8;
+ break;
+ default:
+ printk ("radeonfb: mode %dx%dx%d rejected, color depth invalid\n",
+ var->xres, var->yres, var->bits_per_pixel);
+ return -EINVAL;
+ }
+
+ if (v.yres_virtual < v.yres)
+ v.yres_virtual = v.yres;
+ if (v.xres_virtual < v.xres)
+ v.xres_virtual = v.xres;
+
+
+ /* XXX I'm adjusting xres_virtual to the pitch, that may help XFree
+ * with some panels, though I don't quite like this solution
+ */
+ if (radeon_accel_disabled()) {
+ v.xres_virtual = v.xres_virtual & ~7ul;
+ v.accel_flags = 0;
+ } else {
+ pitch = ((v.xres_virtual * ((v.bits_per_pixel + 1) / 8) + 0x3f)
+ & ~(0x3f)) >> 6;
+ v.xres_virtual = (pitch << 6) / ((v.bits_per_pixel + 1) / 8);
+ }
+
+ if (v.xres_virtual < v.xres)
+ v.xres = v.xres_virtual;
+
+ if (v.xoffset < 0)
+ v.xoffset = 0;
+ if (v.yoffset < 0)
+ v.yoffset = 0;
+
+ if (v.xoffset > v.xres_virtual - v.xres)
+ v.xoffset = v.xres_virtual - v.xres - 1;
+
+ if (v.yoffset > v.yres_virtual - v.yres)
+ v.yoffset = v.yres_virtual - v.yres - 1;
+
+ v.red.msb_right = v.green.msb_right = v.blue.msb_right =
+ v.transp.offset = v.transp.length =
+ v.transp.msb_right = 0;
+
+ memcpy(var, &v, sizeof(v));
+
+ return 0;
+}
+
+
+static int radeonfb_pan_display (struct fb_var_screeninfo *var,
+ struct fb_info *info)
+{
+ struct radeonfb_info *rinfo = info->par;
+
+ if ((var->xoffset + var->xres > var->xres_virtual)
+ || (var->yoffset + var->yres > var->yres_virtual))
+ return -EINVAL;
+
+ if (rinfo->asleep)
+ return 0;
+
+ OUTREG(CRTC_OFFSET, ((var->yoffset * var->xres_virtual + var->xoffset)
+ * var->bits_per_pixel / 8) & ~7);
+ return 0;
+}
+
+
+static int radeonfb_ioctl (struct inode *inode, struct file *file, unsigned int cmd,
+ unsigned long arg, struct fb_info *info)
+{
+ struct radeonfb_info *rinfo = info->par;
+ unsigned int tmp;
+ u32 value = 0;
+ int rc;
+
+ switch (cmd) {
+ /*
+ * TODO: set mirror accordingly for non-Mobility chipsets with 2 CRTC's
+ * and do something better using 2nd CRTC instead of just hackish
+ * routing to second output
+ */
+ case FBIO_RADEON_SET_MIRROR:
+ if (!rinfo->is_mobility)
+ return -EINVAL;
+
+ rc = get_user(value, (__u32*)arg);
+
+ if (rc)
+ return rc;
+
+ if (value & 0x01) {
+ tmp = INREG(LVDS_GEN_CNTL);
+
+ tmp |= (LVDS_ON | LVDS_BLON);
+ } else {
+ tmp = INREG(LVDS_GEN_CNTL);
+
+ tmp &= ~(LVDS_ON | LVDS_BLON);
+ }
+
+ OUTREG(LVDS_GEN_CNTL, tmp);
+
+ if (value & 0x02) {
+ tmp = INREG(CRTC_EXT_CNTL);
+ tmp |= CRTC_CRT_ON;
+
+ mirror = 1;
+ } else {
+ tmp = INREG(CRTC_EXT_CNTL);
+ tmp &= ~CRTC_CRT_ON;
+
+ mirror = 0;
+ }
+
+ OUTREG(CRTC_EXT_CNTL, tmp);
+
+ break;
+ case FBIO_RADEON_GET_MIRROR:
+ if (!rinfo->is_mobility)
+ return -EINVAL;
+
+ tmp = INREG(LVDS_GEN_CNTL);
+ if ((LVDS_ON | LVDS_BLON) & tmp)
+ value |= 0x01;
+
+ tmp = INREG(CRTC_EXT_CNTL);
+ if (CRTC_CRT_ON & tmp)
+ value |= 0x02;
+
+ return put_user(value, (__u32*)arg);
+ default:
+ return -EINVAL;
+ }
+
+ return -EINVAL;
+}
+
+
+static int radeon_screen_blank (struct radeonfb_info *rinfo, int blank)
+{
+ u32 val = INREG(CRTC_EXT_CNTL);
+ u32 val2;
+
+ if (rinfo->mon1_type == MT_LCD)
+ val2 = INREG(LVDS_GEN_CNTL) & ~LVDS_DISPLAY_DIS;
+
+ /* reset it */
+ val &= ~(CRTC_DISPLAY_DIS | CRTC_HSYNC_DIS |
+ CRTC_VSYNC_DIS);
+
+ switch (blank) {
+ case VESA_NO_BLANKING:
+ break;
+ case VESA_VSYNC_SUSPEND:
+ val |= (CRTC_DISPLAY_DIS | CRTC_VSYNC_DIS);
+ break;
+ case VESA_HSYNC_SUSPEND:
+ val |= (CRTC_DISPLAY_DIS | CRTC_HSYNC_DIS);
+ break;
+ case VESA_POWERDOWN:
+ val |= (CRTC_DISPLAY_DIS | CRTC_VSYNC_DIS |
+ CRTC_HSYNC_DIS);
+ val2 |= (LVDS_DISPLAY_DIS);
+ break;
+ }
+
+ switch (rinfo->mon1_type) {
+ case MT_LCD:
+ OUTREG(LVDS_GEN_CNTL, val2);
+ break;
+ case MT_CRT:
+ default:
+ OUTREG(CRTC_EXT_CNTL, val);
+ break;
+ }
+
+ return 0;
+}
+
+int radeonfb_blank (int blank, struct fb_info *info)
+{
+ struct radeonfb_info *rinfo = info->par;
+
+ if (rinfo->asleep)
+ return 0;
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+ if (rinfo->mon1_type == MT_LCD && _machine == _MACH_Pmac && blank)
+ set_backlight_enable(0);
+#endif
+
+ radeon_screen_blank(rinfo, blank);
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+ if (rinfo->mon1_type == MT_LCD && _machine == _MACH_Pmac && !blank)
+ set_backlight_enable(1);
+#endif
+
+ return 0;
+}
+
+static int radeonfb_setcolreg (unsigned regno, unsigned red, unsigned green,
+ unsigned blue, unsigned transp, struct fb_info *info)
+{
+ struct radeonfb_info *rinfo = info->par;
+ u32 pindex;
+ unsigned int i;
+
+ if (regno > 255)
+ return 1;
+
+ red >>= 8;
+ green >>= 8;
+ blue >>= 8;
+ rinfo->palette[regno].red = red;
+ rinfo->palette[regno].green = green;
+ rinfo->palette[regno].blue = blue;
+
+ /* default */
+ pindex = regno;
+
+ if (!rinfo->asleep) {
+ u32 dac_cntl2, vclk_cntl;
+
+ if (rinfo->is_mobility) {
+ vclk_cntl = INPLL(VCLK_ECP_CNTL);
+ OUTPLL(VCLK_ECP_CNTL, vclk_cntl & ~PIXCLK_DAC_ALWAYS_ONb);
+ }
+
+ /* Make sure we are on first palette */
+ if (rinfo->has_CRTC2) {
+ dac_cntl2 = INREG(DAC_CNTL2);
+ dac_cntl2 &= ~DAC2_PALETTE_ACCESS_CNTL;
+ OUTREG(DAC_CNTL2, dac_cntl2);
+ }
+
+ if (rinfo->bpp == 16) {
+ pindex = regno * 8;
+
+ if (rinfo->depth == 16 && regno > 63)
+ return 1;
+ if (rinfo->depth == 15 && regno > 31)
+ return 1;
+
+ /* For 565, the green component is mixed one order below */
+ if (rinfo->depth == 16) {
+ OUTREG(PALETTE_INDEX, pindex>>1);
+ OUTREG(PALETTE_DATA, (rinfo->palette[regno>>1].red << 16) |
+ (green << 8) | (rinfo->palette[regno>>1].blue));
+ green = rinfo->palette[regno<<1].green;
+ }
+ }
+
+ if (rinfo->depth != 16 || regno < 32) {
+ OUTREG(PALETTE_INDEX, pindex);
+ OUTREG(PALETTE_DATA, (red << 16) | (green << 8) | blue);
+ }
+ if (rinfo->is_mobility)
+ OUTPLL(VCLK_ECP_CNTL, vclk_cntl);
+ }
+ if (regno < 16) {
+ u32 *pal = info->pseudo_palette;
+ switch (rinfo->depth) {
+ case 15:
+ pal[regno] = (regno << 10) | (regno << 5) | regno;
+ break;
+ case 16:
+ pal[regno] = (regno << 11) | (regno << 5) | regno;
+ break;
+ case 24:
+ pal[regno] = (regno << 16) | (regno << 8) | regno;
+ break;
+ case 32:
+ i = (regno << 8) | regno;
+ pal[regno] = (i << 16) | i;
+ break;
+ }
+ }
+ return 0;
+}
+
+
+static void radeon_save_state (struct radeonfb_info *rinfo, struct radeon_regs *save)
+{
+ /* CRTC regs */
+ save->crtc_gen_cntl = INREG(CRTC_GEN_CNTL);
+ save->crtc_ext_cntl = INREG(CRTC_EXT_CNTL);
+ save->crtc_more_cntl = INREG(CRTC_MORE_CNTL);
+ save->dac_cntl = INREG(DAC_CNTL);
+ save->crtc_h_total_disp = INREG(CRTC_H_TOTAL_DISP);
+ save->crtc_h_sync_strt_wid = INREG(CRTC_H_SYNC_STRT_WID);
+ save->crtc_v_total_disp = INREG(CRTC_V_TOTAL_DISP);
+ save->crtc_v_sync_strt_wid = INREG(CRTC_V_SYNC_STRT_WID);
+ save->crtc_pitch = INREG(CRTC_PITCH);
+ save->surface_cntl = INREG(SURFACE_CNTL);
+
+ /* FP regs */
+ save->fp_crtc_h_total_disp = INREG(FP_CRTC_H_TOTAL_DISP);
+ save->fp_crtc_v_total_disp = INREG(FP_CRTC_V_TOTAL_DISP);
+ save->fp_gen_cntl = INREG(FP_GEN_CNTL);
+ save->fp_h_sync_strt_wid = INREG(FP_H_SYNC_STRT_WID);
+ save->fp_horz_stretch = INREG(FP_HORZ_STRETCH);
+ save->fp_v_sync_strt_wid = INREG(FP_V_SYNC_STRT_WID);
+ save->fp_vert_stretch = INREG(FP_VERT_STRETCH);
+ save->lvds_gen_cntl = INREG(LVDS_GEN_CNTL);
+ save->lvds_pll_cntl = INREG(LVDS_PLL_CNTL);
+ save->tmds_crc = INREG(TMDS_CRC); save->tmds_transmitter_cntl = INREG(TMDS_TRANSMITTER_CNTL);
+ save->vclk_ecp_cntl = INPLL(VCLK_ECP_CNTL);
+}
+
+
+static void radeon_write_pll_regs(struct radeonfb_info *rinfo, struct radeon_regs *mode)
+{
+ int i;
+
+ /* Workaround from XFree */
+ if (rinfo->is_mobility) {
+ /* A temporal workaround for the occational blanking on certain laptop panels.
+ This appears to related to the PLL divider registers (fail to lock?).
+ It occurs even when all dividers are the same with their old settings.
+ In this case we really don't need to fiddle with PLL registers.
+ By doing this we can avoid the blanking problem with some panels.
+ */
+ if ((mode->ppll_ref_div == (INPLL(PPLL_REF_DIV) & PPLL_REF_DIV_MASK)) &&
+ (mode->ppll_div_3 == (INPLL(PPLL_DIV_3) &
+ (PPLL_POST3_DIV_MASK | PPLL_FB3_DIV_MASK)))) {
+ /* We still have to force a switch to PPLL div 3 thanks to
+ * an XFree86 driver bug which will switch it away in some cases
+ * even when using UseFDev */
+ OUTREGP(CLOCK_CNTL_INDEX, PPLL_DIV_SEL_MASK, ~PPLL_DIV_SEL_MASK);
+ return;
+ }
+ }
+
+ /* Swich VCKL clock input to CPUCLK so it stays fed while PPLL updates*/
+ OUTPLLP(VCLK_ECP_CNTL, VCLK_SRC_SEL_CPUCLK, ~VCLK_SRC_SEL_MASK);
+
+ /* Reset PPLL & enable atomic update */
+ OUTPLLP(PPLL_CNTL,
+ PPLL_RESET | PPLL_ATOMIC_UPDATE_EN | PPLL_VGA_ATOMIC_UPDATE_EN,
+ ~(PPLL_RESET | PPLL_ATOMIC_UPDATE_EN | PPLL_VGA_ATOMIC_UPDATE_EN));
+
+ /* Switch to PPLL div 3 */
+ OUTREGP(CLOCK_CNTL_INDEX, PPLL_DIV_SEL_MASK, ~PPLL_DIV_SEL_MASK);
+
+ /* Set PPLL ref. div */
+ if (rinfo->family == CHIP_FAMILY_R300 ||
+ rinfo->family == CHIP_FAMILY_R350 ||
+ rinfo->family == CHIP_FAMILY_RV350) {
+ if (mode->ppll_ref_div & R300_PPLL_REF_DIV_ACC_MASK) {
+ /* When restoring console mode, use saved PPLL_REF_DIV
+ * setting.
+ */
+ OUTPLLP(PPLL_REF_DIV, mode->ppll_ref_div, 0);
+ } else {
+ /* R300 uses ref_div_acc field as real ref divider */
+ OUTPLLP(PPLL_REF_DIV,
+ (mode->ppll_ref_div << R300_PPLL_REF_DIV_ACC_SHIFT),
+ ~R300_PPLL_REF_DIV_ACC_MASK);
+ }
+ } else
+ OUTPLLP(PPLL_REF_DIV, mode->ppll_ref_div, ~PPLL_REF_DIV_MASK);
+
+ /* Set PPLL divider 3 & post divider*/
+ OUTPLLP(PPLL_DIV_3, mode->ppll_div_3, ~PPLL_FB3_DIV_MASK);
+ OUTPLLP(PPLL_DIV_3, mode->ppll_div_3, ~PPLL_POST3_DIV_MASK);
+
+ /* Write update */
+ while (INPLL(PPLL_REF_DIV) & PPLL_ATOMIC_UPDATE_R)
+ ;
+ OUTPLLP(PPLL_REF_DIV, PPLL_ATOMIC_UPDATE_W, ~PPLL_ATOMIC_UPDATE_W);
+
+ /* Wait read update complete */
+ /* FIXME: Certain revisions of R300 can't recover here. Not sure of
+ the cause yet, but this workaround will mask the problem for now.
+ Other chips usually will pass at the very first test, so the
+ workaround shouldn't have any effect on them. */
+ for (i = 0; (i < 10000 && INPLL(PPLL_REF_DIV) & PPLL_ATOMIC_UPDATE_R); i++)
+ ;
+
+ OUTPLL(HTOTAL_CNTL, 0);
+
+ /* Clear reset & atomic update */
+ OUTPLLP(PPLL_CNTL, 0,
+ ~(PPLL_RESET | PPLL_SLEEP | PPLL_ATOMIC_UPDATE_EN | PPLL_VGA_ATOMIC_UPDATE_EN));
+
+ /* We may want some locking ... oh well */
+ wait_ms(5);
+
+ /* Switch back VCLK source to PPLL */
+ OUTPLLP(VCLK_ECP_CNTL, VCLK_SRC_SEL_PPLLCLK, ~VCLK_SRC_SEL_MASK);
+}
+
+/*
+ * Timer function for delayed LVDS panel power up/down
+ */
+static void radeon_lvds_timer_func(unsigned long data)
+{
+ struct radeonfb_info *rinfo = (struct radeonfb_info *)data;
+
+ OUTREG(LVDS_GEN_CNTL, rinfo->pending_lvds_gen_cntl);
+ if (rinfo->pending_pixclks_cntl) {
+ OUTPLL(PIXCLKS_CNTL, rinfo->pending_pixclks_cntl);
+ rinfo->pending_pixclks_cntl = 0;
+ }
+}
+
+/*
+ * Apply a video mode. This will apply the whole register set, including
+ * the PLL registers, to the card
+ */
+static void radeon_write_mode (struct radeonfb_info *rinfo,
+ struct radeon_regs *mode)
+{
+ int i;
+ int primary_mon = PRIMARY_MONITOR(rinfo);
+
+ if (nomodeset)
+ return;
+
+ del_timer_sync(&rinfo->lvds_timer);
+
+ radeon_screen_blank(rinfo, VESA_POWERDOWN);
+
+ for (i=0; i<9; i++)
+ OUTREG(common_regs[i].reg, common_regs[i].val);
+
+ /* Apply surface registers */
+ for (i=0; i<8; i++) {
+ OUTREG(SURFACE0_LOWER_BOUND + 0x10*i, mode->surf_lower_bound[i]);
+ OUTREG(SURFACE0_UPPER_BOUND + 0x10*i, mode->surf_upper_bound[i]);
+ OUTREG(SURFACE0_INFO + 0x10*i, mode->surf_info[i]);
+ }
+
+ OUTREG(CRTC_GEN_CNTL, mode->crtc_gen_cntl);
+ OUTREGP(CRTC_EXT_CNTL, mode->crtc_ext_cntl,
+ ~(CRTC_HSYNC_DIS | CRTC_VSYNC_DIS | CRTC_DISPLAY_DIS));
+ OUTREG(CRTC_MORE_CNTL, mode->crtc_more_cntl);
+ OUTREGP(DAC_CNTL, mode->dac_cntl, DAC_RANGE_CNTL | DAC_BLANKING);
+ OUTREG(CRTC_H_TOTAL_DISP, mode->crtc_h_total_disp);
+ OUTREG(CRTC_H_SYNC_STRT_WID, mode->crtc_h_sync_strt_wid);
+ OUTREG(CRTC_V_TOTAL_DISP, mode->crtc_v_total_disp);
+ OUTREG(CRTC_V_SYNC_STRT_WID, mode->crtc_v_sync_strt_wid);
+ OUTREG(CRTC_OFFSET, 0);
+ OUTREG(CRTC_OFFSET_CNTL, 0);
+ OUTREG(CRTC_PITCH, mode->crtc_pitch);
+ OUTREG(SURFACE_CNTL, mode->surface_cntl);
+
+ radeon_write_pll_regs(rinfo, mode);
+
+ if ((primary_mon == MT_DFP) || (primary_mon == MT_LCD)) {
+ OUTREG(FP_CRTC_H_TOTAL_DISP, mode->fp_crtc_h_total_disp);
+ OUTREG(FP_CRTC_V_TOTAL_DISP, mode->fp_crtc_v_total_disp);
+ OUTREG(FP_H_SYNC_STRT_WID, mode->fp_h_sync_strt_wid);
+ OUTREG(FP_V_SYNC_STRT_WID, mode->fp_v_sync_strt_wid);
+ OUTREG(FP_HORZ_STRETCH, mode->fp_horz_stretch);
+ OUTREG(FP_VERT_STRETCH, mode->fp_vert_stretch);
+ OUTREG(FP_GEN_CNTL, mode->fp_gen_cntl);
+ OUTREG(TMDS_CRC, mode->tmds_crc);
+ OUTREG(TMDS_TRANSMITTER_CNTL, mode->tmds_transmitter_cntl);
+
+ if (primary_mon == MT_LCD) {
+ unsigned int tmp = INREG(LVDS_GEN_CNTL);
+
+ /* HACK: The backlight control code may have modified init_state.lvds_gen_cntl,
+ * so we update ourselves
+ */
+ mode->lvds_gen_cntl &= ~LVDS_STATE_MASK;
+ mode->lvds_gen_cntl |= (rinfo->init_state.lvds_gen_cntl & LVDS_STATE_MASK);
+
+ if ((tmp & (LVDS_ON | LVDS_BLON)) ==
+ (mode->lvds_gen_cntl & (LVDS_ON | LVDS_BLON))) {
+ OUTREG(LVDS_GEN_CNTL, mode->lvds_gen_cntl);
+ } else {
+ rinfo->pending_pixclks_cntl = INPLL(PIXCLKS_CNTL);
+ if (rinfo->is_mobility || rinfo->is_IGP)
+ OUTPLLP(PIXCLKS_CNTL, 0, ~PIXCLK_LVDS_ALWAYS_ONb);
+ if (!(tmp & (LVDS_ON | LVDS_BLON)))
+ OUTREG(LVDS_GEN_CNTL, mode->lvds_gen_cntl | LVDS_BLON);
+ rinfo->pending_lvds_gen_cntl = mode->lvds_gen_cntl;
+ mod_timer(&rinfo->lvds_timer,
+ jiffies + MS_TO_HZ(rinfo->panel_info.pwr_delay));
+ }
+ }
+ }
+
+ RTRACE("lvds_gen_cntl: %08x\n", INREG(LVDS_GEN_CNTL));
+
+ radeon_screen_blank(rinfo, VESA_NO_BLANKING);
+
+ OUTPLL(VCLK_ECP_CNTL, mode->vclk_ecp_cntl);
+
+ return;
+}
+
+/*
+ * Calculate the PLL values for a given mode
+ */
+static void radeon_calc_pll_regs(struct radeonfb_info *rinfo, struct radeon_regs *regs,
+ unsigned long freq)
+{
+ const struct {
+ int divider;
+ int bitvalue;
+ } *post_div,
+ post_divs[] = {
+ { 1, 0 },
+ { 2, 1 },
+ { 4, 2 },
+ { 8, 3 },
+ { 3, 4 },
+ { 16, 5 },
+ { 6, 6 },
+ { 12, 7 },
+ { 0, 0 },
+ };
+ int fb_div, pll_output_freq;
+ int uses_dvo = 0;
+
+ /* Check if the DVO port is enabled and sourced from the primary CRTC. I'm
+ * not sure which model starts having FP2_GEN_CNTL, I assume anything more
+ * recent than an r(v)100...
+ */
+ while (rinfo->has_CRTC2) {
+ u32 fp2_gen_cntl = INREG(FP2_GEN_CNTL);
+ u32 disp_output_cntl;
+ int source;
+
+ /* FP2 path not enabled */
+ if ((fp2_gen_cntl & FP2_ON) == 0)
+ break;
+ /* Not all chip revs have the same format for this register,
+ * extract the source selection
+ */
+ if (rinfo->family == CHIP_FAMILY_R200 ||
+ rinfo->family == CHIP_FAMILY_R300 ||
+ rinfo->family == CHIP_FAMILY_R350 ||
+ rinfo->family == CHIP_FAMILY_RV350) {
+ source = (fp2_gen_cntl >> 10) & 0x3;
+ /* sourced from transform unit, check for transform unit
+ * own source
+ */
+ if (source == 3) {
+ disp_output_cntl = INREG(DISP_OUTPUT_CNTL);
+ source = (disp_output_cntl >> 12) & 0x3;
+ }
+ } else
+ source = (fp2_gen_cntl >> 13) & 0x1;
+ /* sourced from CRTC2 -> exit */
+ if (source == 1)
+ break;
+
+ /* so we end up on CRTC1, let's set uses_dvo to 1 now */
+ uses_dvo = 1;
+ break;
+ }
+ if (freq > rinfo->pll.ppll_max)
+ freq = rinfo->pll.ppll_max;
+ if (freq*12 < rinfo->pll.ppll_min)
+ freq = rinfo->pll.ppll_min / 12;
+
+ for (post_div = &post_divs[0]; post_div->divider; ++post_div) {
+ pll_output_freq = post_div->divider * freq;
+ /* If we output to the DVO port (external TMDS), we don't allow an
+ * odd PLL divider as those aren't supported on this path
+ */
+ if (uses_dvo && (post_div->divider & 1))
+ continue;
+ if (pll_output_freq >= rinfo->pll.ppll_min &&
+ pll_output_freq <= rinfo->pll.ppll_max)
+ break;
+ }
+
+ fb_div = round_div(rinfo->pll.ref_div*pll_output_freq,
+ rinfo->pll.ref_clk);
+ regs->ppll_ref_div = rinfo->pll.ref_div;
+ regs->ppll_div_3 = fb_div | (post_div->bitvalue << 16);
+
+ RTRACE("post div = 0x%x\n", post_div->bitvalue);
+ RTRACE("fb_div = 0x%x\n", fb_div);
+ RTRACE("ppll_div_3 = 0x%x\n", regs->ppll_div_3);
+}
+
+int radeonfb_set_par(struct fb_info *info)
+{
+ struct radeonfb_info *rinfo = info->par;
+ struct fb_var_screeninfo *mode = &info->var;
+ struct radeon_regs newmode;
+ int hTotal, vTotal, hSyncStart, hSyncEnd,
+ hSyncPol, vSyncStart, vSyncEnd, vSyncPol, cSync;
+ u8 hsync_adj_tab[] = {0, 0x12, 9, 9, 6, 5};
+ u8 hsync_fudge_fp[] = {2, 2, 0, 0, 5, 5};
+ u32 sync, h_sync_pol, v_sync_pol, dotClock, pixClock;
+ int i, freq;
+ int format = 0;
+ int nopllcalc = 0;
+ int hsync_start, hsync_fudge, bytpp, hsync_wid, vsync_wid;
+ int primary_mon = PRIMARY_MONITOR(rinfo);
+ int depth = var_to_depth(mode);
+
+ /* We always want engine to be idle on a mode switch, even
+ * if we won't actually change the mode
+ */
+ radeon_engine_idle();
+
+ hSyncStart = mode->xres + mode->right_margin;
+ hSyncEnd = hSyncStart + mode->hsync_len;
+ hTotal = hSyncEnd + mode->left_margin;
+
+ vSyncStart = mode->yres + mode->lower_margin;
+ vSyncEnd = vSyncStart + mode->vsync_len;
+ vTotal = vSyncEnd + mode->upper_margin;
+ pixClock = mode->pixclock;
+
+ sync = mode->sync;
+ h_sync_pol = sync & FB_SYNC_HOR_HIGH_ACT ? 0 : 1;
+ v_sync_pol = sync & FB_SYNC_VERT_HIGH_ACT ? 0 : 1;
+
+ if (primary_mon == MT_DFP || primary_mon == MT_LCD) {
+ if (rinfo->panel_info.xres < mode->xres)
+ mode->xres = rinfo->panel_info.xres;
+ if (rinfo->panel_info.yres < mode->yres)
+ mode->yres = rinfo->panel_info.yres;
+
+ hTotal = mode->xres + rinfo->panel_info.hblank;
+ hSyncStart = mode->xres + rinfo->panel_info.hOver_plus;
+ hSyncEnd = hSyncStart + rinfo->panel_info.hSync_width;
+
+ vTotal = mode->yres + rinfo->panel_info.vblank;
+ vSyncStart = mode->yres + rinfo->panel_info.vOver_plus;
+ vSyncEnd = vSyncStart + rinfo->panel_info.vSync_width;
+
+ h_sync_pol = !rinfo->panel_info.hAct_high;
+ v_sync_pol = !rinfo->panel_info.vAct_high;
+
+ pixClock = 100000000 / rinfo->panel_info.clock;
+
+ if (rinfo->panel_info.use_bios_dividers) {
+ nopllcalc = 1;
+ newmode.ppll_div_3 = rinfo->panel_info.fbk_divider |
+ (rinfo->panel_info.post_divider << 16);
+ newmode.ppll_ref_div = rinfo->pll.ref_div;
+ }
+ }
+ dotClock = 1000000000 / pixClock;
+ freq = dotClock / 10; /* x100 */
+
+ RTRACE("hStart = %d, hEnd = %d, hTotal = %d\n",
+ hSyncStart, hSyncEnd, hTotal);
+ RTRACE("vStart = %d, vEnd = %d, vTotal = %d\n",
+ vSyncStart, vSyncEnd, vTotal);
+
+ hsync_wid = (hSyncEnd - hSyncStart) / 8;
+ vsync_wid = vSyncEnd - vSyncStart;
+ if (hsync_wid == 0)
+ hsync_wid = 1;
+ else if (hsync_wid > 0x3f) /* max */
+ hsync_wid = 0x3f;
+
+ if (vsync_wid == 0)
+ vsync_wid = 1;
+ else if (vsync_wid > 0x1f) /* max */
+ vsync_wid = 0x1f;
+
+ hSyncPol = mode->sync & FB_SYNC_HOR_HIGH_ACT ? 0 : 1;
+ vSyncPol = mode->sync & FB_SYNC_VERT_HIGH_ACT ? 0 : 1;
+
+ cSync = mode->sync & FB_SYNC_COMP_HIGH_ACT ? (1 << 4) : 0;
+
+ format = radeon_get_dstbpp(depth);
+ bytpp = mode->bits_per_pixel >> 3;
+
+ if ((primary_mon == MT_DFP) || (primary_mon == MT_LCD))
+ hsync_fudge = hsync_fudge_fp[format-1];
+ else
+ hsync_fudge = hsync_adj_tab[format-1];
+
+ hsync_start = hSyncStart - 8 + hsync_fudge;
+
+ newmode.crtc_gen_cntl = CRTC_EXT_DISP_EN | CRTC_EN |
+ (format << 8);
+
+ /* Clear auto-center etc... */
+ newmode.crtc_more_cntl = rinfo->init_state.crtc_more_cntl;
+ newmode.crtc_more_cntl &= 0xfffffff0;
+
+ if ((primary_mon == MT_DFP) || (primary_mon == MT_LCD)) {
+ newmode.crtc_ext_cntl = VGA_ATI_LINEAR | XCRT_CNT_EN;
+ if (mirror)
+ newmode.crtc_ext_cntl |= CRTC_CRT_ON;
+
+ newmode.crtc_gen_cntl &= ~(CRTC_DBL_SCAN_EN |
+ CRTC_INTERLACE_EN);
+ } else {
+ newmode.crtc_ext_cntl = VGA_ATI_LINEAR | XCRT_CNT_EN |
+ CRTC_CRT_ON;
+ }
+
+ newmode.dac_cntl = /* INREG(DAC_CNTL) | */ DAC_MASK_ALL | DAC_VGA_ADR_EN |
+ DAC_8BIT_EN;
+
+ newmode.crtc_h_total_disp = ((((hTotal / 8) - 1) & 0x3ff) |
+ (((mode->xres / 8) - 1) << 16));
+
+ newmode.crtc_h_sync_strt_wid = ((hsync_start & 0x1fff) |
+ (hsync_wid << 16) | (h_sync_pol << 23));
+
+ newmode.crtc_v_total_disp = ((vTotal - 1) & 0xffff) |
+ ((mode->yres - 1) << 16);
+
+ newmode.crtc_v_sync_strt_wid = (((vSyncStart - 1) & 0xfff) |
+ (vsync_wid << 16) | (v_sync_pol << 23));
+
+ if (!radeon_accel_disabled()) {
+ /* We first calculate the engine pitch */
+ rinfo->pitch = ((mode->xres_virtual * ((mode->bits_per_pixel + 1) / 8) + 0x3f)
+ & ~(0x3f)) >> 6;
+
+ /* Then, re-multiply it to get the CRTC pitch */
+ newmode.crtc_pitch = (rinfo->pitch << 3) / ((mode->bits_per_pixel + 1) / 8);
+ } else
+ newmode.crtc_pitch = (mode->xres_virtual >> 3);
+
+ newmode.crtc_pitch |= (newmode.crtc_pitch << 16);
+
+ /*
+ * It looks like recent chips have a problem with SURFACE_CNTL,
+ * setting SURF_TRANSLATION_DIS completely disables the
+ * swapper as well, so we leave it unset now.
+ */
+ newmode.surface_cntl = 0;
+
+#if defined(__BIG_ENDIAN)
+
+ /* Setup swapping on both apertures, though we currently
+ * only use aperture 0, enabling swapper on aperture 1
+ * won't harm
+ */
+ switch (mode->bits_per_pixel) {
+ case 16:
+ newmode.surface_cntl |= NONSURF_AP0_SWP_16BPP;
+ newmode.surface_cntl |= NONSURF_AP1_SWP_16BPP;
+ break;
+ case 24:
+ case 32:
+ newmode.surface_cntl |= NONSURF_AP0_SWP_32BPP;
+ newmode.surface_cntl |= NONSURF_AP1_SWP_32BPP;
+ break;
+ }
+#endif
+
+ /* Clear surface registers */
+ for (i=0; i<8; i++) {
+ newmode.surf_lower_bound[i] = 0;
+ newmode.surf_upper_bound[i] = 0x1f;
+ newmode.surf_info[i] = 0;
+ }
+
+ RTRACE("h_total_disp = 0x%x\t hsync_strt_wid = 0x%x\n",
+ newmode.crtc_h_total_disp, newmode.crtc_h_sync_strt_wid);
+ RTRACE("v_total_disp = 0x%x\t vsync_strt_wid = 0x%x\n",
+ newmode.crtc_v_total_disp, newmode.crtc_v_sync_strt_wid);
+
+ rinfo->bpp = mode->bits_per_pixel;
+ rinfo->depth = depth;
+
+ RTRACE("pixclock = %lu\n", (unsigned long)pixClock);
+ RTRACE("freq = %lu\n", (unsigned long)freq);
+
+ 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);
+ }
+ 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);
+ }
+ 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);
+
+ 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_RAN_PAT_RST | TMDS_ICHCSEL) &
+ ~(TMDS_PLLRST);
+ /* TMDS_PLL_EN bit is reversed on RV (and mobility) chips */
+ if ((rinfo->family == CHIP_FAMILY_R300) ||
+ (rinfo->family == CHIP_FAMILY_R350) ||
+ (rinfo->family == CHIP_FAMILY_RV350) ||
+ (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) {
+ radeon_write_mode (rinfo, &newmode);
+ /* (re)initialize the engine */
+ if (!radeon_accel_disabled())
+ radeon_engine_init (rinfo);
+
+ }
+ /* Update fix */
+ if (!radeon_accel_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
+
+ 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_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_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_FLAG_DEFAULT;
+ info->fbops = &radeonfb_ops;
+ info->display_fg = NULL;
+ 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;
+ if (radeon_accel_disabled())
+ info->fix.accel = FB_ACCEL_NONE;
+ else
+ info->fix.accel = FB_ACCEL_ATI_RADEON;
+
+ fb_alloc_cmap(&info->cmap, 256, 0);
+
+ if (radeon_accel_disabled())
+ info->var.accel_flags &= ~FB_ACCELF_TEXT;
+ else
+ info->var.accel_flags |= FB_ACCELF_TEXT;
+
+ 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"))
+ 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);
+ 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_APERTURE
+static 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 */
+ 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;
+ }
+
+ /*
+ * Hack to get around some busted production M6's
+ * reporting no ram
+ */
+ if (rinfo->video_ram == 0) {
+ switch (pdev->device) {
+ case PCI_CHIP_RADEON_LY:
+ case PCI_CHIP_RADEON_LZ:
+ rinfo->video_ram = 8192 * 1024;
+ break;
+ default:
+ break;
+ }
+ }
+
+ RTRACE("radeonfb: probed %s %ldk videoram\n", (rinfo->ram_type), (rinfo->video_ram/1024));
+
+ rinfo->fb_base = (unsigned long) ioremap (rinfo->fb_base_phys, rinfo->video_ram);
+ if (!rinfo->fb_base) {
+ printk (KERN_ERR "radeonfb: cannot map FB\n");
+ goto unmap_rom;
+ }
+ /* Argh. Scary arch !!! */
+#ifdef CONFIG_PPC64
+ rinfo->fb_base = IO_TOKEN_TO_ADDR(rinfo->fb_base);
+#endif
+
+ /*
+ * Check for required workaround for PLL accesses
+ */
+ rinfo->R300_cg_workaround = (rinfo->family == CHIP_FAMILY_R300 &&
+ (INREG(CONFIG_CNTL) & CFG_ATI_REV_ID_MASK)
+ == CFG_ATI_REV_A11);
+
+ /*
+ * Map the BIOS ROM if any and retreive PLL parameters from
+ * either BIOS or Open Firmware
+ */
+ radeon_map_ROM(rinfo, pdev);
+
+ /*
+ * On x86, the primary display on laptop may have it's BIOS
+ * ROM elsewhere, try to locate it at the legacy memory hole.
+ * We probably need to make sure this is the primary dispay,
+ * but that is difficult without some arch support.
+ */
+#ifdef __i386__
+ if (rinfo->bios_seg == NULL)
+ radeon_find_mem_vbios(rinfo);
+#endif /* __i386__ */
+
+ /* Get informations about the board's PLL */
+ radeon_get_pllinfo(rinfo);
+
+#ifdef CONFIG_FB_RADEON_I2C
+ /* Register I2C bus */
+ radeon_create_i2c_busses(rinfo);
+#endif
+
+ /* set all the vital stuff */
+ radeon_set_fbinfo (rinfo);
+
+ /* Probe screen types */
+ radeon_probe_screens(rinfo, monitor_layout, ignore_edid);
+
+ /* Build mode list, check out panel native model */
+ radeon_check_modes(rinfo, mode_option);
+
+ /* Register some sysfs stuff (should be done better) */
+ if (rinfo->mon1_EDID)
+ sysfs_create_bin_file(&rinfo->pdev->dev.kobj, &edid1_attr);
+ if (rinfo->mon2_EDID)
+ sysfs_create_bin_file(&rinfo->pdev->dev.kobj, &edid2_attr);
+
+ /* save current mode regs before we switch into the new one
+ * so we can restore this upon __exit
+ */
+ radeon_save_state (rinfo, &rinfo->init_state);
+
+ pci_set_drvdata(pdev, info);
+
+ /* Enable PM on mobility chips */
+ if (rinfo->is_mobility) {
+ /* Find PM registers in config space */
+ rinfo->pm_reg = pci_find_capability(pdev, PCI_CAP_ID_PM);
+ /* Enable dynamic PM of chip clocks */
+ radeon_pm_enable_dynamic_mode(rinfo);
+ printk("radeonfb: Power Management enabled for Mobility chipsets\n");
+ }
+
+ if (register_framebuffer(info) < 0) {
+ printk (KERN_ERR "radeonfb: could not register framebuffer\n");
+ goto unmap_fb;
+ }
+
+#ifdef CONFIG_MTRR
+ rinfo->mtrr_hdl = nomtrr ? -1 : mtrr_add(rinfo->fb_base_phys,
+ rinfo->video_ram,
+ MTRR_TYPE_WRCOMB, 1);
+#endif
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+ if (rinfo->mon1_type == MT_LCD) {
+ register_backlight_controller(&radeon_backlight_controller,
+ rinfo, "ati");
+ register_backlight_controller(&radeon_backlight_controller,
+ rinfo, "mnca");
+ }
+#endif
+
+ printk ("radeonfb: %s %s %ld MB\n", rinfo->name, rinfo->ram_type,
+ (rinfo->video_ram/(1024*1024)));
+
+ if (rinfo->bios_seg)
+ radeon_unmap_ROM(rinfo, pdev);
+ RTRACE("radeonfb_pci_register END\n");
+
+ return 0;
+unmap_fb:
+ iounmap ((void*)rinfo->fb_base);
+unmap_rom:
+ if (rinfo->mon1_EDID)
+ kfree(rinfo->mon1_EDID);
+ if (rinfo->mon2_EDID)
+ kfree(rinfo->mon2_EDID);
+ if (rinfo->mon1_modedb)
+ fb_destroy_modedb(rinfo->mon1_modedb);
+#ifdef CONFIG_FB_RADEON_I2C
+ radeon_delete_i2c_busses(rinfo);
+#endif
+ if (rinfo->bios_seg)
+ radeon_unmap_ROM(rinfo, pdev);
+ iounmap ((void*)rinfo->mmio_base);
+release_mmio:
+ release_mem_region (rinfo->mmio_base_phys,
+ pci_resource_len(pdev, 2));
+release_fb:
+ release_mem_region (rinfo->fb_base_phys,
+ pci_resource_len(pdev, 0));
+free_rinfo:
+ framebuffer_release(info);
+ return -ENODEV;
+}
+
+
+
+static void __devexit radeonfb_pci_unregister (struct pci_dev *pdev)
+{
+ struct fb_info *info = pci_get_drvdata(pdev);
+ struct radeonfb_info *rinfo = info->par;
+
+ if (!rinfo)
+ return;
+
+ /* restore original state
+ *
+ * Doesn't quite work yet, possibly because of the PPC hacking
+ * I do on startup, disable for now. --BenH
+ */
+ radeon_write_mode (rinfo, &rinfo->init_state);
+
+ del_timer_sync(&rinfo->lvds_timer);
+
+#ifdef CONFIG_MTRR
+ if (rinfo->mtrr_hdl >= 0)
+ mtrr_del(rinfo->mtrr_hdl, 0, 0);
+#endif
+
+ unregister_framebuffer(info);
+
+ iounmap ((void*)rinfo->mmio_base);
+ iounmap ((void*)rinfo->fb_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));
+
+ if (rinfo->mon1_EDID)
+ kfree(rinfo->mon1_EDID);
+ if (rinfo->mon2_EDID)
+ kfree(rinfo->mon2_EDID);
+ if (rinfo->mon1_modedb)
+ fb_destroy_modedb(rinfo->mon1_modedb);
+#ifdef CONFIG_FB_RADEON_I2C
+ radeon_delete_i2c_busses(rinfo);
+#endif
+ kfree (rinfo);
+}
+
+
+static struct pci_driver radeonfb_driver = {
+ .name = "radeonfb",
+ .id_table = radeonfb_pci_table,
+ .probe = radeonfb_pci_register,
+ .remove = __devexit_p(radeonfb_pci_unregister),
+#ifdef CONFIG_PM
+ .suspend = radeonfb_pci_suspend,
+ .resume = radeonfb_pci_resume,
+#endif /* CONFIG_PM */
+};
+
+
+int __init radeonfb_init (void)
+{
+ radeonfb_noaccel = noaccel;
+ return pci_module_init (&radeonfb_driver);
+}
+
+
+void __exit radeonfb_exit (void)
+{
+ pci_unregister_driver (&radeonfb_driver);
+}
+
+int __init radeonfb_setup (char *options)
+{
+ char *this_opt;
+
+ if (!options || !*options)
+ return 0;
+
+ while ((this_opt = strsep (&options, ",")) != NULL) {
+ if (!*this_opt)
+ continue;
+
+ if (!strncmp(this_opt, "noaccel", 7)) {
+ radeonfb_noaccel = 1;
+ } else if (!strncmp(this_opt, "mirror", 6)) {
+ mirror = 1;
+ } else if (!strncmp(this_opt, "force_dfp", 9)) {
+ force_dfp = 1;
+ } else if (!strncmp(this_opt, "panel_yres:", 11)) {
+ panel_yres = simple_strtoul((this_opt+11), NULL, 0);
+#ifdef CONFIG_MTRR
+ } else if (!strncmp(this_opt, "nomtrr", 6)) {
+ nomtrr = 1;
+#endif
+ } else if (!strncmp(this_opt, "nomodeset", 9)) {
+ nomodeset = 1;
+ } else if (!strncmp(this_opt, "force_measure_pll", 17)) {
+ force_measure_pll = 1;
+ } else if (!strncmp(this_opt, "ignore_edid", 11)) {
+ ignore_edid = 1;
+ } else
+ mode_option = this_opt;
+ }
+ return 0;
+}
+
+
+#ifdef MODULE
+module_init(radeonfb_init);
+module_exit(radeonfb_exit);
+#endif
+
+MODULE_AUTHOR("Ani Joshi");
+MODULE_DESCRIPTION("framebuffer driver for ATI Radeon chipset");
+MODULE_LICENSE("GPL");
+module_param(noaccel, bool, 0);
+MODULE_PARM_DESC(noaccel, "bool: disable acceleration");
+module_param(nomodeset, bool, 0);
+MODULE_PARM_DESC(nomodeset, "bool: disable actual setting of video mode");
+module_param(mirror, bool, 0);
+MODULE_PARM_DESC(mirror, "bool: mirror the display to both monitors");
+module_param(force_dfp, bool, 0);
+MODULE_PARM_DESC(force_dfp, "bool: force display to dfp");
+module_param(ignore_edid, bool, 0);
+MODULE_PARM_DESC(ignore_edid, "bool: Ignore EDID data when doing DDC probe");
+module_param(monitor_layout, charp, 0);
+MODULE_PARM_DESC(monitor_layout, "Specify monitor mapping (like XFree86)");
+module_param(force_measure_pll, bool, 0);
+MODULE_PARM_DESC(force_measure_pll, "Force measurement of PLL (debug)");
+#ifdef CONFIG_MTRR
+module_param(nomtrr, bool, 0);
+MODULE_PARM_DESC(nomtrr, "bool: disable use of MTRR registers");
+#endif
+module_param(panel_yres, int, 0);
+MODULE_PARM_DESC(panel_yres, "int: set panel yres");
+module_param(mode_option, charp, 0);
+MODULE_PARM_DESC(mode_option, "Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\" ");
--- /dev/null
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/fb.h>
+
+
+#include <linux/i2c.h>
+#include <linux/i2c-id.h>
+#include <linux/i2c-algo-bit.h>
+
+#include <asm/io.h>
+
+#include <video/radeon.h>
+#include "radeonfb.h"
+#include "../edid.h"
+
+#define RADEON_DDC 0x50
+
+static void radeon_gpio_setscl(void* data, int state)
+{
+ struct radeon_i2c_chan *chan = data;
+ struct radeonfb_info *rinfo = chan->rinfo;
+ u32 val;
+
+ val = INREG(chan->ddc_reg) & ~(VGA_DDC_CLK_OUT_EN);
+ if (!state)
+ val |= VGA_DDC_CLK_OUT_EN;
+
+ OUTREG(chan->ddc_reg, val);
+ (void)INREG(chan->ddc_reg);
+}
+
+static void radeon_gpio_setsda(void* data, int state)
+{
+ struct radeon_i2c_chan *chan = data;
+ struct radeonfb_info *rinfo = chan->rinfo;
+ u32 val;
+
+ val = INREG(chan->ddc_reg) & ~(VGA_DDC_DATA_OUT_EN);
+ if (!state)
+ val |= VGA_DDC_DATA_OUT_EN;
+
+ OUTREG(chan->ddc_reg, val);
+ (void)INREG(chan->ddc_reg);
+}
+
+static int radeon_gpio_getscl(void* data)
+{
+ struct radeon_i2c_chan *chan = data;
+ struct radeonfb_info *rinfo = chan->rinfo;
+ u32 val;
+
+ val = INREG(chan->ddc_reg);
+
+ return (val & VGA_DDC_CLK_INPUT) ? 1 : 0;
+}
+
+static int radeon_gpio_getsda(void* data)
+{
+ struct radeon_i2c_chan *chan = data;
+ struct radeonfb_info *rinfo = chan->rinfo;
+ u32 val;
+
+ val = INREG(chan->ddc_reg);
+
+ return (val & VGA_DDC_DATA_INPUT) ? 1 : 0;
+}
+
+static int radeon_setup_i2c_bus(struct radeon_i2c_chan *chan, const char *name)
+{
+ int rc;
+
+ strcpy(chan->adapter.name, name);
+ chan->adapter.owner = THIS_MODULE;
+ chan->adapter.id = I2C_ALGO_ATI;
+ chan->adapter.algo_data = &chan->algo;
+ chan->adapter.dev.parent = &chan->rinfo->pdev->dev;
+ chan->algo.setsda = radeon_gpio_setsda;
+ chan->algo.setscl = radeon_gpio_setscl;
+ chan->algo.getsda = radeon_gpio_getsda;
+ chan->algo.getscl = radeon_gpio_getscl;
+ chan->algo.udelay = 40;
+ chan->algo.timeout = 20;
+ chan->algo.data = chan;
+
+ i2c_set_adapdata(&chan->adapter, chan);
+
+ /* Raise SCL and SDA */
+ radeon_gpio_setsda(chan, 1);
+ radeon_gpio_setscl(chan, 1);
+ udelay(20);
+
+ rc = i2c_bit_add_bus(&chan->adapter);
+ if (rc == 0)
+ dev_dbg(&chan->rinfo->pdev->dev, "I2C bus %s registered.\n", name);
+ else
+ dev_warn(&chan->rinfo->pdev->dev, "Failed to register I2C bus %s.\n", name);
+ return rc;
+}
+
+void radeon_create_i2c_busses(struct radeonfb_info *rinfo)
+{
+ rinfo->i2c[0].rinfo = rinfo;
+ rinfo->i2c[0].ddc_reg = GPIO_MONID;
+ radeon_setup_i2c_bus(&rinfo->i2c[0], "monid");
+
+ rinfo->i2c[1].rinfo = rinfo;
+ rinfo->i2c[1].ddc_reg = GPIO_DVI_DDC;
+ radeon_setup_i2c_bus(&rinfo->i2c[1], "dvi");
+
+ rinfo->i2c[2].rinfo = rinfo;
+ rinfo->i2c[2].ddc_reg = GPIO_VGA_DDC;
+ radeon_setup_i2c_bus(&rinfo->i2c[2], "vga");
+
+ rinfo->i2c[3].rinfo = rinfo;
+ rinfo->i2c[3].ddc_reg = GPIO_CRT2_DDC;
+ radeon_setup_i2c_bus(&rinfo->i2c[3], "crt2");
+}
+
+void radeon_delete_i2c_busses(struct radeonfb_info *rinfo)
+{
+ if (rinfo->i2c[0].rinfo)
+ i2c_bit_del_bus(&rinfo->i2c[0].adapter);
+ rinfo->i2c[0].rinfo = NULL;
+
+ if (rinfo->i2c[1].rinfo)
+ i2c_bit_del_bus(&rinfo->i2c[1].adapter);
+ rinfo->i2c[1].rinfo = NULL;
+
+ if (rinfo->i2c[2].rinfo)
+ i2c_bit_del_bus(&rinfo->i2c[2].adapter);
+ rinfo->i2c[2].rinfo = NULL;
+
+ if (rinfo->i2c[3].rinfo)
+ i2c_bit_del_bus(&rinfo->i2c[3].adapter);
+ rinfo->i2c[3].rinfo = NULL;
+}
+
+
+static u8 *radeon_do_probe_i2c_edid(struct radeon_i2c_chan *chan)
+{
+ u8 start = 0x0;
+ struct i2c_msg msgs[] = {
+ {
+ .addr = RADEON_DDC,
+ .len = 1,
+ .buf = &start,
+ }, {
+ .addr = RADEON_DDC,
+ .flags = I2C_M_RD,
+ .len = EDID_LENGTH,
+ },
+ };
+ u8 *buf;
+
+ buf = kmalloc(EDID_LENGTH, GFP_KERNEL);
+ if (!buf) {
+ dev_warn(&chan->rinfo->pdev->dev, "Out of memory!\n");
+ return NULL;
+ }
+ msgs[1].buf = buf;
+
+ if (i2c_transfer(&chan->adapter, msgs, 2) == 2)
+ return buf;
+ dev_dbg(&chan->rinfo->pdev->dev, "Unable to read EDID block.\n");
+ kfree(buf);
+ return NULL;
+}
+
+
+int radeon_probe_i2c_connector(struct radeonfb_info *rinfo, int conn, u8 **out_edid)
+{
+ u32 reg = rinfo->i2c[conn-1].ddc_reg;
+ u8 *edid = NULL;
+ int i, j;
+
+ OUTREG(reg, INREG(reg) &
+ ~(VGA_DDC_DATA_OUTPUT | VGA_DDC_CLK_OUTPUT));
+
+ OUTREG(reg, INREG(reg) & ~(VGA_DDC_CLK_OUT_EN));
+ (void)INREG(reg);
+
+ for (i = 0; i < 3; i++) {
+ /* For some old monitors we need the
+ * following process to initialize/stop DDC
+ */
+ OUTREG(reg, INREG(reg) & ~(VGA_DDC_DATA_OUT_EN));
+ (void)INREG(reg);
+ wait_ms(13);
+
+ OUTREG(reg, INREG(reg) & ~(VGA_DDC_CLK_OUT_EN));
+ (void)INREG(reg);
+ for (j = 0; j < 5; j++) {
+ wait_ms(10);
+ if (INREG(reg) & VGA_DDC_CLK_INPUT)
+ break;
+ }
+ if (j == 5)
+ continue;
+
+ OUTREG(reg, INREG(reg) | VGA_DDC_DATA_OUT_EN);
+ (void)INREG(reg);
+ wait_ms(15);
+ OUTREG(reg, INREG(reg) | VGA_DDC_CLK_OUT_EN);
+ (void)INREG(reg);
+ wait_ms(15);
+ OUTREG(reg, INREG(reg) & ~(VGA_DDC_DATA_OUT_EN));
+ (void)INREG(reg);
+ wait_ms(15);
+
+ /* Do the real work */
+ edid = radeon_do_probe_i2c_edid(&rinfo->i2c[conn-1]);
+
+ OUTREG(reg, INREG(reg) |
+ (VGA_DDC_DATA_OUT_EN | VGA_DDC_CLK_OUT_EN));
+ (void)INREG(reg);
+ wait_ms(15);
+
+ OUTREG(reg, INREG(reg) & ~(VGA_DDC_CLK_OUT_EN));
+ (void)INREG(reg);
+ for (j = 0; j < 10; j++) {
+ wait_ms(10);
+ if (INREG(reg) & VGA_DDC_CLK_INPUT)
+ break;
+ }
+
+ OUTREG(reg, INREG(reg) & ~(VGA_DDC_DATA_OUT_EN));
+ (void)INREG(reg);
+ wait_ms(15);
+ OUTREG(reg, INREG(reg) |
+ (VGA_DDC_DATA_OUT_EN | VGA_DDC_CLK_OUT_EN));
+ (void)INREG(reg);
+ if (edid)
+ break;
+ }
+ if (out_edid)
+ *out_edid = edid;
+ if (!edid) {
+ RTRACE("radeonfb: I2C (port %d) ... not found\n", conn);
+ return MT_NONE;
+ }
+ if (edid[0x14] & 0x80) {
+ if (rinfo->is_mobility && conn == ddc_dvi &&
+ (INREG(LVDS_GEN_CNTL) & LVDS_ON)) {
+ RTRACE("radeonfb: I2C (port %d) ... found LVDS panel\n", conn);
+ return MT_LCD;
+ } else {
+ RTRACE("radeonfb: I2C (port %d) ... found TMDS panel\n", conn);
+ return MT_DFP;
+ }
+ }
+ RTRACE("radeonfb: I2C (port %d) ... found CRT display\n", conn);
+ return MT_CRT;
+}
+
--- /dev/null
+#include "radeonfb.h"
+#include "../edid.h"
+
+#ifdef CONFIG_PPC_OF
+#include <asm/prom.h>
+#include <asm/pci-bridge.h>
+#endif /* CONFIG_PPC_OF */
+
+static struct fb_var_screeninfo radeonfb_default_var = {
+ 640, 480, 640, 480, 0, 0, 8, 0,
+ {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
+ 0, 0, -1, -1, 0, 39721, 40, 24, 32, 11, 96, 2,
+ 0, FB_VMODE_NONINTERLACED
+};
+
+static char *radeon_get_mon_name(int type)
+{
+ char *pret = NULL;
+
+ switch (type) {
+ case MT_NONE:
+ pret = "no";
+ break;
+ case MT_CRT:
+ pret = "CRT";
+ break;
+ case MT_DFP:
+ pret = "DFP";
+ break;
+ case MT_LCD:
+ pret = "LCD";
+ break;
+ case MT_CTV:
+ pret = "CTV";
+ break;
+ case MT_STV:
+ pret = "STV";
+ break;
+ }
+
+ return pret;
+}
+
+
+#ifdef CONFIG_PPC_OF
+/*
+ * Try to find monitor informations & EDID data out of the Open Firmware
+ * device-tree. This also contains some "hacks" to work around a few machine
+ * models with broken OF probing by hard-coding known EDIDs for some Mac
+ * laptops internal LVDS panel. (XXX: not done yet)
+ */
+static int __devinit radeon_parse_montype_prop(struct device_node *dp, u8 **out_EDID, int hdno)
+{
+ static char *propnames[] = { "DFP,EDID", "LCD,EDID", "EDID", "EDID1", "EDID2", NULL };
+ u8 *pedid = NULL;
+ u8 *pmt = NULL;
+ u8 *tmp;
+ int i, mt;
+
+ RTRACE("analyzing OF properties...\n");
+ pmt = (u8 *)get_property(dp, "display-type", NULL);
+ if (!pmt)
+ return MT_NONE;
+ RTRACE("display-type: %s\n", pmt);
+ /* OF says "LCD" for DFP as well, we discriminate from the caller of this
+ * function
+ */
+ if (!strcmp(pmt, "LCD") || !strcmp(pmt, "DFP"))
+ mt = MT_DFP;
+ else if (!strcmp(pmt, "CRT"))
+ mt = MT_CRT;
+ else if (strcmp(pmt, "NONE")) {
+ printk(KERN_WARNING "radeonfb: Unknown OF display-type: %s\n", pmt);
+ return MT_NONE;
+ }
+ for (i = 0; propnames[i] != NULL; ++i) {
+ pedid = (u8 *)get_property(dp, propnames[i], NULL);
+ if (pedid != NULL)
+ break;
+ }
+ /* We didn't find the EDID in the leaf node, some cards will actually
+ * put EDID1/EDID2 in the parent, look for these (typically M6 tipb).
+ * single-head cards have hdno == -1 and skip this step
+ */
+ if (pedid == NULL && dp->parent && (hdno != -1))
+ pedid = get_property(dp->parent, (hdno == 0) ? "EDID1" : "EDID2", NULL);
+ if (pedid == NULL && dp->parent && (hdno == 0))
+ pedid = get_property(dp->parent, "EDID", NULL);
+ if (pedid == NULL)
+ return mt;
+
+ tmp = (u8 *)kmalloc(EDID_LENGTH, GFP_KERNEL);
+ if (!tmp)
+ return mt;
+ memcpy(tmp, pedid, EDID_LENGTH);
+ *out_EDID = tmp;
+ return mt;
+}
+
+static int __devinit radeon_probe_OF_head(struct radeonfb_info *rinfo, int head_no,
+ u8 **out_EDID)
+{
+ struct device_node *dp;
+
+ RTRACE("radeon_probe_OF_head\n");
+
+ dp = pci_device_to_OF_node(rinfo->pdev);
+ while (dp == NULL)
+ return MT_NONE;
+
+ if (rinfo->has_CRTC2) {
+ char *pname;
+ int len, second = 0;
+
+ dp = dp->child;
+ do {
+ if (!dp)
+ return MT_NONE;
+ pname = (char *)get_property(dp, "name", NULL);
+ if (!pname)
+ return MT_NONE;
+ len = strlen(pname);
+ RTRACE("head: %s (letter: %c, head_no: %d)\n",
+ pname, pname[len-1], head_no);
+ if (pname[len-1] == 'A' && head_no == 0) {
+ int mt = radeon_parse_montype_prop(dp, out_EDID, 0);
+ /* Maybe check for LVDS_GEN_CNTL here ? I need to check out
+ * what OF does when booting with lid closed
+ */
+ if (mt == MT_DFP && rinfo->is_mobility)
+ mt = MT_LCD;
+ return mt;
+ } else if (pname[len-1] == 'B' && head_no == 1)
+ return radeon_parse_montype_prop(dp, out_EDID, 1);
+ second = 1;
+ dp = dp->sibling;
+ } while(!second);
+ } else {
+ if (head_no > 0)
+ return MT_NONE;
+ return radeon_parse_montype_prop(dp, out_EDID, -1);
+ }
+ return MT_NONE;
+}
+#endif /* CONFIG_PPC_OF */
+
+
+static int __devinit radeon_get_panel_info_BIOS(struct radeonfb_info *rinfo)
+{
+ unsigned long tmp, tmp0;
+ char stmp[30];
+ int i;
+
+ if (!rinfo->bios_seg)
+ return 0;
+
+ if (!(tmp = BIOS_IN16(rinfo->fp_bios_start + 0x40))) {
+ printk(KERN_ERR "radeonfb: Failed to detect DFP panel info using BIOS\n");
+ return 0;
+ }
+
+ for(i=0; i<24; i++)
+ stmp[i] = BIOS_IN8(tmp+i+1);
+ stmp[24] = 0;
+ printk("radeonfb: panel ID string: %s\n", stmp);
+ rinfo->panel_info.xres = BIOS_IN16(tmp + 25);
+ rinfo->panel_info.yres = BIOS_IN16(tmp + 27);
+ printk("radeonfb: detected LVDS panel size from BIOS: %dx%d\n",
+ rinfo->panel_info.xres, rinfo->panel_info.yres);
+
+ rinfo->panel_info.pwr_delay = BIOS_IN16(tmp + 44);
+ if (rinfo->panel_info.pwr_delay > 2000 || rinfo->panel_info.pwr_delay < 0)
+ rinfo->panel_info.pwr_delay = 2000;
+
+ /*
+ * Some panels only work properly with some divider combinations
+ */
+ rinfo->panel_info.ref_divider = BIOS_IN16(tmp + 46);
+ rinfo->panel_info.post_divider = BIOS_IN8(tmp + 48);
+ rinfo->panel_info.fbk_divider = BIOS_IN16(tmp + 49);
+ if (rinfo->panel_info.ref_divider != 0 &&
+ rinfo->panel_info.fbk_divider > 3) {
+ rinfo->panel_info.use_bios_dividers = 1;
+ printk(KERN_INFO "radeondb: BIOS provided dividers will be used\n");
+ }
+ for(i=0; i<32; i++) {
+ tmp0 = BIOS_IN16(tmp+64+i*2);
+ if (tmp0 == 0)
+ break;
+ if ((BIOS_IN16(tmp0) == rinfo->panel_info.xres) &&
+ (BIOS_IN16(tmp0+2) == rinfo->panel_info.yres)) {
+ rinfo->panel_info.hblank = (BIOS_IN16(tmp0+17) - BIOS_IN16(tmp0+19)) * 8;
+ rinfo->panel_info.hOver_plus = ((BIOS_IN16(tmp0+21) -
+ BIOS_IN16(tmp0+19) -1) * 8) & 0x7fff;
+ rinfo->panel_info.hSync_width = BIOS_IN8(tmp0+23) * 8;
+ rinfo->panel_info.vblank = BIOS_IN16(tmp0+24) - BIOS_IN16(tmp0+26);
+ rinfo->panel_info.vOver_plus = (BIOS_IN16(tmp0+28) & 0x7ff) - BIOS_IN16(tmp0+26);
+ rinfo->panel_info.vSync_width = (BIOS_IN16(tmp0+28) & 0xf800) >> 11;
+ rinfo->panel_info.clock = BIOS_IN16(tmp0+9);
+ /* Assume high active syncs for now until ATI tells me more... maybe we
+ * can probe register values here ?
+ */
+ rinfo->panel_info.hAct_high = 1;
+ rinfo->panel_info.vAct_high = 1;
+ /* Mark panel infos valid */
+ rinfo->panel_info.valid = 1;
+
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * Probe physical connection of a CRT. This code comes from XFree
+ * as well and currently is only implemented for the CRT DAC, the
+ * code for the TVDAC is commented out in XFree as "non working"
+ */
+static int __devinit radeon_crt_is_connected(struct radeonfb_info *rinfo, int is_crt_dac)
+{
+ int connected = 0;
+
+ /* the monitor either wasn't connected or it is a non-DDC CRT.
+ * try to probe it
+ */
+ if(is_crt_dac) {
+ unsigned long ulOrigVCLK_ECP_CNTL;
+ unsigned long ulOrigDAC_CNTL;
+ unsigned long ulOrigDAC_EXT_CNTL;
+ unsigned long ulOrigCRTC_EXT_CNTL;
+ unsigned long ulData;
+ unsigned long ulMask;
+
+ ulOrigVCLK_ECP_CNTL = INPLL(VCLK_ECP_CNTL);
+
+ ulData = ulOrigVCLK_ECP_CNTL;
+ ulData &= ~(PIXCLK_ALWAYS_ONb
+ | PIXCLK_DAC_ALWAYS_ONb);
+ ulMask = ~(PIXCLK_ALWAYS_ONb
+ | PIXCLK_DAC_ALWAYS_ONb);
+ OUTPLLP(VCLK_ECP_CNTL, ulData, ulMask);
+
+ ulOrigCRTC_EXT_CNTL = INREG(CRTC_EXT_CNTL);
+ ulData = ulOrigCRTC_EXT_CNTL;
+ ulData |= CRTC_CRT_ON;
+ OUTREG(CRTC_EXT_CNTL, ulData);
+
+ ulOrigDAC_EXT_CNTL = INREG(DAC_EXT_CNTL);
+ ulData = ulOrigDAC_EXT_CNTL;
+ ulData &= ~DAC_FORCE_DATA_MASK;
+ ulData |= (DAC_FORCE_BLANK_OFF_EN
+ |DAC_FORCE_DATA_EN
+ |DAC_FORCE_DATA_SEL_MASK);
+ if ((rinfo->family == CHIP_FAMILY_RV250) ||
+ (rinfo->family == CHIP_FAMILY_RV280))
+ ulData |= (0x01b6 << DAC_FORCE_DATA_SHIFT);
+ else
+ ulData |= (0x01ac << DAC_FORCE_DATA_SHIFT);
+
+ OUTREG(DAC_EXT_CNTL, ulData);
+
+ ulOrigDAC_CNTL = INREG(DAC_CNTL);
+ ulData = ulOrigDAC_CNTL;
+ ulData |= DAC_CMP_EN;
+ ulData &= ~(DAC_RANGE_CNTL_MASK
+ | DAC_PDWN);
+ ulData |= 0x2;
+ OUTREG(DAC_CNTL, ulData);
+
+ mdelay(1);
+
+ ulData = INREG(DAC_CNTL);
+ connected = (DAC_CMP_OUTPUT & ulData) ? 1 : 0;
+
+ ulData = ulOrigVCLK_ECP_CNTL;
+ ulMask = 0xFFFFFFFFL;
+ OUTPLLP(VCLK_ECP_CNTL, ulData, ulMask);
+
+ OUTREG(DAC_CNTL, ulOrigDAC_CNTL );
+ OUTREG(DAC_EXT_CNTL, ulOrigDAC_EXT_CNTL );
+ OUTREG(CRTC_EXT_CNTL, ulOrigCRTC_EXT_CNTL);
+ }
+
+ return connected ? MT_CRT : MT_NONE;
+}
+
+/*
+ * Parse the "monitor_layout" string if any. This code is mostly
+ * copied from XFree's radeon driver
+ */
+static int __devinit radeon_parse_monitor_layout(struct radeonfb_info *rinfo,
+ const char *monitor_layout)
+{
+ char s1[5], s2[5];
+ int i = 0, second = 0;
+ const char *s;
+
+ if (!monitor_layout)
+ return 0;
+
+ s = monitor_layout;
+ do {
+ switch(*s) {
+ case ',':
+ s1[i] = '\0';
+ i = 0;
+ second = 1;
+ break;
+ case ' ':
+ case '\0':
+ break;
+ default:
+ if (i > 4)
+ break;
+ if (second)
+ s2[i] = *s;
+ else
+ s1[i] = *s;
+ i++;
+ }
+ } while (*s++);
+ if (second)
+ s2[i] = 0;
+ else {
+ s1[i] = 0;
+ s2[0] = 0;
+ }
+ if (strcmp(s1, "CRT") == 0)
+ rinfo->mon1_type = MT_CRT;
+ else if (strcmp(s1, "TMDS") == 0)
+ rinfo->mon1_type = MT_DFP;
+ else if (strcmp(s1, "LVDS") == 0)
+ rinfo->mon1_type = MT_LCD;
+
+ if (strcmp(s2, "CRT") == 0)
+ rinfo->mon2_type = MT_CRT;
+ else if (strcmp(s2, "TMDS") == 0)
+ rinfo->mon2_type = MT_DFP;
+ else if (strcmp(s2, "LVDS") == 0)
+ rinfo->mon2_type = MT_LCD;
+
+ return 1;
+}
+
+/*
+ * Probe display on both primary and secondary card's connector (if any)
+ * by various available techniques (i2c, OF device tree, BIOS, ...) and
+ * try to retreive EDID. The algorithm here comes from XFree's radeon
+ * driver
+ */
+void __devinit radeon_probe_screens(struct radeonfb_info *rinfo,
+ const char *monitor_layout, int ignore_edid)
+{
+#ifdef CONFIG_FB_RADEON_I2C
+ int ddc_crt2_used = 0;
+#endif
+ int tmp, i;
+
+ if (radeon_parse_monitor_layout(rinfo, monitor_layout)) {
+
+ /*
+ * If user specified a monitor_layout option, use it instead
+ * of auto-detecting. Maybe we should only use this argument
+ * on the first radeon card probed or provide a way to specify
+ * a layout for each card ?
+ */
+
+ RTRACE("Using specified monitor layout: %s", monitor_layout);
+#ifdef CONFIG_FB_RADEON_I2C
+ if (!ignore_edid) {
+ if (rinfo->mon1_type != MT_NONE)
+ if (!radeon_probe_i2c_connector(rinfo, ddc_dvi, &rinfo->mon1_EDID)) {
+ radeon_probe_i2c_connector(rinfo, ddc_crt2, &rinfo->mon1_EDID);
+ ddc_crt2_used = 1;
+ }
+ if (rinfo->mon2_type != MT_NONE)
+ if (!radeon_probe_i2c_connector(rinfo, ddc_vga, &rinfo->mon2_EDID) &&
+ !ddc_crt2_used)
+ radeon_probe_i2c_connector(rinfo, ddc_crt2, &rinfo->mon2_EDID);
+ }
+#endif /* CONFIG_FB_RADEON_I2C */
+ if (rinfo->mon1_type == MT_NONE) {
+ if (rinfo->mon2_type != MT_NONE) {
+ rinfo->mon1_type = rinfo->mon2_type;
+ rinfo->mon1_EDID = rinfo->mon2_EDID;
+ } else {
+ rinfo->mon1_type = MT_CRT;
+ printk(KERN_INFO "radeonfb: No valid monitor, assuming CRT on first port\n");
+ }
+ rinfo->mon2_type = MT_NONE;
+ rinfo->mon2_EDID = NULL;
+ }
+ } else {
+
+ /*
+ * Auto-detecting display type (well... trying to ...)
+ */
+
+ RTRACE("Starting monitor auto detection...\n");
+
+ /*
+ * Old single head cards
+ */
+ if (!rinfo->has_CRTC2) {
+#ifdef CONFIG_PPC_OF
+ if (rinfo->mon1_type == MT_NONE)
+ rinfo->mon1_type = radeon_probe_OF_head(rinfo, 0,
+ &rinfo->mon1_EDID);
+#endif /* CONFIG_PPC_OF */
+#ifdef CONFIG_FB_RADEON_I2C
+ if (rinfo->mon1_type == MT_NONE)
+ rinfo->mon1_type = radeon_probe_i2c_connector(rinfo, ddc_dvi,
+ &rinfo->mon1_EDID);
+ if (rinfo->mon1_type == MT_NONE)
+ rinfo->mon1_type =
+ radeon_probe_i2c_connector(rinfo, ddc_vga,
+ &rinfo->mon1_EDID);
+ if (rinfo->mon1_type == MT_NONE)
+ rinfo->mon1_type =
+ radeon_probe_i2c_connector(rinfo, ddc_crt2,
+ &rinfo->mon1_EDID);
+#endif /* CONFIG_FB_RADEON_I2C */
+ if (rinfo->mon1_type == MT_NONE)
+ rinfo->mon1_type = MT_CRT;
+ goto bail;
+ }
+
+ /*
+ * Check for cards with reversed DACs or TMDS controllers using BIOS
+ */
+ if (rinfo->bios_seg &&
+ (tmp = BIOS_IN16(rinfo->fp_bios_start + 0x50))) {
+ for (i = 1; i < 4; i++) {
+ unsigned int tmp0;
+
+ if (!BIOS_IN8(tmp + i*2) && i > 1)
+ break;
+ tmp0 = BIOS_IN16(tmp + i*2);
+ if ((!(tmp0 & 0x01)) && (((tmp0 >> 8) & 0x0f) == ddc_dvi)) {
+ rinfo->reversed_DAC = 1;
+ printk(KERN_INFO "radeonfb: Reversed DACs detected\n");
+ }
+ if ((((tmp0 >> 8) & 0x0f) == ddc_dvi) && ((tmp0 >> 4) & 0x01)) {
+ rinfo->reversed_TMDS = 1;
+ printk(KERN_INFO "radeonfb: Reversed TMDS detected\n");
+ }
+ }
+ }
+
+ /*
+ * Probe primary head (DVI or laptop internal panel)
+ */
+#ifdef CONFIG_PPC_OF
+ if (rinfo->mon1_type == MT_NONE)
+ rinfo->mon1_type = radeon_probe_OF_head(rinfo, 0, &rinfo->mon1_EDID);
+#endif /* CONFIG_PPC_OF */
+#ifdef CONFIG_FB_RADEON_I2C
+ if (rinfo->mon1_type == MT_NONE)
+ rinfo->mon1_type = radeon_probe_i2c_connector(rinfo, ddc_dvi,
+ &rinfo->mon1_EDID);
+ if (rinfo->mon1_type == MT_NONE) {
+ rinfo->mon1_type = radeon_probe_i2c_connector(rinfo, ddc_crt2,
+ &rinfo->mon1_EDID);
+ if (rinfo->mon1_type != MT_NONE)
+ ddc_crt2_used = 1;
+ }
+#endif /* CONFIG_FB_RADEON_I2C */
+ if (rinfo->mon1_type == MT_NONE && rinfo->is_mobility &&
+ ((rinfo->bios_seg && (INREG(BIOS_4_SCRATCH) & 4))
+ || (INREG(LVDS_GEN_CNTL) & LVDS_ON))) {
+ rinfo->mon1_type = MT_LCD;
+ printk("Non-DDC laptop panel detected\n");
+ }
+ if (rinfo->mon1_type == MT_NONE)
+ rinfo->mon1_type = radeon_crt_is_connected(rinfo, rinfo->reversed_DAC);
+
+ /*
+ * Probe secondary head (mostly VGA, can be DVI)
+ */
+#ifdef CONFIG_PPC_OF
+ if (rinfo->mon2_type == MT_NONE)
+ rinfo->mon2_type = radeon_probe_OF_head(rinfo, 1, &rinfo->mon2_EDID);
+#endif /* CONFIG_PPC_OF */
+#ifdef CONFIG_FB_RADEON_I2C
+ if (rinfo->mon2_type == MT_NONE)
+ rinfo->mon2_type = radeon_probe_i2c_connector(rinfo, ddc_vga,
+ &rinfo->mon2_EDID);
+ if (rinfo->mon2_type == MT_NONE && !ddc_crt2_used)
+ rinfo->mon2_type = radeon_probe_i2c_connector(rinfo, ddc_crt2,
+ &rinfo->mon2_EDID);
+#endif /* CONFIG_FB_RADEON_I2C */
+ if (rinfo->mon2_type == MT_NONE)
+ rinfo->mon2_type = radeon_crt_is_connected(rinfo, !rinfo->reversed_DAC);
+
+ /*
+ * If we only detected port 2, we swap them, if none detected,
+ * assume CRT (maybe fallback to old BIOS_SCRATCH stuff ? or look
+ * at FP registers ?)
+ */
+ if (rinfo->mon1_type == MT_NONE) {
+ if (rinfo->mon2_type != MT_NONE) {
+ rinfo->mon1_type = rinfo->mon2_type;
+ rinfo->mon1_EDID = rinfo->mon2_EDID;
+ } else
+ rinfo->mon1_type = MT_CRT;
+ rinfo->mon2_type = MT_NONE;
+ rinfo->mon2_EDID = NULL;
+ }
+
+ /*
+ * Deal with reversed TMDS
+ */
+ if (rinfo->reversed_TMDS) {
+ /* Always keep internal TMDS as primary head */
+ if (rinfo->mon1_type == MT_DFP || rinfo->mon2_type == MT_DFP) {
+ int tmp_type = rinfo->mon1_type;
+ u8 *tmp_EDID = rinfo->mon1_EDID;
+ rinfo->mon1_type = rinfo->mon2_type;
+ rinfo->mon1_EDID = rinfo->mon2_EDID;
+ rinfo->mon2_type = tmp_type;
+ rinfo->mon2_EDID = tmp_EDID;
+ if (rinfo->mon1_type == MT_CRT || rinfo->mon2_type == MT_CRT)
+ rinfo->reversed_DAC ^= 1;
+ }
+ }
+ }
+ if (ignore_edid) {
+ if (rinfo->mon1_EDID)
+ kfree(rinfo->mon1_EDID);
+ rinfo->mon1_EDID = NULL;
+ if (rinfo->mon2_EDID)
+ kfree(rinfo->mon2_EDID);
+ rinfo->mon2_EDID = NULL;
+ }
+
+ bail:
+ printk(KERN_INFO "radeonfb: Monitor 1 type %s found\n",
+ radeon_get_mon_name(rinfo->mon1_type));
+ if (rinfo->mon1_EDID)
+ printk(KERN_INFO "radeonfb: EDID probed\n");
+ if (!rinfo->has_CRTC2)
+ return;
+ printk(KERN_INFO "radeonfb: Monitor 2 type %s found\n",
+ radeon_get_mon_name(rinfo->mon2_type));
+ if (rinfo->mon2_EDID)
+ printk(KERN_INFO "radeonfb: EDID probed\n");
+}
+
+
+/*
+ * This functions applyes any arch/model/machine specific fixups
+ * to the panel info. It may eventually alter EDID block as
+ * well or whatever is specific to a given model and not probed
+ * properly by the default code
+ */
+static void radeon_fixup_panel_info(struct radeonfb_info *rinfo)
+{
+ /*
+ * A few iBook laptop panels seem to need a fixed PLL setting
+ *
+ * We should probably do this differently based on the panel
+ * type/model or eventually some other device-tree informations,
+ * but these tweaks below work enough for now. --BenH
+ */
+#ifdef CONFIG_PPC_OF
+ /* iBook2's */
+ if (machine_is_compatible("PowerBook4,3")) {
+ rinfo->panel_info.ref_divider = rinfo->pll.ref_div;;
+ rinfo->panel_info.post_divider = 0x6;
+ rinfo->panel_info.fbk_divider = 0xad;
+ rinfo->panel_info.use_bios_dividers = 1;
+ }
+ /* Aluminium PowerBook 17" */
+ if (machine_is_compatible("PowerBook5,3")) {
+ rinfo->panel_info.ref_divider = rinfo->pll.ref_div;;
+ rinfo->panel_info.post_divider = 0x4;
+ rinfo->panel_info.fbk_divider = 0x80;
+ rinfo->panel_info.use_bios_dividers = 1;
+ }
+ /* iBook G4 */
+ if (machine_is_compatible("PowerBook6,3")) {
+ rinfo->panel_info.ref_divider = rinfo->pll.ref_div;;
+ rinfo->panel_info.post_divider = 0x6;
+ rinfo->panel_info.fbk_divider = 0xad;
+ rinfo->panel_info.use_bios_dividers = 1;
+ }
+#endif /* CONFIG_PPC_OF */
+}
+
+
+/*
+ * Fill up panel infos from a mode definition, either returned by the EDID
+ * or from the default mode when we can't do any better
+ */
+static void radeon_var_to_panel_info(struct radeonfb_info *rinfo, struct fb_var_screeninfo *var)
+{
+ rinfo->panel_info.xres = var->xres;
+ rinfo->panel_info.yres = var->yres;
+ rinfo->panel_info.clock = 100000000 / var->pixclock;
+ rinfo->panel_info.hOver_plus = var->right_margin;
+ rinfo->panel_info.hSync_width = var->hsync_len;
+ rinfo->panel_info.hblank = var->left_margin +
+ (var->right_margin + var->hsync_len);
+ rinfo->panel_info.vOver_plus = var->lower_margin;
+ rinfo->panel_info.vSync_width = var->vsync_len;
+ rinfo->panel_info.vblank = var->upper_margin +
+ (var->lower_margin + var->vsync_len);
+ rinfo->panel_info.hAct_high =
+ (var->sync & FB_SYNC_HOR_HIGH_ACT) != 0;
+ rinfo->panel_info.vAct_high =
+ (var->sync & FB_SYNC_VERT_HIGH_ACT) != 0;
+ rinfo->panel_info.valid = 1;
+ /* We use a default of 200ms for the panel power delay,
+ * I need to have a real schedule() instead of mdelay's in the panel code.
+ * we might be possible to figure out a better power delay either from
+ * MacOS OF tree or from the EDID block (proprietary extensions ?)
+ */
+ rinfo->panel_info.pwr_delay = 200;
+}
+
+static void radeon_var_to_videomode(struct fb_videomode *mode,
+ const struct fb_var_screeninfo *var)
+{
+ mode->xres = var->xres;
+ mode->yres = var->yres;
+ mode->pixclock = var->pixclock;
+ mode->left_margin = var->left_margin;
+ mode->right_margin = var->right_margin;
+ mode->upper_margin = var->upper_margin;
+ mode->lower_margin = var->lower_margin;
+ mode->hsync_len = var->hsync_len;
+ mode->vsync_len = var->vsync_len;
+ mode->sync = var->sync;
+ mode->vmode = var->vmode;
+}
+
+static void radeon_videomode_to_var(struct fb_var_screeninfo *var,
+ const struct fb_videomode *mode)
+{
+ var->xres = mode->xres;
+ var->yres = mode->yres;
+ var->xres_virtual = mode->xres;
+ var->yres_virtual = mode->yres;
+ var->xoffset = 0;
+ var->yoffset = 0;
+ var->pixclock = mode->pixclock;
+ var->left_margin = mode->left_margin;
+ var->right_margin = mode->right_margin;
+ var->upper_margin = mode->upper_margin;
+ var->lower_margin = mode->lower_margin;
+ var->hsync_len = mode->hsync_len;
+ var->vsync_len = mode->vsync_len;
+ var->sync = mode->sync;
+ var->vmode = mode->vmode;
+}
+
+/*
+ * Build the modedb for head 1 (head 2 will come later), check panel infos
+ * from either BIOS or EDID, and pick up the default mode
+ */
+void __devinit radeon_check_modes(struct radeonfb_info *rinfo, const char *mode_option)
+{
+ int has_default_mode = 0;
+
+ /*
+ * Fill default var first
+ */
+ rinfo->info->var = radeonfb_default_var;
+
+ /*
+ * First check out what BIOS has to say
+ */
+ if (rinfo->mon1_type == MT_LCD)
+ radeon_get_panel_info_BIOS(rinfo);
+
+ /*
+ * Parse EDID detailed timings and deduce panel infos if any. Right now
+ * we only deal with first entry returned by parse_EDID, we may do better
+ * some day...
+ */
+ if (!rinfo->panel_info.use_bios_dividers && rinfo->mon1_type != MT_CRT
+ && rinfo->mon1_EDID) {
+ struct fb_var_screeninfo var;
+ RTRACE("Parsing EDID data for panel info\n");
+ if (parse_edid(rinfo->mon1_EDID, &var) == 0) {
+ if (var.xres >= rinfo->panel_info.xres &&
+ var.yres >= rinfo->panel_info.yres)
+ radeon_var_to_panel_info(rinfo, &var);
+ }
+ }
+
+ /*
+ * Do any additional platform/arch fixups to the panel infos
+ */
+ radeon_fixup_panel_info(rinfo);
+
+ /*
+ * If we have some valid panel infos, we setup the default mode based on
+ * those
+ */
+ if (rinfo->mon1_type != MT_CRT && rinfo->panel_info.valid) {
+ struct fb_var_screeninfo *var = &rinfo->info->var;
+
+ RTRACE("Setting up default mode based on panel info\n");
+ var->xres = rinfo->panel_info.xres;
+ var->yres = rinfo->panel_info.yres;
+ var->xres_virtual = rinfo->panel_info.xres;
+ var->yres_virtual = rinfo->panel_info.yres;
+ var->xoffset = var->yoffset = 0;
+ var->bits_per_pixel = 8;
+ var->pixclock = 100000000 / rinfo->panel_info.clock;
+ var->left_margin = (rinfo->panel_info.hblank - rinfo->panel_info.hOver_plus
+ - rinfo->panel_info.hSync_width);
+ var->right_margin = rinfo->panel_info.hOver_plus;
+ var->upper_margin = (rinfo->panel_info.vblank - rinfo->panel_info.vOver_plus
+ - rinfo->panel_info.vSync_width);
+ var->lower_margin = rinfo->panel_info.vOver_plus;
+ var->hsync_len = rinfo->panel_info.hSync_width;
+ var->vsync_len = rinfo->panel_info.vSync_width;
+ var->sync = 0;
+ if (rinfo->panel_info.hAct_high)
+ var->sync |= FB_SYNC_HOR_HIGH_ACT;
+ if (rinfo->panel_info.vAct_high)
+ var->sync |= FB_SYNC_VERT_HIGH_ACT;
+ var->vmode = 0;
+ has_default_mode = 1;
+ }
+
+ /*
+ * Now build modedb from EDID
+ */
+ if (rinfo->mon1_EDID) {
+ rinfo->mon1_modedb = fb_create_modedb(rinfo->mon1_EDID,
+ &rinfo->mon1_dbsize);
+ fb_get_monitor_limits(rinfo->mon1_EDID, &rinfo->info->monspecs);
+ }
+
+
+ /*
+ * Finally, if we don't have panel infos we need to figure some (or
+ * we try to read it from card), we try to pick a default mode
+ * and create some panel infos. Whatever...
+ */
+ if (rinfo->mon1_type != MT_CRT && !rinfo->panel_info.valid) {
+ struct fb_videomode *modedb;
+ int dbsize;
+ char modename[32];
+
+ RTRACE("Guessing panel info...\n");
+ if (rinfo->panel_info.xres == 0 || rinfo->panel_info.yres == 0) {
+ u32 tmp = INREG(FP_HORZ_STRETCH) & HORZ_PANEL_SIZE;
+ rinfo->panel_info.xres = ((tmp >> HORZ_PANEL_SHIFT) + 1) * 8;
+ tmp = INREG(FP_VERT_STRETCH) & VERT_PANEL_SIZE;
+ rinfo->panel_info.yres = (tmp >> VERT_PANEL_SHIFT) + 1;
+ }
+ if (rinfo->panel_info.xres == 0 || rinfo->panel_info.yres == 0) {
+ printk(KERN_WARNING "radeonfb: Can't find panel size, going back to CRT\n");
+ rinfo->mon1_type = MT_CRT;
+ goto pickup_default;
+ }
+ printk(KERN_WARNING "radeonfb: Asssuming panel size %dx%d\n",
+ rinfo->panel_info.xres, rinfo->panel_info.yres);
+ modedb = rinfo->mon1_modedb;
+ dbsize = rinfo->mon1_dbsize;
+ snprintf(modename, 31, "%dx%d", rinfo->panel_info.xres, rinfo->panel_info.yres);
+ if (fb_find_mode(&rinfo->info->var, rinfo->info, modename,
+ modedb, dbsize, NULL, 8) == 0) {
+ printk(KERN_WARNING "radeonfb: Can't find mode for panel size, going back to CRT\n");
+ rinfo->mon1_type = MT_CRT;
+ goto pickup_default;
+ }
+ has_default_mode = 1;
+ radeon_var_to_panel_info(rinfo, &rinfo->info->var);
+ }
+
+ pickup_default:
+ /*
+ * Pick up a random default mode
+ */
+ if (!has_default_mode || mode_option) {
+ struct fb_videomode default_mode;
+ if (has_default_mode)
+ radeon_var_to_videomode(&default_mode, &rinfo->info->var);
+ else
+ radeon_var_to_videomode(&default_mode, &radeonfb_default_var);
+ if (fb_find_mode(&rinfo->info->var, rinfo->info, mode_option,
+ rinfo->mon1_modedb, rinfo->mon1_dbsize, &default_mode, 8) == 0)
+ rinfo->info->var = radeonfb_default_var;
+ }
+
+}
+
+/*
+ * The code below is used to pick up a mode in check_var and
+ * set_var. It should be made generic
+ */
+
+/*
+ * This is used when looking for modes. We assign a "goodness" value
+ * to a mode in the modedb depending how "close" it is from what we
+ * are looking for.
+ * Currently, we don't compare that much, we could do better but
+ * the current fbcon doesn't quite mind ;)
+ */
+static int radeon_compare_modes(const struct fb_var_screeninfo *var,
+ const struct fb_videomode *mode)
+{
+ int goodness = 0;
+
+ if (var->yres == mode->yres)
+ goodness += 10;
+ if (var->xres == mode->xres)
+ goodness += 9;
+ return goodness;
+}
+
+/*
+ * This function is called by check_var, it gets the passed in mode parameter, and
+ * outputs a valid mode matching the passed-in one as closely as possible.
+ * We need something better ultimately. Things like fbcon basically pass us out
+ * current mode with xres/yres hacked, while things like XFree will actually
+ * produce a full timing that we should respect as much as possible.
+ *
+ * This is why I added the FB_ACTIVATE_FIND that is used by fbcon. Without this,
+ * we do a simple spec match, that's all. With it, we actually look for a mode in
+ * either our monitor modedb or the vesa one if none
+ *
+ */
+int radeon_match_mode(struct radeonfb_info *rinfo,
+ struct fb_var_screeninfo *dest,
+ const struct fb_var_screeninfo *src)
+{
+ const struct fb_videomode *db = vesa_modes;
+ int i, dbsize = 34;
+ int has_rmx, native_db = 0;
+ int goodness = 0;
+ const struct fb_videomode *candidate = NULL;
+
+ /* Start with a copy of the requested mode */
+ memcpy(dest, src, sizeof(struct fb_var_screeninfo));
+
+ /* Check if we have a modedb built from EDID */
+ if (rinfo->mon1_modedb) {
+ db = rinfo->mon1_modedb;
+ dbsize = rinfo->mon1_dbsize;
+ native_db = 1;
+ }
+
+ /* Check if we have a scaler allowing any fancy mode */
+ has_rmx = rinfo->mon1_type == MT_LCD || rinfo->mon1_type == MT_DFP;
+
+ /* If we have a scaler and are passed FB_ACTIVATE_TEST or
+ * FB_ACTIVATE_NOW, just do basic checking and return if the
+ * mode match
+ */
+ if ((src->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_TEST ||
+ (src->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
+ /* We don't have an RMX, validate timings. If we don't have
+ * monspecs, we should be paranoid and not let use go above
+ * 640x480-60, but I assume userland knows what it's doing here
+ * (though I may be proven wrong...)
+ */
+ if (has_rmx == 0 && rinfo->mon1_modedb)
+ if (fb_validate_mode((struct fb_var_screeninfo *)src, rinfo->info))
+ return -EINVAL;
+ return 0;
+ }
+
+ /* Now look for a mode in the database */
+ while (db) {
+ for (i = 0; i < dbsize; i++) {
+ int g;
+
+ if (db[i].yres < src->yres)
+ continue;
+ if (db[i].xres < src->xres)
+ continue;
+ g = radeon_compare_modes(src, &db[i]);
+ /* If the new mode is at least as good as the previous one,
+ * then it's our new candidate
+ */
+ if (g >= goodness) {
+ candidate = &db[i];
+ goodness = g;
+ }
+ }
+ db = NULL;
+ /* If we have a scaler, we allow any mode from the database */
+ if (native_db && has_rmx) {
+ db = vesa_modes;
+ dbsize = 34;
+ native_db = 0;
+ }
+ }
+
+ /* If we have found a match, return it */
+ if (candidate != NULL) {
+ radeon_videomode_to_var(dest, candidate);
+ return 0;
+ }
+
+ /* If we haven't and don't have a scaler, fail */
+ if (!has_rmx)
+ return -EINVAL;
+
+ return 0;
+}
--- /dev/null
+#include "radeonfb.h"
+
+#include <linux/console.h>
+#include <linux/agp_backend.h>
+
+/*
+ * Currently, only PowerMac do D2 state
+ */
+#define CONFIG_RADEON_HAS_D2 CONFIG_PPC_PMAC
+
+#ifdef CONFIG_RADEON_HAS_D2
+/*
+ * On PowerMac, we assume any mobility chip based machine does D2
+ */
+#ifdef CONFIG_PPC_PMAC
+static inline int radeon_suspend_to_d2(struct radeonfb_info *rinfo, u32 state)
+{
+ return rinfo->is_mobility;
+}
+#else
+static inline int radeon_suspend_to_d2(struct radeonfb_info *rinfo, u32 state)
+{
+ return 0;
+}
+#endif
+
+#endif /* CONFIG_RADEON_HAS_D2 */
+
+/*
+ * Radeon M6, M7 and M9 Power Management code. This code currently
+ * only supports the mobile chips in D2 mode, that is typically what
+ * is used on Apple laptops, it's based from some informations provided
+ * by ATI along with hours of tracing of MacOS drivers.
+ *
+ * New version of this code almost totally rewritten by ATI, many thanks
+ * for their support.
+ */
+
+void radeon_pm_disable_dynamic_mode(struct radeonfb_info *rinfo)
+{
+
+ u32 sclk_cntl;
+ u32 mclk_cntl;
+ u32 sclk_more_cntl;
+
+ u32 vclk_ecp_cntl;
+ u32 pixclks_cntl;
+
+ /* Mobility chips only, untested on M9+/M10/11 */
+ if (!rinfo->is_mobility)
+ return;
+ if (rinfo->family > CHIP_FAMILY_RV250)
+ return;
+
+ /* Force Core Clocks */
+ sclk_cntl = INPLL( pllSCLK_CNTL_M6);
+ sclk_cntl |= SCLK_CNTL_M6__FORCE_CP|
+ SCLK_CNTL_M6__FORCE_HDP|
+ SCLK_CNTL_M6__FORCE_DISP1|
+ SCLK_CNTL_M6__FORCE_DISP2|
+ SCLK_CNTL_M6__FORCE_TOP|
+ SCLK_CNTL_M6__FORCE_E2|
+ SCLK_CNTL_M6__FORCE_SE|
+ SCLK_CNTL_M6__FORCE_IDCT|
+ SCLK_CNTL_M6__FORCE_VIP|
+ SCLK_CNTL_M6__FORCE_RE|
+ SCLK_CNTL_M6__FORCE_PB|
+ SCLK_CNTL_M6__FORCE_TAM|
+ SCLK_CNTL_M6__FORCE_TDM|
+ SCLK_CNTL_M6__FORCE_RB|
+ SCLK_CNTL_M6__FORCE_TV_SCLK|
+ SCLK_CNTL_M6__FORCE_SUBPIC|
+ SCLK_CNTL_M6__FORCE_OV0;
+ OUTPLL( pllSCLK_CNTL_M6, sclk_cntl);
+
+
+
+ sclk_more_cntl = INPLL(pllSCLK_MORE_CNTL);
+ sclk_more_cntl |= SCLK_MORE_CNTL__FORCE_DISPREGS|
+ SCLK_MORE_CNTL__FORCE_MC_GUI|
+ SCLK_MORE_CNTL__FORCE_MC_HOST;
+ OUTPLL(pllSCLK_MORE_CNTL, sclk_more_cntl);
+
+ /* Force Display clocks */
+ vclk_ecp_cntl = INPLL( pllVCLK_ECP_CNTL);
+ vclk_ecp_cntl &= ~( VCLK_ECP_CNTL__PIXCLK_ALWAYS_ONb |
+ VCLK_ECP_CNTL__PIXCLK_DAC_ALWAYS_ONb);
+
+ OUTPLL( pllVCLK_ECP_CNTL, vclk_ecp_cntl);
+
+ pixclks_cntl = INPLL( pllPIXCLKS_CNTL);
+ pixclks_cntl &= ~( PIXCLKS_CNTL__PIXCLK_GV_ALWAYS_ONb |
+ PIXCLKS_CNTL__PIXCLK_BLEND_ALWAYS_ONb|
+ PIXCLKS_CNTL__PIXCLK_DIG_TMDS_ALWAYS_ONb |
+ PIXCLKS_CNTL__PIXCLK_LVDS_ALWAYS_ONb|
+ PIXCLKS_CNTL__PIXCLK_TMDS_ALWAYS_ONb|
+ PIXCLKS_CNTL__PIX2CLK_ALWAYS_ONb|
+ PIXCLKS_CNTL__PIX2CLK_DAC_ALWAYS_ONb);
+
+ OUTPLL( pllPIXCLKS_CNTL, pixclks_cntl);
+
+ /* Force Memory Clocks */
+ mclk_cntl = INPLL( pllMCLK_CNTL_M6);
+ mclk_cntl &= ~( MCLK_CNTL_M6__FORCE_MCLKA |
+ MCLK_CNTL_M6__FORCE_MCLKB |
+ MCLK_CNTL_M6__FORCE_YCLKA |
+ MCLK_CNTL_M6__FORCE_YCLKB );
+ OUTPLL( pllMCLK_CNTL_M6, mclk_cntl);
+}
+
+void radeon_pm_enable_dynamic_mode(struct radeonfb_info *rinfo)
+{
+ u32 clk_pwrmgt_cntl;
+ u32 sclk_cntl;
+ u32 sclk_more_cntl;
+ u32 clk_pin_cntl;
+ u32 pixclks_cntl;
+ u32 vclk_ecp_cntl;
+ u32 mclk_cntl;
+ u32 mclk_misc;
+
+ /* Mobility chips only, untested on M9+/M10/11 */
+ if (!rinfo->is_mobility)
+ return;
+ if (rinfo->family > CHIP_FAMILY_RV250)
+ return;
+
+ /* Set Latencies */
+ clk_pwrmgt_cntl = INPLL( pllCLK_PWRMGT_CNTL_M6);
+
+ clk_pwrmgt_cntl &= ~( CLK_PWRMGT_CNTL_M6__ENGINE_DYNCLK_MODE_MASK|
+ CLK_PWRMGT_CNTL_M6__ACTIVE_HILO_LAT_MASK|
+ CLK_PWRMGT_CNTL_M6__DISP_DYN_STOP_LAT_MASK|
+ CLK_PWRMGT_CNTL_M6__DYN_STOP_MODE_MASK);
+ /* Mode 1 */
+ clk_pwrmgt_cntl = CLK_PWRMGT_CNTL_M6__MC_CH_MODE|
+ CLK_PWRMGT_CNTL_M6__ENGINE_DYNCLK_MODE |
+ (1<<CLK_PWRMGT_CNTL_M6__ACTIVE_HILO_LAT__SHIFT) |
+ (0<<CLK_PWRMGT_CNTL_M6__DISP_DYN_STOP_LAT__SHIFT)|
+ (0<<CLK_PWRMGT_CNTL_M6__DYN_STOP_MODE__SHIFT);
+
+ OUTPLL( pllCLK_PWRMGT_CNTL_M6, clk_pwrmgt_cntl);
+
+
+ clk_pin_cntl = INPLL( pllCLK_PIN_CNTL);
+ clk_pin_cntl |= CLK_PIN_CNTL__SCLK_DYN_START_CNTL;
+
+ OUTPLL( pllCLK_PIN_CNTL, clk_pin_cntl);
+
+ /* Enable Dyanmic mode for SCLK */
+
+ sclk_cntl = INPLL( pllSCLK_CNTL_M6);
+ sclk_cntl &= SCLK_CNTL_M6__SCLK_SRC_SEL_MASK;
+ sclk_cntl |= SCLK_CNTL_M6__FORCE_VIP;
+
+ OUTPLL( pllSCLK_CNTL_M6, sclk_cntl);
+
+
+ sclk_more_cntl = INPLL(pllSCLK_MORE_CNTL);
+ sclk_more_cntl &= ~(SCLK_MORE_CNTL__FORCE_DISPREGS);
+
+ OUTPLL(pllSCLK_MORE_CNTL, sclk_more_cntl);
+
+
+ /* Enable Dynamic mode for PIXCLK & PIX2CLK */
+
+ pixclks_cntl = INPLL( pllPIXCLKS_CNTL);
+
+ pixclks_cntl|= PIXCLKS_CNTL__PIX2CLK_ALWAYS_ONb |
+ PIXCLKS_CNTL__PIX2CLK_DAC_ALWAYS_ONb|
+ PIXCLKS_CNTL__PIXCLK_BLEND_ALWAYS_ONb|
+ PIXCLKS_CNTL__PIXCLK_GV_ALWAYS_ONb|
+ PIXCLKS_CNTL__PIXCLK_DIG_TMDS_ALWAYS_ONb|
+ PIXCLKS_CNTL__PIXCLK_LVDS_ALWAYS_ONb|
+ PIXCLKS_CNTL__PIXCLK_TMDS_ALWAYS_ONb;
+
+ OUTPLL( pllPIXCLKS_CNTL, pixclks_cntl);
+
+
+ vclk_ecp_cntl = INPLL( pllVCLK_ECP_CNTL);
+
+ vclk_ecp_cntl|= VCLK_ECP_CNTL__PIXCLK_ALWAYS_ONb |
+ VCLK_ECP_CNTL__PIXCLK_DAC_ALWAYS_ONb;
+
+ OUTPLL( pllVCLK_ECP_CNTL, vclk_ecp_cntl);
+
+
+ /* Enable Dynamic mode for MCLK */
+
+ mclk_cntl = INPLL( pllMCLK_CNTL_M6);
+ mclk_cntl |= MCLK_CNTL_M6__FORCE_MCLKA|
+ MCLK_CNTL_M6__FORCE_MCLKB|
+ MCLK_CNTL_M6__FORCE_YCLKA|
+ MCLK_CNTL_M6__FORCE_YCLKB;
+
+ OUTPLL( pllMCLK_CNTL_M6, mclk_cntl);
+
+ mclk_misc = INPLL(pllMCLK_MISC);
+ mclk_misc |= MCLK_MISC__MC_MCLK_MAX_DYN_STOP_LAT|
+ MCLK_MISC__IO_MCLK_MAX_DYN_STOP_LAT|
+ MCLK_MISC__MC_MCLK_DYN_ENABLE|
+ MCLK_MISC__IO_MCLK_DYN_ENABLE;
+
+ OUTPLL(pllMCLK_MISC, mclk_misc);
+}
+
+#ifdef CONFIG_PM
+
+static void OUTMC( struct radeonfb_info *rinfo, u8 indx, u32 value)
+{
+ OUTREG( MC_IND_INDEX, indx | MC_IND_INDEX__MC_IND_WR_EN);
+ OUTREG( MC_IND_DATA, value);
+}
+
+static u32 INMC(struct radeonfb_info *rinfo, u8 indx)
+{
+ OUTREG( MC_IND_INDEX, indx);
+ return INREG( MC_IND_DATA);
+}
+
+static void radeon_pm_save_regs(struct radeonfb_info *rinfo)
+{
+ rinfo->save_regs[0] = INPLL(PLL_PWRMGT_CNTL);
+ rinfo->save_regs[1] = INPLL(CLK_PWRMGT_CNTL);
+ rinfo->save_regs[2] = INPLL(MCLK_CNTL);
+ rinfo->save_regs[3] = INPLL(SCLK_CNTL);
+ rinfo->save_regs[4] = INPLL(CLK_PIN_CNTL);
+ rinfo->save_regs[5] = INPLL(VCLK_ECP_CNTL);
+ rinfo->save_regs[6] = INPLL(PIXCLKS_CNTL);
+ rinfo->save_regs[7] = INPLL(MCLK_MISC);
+ rinfo->save_regs[8] = INPLL(P2PLL_CNTL);
+
+ rinfo->save_regs[9] = INREG(DISP_MISC_CNTL);
+ rinfo->save_regs[10] = INREG(DISP_PWR_MAN);
+ rinfo->save_regs[11] = INREG(LVDS_GEN_CNTL);
+ rinfo->save_regs[12] = INREG(LVDS_PLL_CNTL);
+ rinfo->save_regs[13] = INREG(TV_DAC_CNTL);
+ rinfo->save_regs[14] = INREG(BUS_CNTL1);
+ rinfo->save_regs[15] = INREG(CRTC_OFFSET_CNTL);
+ rinfo->save_regs[16] = INREG(AGP_CNTL);
+ rinfo->save_regs[17] = (INREG(CRTC_GEN_CNTL) & 0xfdffffff) | 0x04000000;
+ rinfo->save_regs[18] = (INREG(CRTC2_GEN_CNTL) & 0xfdffffff) | 0x04000000;
+ rinfo->save_regs[19] = INREG(GPIOPAD_A);
+ rinfo->save_regs[20] = INREG(GPIOPAD_EN);
+ rinfo->save_regs[21] = INREG(GPIOPAD_MASK);
+ rinfo->save_regs[22] = INREG(ZV_LCDPAD_A);
+ rinfo->save_regs[23] = INREG(ZV_LCDPAD_EN);
+ rinfo->save_regs[24] = INREG(ZV_LCDPAD_MASK);
+ rinfo->save_regs[25] = INREG(GPIO_VGA_DDC);
+ rinfo->save_regs[26] = INREG(GPIO_DVI_DDC);
+ rinfo->save_regs[27] = INREG(GPIO_MONID);
+ rinfo->save_regs[28] = INREG(GPIO_CRT2_DDC);
+
+ rinfo->save_regs[29] = INREG(SURFACE_CNTL);
+ rinfo->save_regs[30] = INREG(MC_FB_LOCATION);
+ rinfo->save_regs[31] = INREG(DISPLAY_BASE_ADDR);
+ rinfo->save_regs[32] = INREG(MC_AGP_LOCATION);
+ rinfo->save_regs[33] = INREG(CRTC2_DISPLAY_BASE_ADDR);
+}
+
+static void radeon_pm_restore_regs(struct radeonfb_info *rinfo)
+{
+ OUTPLL(P2PLL_CNTL, rinfo->save_regs[8] & 0xFFFFFFFE); /* First */
+
+ OUTPLL(PLL_PWRMGT_CNTL, rinfo->save_regs[0]);
+ OUTPLL(CLK_PWRMGT_CNTL, rinfo->save_regs[1]);
+ OUTPLL(MCLK_CNTL, rinfo->save_regs[2]);
+ OUTPLL(SCLK_CNTL, rinfo->save_regs[3]);
+ OUTPLL(CLK_PIN_CNTL, rinfo->save_regs[4]);
+ OUTPLL(VCLK_ECP_CNTL, rinfo->save_regs[5]);
+ OUTPLL(PIXCLKS_CNTL, rinfo->save_regs[6]);
+ OUTPLL(MCLK_MISC, rinfo->save_regs[7]);
+
+ OUTREG(SURFACE_CNTL, rinfo->save_regs[29]);
+ OUTREG(MC_FB_LOCATION, rinfo->save_regs[30]);
+ OUTREG(DISPLAY_BASE_ADDR, rinfo->save_regs[31]);
+ OUTREG(MC_AGP_LOCATION, rinfo->save_regs[32]);
+ OUTREG(CRTC2_DISPLAY_BASE_ADDR, rinfo->save_regs[33]);
+
+ OUTREG(DISP_MISC_CNTL, rinfo->save_regs[9]);
+ OUTREG(DISP_PWR_MAN, rinfo->save_regs[10]);
+ OUTREG(LVDS_GEN_CNTL, rinfo->save_regs[11]);
+ OUTREG(LVDS_PLL_CNTL,rinfo->save_regs[12]);
+ OUTREG(TV_DAC_CNTL, rinfo->save_regs[13]);
+ OUTREG(BUS_CNTL1, rinfo->save_regs[14]);
+ OUTREG(CRTC_OFFSET_CNTL, rinfo->save_regs[15]);
+ OUTREG(AGP_CNTL, rinfo->save_regs[16]);
+ OUTREG(CRTC_GEN_CNTL, rinfo->save_regs[17]);
+ OUTREG(CRTC2_GEN_CNTL, rinfo->save_regs[18]);
+
+ // wait VBL before that one ?
+ OUTPLL(P2PLL_CNTL, rinfo->save_regs[8]);
+
+ OUTREG(GPIOPAD_A, rinfo->save_regs[19]);
+ OUTREG(GPIOPAD_EN, rinfo->save_regs[20]);
+ OUTREG(GPIOPAD_MASK, rinfo->save_regs[21]);
+ OUTREG(ZV_LCDPAD_A, rinfo->save_regs[22]);
+ OUTREG(ZV_LCDPAD_EN, rinfo->save_regs[23]);
+ OUTREG(ZV_LCDPAD_MASK, rinfo->save_regs[24]);
+ OUTREG(GPIO_VGA_DDC, rinfo->save_regs[25]);
+ OUTREG(GPIO_DVI_DDC, rinfo->save_regs[26]);
+ OUTREG(GPIO_MONID, rinfo->save_regs[27]);
+ OUTREG(GPIO_CRT2_DDC, rinfo->save_regs[28]);
+}
+
+static void radeon_pm_disable_iopad(struct radeonfb_info *rinfo)
+{
+ OUTREG(GPIOPAD_MASK, 0x0001ffff);
+ OUTREG(GPIOPAD_EN, 0x00000400);
+ OUTREG(GPIOPAD_A, 0x00000000);
+ OUTREG(ZV_LCDPAD_MASK, 0x00000000);
+ OUTREG(ZV_LCDPAD_EN, 0x00000000);
+ OUTREG(ZV_LCDPAD_A, 0x00000000);
+ OUTREG(GPIO_VGA_DDC, 0x00030000);
+ OUTREG(GPIO_DVI_DDC, 0x00000000);
+ OUTREG(GPIO_MONID, 0x00030000);
+ OUTREG(GPIO_CRT2_DDC, 0x00000000);
+}
+
+static void radeon_pm_program_v2clk(struct radeonfb_info *rinfo)
+{
+ /* Set v2clk to 65MHz */
+ OUTPLL(pllPIXCLKS_CNTL,
+ INPLL(pllPIXCLKS_CNTL) & ~PIXCLKS_CNTL__PIX2CLK_SRC_SEL_MASK);
+
+ OUTPLL(pllP2PLL_REF_DIV, 0x0000000c);
+ OUTPLL(pllP2PLL_CNTL, 0x0000bf00);
+ OUTPLL(pllP2PLL_DIV_0, 0x00020074 | P2PLL_DIV_0__P2PLL_ATOMIC_UPDATE_W);
+
+ OUTPLL(pllP2PLL_CNTL, INPLL(pllP2PLL_CNTL) & ~P2PLL_CNTL__P2PLL_SLEEP);
+ mdelay(1);
+
+ OUTPLL(pllP2PLL_CNTL, INPLL(pllP2PLL_CNTL) & ~P2PLL_CNTL__P2PLL_RESET);
+ mdelay( 1);
+
+ OUTPLL(pllPIXCLKS_CNTL,
+ (INPLL(pllPIXCLKS_CNTL) & ~PIXCLKS_CNTL__PIX2CLK_SRC_SEL_MASK)
+ | (0x03 << PIXCLKS_CNTL__PIX2CLK_SRC_SEL__SHIFT));
+ mdelay( 1);
+}
+
+static void radeon_pm_low_current(struct radeonfb_info *rinfo)
+{
+ u32 reg;
+
+ reg = INREG(BUS_CNTL1);
+ reg &= ~BUS_CNTL1_MOBILE_PLATFORM_SEL_MASK;
+ reg |= BUS_CNTL1_AGPCLK_VALID | (1<<BUS_CNTL1_MOBILE_PLATFORM_SEL_SHIFT);
+ OUTREG(BUS_CNTL1, reg);
+
+ reg = INPLL(PLL_PWRMGT_CNTL);
+ reg |= PLL_PWRMGT_CNTL_SPLL_TURNOFF | PLL_PWRMGT_CNTL_PPLL_TURNOFF |
+ PLL_PWRMGT_CNTL_P2PLL_TURNOFF | PLL_PWRMGT_CNTL_TVPLL_TURNOFF;
+ reg &= ~PLL_PWRMGT_CNTL_SU_MCLK_USE_BCLK;
+ reg &= ~PLL_PWRMGT_CNTL_MOBILE_SU;
+ OUTPLL(PLL_PWRMGT_CNTL, reg);
+
+ reg = INREG(TV_DAC_CNTL);
+ reg &= ~(TV_DAC_CNTL_BGADJ_MASK |TV_DAC_CNTL_DACADJ_MASK);
+ reg |=TV_DAC_CNTL_BGSLEEP | TV_DAC_CNTL_RDACPD | TV_DAC_CNTL_GDACPD |
+ TV_DAC_CNTL_BDACPD |
+ (8<<TV_DAC_CNTL_BGADJ__SHIFT) | (8<<TV_DAC_CNTL_DACADJ__SHIFT);
+ OUTREG(TV_DAC_CNTL, reg);
+
+ reg = INREG(TMDS_TRANSMITTER_CNTL);
+ reg &= ~(TMDS_PLL_EN | TMDS_PLLRST);
+ OUTREG(TMDS_TRANSMITTER_CNTL, reg);
+
+ reg = INREG(DAC_CNTL);
+ reg &= ~DAC_CMP_EN;
+ OUTREG(DAC_CNTL, reg);
+
+ reg = INREG(DAC_CNTL2);
+ reg &= ~DAC2_CMP_EN;
+ OUTREG(DAC_CNTL2, reg);
+
+ reg = INREG(TV_DAC_CNTL);
+ reg &= ~TV_DAC_CNTL_DETECT;
+ OUTREG(TV_DAC_CNTL, reg);
+}
+
+static void radeon_pm_setup_for_suspend(struct radeonfb_info *rinfo)
+{
+
+ u32 sclk_cntl, mclk_cntl, sclk_more_cntl;
+
+ u32 pll_pwrmgt_cntl;
+ u32 clk_pwrmgt_cntl;
+ u32 clk_pin_cntl;
+ u32 vclk_ecp_cntl;
+ u32 pixclks_cntl;
+ u32 disp_mis_cntl;
+ u32 disp_pwr_man;
+
+
+ /* Force Core Clocks */
+ sclk_cntl = INPLL( pllSCLK_CNTL_M6);
+ sclk_cntl |= SCLK_CNTL_M6__IDCT_MAX_DYN_STOP_LAT|
+ SCLK_CNTL_M6__VIP_MAX_DYN_STOP_LAT|
+ SCLK_CNTL_M6__RE_MAX_DYN_STOP_LAT|
+ SCLK_CNTL_M6__PB_MAX_DYN_STOP_LAT|
+ SCLK_CNTL_M6__TAM_MAX_DYN_STOP_LAT|
+ SCLK_CNTL_M6__TDM_MAX_DYN_STOP_LAT|
+ SCLK_CNTL_M6__RB_MAX_DYN_STOP_LAT|
+
+ SCLK_CNTL_M6__FORCE_DISP2|
+ SCLK_CNTL_M6__FORCE_CP|
+ SCLK_CNTL_M6__FORCE_HDP|
+ SCLK_CNTL_M6__FORCE_DISP1|
+ SCLK_CNTL_M6__FORCE_TOP|
+ SCLK_CNTL_M6__FORCE_E2|
+ SCLK_CNTL_M6__FORCE_SE|
+ SCLK_CNTL_M6__FORCE_IDCT|
+ SCLK_CNTL_M6__FORCE_VIP|
+
+ SCLK_CNTL_M6__FORCE_RE|
+ SCLK_CNTL_M6__FORCE_PB|
+ SCLK_CNTL_M6__FORCE_TAM|
+ SCLK_CNTL_M6__FORCE_TDM|
+ SCLK_CNTL_M6__FORCE_RB|
+ SCLK_CNTL_M6__FORCE_TV_SCLK|
+ SCLK_CNTL_M6__FORCE_SUBPIC|
+ SCLK_CNTL_M6__FORCE_OV0;
+
+ OUTPLL( pllSCLK_CNTL_M6, sclk_cntl);
+
+ sclk_more_cntl = INPLL(pllSCLK_MORE_CNTL);
+ sclk_more_cntl |= SCLK_MORE_CNTL__FORCE_DISPREGS |
+ SCLK_MORE_CNTL__FORCE_MC_GUI |
+ SCLK_MORE_CNTL__FORCE_MC_HOST;
+
+ OUTPLL(pllSCLK_MORE_CNTL, sclk_more_cntl);
+
+
+ mclk_cntl = INPLL( pllMCLK_CNTL_M6);
+ mclk_cntl &= ~( MCLK_CNTL_M6__FORCE_MCLKA |
+ MCLK_CNTL_M6__FORCE_MCLKB |
+ MCLK_CNTL_M6__FORCE_YCLKA |
+ MCLK_CNTL_M6__FORCE_YCLKB |
+ MCLK_CNTL_M6__FORCE_MC
+ );
+ OUTPLL( pllMCLK_CNTL_M6, mclk_cntl);
+
+ /* Force Display clocks */
+ vclk_ecp_cntl = INPLL( pllVCLK_ECP_CNTL);
+ vclk_ecp_cntl &= ~(VCLK_ECP_CNTL__PIXCLK_ALWAYS_ONb |VCLK_ECP_CNTL__PIXCLK_DAC_ALWAYS_ONb);
+ vclk_ecp_cntl |= VCLK_ECP_CNTL__ECP_FORCE_ON;
+ OUTPLL( pllVCLK_ECP_CNTL, vclk_ecp_cntl);
+
+
+ pixclks_cntl = INPLL( pllPIXCLKS_CNTL);
+ pixclks_cntl &= ~( PIXCLKS_CNTL__PIXCLK_GV_ALWAYS_ONb |
+ PIXCLKS_CNTL__PIXCLK_BLEND_ALWAYS_ONb|
+ PIXCLKS_CNTL__PIXCLK_DIG_TMDS_ALWAYS_ONb |
+ PIXCLKS_CNTL__PIXCLK_LVDS_ALWAYS_ONb|
+ PIXCLKS_CNTL__PIXCLK_TMDS_ALWAYS_ONb|
+ PIXCLKS_CNTL__PIX2CLK_ALWAYS_ONb|
+ PIXCLKS_CNTL__PIX2CLK_DAC_ALWAYS_ONb);
+
+ OUTPLL( pllPIXCLKS_CNTL, pixclks_cntl);
+
+
+
+ /* Enable System power management */
+ pll_pwrmgt_cntl = INPLL( pllPLL_PWRMGT_CNTL);
+
+ pll_pwrmgt_cntl |= PLL_PWRMGT_CNTL__SPLL_TURNOFF |
+ PLL_PWRMGT_CNTL__MPLL_TURNOFF|
+ PLL_PWRMGT_CNTL__PPLL_TURNOFF|
+ PLL_PWRMGT_CNTL__P2PLL_TURNOFF|
+ PLL_PWRMGT_CNTL__TVPLL_TURNOFF;
+
+ OUTPLL( pllPLL_PWRMGT_CNTL, pll_pwrmgt_cntl);
+
+ clk_pwrmgt_cntl = INPLL( pllCLK_PWRMGT_CNTL_M6);
+
+ clk_pwrmgt_cntl &= ~( CLK_PWRMGT_CNTL_M6__MPLL_PWRMGT_OFF|
+ CLK_PWRMGT_CNTL_M6__SPLL_PWRMGT_OFF|
+ CLK_PWRMGT_CNTL_M6__PPLL_PWRMGT_OFF|
+ CLK_PWRMGT_CNTL_M6__P2PLL_PWRMGT_OFF|
+ CLK_PWRMGT_CNTL_M6__MCLK_TURNOFF|
+ CLK_PWRMGT_CNTL_M6__SCLK_TURNOFF|
+ CLK_PWRMGT_CNTL_M6__PCLK_TURNOFF|
+ CLK_PWRMGT_CNTL_M6__P2CLK_TURNOFF|
+ CLK_PWRMGT_CNTL_M6__TVPLL_PWRMGT_OFF|
+ CLK_PWRMGT_CNTL_M6__GLOBAL_PMAN_EN|
+ CLK_PWRMGT_CNTL_M6__ENGINE_DYNCLK_MODE|
+ CLK_PWRMGT_CNTL_M6__ACTIVE_HILO_LAT_MASK|
+ CLK_PWRMGT_CNTL_M6__CG_NO1_DEBUG_MASK
+ );
+
+ clk_pwrmgt_cntl |= CLK_PWRMGT_CNTL_M6__GLOBAL_PMAN_EN | CLK_PWRMGT_CNTL_M6__DISP_PM;
+
+ OUTPLL( pllCLK_PWRMGT_CNTL_M6, clk_pwrmgt_cntl);
+
+ clk_pin_cntl = INPLL( pllCLK_PIN_CNTL);
+
+ clk_pin_cntl &= ~CLK_PIN_CNTL__ACCESS_REGS_IN_SUSPEND;
+ OUTPLL( pllMCLK_MISC, INPLL( pllMCLK_MISC) | MCLK_MISC__EN_MCLK_TRISTATE_IN_SUSPEND);
+
+ /* AGP PLL control */
+ OUTREG(BUS_CNTL1, INREG(BUS_CNTL1) | BUS_CNTL1__AGPCLK_VALID);
+
+ OUTREG(BUS_CNTL1,
+ (INREG(BUS_CNTL1) & ~BUS_CNTL1__MOBILE_PLATFORM_SEL_MASK)
+ | (2<<BUS_CNTL1__MOBILE_PLATFORM_SEL__SHIFT)); // 440BX
+ OUTREG(CRTC_OFFSET_CNTL, (INREG(CRTC_OFFSET_CNTL) & ~CRTC_OFFSET_CNTL__CRTC_STEREO_SYNC_OUT_EN));
+
+ clk_pin_cntl &= ~CLK_PIN_CNTL__CG_CLK_TO_OUTPIN;
+ clk_pin_cntl |= CLK_PIN_CNTL__XTALIN_ALWAYS_ONb;
+ OUTPLL( pllCLK_PIN_CNTL, clk_pin_cntl);
+
+ /* Solano2M */
+ OUTREG(AGP_CNTL,
+ (INREG(AGP_CNTL) & ~(AGP_CNTL__MAX_IDLE_CLK_MASK))
+ | (0x20<<AGP_CNTL__MAX_IDLE_CLK__SHIFT));
+
+ /* ACPI mode */
+ OUTPLL( pllPLL_PWRMGT_CNTL, INPLL( pllPLL_PWRMGT_CNTL) & ~PLL_PWRMGT_CNTL__PM_MODE_SEL);
+
+
+ disp_mis_cntl = INREG(DISP_MISC_CNTL);
+
+ disp_mis_cntl &= ~( DISP_MISC_CNTL__SOFT_RESET_GRPH_PP |
+ DISP_MISC_CNTL__SOFT_RESET_SUBPIC_PP |
+ DISP_MISC_CNTL__SOFT_RESET_OV0_PP |
+ DISP_MISC_CNTL__SOFT_RESET_GRPH_SCLK|
+ DISP_MISC_CNTL__SOFT_RESET_SUBPIC_SCLK|
+ DISP_MISC_CNTL__SOFT_RESET_OV0_SCLK|
+ DISP_MISC_CNTL__SOFT_RESET_GRPH2_PP|
+ DISP_MISC_CNTL__SOFT_RESET_GRPH2_SCLK|
+ DISP_MISC_CNTL__SOFT_RESET_LVDS|
+ DISP_MISC_CNTL__SOFT_RESET_TMDS|
+ DISP_MISC_CNTL__SOFT_RESET_DIG_TMDS|
+ DISP_MISC_CNTL__SOFT_RESET_TV);
+
+ OUTREG(DISP_MISC_CNTL, disp_mis_cntl);
+
+ disp_pwr_man = INREG(DISP_PWR_MAN);
+
+ disp_pwr_man &= ~( DISP_PWR_MAN__DISP_PWR_MAN_D3_CRTC_EN |
+ DISP_PWR_MAN__DISP2_PWR_MAN_D3_CRTC2_EN |
+ DISP_PWR_MAN__DISP_PWR_MAN_DPMS_MASK|
+ DISP_PWR_MAN__DISP_D3_RST|
+ DISP_PWR_MAN__DISP_D3_REG_RST
+ );
+
+ disp_pwr_man |= DISP_PWR_MAN__DISP_D3_GRPH_RST|
+ DISP_PWR_MAN__DISP_D3_SUBPIC_RST|
+ DISP_PWR_MAN__DISP_D3_OV0_RST|
+ DISP_PWR_MAN__DISP_D1D2_GRPH_RST|
+ DISP_PWR_MAN__DISP_D1D2_SUBPIC_RST|
+ DISP_PWR_MAN__DISP_D1D2_OV0_RST|
+ DISP_PWR_MAN__DIG_TMDS_ENABLE_RST|
+ DISP_PWR_MAN__TV_ENABLE_RST|
+// DISP_PWR_MAN__AUTO_PWRUP_EN|
+ 0;
+
+ OUTREG(DISP_PWR_MAN, disp_pwr_man);
+
+ clk_pwrmgt_cntl = INPLL( pllCLK_PWRMGT_CNTL_M6);
+ pll_pwrmgt_cntl = INPLL( pllPLL_PWRMGT_CNTL) ;
+ clk_pin_cntl = INPLL( pllCLK_PIN_CNTL);
+ disp_pwr_man = INREG(DISP_PWR_MAN);
+
+
+ /* D2 */
+ clk_pwrmgt_cntl |= CLK_PWRMGT_CNTL_M6__DISP_PM;
+ pll_pwrmgt_cntl |= PLL_PWRMGT_CNTL__MOBILE_SU | PLL_PWRMGT_CNTL__SU_SCLK_USE_BCLK;
+ clk_pin_cntl |= CLK_PIN_CNTL__XTALIN_ALWAYS_ONb;
+ disp_pwr_man &= ~(DISP_PWR_MAN__DISP_PWR_MAN_D3_CRTC_EN_MASK | DISP_PWR_MAN__DISP2_PWR_MAN_D3_CRTC2_EN_MASK);
+
+
+ OUTPLL( pllCLK_PWRMGT_CNTL_M6, clk_pwrmgt_cntl);
+ OUTPLL( pllPLL_PWRMGT_CNTL, pll_pwrmgt_cntl);
+ OUTPLL( pllCLK_PIN_CNTL, clk_pin_cntl);
+ OUTREG(DISP_PWR_MAN, disp_pwr_man);
+
+ /* disable display request & disable display */
+ OUTREG( CRTC_GEN_CNTL, (INREG( CRTC_GEN_CNTL) & ~CRTC_GEN_CNTL__CRTC_EN) | CRTC_GEN_CNTL__CRTC_DISP_REQ_EN_B);
+ OUTREG( CRTC2_GEN_CNTL, (INREG( CRTC2_GEN_CNTL) & ~CRTC2_GEN_CNTL__CRTC2_EN) | CRTC2_GEN_CNTL__CRTC2_DISP_REQ_EN_B);
+
+ mdelay(17);
+
+}
+
+static void radeon_pm_yclk_mclk_sync(struct radeonfb_info *rinfo)
+{
+ u32 mc_chp_io_cntl_a1, mc_chp_io_cntl_b1;
+
+ mc_chp_io_cntl_a1 = INMC( rinfo, ixMC_CHP_IO_CNTL_A1) & ~MC_CHP_IO_CNTL_A1__MEM_SYNC_ENA_MASK;
+ mc_chp_io_cntl_b1 = INMC( rinfo, ixMC_CHP_IO_CNTL_B1) & ~MC_CHP_IO_CNTL_B1__MEM_SYNC_ENB_MASK;
+
+ OUTMC( rinfo, ixMC_CHP_IO_CNTL_A1, mc_chp_io_cntl_a1 | (1<<MC_CHP_IO_CNTL_A1__MEM_SYNC_ENA__SHIFT));
+ OUTMC( rinfo, ixMC_CHP_IO_CNTL_B1, mc_chp_io_cntl_b1 | (1<<MC_CHP_IO_CNTL_B1__MEM_SYNC_ENB__SHIFT));
+
+ /* Wassup ? This doesn't seem to be defined, let's hope we are ok this way --BenH */
+#ifdef MCLK_YCLK_SYNC_ENABLE
+ mc_chp_io_cntl_a1 |= (2<<MC_CHP_IO_CNTL_A1__MEM_SYNC_ENA__SHIFT);
+ mc_chp_io_cntl_b1 |= (2<<MC_CHP_IO_CNTL_B1__MEM_SYNC_ENB__SHIFT);
+#endif
+
+ OUTMC( rinfo, ixMC_CHP_IO_CNTL_A1, mc_chp_io_cntl_a1);
+ OUTMC( rinfo, ixMC_CHP_IO_CNTL_B1, mc_chp_io_cntl_b1);
+
+ mdelay( 1);
+}
+
+static void radeon_pm_program_mode_reg(struct radeonfb_info *rinfo, u16 value, u8 delay_required)
+{
+ u32 mem_sdram_mode;
+
+ mem_sdram_mode = INREG( MEM_SDRAM_MODE_REG);
+
+ mem_sdram_mode &= ~MEM_SDRAM_MODE_REG__MEM_MODE_REG_MASK;
+ mem_sdram_mode |= (value<<MEM_SDRAM_MODE_REG__MEM_MODE_REG__SHIFT) | MEM_SDRAM_MODE_REG__MEM_CFG_TYPE;
+ OUTREG( MEM_SDRAM_MODE_REG, mem_sdram_mode);
+
+ mem_sdram_mode |= MEM_SDRAM_MODE_REG__MEM_SDRAM_RESET;
+ OUTREG( MEM_SDRAM_MODE_REG, mem_sdram_mode);
+
+ mem_sdram_mode &= ~MEM_SDRAM_MODE_REG__MEM_SDRAM_RESET;
+ OUTREG( MEM_SDRAM_MODE_REG, mem_sdram_mode);
+
+ if (delay_required == 1)
+ while( (INREG( MC_STATUS) & (MC_STATUS__MEM_PWRUP_COMPL_A | MC_STATUS__MEM_PWRUP_COMPL_B) ) == 0 )
+ { };
+}
+
+
+static void radeon_pm_enable_dll(struct radeonfb_info *rinfo)
+{
+#define DLL_RESET_DELAY 5
+#define DLL_SLEEP_DELAY 1
+
+ u32 DLL_CKO_Value = INPLL(pllMDLL_CKO) | MDLL_CKO__MCKOA_SLEEP | MDLL_CKO__MCKOA_RESET;
+ u32 DLL_CKA_Value = INPLL(pllMDLL_RDCKA) | MDLL_RDCKA__MRDCKA0_SLEEP | MDLL_RDCKA__MRDCKA1_SLEEP | MDLL_RDCKA__MRDCKA0_RESET | MDLL_RDCKA__MRDCKA1_RESET;
+ u32 DLL_CKB_Value = INPLL(pllMDLL_RDCKB) | MDLL_RDCKB__MRDCKB0_SLEEP | MDLL_RDCKB__MRDCKB1_SLEEP | MDLL_RDCKB__MRDCKB0_RESET | MDLL_RDCKB__MRDCKB1_RESET;
+
+ /* Setting up the DLL range for write */
+ OUTPLL(pllMDLL_CKO, DLL_CKO_Value);
+ OUTPLL(pllMDLL_RDCKA, DLL_CKA_Value);
+ OUTPLL(pllMDLL_RDCKB, DLL_CKB_Value);
+
+ mdelay( DLL_RESET_DELAY);
+
+ /* Channel A */
+
+ /* Power Up */
+ DLL_CKO_Value &= ~(MDLL_CKO__MCKOA_SLEEP );
+ OUTPLL(pllMDLL_CKO, DLL_CKO_Value);
+ mdelay( DLL_SLEEP_DELAY);
+
+ DLL_CKO_Value &= ~(MDLL_CKO__MCKOA_RESET );
+ OUTPLL(pllMDLL_CKO, DLL_CKO_Value);
+ mdelay( DLL_RESET_DELAY);
+
+ /* Power Up */
+ DLL_CKA_Value &= ~(MDLL_RDCKA__MRDCKA0_SLEEP );
+ OUTPLL(pllMDLL_RDCKA, DLL_CKA_Value);
+ mdelay( DLL_SLEEP_DELAY);
+
+ DLL_CKA_Value &= ~(MDLL_RDCKA__MRDCKA0_RESET );
+ OUTPLL(pllMDLL_RDCKA, DLL_CKA_Value);
+ mdelay( DLL_RESET_DELAY);
+
+ /* Power Up */
+ DLL_CKA_Value &= ~(MDLL_RDCKA__MRDCKA1_SLEEP);
+ OUTPLL(pllMDLL_RDCKA, DLL_CKA_Value);
+ mdelay( DLL_SLEEP_DELAY);
+
+ DLL_CKA_Value &= ~(MDLL_RDCKA__MRDCKA1_RESET);
+ OUTPLL(pllMDLL_RDCKA, DLL_CKA_Value);
+ mdelay( DLL_RESET_DELAY);
+
+
+ /* Channel B */
+
+ /* Power Up */
+ DLL_CKO_Value &= ~(MDLL_CKO__MCKOB_SLEEP );
+ OUTPLL(pllMDLL_CKO, DLL_CKO_Value);
+ mdelay( DLL_SLEEP_DELAY);
+
+ DLL_CKO_Value &= ~(MDLL_CKO__MCKOB_RESET );
+ OUTPLL(pllMDLL_CKO, DLL_CKO_Value);
+ mdelay( DLL_RESET_DELAY);
+
+ /* Power Up */
+ DLL_CKB_Value &= ~(MDLL_RDCKB__MRDCKB0_SLEEP);
+ OUTPLL(pllMDLL_RDCKB, DLL_CKB_Value);
+ mdelay( DLL_SLEEP_DELAY);
+
+ DLL_CKB_Value &= ~(MDLL_RDCKB__MRDCKB0_RESET);
+ OUTPLL(pllMDLL_RDCKB, DLL_CKB_Value);
+ mdelay( DLL_RESET_DELAY);
+
+ /* Power Up */
+ DLL_CKB_Value &= ~(MDLL_RDCKB__MRDCKB1_SLEEP);
+ OUTPLL(pllMDLL_RDCKB, DLL_CKB_Value);
+ mdelay( DLL_SLEEP_DELAY);
+
+ DLL_CKB_Value &= ~(MDLL_RDCKB__MRDCKB1_RESET);
+ OUTPLL(pllMDLL_RDCKB, DLL_CKB_Value);
+ mdelay( DLL_RESET_DELAY);
+
+#undef DLL_RESET_DELAY
+#undef DLL_SLEEP_DELAY
+}
+
+static void radeon_pm_full_reset_sdram(struct radeonfb_info *rinfo)
+{
+ u32 crtcGenCntl, crtcGenCntl2, memRefreshCntl, crtc_more_cntl, fp_gen_cntl, fp2_gen_cntl;
+
+ crtcGenCntl = INREG( CRTC_GEN_CNTL);
+ crtcGenCntl2 = INREG( CRTC2_GEN_CNTL);
+
+ memRefreshCntl = INREG( MEM_REFRESH_CNTL);
+ crtc_more_cntl = INREG( CRTC_MORE_CNTL);
+ fp_gen_cntl = INREG( FP_GEN_CNTL);
+ fp2_gen_cntl = INREG( FP2_GEN_CNTL);
+
+
+ OUTREG( CRTC_MORE_CNTL, 0);
+ OUTREG( FP_GEN_CNTL, 0);
+ OUTREG( FP2_GEN_CNTL, 0);
+
+ OUTREG( CRTC_GEN_CNTL, (crtcGenCntl | CRTC_GEN_CNTL__CRTC_DISP_REQ_EN_B) );
+ OUTREG( CRTC2_GEN_CNTL, (crtcGenCntl2 | CRTC2_GEN_CNTL__CRTC2_DISP_REQ_EN_B) );
+
+ /* Disable refresh */
+ OUTREG( MEM_REFRESH_CNTL, memRefreshCntl | MEM_REFRESH_CNTL__MEM_REFRESH_DIS);
+
+ /* Reset memory */
+ OUTREG( MEM_SDRAM_MODE_REG,
+ INREG( MEM_SDRAM_MODE_REG) & ~MEM_SDRAM_MODE_REG__MC_INIT_COMPLETE); // Init Not Complete
+
+ /* DLL */
+ radeon_pm_enable_dll(rinfo);
+
+ // MLCK /YCLK sync
+ radeon_pm_yclk_mclk_sync(rinfo);
+
+ /* M6, M7 and M9 so far ... */
+ if (rinfo->is_mobility && rinfo->family <= CHIP_FAMILY_RV250) {
+ radeon_pm_program_mode_reg(rinfo, 0x2000, 1);
+ radeon_pm_program_mode_reg(rinfo, 0x2001, 1);
+ radeon_pm_program_mode_reg(rinfo, 0x2002, 1);
+ radeon_pm_program_mode_reg(rinfo, 0x0132, 1);
+ radeon_pm_program_mode_reg(rinfo, 0x0032, 1);
+ }
+
+ OUTREG( MEM_SDRAM_MODE_REG,
+ INREG( MEM_SDRAM_MODE_REG) | MEM_SDRAM_MODE_REG__MC_INIT_COMPLETE); // Init Complete
+
+ OUTREG( MEM_REFRESH_CNTL, memRefreshCntl);
+
+ OUTREG( CRTC_GEN_CNTL, crtcGenCntl);
+ OUTREG( CRTC2_GEN_CNTL, crtcGenCntl2);
+ OUTREG( FP_GEN_CNTL, fp_gen_cntl);
+ OUTREG( FP2_GEN_CNTL, fp2_gen_cntl);
+
+ OUTREG( CRTC_MORE_CNTL, crtc_more_cntl);
+
+ mdelay( 15);
+}
+
+static void radeon_set_suspend(struct radeonfb_info *rinfo, int suspend)
+{
+ u16 pwr_cmd;
+
+ if (!rinfo->pm_reg)
+ return;
+
+ /* Set the chip into appropriate suspend mode (we use D2,
+ * D3 would require a compete re-initialization of the chip,
+ * including PCI config registers, clocks, AGP conf, ...)
+ */
+ if (suspend) {
+ printk(KERN_DEBUG "radeonfb: switching to D2 state...\n");
+
+ /* Disable dynamic power management of clocks for the
+ * duration of the suspend/resume process
+ */
+ radeon_pm_disable_dynamic_mode(rinfo);
+ /* Save some registers */
+ radeon_pm_save_regs(rinfo);
+
+ /* Prepare mobility chips for suspend. Only do that on <= RV250 chips that
+ * have been tested
+ */
+ if (rinfo->is_mobility && rinfo->family <= CHIP_FAMILY_RV250) {
+ /* Program V2CLK */
+ radeon_pm_program_v2clk(rinfo);
+
+ /* Disable IO PADs */
+ radeon_pm_disable_iopad(rinfo);
+
+ /* Set low current */
+ radeon_pm_low_current(rinfo);
+
+ /* Prepare chip for power management */
+ radeon_pm_setup_for_suspend(rinfo);
+
+ /* Reset the MDLL */
+ OUTPLL( pllMDLL_CKO, INPLL( pllMDLL_CKO) | MDLL_CKO__MCKOA_RESET | MDLL_CKO__MCKOB_RESET);
+ }
+
+ /* Switch PCI power managment to D2. */
+ for (;;) {
+ pci_read_config_word(
+ rinfo->pdev, rinfo->pm_reg+PCI_PM_CTRL,
+ &pwr_cmd);
+ if (pwr_cmd & 2)
+ break;
+ pci_write_config_word(
+ rinfo->pdev, rinfo->pm_reg+PCI_PM_CTRL,
+ (pwr_cmd & ~PCI_PM_CTRL_STATE_MASK) | 2);
+ mdelay(500);
+ }
+ } else {
+ printk(KERN_DEBUG "radeonfb: switching to D0 state...\n");
+
+ /* Switch back PCI powermanagment to D0 */
+ mdelay(200);
+ pci_write_config_word(rinfo->pdev, rinfo->pm_reg+PCI_PM_CTRL, 0);
+ mdelay(500);
+
+ /* Reset the SDRAM controller */
+ radeon_pm_full_reset_sdram(rinfo);
+
+ /* Restore some registers */
+ radeon_pm_restore_regs(rinfo);
+ radeon_pm_enable_dynamic_mode(rinfo);
+ }
+}
+
+int radeonfb_pci_suspend(struct pci_dev *pdev, u32 state)
+{
+ struct fb_info *info = pci_get_drvdata(pdev);
+ struct radeonfb_info *rinfo = info->par;
+
+ /* We don't do anything but D2, for now we return 0, but
+ * we may want to change that. How do we know if the BIOS
+ * can properly take care of D3 ? Also, with swsusp, we
+ * know we'll be rebooted, ...
+ */
+
+ printk(KERN_DEBUG "radeonfb: suspending to state: %d...\n", state);
+
+ acquire_console_sem();
+
+ /* Userland should do this but doesn't... bridge gets suspended
+ * too late. Unfortunately, that works only when AGP is built-in,
+ * not for a module.
+ */
+#ifdef CONFIG_AGP
+ agp_enable(0);
+#endif
+
+ fb_set_suspend(info, 1);
+
+ if (!radeon_accel_disabled()) {
+ /* Make sure engine is reset */
+ radeon_engine_idle();
+ radeon_engine_reset(rinfo);
+ radeon_engine_idle();
+ }
+
+ /* Blank display and LCD */
+ radeonfb_blank(VESA_POWERDOWN+1, info);
+
+ /* Sleep */
+ rinfo->asleep = 1;
+ rinfo->lock_blank = 1;
+
+ /* Suspend the chip to D2 state when supported
+ */
+#ifdef CONFIG_RADEON_HAS_D2
+ if (radeon_suspend_to_d2(rinfo, state))
+ radeon_set_suspend(rinfo, 1);
+#endif /* CONFIG_RADEON_HAS_D2 */
+
+ release_console_sem();
+
+ pdev->dev.power_state = state;
+
+ return 0;
+}
+
+int radeonfb_pci_resume(struct pci_dev *pdev)
+{
+ struct fb_info *info = pci_get_drvdata(pdev);
+ struct radeonfb_info *rinfo = info->par;
+
+ if (pdev->dev.power_state == 0)
+ return 0;
+
+ acquire_console_sem();
+
+ /* Wakeup chip */
+#ifdef CONFIG_RADEON_HAS_D2
+ if (radeon_suspend_to_d2(rinfo, 0))
+ radeon_set_suspend(rinfo, 0);
+#endif /* CONFIG_RADEON_HAS_D2 */
+
+ rinfo->asleep = 0;
+
+ /* Restore display & engine */
+ radeonfb_set_par(info);
+ fb_pan_display(info, &info->var);
+ fb_set_cmap(&info->cmap, 1, info);
+
+ /* Refresh */
+ fb_set_suspend(info, 0);
+
+ /* Unblank */
+ rinfo->lock_blank = 0;
+ radeonfb_blank(0, info);
+
+ release_console_sem();
+
+ pdev->dev.power_state = 0;
+
+ printk(KERN_DEBUG "radeonfb: resumed !\n");
+
+ return 0;
+}
+
+#endif /* CONFIG_PM */
--- /dev/null
+#ifndef __RADEONFB_H__
+#define __RADEONFB_H__
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/fb.h>
+
+
+#include <linux/i2c.h>
+#include <linux/i2c-id.h>
+#include <linux/i2c-algo-bit.h>
+
+#include <asm/io.h>
+
+#include <video/radeon.h>
+
+/***************************************************************
+ * Most of the definitions here are adapted right from XFree86 *
+ ***************************************************************/
+
+
+/*
+ * Chip families. Must fit in the low 16 bits of a long word
+ */
+enum radeon_family {
+ CHIP_FAMILY_UNKNOW,
+ CHIP_FAMILY_LEGACY,
+ CHIP_FAMILY_RADEON,
+ CHIP_FAMILY_RV100,
+ CHIP_FAMILY_RS100, /* U1 (IGP320M) or A3 (IGP320)*/
+ CHIP_FAMILY_RV200,
+ CHIP_FAMILY_RS200, /* U2 (IGP330M/340M/350M) or A4 (IGP330/340/345/350), RS250 (IGP 7000) */
+ CHIP_FAMILY_R200,
+ CHIP_FAMILY_RV250,
+ CHIP_FAMILY_RS300, /* Radeon 9000 IGP */
+ CHIP_FAMILY_RV280,
+ CHIP_FAMILY_R300,
+ CHIP_FAMILY_R350,
+ CHIP_FAMILY_RV350,
+ CHIP_FAMILY_LAST,
+};
+
+/*
+ * Chip flags
+ */
+enum radeon_chip_flags {
+ CHIP_FAMILY_MASK = 0x0000ffffUL,
+ CHIP_FLAGS_MASK = 0xffff0000UL,
+ CHIP_IS_MOBILITY = 0x00010000UL,
+ CHIP_IS_IGP = 0x00020000UL,
+ CHIP_HAS_CRTC2 = 0x00040000UL,
+};
+
+
+/*
+ * Monitor types
+ */
+enum radeon_montype {
+ MT_NONE = 0,
+ MT_CRT, /* CRT */
+ MT_LCD, /* LCD */
+ MT_DFP, /* DVI */
+ MT_CTV, /* composite TV */
+ MT_STV /* S-Video out */
+};
+
+/*
+ * DDC i2c ports
+ */
+enum ddc_type {
+ ddc_none,
+ ddc_monid,
+ ddc_dvi,
+ ddc_vga,
+ ddc_crt2,
+};
+
+/*
+ * Connector types
+ */
+enum conn_type {
+ conn_none,
+ conn_proprietary,
+ conn_crt,
+ conn_DVI_I,
+ conn_DVI_D,
+};
+
+
+/*
+ * PLL infos
+ */
+struct pll_info {
+ int ppll_max;
+ int ppll_min;
+ int sclk, mclk;
+ int ref_div;
+ int ref_clk;
+};
+
+/*
+ * VRAM infos
+ */
+struct ram_info {
+ int ml;
+ int mb;
+ int trcd;
+ int trp;
+ int twr;
+ int cl;
+ int tr2w;
+ int loop_latency;
+ int rloop;
+};
+
+
+/*
+ * This structure contains the various registers manipulated by this
+ * driver for setting or restoring a mode. It's mostly copied from
+ * XFree's RADEONSaveRec structure. A few chip settings might still be
+ * tweaked without beeing reflected or saved in these registers though
+ */
+struct radeon_regs {
+ /* Common registers */
+ u32 ovr_clr;
+ u32 ovr_wid_left_right;
+ u32 ovr_wid_top_bottom;
+ u32 ov0_scale_cntl;
+ u32 mpp_tb_config;
+ u32 mpp_gp_config;
+ u32 subpic_cntl;
+ u32 viph_control;
+ u32 i2c_cntl_1;
+ u32 gen_int_cntl;
+ u32 cap0_trig_cntl;
+ u32 cap1_trig_cntl;
+ u32 bus_cntl;
+ u32 surface_cntl;
+ u32 bios_5_scratch;
+
+ /* Other registers to save for VT switches or driver load/unload */
+ u32 dp_datatype;
+ u32 rbbm_soft_reset;
+ u32 clock_cntl_index;
+ u32 amcgpio_en_reg;
+ u32 amcgpio_mask;
+
+ /* Surface/tiling registers */
+ u32 surf_lower_bound[8];
+ u32 surf_upper_bound[8];
+ u32 surf_info[8];
+
+ /* CRTC registers */
+ u32 crtc_gen_cntl;
+ u32 crtc_ext_cntl;
+ u32 dac_cntl;
+ u32 crtc_h_total_disp;
+ u32 crtc_h_sync_strt_wid;
+ u32 crtc_v_total_disp;
+ u32 crtc_v_sync_strt_wid;
+ u32 crtc_offset;
+ u32 crtc_offset_cntl;
+ u32 crtc_pitch;
+ u32 disp_merge_cntl;
+ u32 grph_buffer_cntl;
+ u32 crtc_more_cntl;
+
+ /* CRTC2 registers */
+ u32 crtc2_gen_cntl;
+ u32 dac2_cntl;
+ u32 disp_output_cntl;
+ u32 disp_hw_debug;
+ u32 disp2_merge_cntl;
+ u32 grph2_buffer_cntl;
+ u32 crtc2_h_total_disp;
+ u32 crtc2_h_sync_strt_wid;
+ u32 crtc2_v_total_disp;
+ u32 crtc2_v_sync_strt_wid;
+ u32 crtc2_offset;
+ u32 crtc2_offset_cntl;
+ u32 crtc2_pitch;
+
+ /* Flat panel regs */
+ u32 fp_crtc_h_total_disp;
+ u32 fp_crtc_v_total_disp;
+ u32 fp_gen_cntl;
+ u32 fp2_gen_cntl;
+ u32 fp_h_sync_strt_wid;
+ u32 fp2_h_sync_strt_wid;
+ u32 fp_horz_stretch;
+ u32 fp_panel_cntl;
+ u32 fp_v_sync_strt_wid;
+ u32 fp2_v_sync_strt_wid;
+ u32 fp_vert_stretch;
+ u32 lvds_gen_cntl;
+ u32 lvds_pll_cntl;
+ u32 tmds_crc;
+ u32 tmds_transmitter_cntl;
+
+ /* Computed values for PLL */
+ u32 dot_clock_freq;
+ int feedback_div;
+ int post_div;
+
+ /* PLL registers */
+ u32 ppll_div_3;
+ u32 ppll_ref_div;
+ u32 vclk_ecp_cntl;
+
+ /* Computed values for PLL2 */
+ u32 dot_clock_freq_2;
+ int feedback_div_2;
+ int post_div_2;
+
+ /* PLL2 registers */
+ u32 p2pll_ref_div;
+ u32 p2pll_div_0;
+ u32 htotal_cntl2;
+
+ /* Palette */
+ int palette_valid;
+ u32 palette[256];
+ u32 palette2[256];
+};
+
+struct panel_info {
+ int xres, yres;
+ int valid;
+ int clock;
+ int hOver_plus, hSync_width, hblank;
+ int vOver_plus, vSync_width, vblank;
+ int hAct_high, vAct_high, interlaced;
+ int pwr_delay;
+ int use_bios_dividers;
+ int ref_divider;
+ int post_divider;
+ int fbk_divider;
+};
+
+struct radeonfb_info;
+
+#ifdef CONFIG_FB_RADEON_I2C
+struct radeon_i2c_chan {
+ struct radeonfb_info *rinfo;
+ u32 ddc_reg;
+ struct i2c_adapter adapter;
+ struct i2c_algo_bit_data algo;
+};
+#endif
+
+struct radeonfb_info {
+ struct fb_info *info;
+
+ struct radeon_regs state;
+ struct radeon_regs init_state;
+
+ char name[DEVICE_NAME_SIZE];
+ char ram_type[12];
+
+ unsigned long mmio_base_phys;
+ unsigned long fb_base_phys;
+
+ unsigned long mmio_base;
+ unsigned long fb_base;
+
+ unsigned long fb_local_base;
+
+ struct pci_dev *pdev;
+
+ u8 *bios_seg;
+ int fp_bios_start;
+
+ u32 pseudo_palette[17];
+ struct { u8 red, green, blue, pad; }
+ palette[256];
+
+ int chipset;
+ u8 family;
+ u8 rev;
+ unsigned long video_ram;
+
+ int pitch, bpp, depth;
+
+ int has_CRTC2;
+ int is_mobility;
+ int is_IGP;
+ int R300_cg_workaround;
+ int reversed_DAC;
+ int reversed_TMDS;
+ struct panel_info panel_info;
+ int mon1_type;
+ u8 *mon1_EDID;
+ struct fb_videomode *mon1_modedb;
+ int mon1_dbsize;
+ int mon2_type;
+ u8 *mon2_EDID;
+
+ u32 dp_gui_master_cntl;
+
+ struct pll_info pll;
+
+ struct ram_info ram;
+
+ int mtrr_hdl;
+
+ int pm_reg;
+ u32 save_regs[64];
+ int asleep;
+ int lock_blank;
+
+ /* Lock on register access */
+ spinlock_t reg_lock;
+
+ /* Timer used for delayed LVDS operations */
+ struct timer_list lvds_timer;
+ u32 pending_lvds_gen_cntl;
+ u32 pending_pixclks_cntl;
+
+#ifdef CONFIG_FB_RADEON_I2C
+ struct radeon_i2c_chan i2c[4];
+#endif
+};
+
+
+#define PRIMARY_MONITOR(rinfo) (rinfo->mon1_type)
+
+
+/*
+ * Debugging stuffs
+ */
+#define DEBUG 0
+
+#if DEBUG
+#define RTRACE printk
+#else
+#define RTRACE if(0) printk
+#endif
+
+
+/*
+ * IO macros
+ */
+
+#define INREG8(addr) readb((rinfo->mmio_base)+addr)
+#define OUTREG8(addr,val) writeb(val, (rinfo->mmio_base)+addr)
+#define INREG(addr) readl((rinfo->mmio_base)+addr)
+#define OUTREG(addr,val) writel(val, (rinfo->mmio_base)+addr)
+
+static inline void R300_cg_workardound(struct radeonfb_info *rinfo)
+{
+ u32 save, tmp;
+ save = INREG(CLOCK_CNTL_INDEX);
+ tmp = save & ~(0x3f | PLL_WR_EN);
+ OUTREG(CLOCK_CNTL_INDEX, tmp);
+ tmp = INREG(CLOCK_CNTL_DATA);
+ OUTREG(CLOCK_CNTL_INDEX, save);
+}
+
+#define __OUTPLL(addr,val) \
+ do { \
+ OUTREG8(CLOCK_CNTL_INDEX, (addr & 0x0000003f) | 0x00000080); \
+ OUTREG(CLOCK_CNTL_DATA, val); \
+} while(0)
+
+
+static inline u32 __INPLL(struct radeonfb_info *rinfo, u32 addr)
+{
+ u32 data;
+ OUTREG8(CLOCK_CNTL_INDEX, addr & 0x0000003f);
+ data = (INREG(CLOCK_CNTL_DATA));
+ if (rinfo->R300_cg_workaround)
+ R300_cg_workardound(rinfo);
+ return data;
+}
+
+static inline u32 _INPLL(struct radeonfb_info *rinfo, u32 addr)
+{
+ unsigned long flags;
+ u32 data;
+
+ spin_lock_irqsave(&rinfo->reg_lock, flags);
+ data = __INPLL(rinfo, addr);
+ spin_unlock_irqrestore(&rinfo->reg_lock, flags);
+ return data;
+}
+
+#define INPLL(addr) _INPLL(rinfo, addr)
+
+#define OUTPLL(addr,val) \
+ do { \
+ unsigned long flags;\
+ spin_lock_irqsave(&rinfo->reg_lock, flags); \
+ __OUTPLL(addr, val); \
+ spin_unlock_irqrestore(&rinfo->reg_lock, flags); \
+ } while(0)
+
+#define OUTPLLP(addr,val,mask) \
+ do { \
+ unsigned long flags; \
+ unsigned int _tmp; \
+ spin_lock_irqsave(&rinfo->reg_lock, flags); \
+ _tmp = __INPLL(rinfo,addr); \
+ _tmp &= (mask); \
+ _tmp |= (val); \
+ __OUTPLL(addr, _tmp); \
+ spin_unlock_irqrestore(&rinfo->reg_lock, flags); \
+ } while (0)
+
+#define OUTREGP(addr,val,mask) \
+ do { \
+ unsigned long flags; \
+ unsigned int _tmp; \
+ spin_lock_irqsave(&rinfo->reg_lock, flags); \
+ _tmp = INREG(addr); \
+ _tmp &= (mask); \
+ _tmp |= (val); \
+ OUTREG(addr, _tmp); \
+ spin_unlock_irqrestore(&rinfo->reg_lock, flags); \
+ } while (0)
+
+#define MS_TO_HZ(ms) ((ms * HZ + 999) / 1000)
+
+#define BIOS_IN8(v) (readb(rinfo->bios_seg + (v)))
+#define BIOS_IN16(v) (readb(rinfo->bios_seg + (v)) | \
+ (readb(rinfo->bios_seg + (v) + 1) << 8))
+#define BIOS_IN32(v) (readb(rinfo->bios_seg + (v)) | \
+ (readb(rinfo->bios_seg + (v) + 1) << 8) | \
+ (readb(rinfo->bios_seg + (v) + 2) << 16) | \
+ (readb(rinfo->bios_seg + (v) + 3) << 24))
+
+/*
+ * Inline utilities
+ */
+
+static inline void wait_ms(unsigned long ms)
+{
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout((ms * HZ + 999) / 1000);
+}
+
+
+
+static inline int round_div(int num, int den)
+{
+ return (num + (den / 2)) / den;
+}
+
+static inline int var_to_depth(const struct fb_var_screeninfo *var)
+{
+ if (var->bits_per_pixel != 16)
+ return var->bits_per_pixel;
+ return (var->green.length == 5) ? 15 : 16;
+}
+
+static inline u32 radeon_get_dstbpp(u16 depth)
+{
+ switch (depth) {
+ case 8:
+ return DST_8BPP;
+ case 15:
+ return DST_15BPP;
+ case 16:
+ return DST_16BPP;
+ case 32:
+ return DST_32BPP;
+ default:
+ return 0;
+ }
+}
+
+/*
+ * 2D Engine helper routines
+ */
+static inline void radeon_engine_flush (struct radeonfb_info *rinfo)
+{
+ int i;
+
+ /* initiate flush */
+ OUTREGP(RB2D_DSTCACHE_CTLSTAT, RB2D_DC_FLUSH_ALL,
+ ~RB2D_DC_FLUSH_ALL);
+
+ for (i=0; i < 2000000; i++) {
+ if (!(INREG(RB2D_DSTCACHE_CTLSTAT) & RB2D_DC_BUSY))
+ return;
+ udelay(1);
+ }
+ printk(KERN_ERR "radeonfb: Flush Timeout !\n");
+}
+
+
+static inline void _radeon_fifo_wait (struct radeonfb_info *rinfo, int entries)
+{
+ int i;
+
+ for (i=0; i<2000000; i++) {
+ if ((INREG(RBBM_STATUS) & 0x7f) >= entries)
+ return;
+ udelay(1);
+ }
+ printk(KERN_ERR "radeonfb: FIFO Timeout !\n");
+}
+
+
+static inline void _radeon_engine_idle (struct radeonfb_info *rinfo)
+{
+ int i;
+
+ /* ensure FIFO is empty before waiting for idle */
+ _radeon_fifo_wait (rinfo, 64);
+
+ for (i=0; i<2000000; i++) {
+ if (((INREG(RBBM_STATUS) & GUI_ACTIVE)) == 0) {
+ radeon_engine_flush (rinfo);
+ return;
+ }
+ udelay(1);
+ }
+ printk(KERN_ERR "radeonfb: Idle Timeout !\n");
+}
+
+static inline int radeon_accel_disabled(void)
+{
+ extern int radeonfb_noaccel;
+ return radeonfb_noaccel;
+}
+
+#define radeon_engine_idle() _radeon_engine_idle(rinfo)
+#define radeon_fifo_wait(entries) _radeon_fifo_wait(rinfo,entries)
+
+
+/* I2C Functions */
+extern void radeon_create_i2c_busses(struct radeonfb_info *rinfo);
+extern void radeon_delete_i2c_busses(struct radeonfb_info *rinfo);
+extern int radeon_probe_i2c_connector(struct radeonfb_info *rinfo, int conn, u8 **out_edid);
+
+/* PM Functions */
+extern void radeon_pm_disable_dynamic_mode(struct radeonfb_info *rinfo);
+extern void radeon_pm_enable_dynamic_mode(struct radeonfb_info *rinfo);
+extern int radeonfb_pci_suspend(struct pci_dev *pdev, u32 state);
+extern int radeonfb_pci_resume(struct pci_dev *pdev);
+
+/* Monitor probe functions */
+extern void radeon_probe_screens(struct radeonfb_info *rinfo,
+ const char *monitor_layout, int ignore_edid);
+extern void radeon_check_modes(struct radeonfb_info *rinfo, const char *mode_option);
+extern int radeon_match_mode(struct radeonfb_info *rinfo,
+ struct fb_var_screeninfo *dest,
+ const struct fb_var_screeninfo *src);
+
+/* Accel functions */
+extern void radeonfb_fillrect(struct fb_info *info, const struct fb_fillrect *region);
+extern void radeonfb_copyarea(struct fb_info *info, const struct fb_copyarea *area);
+extern void radeonfb_imageblit(struct fb_info *p, const struct fb_image *image);
+extern int radeonfb_sync(struct fb_info *info);
+extern void radeon_engine_init (struct radeonfb_info *rinfo);
+extern void radeon_engine_reset(struct radeonfb_info *rinfo);
+
+/* Other functions */
+extern int radeonfb_blank(int blank, struct fb_info *info);
+extern int radeonfb_set_par(struct fb_info *info);
+
+#endif /* __RADEONFB_H__ */
return 0;
}
+void fb_set_suspend(struct fb_info *info, int state)
+{
+}
/**
* fbmem_init - init frame buffer subsystem
EXPORT_SYMBOL(fb_get_buffer_offset);
EXPORT_SYMBOL(move_buf_unaligned);
EXPORT_SYMBOL(move_buf_aligned);
+EXPORT_SYMBOL(fb_set_suspend);
MODULE_LICENSE("GPL");
if (radeon_read_OF(rinfo)) {
unsigned int tmp, Nx, M, ref_div, xclk;
- tmp = INPLL(M_SPLL_REF_FB_DIV);
+ tmp = INPLL(X_MPLL_REF_FB_DIV);
ref_div = INPLL(PPLL_REF_DIV) & 0x3ff;
Nx = (tmp & 0xff00) >> 8;
return;
}
- tmp = INREG(RADEON_BIOS_4_SCRATCH);
+ tmp = INREG(BIOS_4_SCRATCH);
printk(KERN_DEBUG "radeon_get_moninfo: bios 4 scratch = %x\n", tmp);
if (rinfo->hasCRTC2) {
/* DFP */
newmode.fp_gen_cntl |= (FP_FPON | FP_TMDS_EN);
newmode.tmds_transmitter_cntl = (TMDS_RAN_PAT_RST |
- ICHCSEL | TMDS_PLL_EN) &
+ TMDS_ICHCSEL | TMDS_PLL_EN) &
~(TMDS_PLLRST);
newmode.crtc_ext_cntl &= ~CRTC_CRT_ON;
}
u32 idx);
extern void move_buf_aligned(struct fb_info *info, u8 * dst, u8 * src,
u32 d_pitch, u32 s_pitch, u32 height);
+extern void fb_set_suspend(struct fb_info *info, int state);
extern struct fb_info *registered_fb[FB_MAX];
extern int num_registered_fb;
#define DSTCACHE_CTLSTAT 0x1714
#define DEFAULT_PITCH_OFFSET 0x16E0
#define DEFAULT_SC_BOTTOM_RIGHT 0x16E8
+#define DEFAULT_SC_TOP_LEFT 0x16EC
+#define SRC_PITCH_OFFSET 0x1428
+#define DST_PITCH_OFFSET 0x142C
#define DP_GUI_MASTER_CNTL 0x146C
#define SC_TOP_LEFT 0x16EC
#define SC_BOTTOM_RIGHT 0x16F0
#define RB2D_DSTCACHE_CTLSTAT 0x342C
#define LVDS_GEN_CNTL 0x02d0
#define LVDS_PLL_CNTL 0x02d4
+#define FP2_GEN_CNTL 0x0288
+#define TMDS_CNTL 0x0294
#define TMDS_CRC 0x02a0
#define TMDS_TRANSMITTER_CNTL 0x02a4
+#define MPP_TB_CONFIG 0x01c0
+
+//#define BASE_CODE 0x0f0b
+#define BIOS_0_SCRATCH 0x0010
+#define BIOS_1_SCRATCH 0x0014
+#define BIOS_2_SCRATCH 0x0018
+#define BIOS_3_SCRATCH 0x001c
+#define BIOS_4_SCRATCH 0x0020
+#define BIOS_5_SCRATCH 0x0024
+#define BIOS_6_SCRATCH 0x0028
+#define BIOS_7_SCRATCH 0x002c
-#define RADEON_BASE_CODE 0x0f0b
-#define RADEON_BIOS_0_SCRATCH 0x0010
-#define RADEON_BIOS_1_SCRATCH 0x0014
-#define RADEON_BIOS_2_SCRATCH 0x0018
-#define RADEON_BIOS_3_SCRATCH 0x001c
-#define RADEON_BIOS_4_SCRATCH 0x0020
-#define RADEON_BIOS_5_SCRATCH 0x0024
-#define RADEON_BIOS_6_SCRATCH 0x0028
-#define RADEON_BIOS_7_SCRATCH 0x002c
+#define HDP_SOFT_RESET (1 << 26)
#define TV_DAC_CNTL 0x088c
#define GPIOPAD_MASK 0x0198
#define PPLL_DIV_3 0x0007
#define VCLK_ECP_CNTL 0x0008
#define HTOTAL_CNTL 0x0009
-#define M_SPLL_REF_FB_DIV 0x000a
+#define X_MPLL_REF_FB_DIV 0x000a
#define AGP_PLL_CNTL 0x000b
#define SPLL_CNTL 0x000c
#define SCLK_CNTL 0x000d
#define P2PLL_CNTL 0x002a
#define P2PLL_REF_DIV 0x002b
#define PIXCLKS_CNTL 0x002d
+#define SCLK_MORE_CNTL 0x0035
/* MCLK_CNTL bit constants */
#define FORCEON_MCLKA (1 << 16)
#define FORCEON_MC (1 << 20)
#define FORCEON_AIC (1 << 21)
+/* SCLK_CNTL bit constants */
+#define DYN_STOP_LAT_MASK 0x00007ff8
+#define CP_MAX_DYN_STOP_LAT 0x0008
+#define SCLK_FORCEON_MASK 0xffff8000
+
+/* SCLK_MORE_CNTL bit constants */
+#define SCLK_MORE_FORCEON 0x0700
/* BUS_CNTL bit constants */
#define BUS_DBL_RESYNC 0x00000001
#define BUS_READ_BURST 0x40000000
#define BUS_RDY_READ_DLY 0x80000000
+/* PIXCLKS_CNTL */
+#define PIX2CLK_SRC_SEL_MASK 0x03
+#define PIX2CLK_SRC_SEL_CPUCLK 0x00
+#define PIX2CLK_SRC_SEL_PSCANCLK 0x01
+#define PIX2CLK_SRC_SEL_BYTECLK 0x02
+#define PIX2CLK_SRC_SEL_P2PLLCLK 0x03
+#define PIX2CLK_ALWAYS_ONb (1<<6)
+#define PIX2CLK_DAC_ALWAYS_ONb (1<<7)
+#define PIXCLK_TV_SRC_SEL (1 << 8)
+#define PIXCLK_LVDS_ALWAYS_ONb (1 << 14)
+#define PIXCLK_TMDS_ALWAYS_ONb (1 << 15)
+
/* CLOCK_CNTL_INDEX bit constants */
#define PLL_WR_EN 0x00000080
/* CONFIG_CNTL bit constants */
#define CFG_VGA_RAM_EN 0x00000100
+#define CFG_ATI_REV_ID_MASK (0xf << 16)
+#define CFG_ATI_REV_A11 (0 << 16)
/* CRTC_EXT_CNTL bit constants */
#define VGA_ATI_LINEAR 0x00000008
#define CRTC_DBL_SCAN_EN 0x00000001
#define CRTC_CUR_EN 0x00010000
#define CRTC_INTERLACE_EN (1 << 1)
+#define CRTC_BYPASS_LUT_EN (1 << 14)
#define CRTC_EXT_DISP_EN (1 << 24)
#define CRTC_EN (1 << 25)
#define CRTC_DISP_REQ_EN_B (1 << 26)
/* CUR_OFFSET, CUR_HORZ_VERT_POSN, CUR_HORZ_VERT_OFF bit constants */
#define CUR_LOCK 0x80000000
+/* GPIO bit constants */
+#define GPIO_A_0 (1 << 0)
+#define GPIO_A_1 (1 << 1)
+#define GPIO_Y_0 (1 << 8)
+#define GPIO_Y_1 (1 << 9)
+#define GPIO_EN_0 (1 << 16)
+#define GPIO_EN_1 (1 << 17)
+#define GPIO_MASK_0 (1 << 24)
+#define GPIO_MASK_1 (1 << 25)
+#define VGA_DDC_DATA_OUTPUT GPIO_A_0
+#define VGA_DDC_CLK_OUTPUT GPIO_A_1
+#define VGA_DDC_DATA_INPUT GPIO_Y_0
+#define VGA_DDC_CLK_INPUT GPIO_Y_1
+#define VGA_DDC_DATA_OUT_EN GPIO_EN_0
+#define VGA_DDC_CLK_OUT_EN GPIO_EN_1
+
/* FP bit constants */
#define FP_CRTC_H_TOTAL_MASK 0x000003ff
#define FP_USE_SHADOW_EN (1 << 24)
#define FP_CRT_SYNC_ALT (1 << 26)
+/* FP2_GEN_CNTL bit constants */
+#define FP2_BLANK_EN (1 << 1)
+#define FP2_ON (1 << 2)
+#define FP2_PANEL_FORMAT (1 << 3)
+#define FP2_SOURCE_SEL_MASK (3 << 10)
+#define FP2_SOURCE_SEL_CRTC2 (1 << 10)
+#define FP2_SRC_SEL_MASK (3 << 13)
+#define FP2_SRC_SEL_CRTC2 (1 << 13)
+#define FP2_FP_POL (1 << 16)
+#define FP2_LP_POL (1 << 17)
+#define FP2_SCK_POL (1 << 18)
+#define FP2_LCD_CNTL_MASK (7 << 19)
+#define FP2_PAD_FLOP_EN (1 << 22)
+#define FP2_CRC_EN (1 << 23)
+#define FP2_CRC_READ_EN (1 << 24)
+#define FP2_DV0_EN (1 << 25)
+#define FP2_DV0_RATE_SEL_SDR (1 << 26)
+
+
/* LVDS_GEN_CNTL bit constants */
#define LVDS_ON (1 << 0)
#define LVDS_DISPLAY_DIS (1 << 1)
#define TMDS_PLL_EN (1 << 0)
#define TMDS_PLLRST (1 << 1)
#define TMDS_RAN_PAT_RST (1 << 7)
-#define ICHCSEL (1 << 28)
+#define TMDS_ICHCSEL (1 << 28)
/* FP_HORZ_STRETCH bit constants */
#define HORZ_STRETCH_RATIO_MASK 0xffff
#define DAC_4BPP_PIX_ORDER 0x00000200
#define DAC_CRC_EN 0x00080000
#define DAC_MASK_ALL (0xff << 24)
+#define DAC_PDWN (1 << 15)
#define DAC_EXPAND_MODE (1 << 14)
#define DAC_VGA_ADR_EN (1 << 13)
-#define DAC_RANGE_CNTL (3 << 0)
-#define DAC_BLANKING (1 << 2)
-#define DAC_CMP_EN (1 << 3)
+#define DAC_RANGE_CNTL (3 << 0)
+#define DAC_RANGE_CNTL_MASK 0x03
+#define DAC_BLANKING (1 << 2)
+#define DAC_CMP_EN (1 << 3)
+#define DAC_CMP_OUTPUT (1 << 7)
/* DAC_CNTL2 bit constants */
#define DAC2_CMP_EN (1 << 7)
+#define DAC2_PALETTE_ACCESS_CNTL (1 << 5)
+
+/* DAC_EXT_CNTL bit constants */
+#define DAC_FORCE_BLANK_OFF_EN (1 << 4)
+#define DAC_FORCE_DATA_EN (1 << 5)
+#define DAC_FORCE_DATA_SEL_MASK (3 << 6)
+#define DAC_FORCE_DATA_MASK 0x0003ff00
+#define DAC_FORCE_DATA_SHIFT 8
/* GEN_RESET_CNTL bit constants */
#define SOFT_RESET_GUI 0x00000001
#define MRDCKA1_RESET 0x00020000
/* VCLK_ECP_CNTL constants */
+#define VCLK_SRC_SEL_MASK 0x03
+#define VCLK_SRC_SEL_CPUCLK 0x00
+#define VCLK_SRC_SEL_PSCANCLK 0x01
+#define VCLK_SRC_SEL_BYTECLK 0x02
+#define VCLK_SRC_SEL_PPLLCLK 0x03
#define PIXCLK_ALWAYS_ONb 0x00000040
#define PIXCLK_DAC_ALWAYS_ONb 0x00000080
#define DEFAULT_TILE_MASK 0xc0000000
#define PPLL_DIV_SEL_MASK 0x00000300
#define PPLL_RESET 0x00000001
+#define PPLL_SLEEP 0x00000002
#define PPLL_ATOMIC_UPDATE_EN 0x00010000
#define PPLL_REF_DIV_MASK 0x000003ff
#define PPLL_FB3_DIV_MASK 0x000007ff
#define PPLL_ATOMIC_UPDATE_R 0x00008000
#define PPLL_ATOMIC_UPDATE_W 0x00008000
#define PPLL_VGA_ATOMIC_UPDATE_EN 0x00020000
+#define R300_PPLL_REF_DIV_ACC_MASK (0x3ff << 18)
+#define R300_PPLL_REF_DIV_ACC_SHIFT 18
#define GUI_ACTIVE 0x80000000
+
+#define MC_IND_INDEX 0x01F8
+#define MC_IND_DATA 0x01FC
+#define MEM_REFRESH_CNTL 0x0178
+
+// CLK_PIN_CNTL
+#define CLK_PIN_CNTL__OSC_EN_MASK 0x00000001L
+#define CLK_PIN_CNTL__OSC_EN 0x00000001L
+#define CLK_PIN_CNTL__XTL_LOW_GAIN_MASK 0x00000004L
+#define CLK_PIN_CNTL__XTL_LOW_GAIN 0x00000004L
+#define CLK_PIN_CNTL__DONT_USE_XTALIN_MASK 0x00000010L
+#define CLK_PIN_CNTL__DONT_USE_XTALIN 0x00000010L
+#define CLK_PIN_CNTL__SLOW_CLOCK_SOURCE_MASK 0x00000020L
+#define CLK_PIN_CNTL__SLOW_CLOCK_SOURCE 0x00000020L
+#define CLK_PIN_CNTL__CG_CLK_TO_OUTPIN_MASK 0x00000800L
+#define CLK_PIN_CNTL__CG_CLK_TO_OUTPIN 0x00000800L
+#define CLK_PIN_CNTL__CG_COUNT_UP_TO_OUTPIN_MASK 0x00001000L
+#define CLK_PIN_CNTL__CG_COUNT_UP_TO_OUTPIN 0x00001000L
+#define CLK_PIN_CNTL__ACCESS_REGS_IN_SUSPEND_MASK 0x00002000L
+#define CLK_PIN_CNTL__ACCESS_REGS_IN_SUSPEND 0x00002000L
+#define CLK_PIN_CNTL__CG_SPARE_MASK 0x00004000L
+#define CLK_PIN_CNTL__CG_SPARE 0x00004000L
+#define CLK_PIN_CNTL__SCLK_DYN_START_CNTL_MASK 0x00008000L
+#define CLK_PIN_CNTL__SCLK_DYN_START_CNTL 0x00008000L
+#define CLK_PIN_CNTL__CP_CLK_RUNNING_MASK 0x00010000L
+#define CLK_PIN_CNTL__CP_CLK_RUNNING 0x00010000L
+#define CLK_PIN_CNTL__CG_SPARE_RD_MASK 0x00060000L
+#define CLK_PIN_CNTL__XTALIN_ALWAYS_ONb_MASK 0x00080000L
+#define CLK_PIN_CNTL__XTALIN_ALWAYS_ONb 0x00080000L
+#define CLK_PIN_CNTL__PWRSEQ_DELAY_MASK 0xff000000L
+
+// CLK_PWRMGT_CNTL_M6
+#define CLK_PWRMGT_CNTL_M6__MPLL_PWRMGT_OFF__SHIFT 0x00000000
+#define CLK_PWRMGT_CNTL_M6__SPLL_PWRMGT_OFF__SHIFT 0x00000001
+#define CLK_PWRMGT_CNTL_M6__PPLL_PWRMGT_OFF__SHIFT 0x00000002
+#define CLK_PWRMGT_CNTL_M6__P2PLL_PWRMGT_OFF__SHIFT 0x00000003
+#define CLK_PWRMGT_CNTL_M6__MCLK_TURNOFF__SHIFT 0x00000004
+#define CLK_PWRMGT_CNTL_M6__SCLK_TURNOFF__SHIFT 0x00000005
+#define CLK_PWRMGT_CNTL_M6__PCLK_TURNOFF__SHIFT 0x00000006
+#define CLK_PWRMGT_CNTL_M6__P2CLK_TURNOFF__SHIFT 0x00000007
+#define CLK_PWRMGT_CNTL_M6__MC_CH_MODE__SHIFT 0x00000008
+#define CLK_PWRMGT_CNTL_M6__TEST_MODE__SHIFT 0x00000009
+#define CLK_PWRMGT_CNTL_M6__GLOBAL_PMAN_EN__SHIFT 0x0000000a
+#define CLK_PWRMGT_CNTL_M6__ENGINE_DYNCLK_MODE__SHIFT 0x0000000c
+#define CLK_PWRMGT_CNTL_M6__ACTIVE_HILO_LAT__SHIFT 0x0000000d
+#define CLK_PWRMGT_CNTL_M6__DISP_DYN_STOP_LAT__SHIFT 0x0000000f
+#define CLK_PWRMGT_CNTL_M6__MC_BUSY__SHIFT 0x00000010
+#define CLK_PWRMGT_CNTL_M6__MC_INT_CNTL__SHIFT 0x00000011
+#define CLK_PWRMGT_CNTL_M6__MC_SWITCH__SHIFT 0x00000012
+#define CLK_PWRMGT_CNTL_M6__DLL_READY__SHIFT 0x00000013
+#define CLK_PWRMGT_CNTL_M6__DISP_PM__SHIFT 0x00000014
+#define CLK_PWRMGT_CNTL_M6__DYN_STOP_MODE__SHIFT 0x00000015
+#define CLK_PWRMGT_CNTL_M6__CG_NO1_DEBUG__SHIFT 0x00000018
+#define CLK_PWRMGT_CNTL_M6__TVPLL_PWRMGT_OFF__SHIFT 0x0000001e
+#define CLK_PWRMGT_CNTL_M6__TVCLK_TURNOFF__SHIFT 0x0000001f
+
+// P2PLL_CNTL
+#define P2PLL_CNTL__P2PLL_RESET_MASK 0x00000001L
+#define P2PLL_CNTL__P2PLL_RESET 0x00000001L
+#define P2PLL_CNTL__P2PLL_SLEEP_MASK 0x00000002L
+#define P2PLL_CNTL__P2PLL_SLEEP 0x00000002L
+#define P2PLL_CNTL__P2PLL_TST_EN_MASK 0x00000004L
+#define P2PLL_CNTL__P2PLL_TST_EN 0x00000004L
+#define P2PLL_CNTL__P2PLL_REFCLK_SEL_MASK 0x00000010L
+#define P2PLL_CNTL__P2PLL_REFCLK_SEL 0x00000010L
+#define P2PLL_CNTL__P2PLL_FBCLK_SEL_MASK 0x00000020L
+#define P2PLL_CNTL__P2PLL_FBCLK_SEL 0x00000020L
+#define P2PLL_CNTL__P2PLL_TCPOFF_MASK 0x00000040L
+#define P2PLL_CNTL__P2PLL_TCPOFF 0x00000040L
+#define P2PLL_CNTL__P2PLL_TVCOMAX_MASK 0x00000080L
+#define P2PLL_CNTL__P2PLL_TVCOMAX 0x00000080L
+#define P2PLL_CNTL__P2PLL_PCP_MASK 0x00000700L
+#define P2PLL_CNTL__P2PLL_PVG_MASK 0x00003800L
+#define P2PLL_CNTL__P2PLL_PDC_MASK 0x0000c000L
+#define P2PLL_CNTL__P2PLL_ATOMIC_UPDATE_EN_MASK 0x00010000L
+#define P2PLL_CNTL__P2PLL_ATOMIC_UPDATE_EN 0x00010000L
+#define P2PLL_CNTL__P2PLL_ATOMIC_UPDATE_SYNC_MASK 0x00040000L
+#define P2PLL_CNTL__P2PLL_ATOMIC_UPDATE_SYNC 0x00040000L
+#define P2PLL_CNTL__P2PLL_DISABLE_AUTO_RESET_MASK 0x00080000L
+#define P2PLL_CNTL__P2PLL_DISABLE_AUTO_RESET 0x00080000L
+
+// PIXCLKS_CNTL
+#define PIXCLKS_CNTL__PIX2CLK_SRC_SEL__SHIFT 0x00000000
+#define PIXCLKS_CNTL__PIX2CLK_INVERT__SHIFT 0x00000004
+#define PIXCLKS_CNTL__PIX2CLK_SRC_INVERT__SHIFT 0x00000005
+#define PIXCLKS_CNTL__PIX2CLK_ALWAYS_ONb__SHIFT 0x00000006
+#define PIXCLKS_CNTL__PIX2CLK_DAC_ALWAYS_ONb__SHIFT 0x00000007
+#define PIXCLKS_CNTL__PIXCLK_TV_SRC_SEL__SHIFT 0x00000008
+#define PIXCLKS_CNTL__PIXCLK_BLEND_ALWAYS_ONb__SHIFT 0x0000000b
+#define PIXCLKS_CNTL__PIXCLK_GV_ALWAYS_ONb__SHIFT 0x0000000c
+#define PIXCLKS_CNTL__PIXCLK_DIG_TMDS_ALWAYS_ONb__SHIFT 0x0000000d
+#define PIXCLKS_CNTL__PIXCLK_LVDS_ALWAYS_ONb__SHIFT 0x0000000e
+#define PIXCLKS_CNTL__PIXCLK_TMDS_ALWAYS_ONb__SHIFT 0x0000000f
+
+
+// PIXCLKS_CNTL
+#define PIXCLKS_CNTL__PIX2CLK_SRC_SEL_MASK 0x00000003L
+#define PIXCLKS_CNTL__PIX2CLK_INVERT_MASK 0x00000010L
+#define PIXCLKS_CNTL__PIX2CLK_INVERT 0x00000010L
+#define PIXCLKS_CNTL__PIX2CLK_SRC_INVERT_MASK 0x00000020L
+#define PIXCLKS_CNTL__PIX2CLK_SRC_INVERT 0x00000020L
+#define PIXCLKS_CNTL__PIX2CLK_ALWAYS_ONb_MASK 0x00000040L
+#define PIXCLKS_CNTL__PIX2CLK_ALWAYS_ONb 0x00000040L
+#define PIXCLKS_CNTL__PIX2CLK_DAC_ALWAYS_ONb_MASK 0x00000080L
+#define PIXCLKS_CNTL__PIX2CLK_DAC_ALWAYS_ONb 0x00000080L
+#define PIXCLKS_CNTL__PIXCLK_TV_SRC_SEL_MASK 0x00000100L
+#define PIXCLKS_CNTL__PIXCLK_TV_SRC_SEL 0x00000100L
+#define PIXCLKS_CNTL__PIXCLK_BLEND_ALWAYS_ONb_MASK 0x00000800L
+#define PIXCLKS_CNTL__PIXCLK_BLEND_ALWAYS_ONb 0x00000800L
+#define PIXCLKS_CNTL__PIXCLK_GV_ALWAYS_ONb_MASK 0x00001000L
+#define PIXCLKS_CNTL__PIXCLK_GV_ALWAYS_ONb 0x00001000L
+#define PIXCLKS_CNTL__PIXCLK_DIG_TMDS_ALWAYS_ONb_MASK 0x00002000L
+#define PIXCLKS_CNTL__PIXCLK_DIG_TMDS_ALWAYS_ONb 0x00002000L
+#define PIXCLKS_CNTL__PIXCLK_LVDS_ALWAYS_ONb_MASK 0x00004000L
+#define PIXCLKS_CNTL__PIXCLK_LVDS_ALWAYS_ONb 0x00004000L
+#define PIXCLKS_CNTL__PIXCLK_TMDS_ALWAYS_ONb_MASK 0x00008000L
+#define PIXCLKS_CNTL__PIXCLK_TMDS_ALWAYS_ONb 0x00008000L
+
+
+// P2PLL_DIV_0
+#define P2PLL_DIV_0__P2PLL_FB_DIV_MASK 0x000007ffL
+#define P2PLL_DIV_0__P2PLL_ATOMIC_UPDATE_W_MASK 0x00008000L
+#define P2PLL_DIV_0__P2PLL_ATOMIC_UPDATE_W 0x00008000L
+#define P2PLL_DIV_0__P2PLL_ATOMIC_UPDATE_R_MASK 0x00008000L
+#define P2PLL_DIV_0__P2PLL_ATOMIC_UPDATE_R 0x00008000L
+#define P2PLL_DIV_0__P2PLL_POST_DIV_MASK 0x00070000L
+
+// SCLK_CNTL_M6
+#define SCLK_CNTL_M6__SCLK_SRC_SEL_MASK 0x00000007L
+#define SCLK_CNTL_M6__CP_MAX_DYN_STOP_LAT_MASK 0x00000008L
+#define SCLK_CNTL_M6__CP_MAX_DYN_STOP_LAT 0x00000008L
+#define SCLK_CNTL_M6__HDP_MAX_DYN_STOP_LAT_MASK 0x00000010L
+#define SCLK_CNTL_M6__HDP_MAX_DYN_STOP_LAT 0x00000010L
+#define SCLK_CNTL_M6__TV_MAX_DYN_STOP_LAT_MASK 0x00000020L
+#define SCLK_CNTL_M6__TV_MAX_DYN_STOP_LAT 0x00000020L
+#define SCLK_CNTL_M6__E2_MAX_DYN_STOP_LAT_MASK 0x00000040L
+#define SCLK_CNTL_M6__E2_MAX_DYN_STOP_LAT 0x00000040L
+#define SCLK_CNTL_M6__SE_MAX_DYN_STOP_LAT_MASK 0x00000080L
+#define SCLK_CNTL_M6__SE_MAX_DYN_STOP_LAT 0x00000080L
+#define SCLK_CNTL_M6__IDCT_MAX_DYN_STOP_LAT_MASK 0x00000100L
+#define SCLK_CNTL_M6__IDCT_MAX_DYN_STOP_LAT 0x00000100L
+#define SCLK_CNTL_M6__VIP_MAX_DYN_STOP_LAT_MASK 0x00000200L
+#define SCLK_CNTL_M6__VIP_MAX_DYN_STOP_LAT 0x00000200L
+#define SCLK_CNTL_M6__RE_MAX_DYN_STOP_LAT_MASK 0x00000400L
+#define SCLK_CNTL_M6__RE_MAX_DYN_STOP_LAT 0x00000400L
+#define SCLK_CNTL_M6__PB_MAX_DYN_STOP_LAT_MASK 0x00000800L
+#define SCLK_CNTL_M6__PB_MAX_DYN_STOP_LAT 0x00000800L
+#define SCLK_CNTL_M6__TAM_MAX_DYN_STOP_LAT_MASK 0x00001000L
+#define SCLK_CNTL_M6__TAM_MAX_DYN_STOP_LAT 0x00001000L
+#define SCLK_CNTL_M6__TDM_MAX_DYN_STOP_LAT_MASK 0x00002000L
+#define SCLK_CNTL_M6__TDM_MAX_DYN_STOP_LAT 0x00002000L
+#define SCLK_CNTL_M6__RB_MAX_DYN_STOP_LAT_MASK 0x00004000L
+#define SCLK_CNTL_M6__RB_MAX_DYN_STOP_LAT 0x00004000L
+#define SCLK_CNTL_M6__FORCE_DISP2_MASK 0x00008000L
+#define SCLK_CNTL_M6__FORCE_DISP2 0x00008000L
+#define SCLK_CNTL_M6__FORCE_CP_MASK 0x00010000L
+#define SCLK_CNTL_M6__FORCE_CP 0x00010000L
+#define SCLK_CNTL_M6__FORCE_HDP_MASK 0x00020000L
+#define SCLK_CNTL_M6__FORCE_HDP 0x00020000L
+#define SCLK_CNTL_M6__FORCE_DISP1_MASK 0x00040000L
+#define SCLK_CNTL_M6__FORCE_DISP1 0x00040000L
+#define SCLK_CNTL_M6__FORCE_TOP_MASK 0x00080000L
+#define SCLK_CNTL_M6__FORCE_TOP 0x00080000L
+#define SCLK_CNTL_M6__FORCE_E2_MASK 0x00100000L
+#define SCLK_CNTL_M6__FORCE_E2 0x00100000L
+#define SCLK_CNTL_M6__FORCE_SE_MASK 0x00200000L
+#define SCLK_CNTL_M6__FORCE_SE 0x00200000L
+#define SCLK_CNTL_M6__FORCE_IDCT_MASK 0x00400000L
+#define SCLK_CNTL_M6__FORCE_IDCT 0x00400000L
+#define SCLK_CNTL_M6__FORCE_VIP_MASK 0x00800000L
+#define SCLK_CNTL_M6__FORCE_VIP 0x00800000L
+#define SCLK_CNTL_M6__FORCE_RE_MASK 0x01000000L
+#define SCLK_CNTL_M6__FORCE_RE 0x01000000L
+#define SCLK_CNTL_M6__FORCE_PB_MASK 0x02000000L
+#define SCLK_CNTL_M6__FORCE_PB 0x02000000L
+#define SCLK_CNTL_M6__FORCE_TAM_MASK 0x04000000L
+#define SCLK_CNTL_M6__FORCE_TAM 0x04000000L
+#define SCLK_CNTL_M6__FORCE_TDM_MASK 0x08000000L
+#define SCLK_CNTL_M6__FORCE_TDM 0x08000000L
+#define SCLK_CNTL_M6__FORCE_RB_MASK 0x10000000L
+#define SCLK_CNTL_M6__FORCE_RB 0x10000000L
+#define SCLK_CNTL_M6__FORCE_TV_SCLK_MASK 0x20000000L
+#define SCLK_CNTL_M6__FORCE_TV_SCLK 0x20000000L
+#define SCLK_CNTL_M6__FORCE_SUBPIC_MASK 0x40000000L
+#define SCLK_CNTL_M6__FORCE_SUBPIC 0x40000000L
+#define SCLK_CNTL_M6__FORCE_OV0_MASK 0x80000000L
+#define SCLK_CNTL_M6__FORCE_OV0 0x80000000L
+
+// SCLK_MORE_CNTL
+#define SCLK_MORE_CNTL__DISPREGS_MAX_DYN_STOP_LAT_MASK 0x00000001L
+#define SCLK_MORE_CNTL__DISPREGS_MAX_DYN_STOP_LAT 0x00000001L
+#define SCLK_MORE_CNTL__MC_GUI_MAX_DYN_STOP_LAT_MASK 0x00000002L
+#define SCLK_MORE_CNTL__MC_GUI_MAX_DYN_STOP_LAT 0x00000002L
+#define SCLK_MORE_CNTL__MC_HOST_MAX_DYN_STOP_LAT_MASK 0x00000004L
+#define SCLK_MORE_CNTL__MC_HOST_MAX_DYN_STOP_LAT 0x00000004L
+#define SCLK_MORE_CNTL__FORCE_DISPREGS_MASK 0x00000100L
+#define SCLK_MORE_CNTL__FORCE_DISPREGS 0x00000100L
+#define SCLK_MORE_CNTL__FORCE_MC_GUI_MASK 0x00000200L
+#define SCLK_MORE_CNTL__FORCE_MC_GUI 0x00000200L
+#define SCLK_MORE_CNTL__FORCE_MC_HOST_MASK 0x00000400L
+#define SCLK_MORE_CNTL__FORCE_MC_HOST 0x00000400L
+#define SCLK_MORE_CNTL__STOP_SCLK_EN_MASK 0x00001000L
+#define SCLK_MORE_CNTL__STOP_SCLK_EN 0x00001000L
+#define SCLK_MORE_CNTL__STOP_SCLK_A_MASK 0x00002000L
+#define SCLK_MORE_CNTL__STOP_SCLK_A 0x00002000L
+#define SCLK_MORE_CNTL__STOP_SCLK_B_MASK 0x00004000L
+#define SCLK_MORE_CNTL__STOP_SCLK_B 0x00004000L
+#define SCLK_MORE_CNTL__STOP_SCLK_C_MASK 0x00008000L
+#define SCLK_MORE_CNTL__STOP_SCLK_C 0x00008000L
+#define SCLK_MORE_CNTL__HALF_SPEED_SCLK_MASK 0x00010000L
+#define SCLK_MORE_CNTL__HALF_SPEED_SCLK 0x00010000L
+#define SCLK_MORE_CNTL__IO_CG_VOLTAGE_DROP_MASK 0x00020000L
+#define SCLK_MORE_CNTL__IO_CG_VOLTAGE_DROP 0x00020000L
+#define SCLK_MORE_CNTL__TVFB_SOFT_RESET_MASK 0x00040000L
+#define SCLK_MORE_CNTL__TVFB_SOFT_RESET 0x00040000L
+#define SCLK_MORE_CNTL__VOLTAGE_DROP_SYNC_MASK 0x00080000L
+#define SCLK_MORE_CNTL__VOLTAGE_DROP_SYNC 0x00080000L
+#define SCLK_MORE_CNTL__VOLTAGE_DELAY_SEL_MASK 0x00300000L
+#define SCLK_MORE_CNTL__IDLE_DELAY_HALF_SCLK_MASK 0x00400000L
+#define SCLK_MORE_CNTL__IDLE_DELAY_HALF_SCLK 0x00400000L
+#define SCLK_MORE_CNTL__AGP_BUSY_HALF_SCLK_MASK 0x00800000L
+#define SCLK_MORE_CNTL__AGP_BUSY_HALF_SCLK 0x00800000L
+#define SCLK_MORE_CNTL__CG_SPARE_RD_C_MASK 0xff000000L
+
+// MCLK_CNTL_M6
+#define MCLK_CNTL_M6__MCLKA_SRC_SEL_MASK 0x00000007L
+#define MCLK_CNTL_M6__YCLKA_SRC_SEL_MASK 0x00000070L
+#define MCLK_CNTL_M6__MCLKB_SRC_SEL_MASK 0x00000700L
+#define MCLK_CNTL_M6__YCLKB_SRC_SEL_MASK 0x00007000L
+#define MCLK_CNTL_M6__FORCE_MCLKA_MASK 0x00010000L
+#define MCLK_CNTL_M6__FORCE_MCLKA 0x00010000L
+#define MCLK_CNTL_M6__FORCE_MCLKB_MASK 0x00020000L
+#define MCLK_CNTL_M6__FORCE_MCLKB 0x00020000L
+#define MCLK_CNTL_M6__FORCE_YCLKA_MASK 0x00040000L
+#define MCLK_CNTL_M6__FORCE_YCLKA 0x00040000L
+#define MCLK_CNTL_M6__FORCE_YCLKB_MASK 0x00080000L
+#define MCLK_CNTL_M6__FORCE_YCLKB 0x00080000L
+#define MCLK_CNTL_M6__FORCE_MC_MASK 0x00100000L
+#define MCLK_CNTL_M6__FORCE_MC 0x00100000L
+#define MCLK_CNTL_M6__FORCE_AIC_MASK 0x00200000L
+#define MCLK_CNTL_M6__FORCE_AIC 0x00200000L
+#define MCLK_CNTL_M6__MRDCKA0_SOUTSEL_MASK 0x03000000L
+#define MCLK_CNTL_M6__MRDCKA1_SOUTSEL_MASK 0x0c000000L
+#define MCLK_CNTL_M6__MRDCKB0_SOUTSEL_MASK 0x30000000L
+#define MCLK_CNTL_M6__MRDCKB1_SOUTSEL_MASK 0xc0000000L
+
+// MCLK_MISC
+#define MCLK_MISC__SCLK_SOURCED_FROM_MPLL_SEL_MASK 0x00000003L
+#define MCLK_MISC__MCLK_FROM_SPLL_DIV_SEL_MASK 0x00000004L
+#define MCLK_MISC__MCLK_FROM_SPLL_DIV_SEL 0x00000004L
+#define MCLK_MISC__ENABLE_SCLK_FROM_MPLL_MASK 0x00000008L
+#define MCLK_MISC__ENABLE_SCLK_FROM_MPLL 0x00000008L
+#define MCLK_MISC__MPLL_MODEA_MODEC_HW_SEL_EN_MASK 0x00000010L
+#define MCLK_MISC__MPLL_MODEA_MODEC_HW_SEL_EN 0x00000010L
+#define MCLK_MISC__DLL_READY_LAT_MASK 0x00000100L
+#define MCLK_MISC__DLL_READY_LAT 0x00000100L
+#define MCLK_MISC__MC_MCLK_MAX_DYN_STOP_LAT_MASK 0x00001000L
+#define MCLK_MISC__MC_MCLK_MAX_DYN_STOP_LAT 0x00001000L
+#define MCLK_MISC__IO_MCLK_MAX_DYN_STOP_LAT_MASK 0x00002000L
+#define MCLK_MISC__IO_MCLK_MAX_DYN_STOP_LAT 0x00002000L
+#define MCLK_MISC__MC_MCLK_DYN_ENABLE_MASK 0x00004000L
+#define MCLK_MISC__MC_MCLK_DYN_ENABLE 0x00004000L
+#define MCLK_MISC__IO_MCLK_DYN_ENABLE_MASK 0x00008000L
+#define MCLK_MISC__IO_MCLK_DYN_ENABLE 0x00008000L
+#define MCLK_MISC__CGM_CLK_TO_OUTPIN_MASK 0x00010000L
+#define MCLK_MISC__CGM_CLK_TO_OUTPIN 0x00010000L
+#define MCLK_MISC__CLK_OR_COUNT_SEL_MASK 0x00020000L
+#define MCLK_MISC__CLK_OR_COUNT_SEL 0x00020000L
+#define MCLK_MISC__EN_MCLK_TRISTATE_IN_SUSPEND_MASK 0x00040000L
+#define MCLK_MISC__EN_MCLK_TRISTATE_IN_SUSPEND 0x00040000L
+#define MCLK_MISC__CGM_SPARE_RD_MASK 0x00300000L
+#define MCLK_MISC__CGM_SPARE_A_RD_MASK 0x00c00000L
+#define MCLK_MISC__TCLK_TO_YCLKB_EN_MASK 0x01000000L
+#define MCLK_MISC__TCLK_TO_YCLKB_EN 0x01000000L
+#define MCLK_MISC__CGM_SPARE_A_MASK 0x0e000000L
+
+// VCLK_ECP_CNTL
+#define VCLK_ECP_CNTL__VCLK_SRC_SEL_MASK 0x00000003L
+#define VCLK_ECP_CNTL__VCLK_INVERT_MASK 0x00000010L
+#define VCLK_ECP_CNTL__VCLK_INVERT 0x00000010L
+#define VCLK_ECP_CNTL__PIXCLK_SRC_INVERT_MASK 0x00000020L
+#define VCLK_ECP_CNTL__PIXCLK_SRC_INVERT 0x00000020L
+#define VCLK_ECP_CNTL__PIXCLK_ALWAYS_ONb_MASK 0x00000040L
+#define VCLK_ECP_CNTL__PIXCLK_ALWAYS_ONb 0x00000040L
+#define VCLK_ECP_CNTL__PIXCLK_DAC_ALWAYS_ONb_MASK 0x00000080L
+#define VCLK_ECP_CNTL__PIXCLK_DAC_ALWAYS_ONb 0x00000080L
+#define VCLK_ECP_CNTL__ECP_DIV_MASK 0x00000300L
+#define VCLK_ECP_CNTL__ECP_FORCE_ON_MASK 0x00040000L
+#define VCLK_ECP_CNTL__ECP_FORCE_ON 0x00040000L
+#define VCLK_ECP_CNTL__SUBCLK_FORCE_ON_MASK 0x00080000L
+#define VCLK_ECP_CNTL__SUBCLK_FORCE_ON 0x00080000L
+
+// PLL_PWRMGT_CNTL
+#define PLL_PWRMGT_CNTL__MPLL_TURNOFF_MASK 0x00000001L
+#define PLL_PWRMGT_CNTL__MPLL_TURNOFF 0x00000001L
+#define PLL_PWRMGT_CNTL__SPLL_TURNOFF_MASK 0x00000002L
+#define PLL_PWRMGT_CNTL__SPLL_TURNOFF 0x00000002L
+#define PLL_PWRMGT_CNTL__PPLL_TURNOFF_MASK 0x00000004L
+#define PLL_PWRMGT_CNTL__PPLL_TURNOFF 0x00000004L
+#define PLL_PWRMGT_CNTL__P2PLL_TURNOFF_MASK 0x00000008L
+#define PLL_PWRMGT_CNTL__P2PLL_TURNOFF 0x00000008L
+#define PLL_PWRMGT_CNTL__TVPLL_TURNOFF_MASK 0x00000010L
+#define PLL_PWRMGT_CNTL__TVPLL_TURNOFF 0x00000010L
+#define PLL_PWRMGT_CNTL__AGPCLK_DYN_STOP_LAT_MASK 0x000001e0L
+#define PLL_PWRMGT_CNTL__APM_POWER_STATE_MASK 0x00000600L
+#define PLL_PWRMGT_CNTL__APM_PWRSTATE_RD_MASK 0x00001800L
+#define PLL_PWRMGT_CNTL__PM_MODE_SEL_MASK 0x00002000L
+#define PLL_PWRMGT_CNTL__PM_MODE_SEL 0x00002000L
+#define PLL_PWRMGT_CNTL__EN_PWRSEQ_DONE_COND_MASK 0x00004000L
+#define PLL_PWRMGT_CNTL__EN_PWRSEQ_DONE_COND 0x00004000L
+#define PLL_PWRMGT_CNTL__EN_DISP_PARKED_COND_MASK 0x00008000L
+#define PLL_PWRMGT_CNTL__EN_DISP_PARKED_COND 0x00008000L
+#define PLL_PWRMGT_CNTL__MOBILE_SU_MASK 0x00010000L
+#define PLL_PWRMGT_CNTL__MOBILE_SU 0x00010000L
+#define PLL_PWRMGT_CNTL__SU_SCLK_USE_BCLK_MASK 0x00020000L
+#define PLL_PWRMGT_CNTL__SU_SCLK_USE_BCLK 0x00020000L
+#define PLL_PWRMGT_CNTL__SU_MCLK_USE_BCLK_MASK 0x00040000L
+#define PLL_PWRMGT_CNTL__SU_MCLK_USE_BCLK 0x00040000L
+#define PLL_PWRMGT_CNTL__SU_SUSTAIN_DISABLE_MASK 0x00080000L
+#define PLL_PWRMGT_CNTL__SU_SUSTAIN_DISABLE 0x00080000L
+#define PLL_PWRMGT_CNTL__TCL_BYPASS_DISABLE_MASK 0x00100000L
+#define PLL_PWRMGT_CNTL__TCL_BYPASS_DISABLE 0x00100000L
+#define PLL_PWRMGT_CNTL__TCL_CLOCK_ACTIVE_RD_MASK 0x00200000L
+#define PLL_PWRMGT_CNTL__TCL_CLOCK_ACTIVE_RD 0x00200000L
+#define PLL_PWRMGT_CNTL__CG_NO2_DEBUG_MASK 0xff000000L
+
+// CLK_PWRMGT_CNTL_M6
+#define CLK_PWRMGT_CNTL_M6__MPLL_PWRMGT_OFF_MASK 0x00000001L
+#define CLK_PWRMGT_CNTL_M6__MPLL_PWRMGT_OFF 0x00000001L
+#define CLK_PWRMGT_CNTL_M6__SPLL_PWRMGT_OFF_MASK 0x00000002L
+#define CLK_PWRMGT_CNTL_M6__SPLL_PWRMGT_OFF 0x00000002L
+#define CLK_PWRMGT_CNTL_M6__PPLL_PWRMGT_OFF_MASK 0x00000004L
+#define CLK_PWRMGT_CNTL_M6__PPLL_PWRMGT_OFF 0x00000004L
+#define CLK_PWRMGT_CNTL_M6__P2PLL_PWRMGT_OFF_MASK 0x00000008L
+#define CLK_PWRMGT_CNTL_M6__P2PLL_PWRMGT_OFF 0x00000008L
+#define CLK_PWRMGT_CNTL_M6__MCLK_TURNOFF_MASK 0x00000010L
+#define CLK_PWRMGT_CNTL_M6__MCLK_TURNOFF 0x00000010L
+#define CLK_PWRMGT_CNTL_M6__SCLK_TURNOFF_MASK 0x00000020L
+#define CLK_PWRMGT_CNTL_M6__SCLK_TURNOFF 0x00000020L
+#define CLK_PWRMGT_CNTL_M6__PCLK_TURNOFF_MASK 0x00000040L
+#define CLK_PWRMGT_CNTL_M6__PCLK_TURNOFF 0x00000040L
+#define CLK_PWRMGT_CNTL_M6__P2CLK_TURNOFF_MASK 0x00000080L
+#define CLK_PWRMGT_CNTL_M6__P2CLK_TURNOFF 0x00000080L
+#define CLK_PWRMGT_CNTL_M6__MC_CH_MODE_MASK 0x00000100L
+#define CLK_PWRMGT_CNTL_M6__MC_CH_MODE 0x00000100L
+#define CLK_PWRMGT_CNTL_M6__TEST_MODE_MASK 0x00000200L
+#define CLK_PWRMGT_CNTL_M6__TEST_MODE 0x00000200L
+#define CLK_PWRMGT_CNTL_M6__GLOBAL_PMAN_EN_MASK 0x00000400L
+#define CLK_PWRMGT_CNTL_M6__GLOBAL_PMAN_EN 0x00000400L
+#define CLK_PWRMGT_CNTL_M6__ENGINE_DYNCLK_MODE_MASK 0x00001000L
+#define CLK_PWRMGT_CNTL_M6__ENGINE_DYNCLK_MODE 0x00001000L
+#define CLK_PWRMGT_CNTL_M6__ACTIVE_HILO_LAT_MASK 0x00006000L
+#define CLK_PWRMGT_CNTL_M6__DISP_DYN_STOP_LAT_MASK 0x00008000L
+#define CLK_PWRMGT_CNTL_M6__DISP_DYN_STOP_LAT 0x00008000L
+#define CLK_PWRMGT_CNTL_M6__MC_BUSY_MASK 0x00010000L
+#define CLK_PWRMGT_CNTL_M6__MC_BUSY 0x00010000L
+#define CLK_PWRMGT_CNTL_M6__MC_INT_CNTL_MASK 0x00020000L
+#define CLK_PWRMGT_CNTL_M6__MC_INT_CNTL 0x00020000L
+#define CLK_PWRMGT_CNTL_M6__MC_SWITCH_MASK 0x00040000L
+#define CLK_PWRMGT_CNTL_M6__MC_SWITCH 0x00040000L
+#define CLK_PWRMGT_CNTL_M6__DLL_READY_MASK 0x00080000L
+#define CLK_PWRMGT_CNTL_M6__DLL_READY 0x00080000L
+#define CLK_PWRMGT_CNTL_M6__DISP_PM_MASK 0x00100000L
+#define CLK_PWRMGT_CNTL_M6__DISP_PM 0x00100000L
+#define CLK_PWRMGT_CNTL_M6__DYN_STOP_MODE_MASK 0x00e00000L
+#define CLK_PWRMGT_CNTL_M6__CG_NO1_DEBUG_MASK 0x3f000000L
+#define CLK_PWRMGT_CNTL_M6__TVPLL_PWRMGT_OFF_MASK 0x40000000L
+#define CLK_PWRMGT_CNTL_M6__TVPLL_PWRMGT_OFF 0x40000000L
+#define CLK_PWRMGT_CNTL_M6__TVCLK_TURNOFF_MASK 0x80000000L
+#define CLK_PWRMGT_CNTL_M6__TVCLK_TURNOFF 0x80000000L
+
+// BUS_CNTL1
+#define BUS_CNTL1__PMI_IO_DISABLE_MASK 0x00000001L
+#define BUS_CNTL1__PMI_IO_DISABLE 0x00000001L
+#define BUS_CNTL1__PMI_MEM_DISABLE_MASK 0x00000002L
+#define BUS_CNTL1__PMI_MEM_DISABLE 0x00000002L
+#define BUS_CNTL1__PMI_BM_DISABLE_MASK 0x00000004L
+#define BUS_CNTL1__PMI_BM_DISABLE 0x00000004L
+#define BUS_CNTL1__PMI_INT_DISABLE_MASK 0x00000008L
+#define BUS_CNTL1__PMI_INT_DISABLE 0x00000008L
+#define BUS_CNTL1__BUS2_IMMEDIATE_PMI_DISABLE_MASK 0x00000020L
+#define BUS_CNTL1__BUS2_IMMEDIATE_PMI_DISABLE 0x00000020L
+#define BUS_CNTL1__BUS2_VGA_REG_COHERENCY_DIS_MASK 0x00000100L
+#define BUS_CNTL1__BUS2_VGA_REG_COHERENCY_DIS 0x00000100L
+#define BUS_CNTL1__BUS2_VGA_MEM_COHERENCY_DIS_MASK 0x00000200L
+#define BUS_CNTL1__BUS2_VGA_MEM_COHERENCY_DIS 0x00000200L
+#define BUS_CNTL1__BUS2_HDP_REG_COHERENCY_DIS_MASK 0x00000400L
+#define BUS_CNTL1__BUS2_HDP_REG_COHERENCY_DIS 0x00000400L
+#define BUS_CNTL1__BUS2_GUI_INITIATOR_COHERENCY_DIS_MASK 0x00000800L
+#define BUS_CNTL1__BUS2_GUI_INITIATOR_COHERENCY_DIS 0x00000800L
+#define BUS_CNTL1__MOBILE_PLATFORM_SEL_MASK 0x0c000000L
+#define BUS_CNTL1__SEND_SBA_LATENCY_MASK 0x70000000L
+#define BUS_CNTL1__AGPCLK_VALID_MASK 0x80000000L
+#define BUS_CNTL1__AGPCLK_VALID 0x80000000L
+
+// BUS_CNTL1
+#define BUS_CNTL1__PMI_IO_DISABLE__SHIFT 0x00000000
+#define BUS_CNTL1__PMI_MEM_DISABLE__SHIFT 0x00000001
+#define BUS_CNTL1__PMI_BM_DISABLE__SHIFT 0x00000002
+#define BUS_CNTL1__PMI_INT_DISABLE__SHIFT 0x00000003
+#define BUS_CNTL1__BUS2_IMMEDIATE_PMI_DISABLE__SHIFT 0x00000005
+#define BUS_CNTL1__BUS2_VGA_REG_COHERENCY_DIS__SHIFT 0x00000008
+#define BUS_CNTL1__BUS2_VGA_MEM_COHERENCY_DIS__SHIFT 0x00000009
+#define BUS_CNTL1__BUS2_HDP_REG_COHERENCY_DIS__SHIFT 0x0000000a
+#define BUS_CNTL1__BUS2_GUI_INITIATOR_COHERENCY_DIS__SHIFT 0x0000000b
+#define BUS_CNTL1__MOBILE_PLATFORM_SEL__SHIFT 0x0000001a
+#define BUS_CNTL1__SEND_SBA_LATENCY__SHIFT 0x0000001c
+#define BUS_CNTL1__AGPCLK_VALID__SHIFT 0x0000001f
+
+// CRTC_OFFSET_CNTL
+#define CRTC_OFFSET_CNTL__CRTC_TILE_LINE_MASK 0x0000000fL
+#define CRTC_OFFSET_CNTL__CRTC_TILE_LINE_RIGHT_MASK 0x000000f0L
+#define CRTC_OFFSET_CNTL__CRTC_TILE_EN_RIGHT_MASK 0x00004000L
+#define CRTC_OFFSET_CNTL__CRTC_TILE_EN_RIGHT 0x00004000L
+#define CRTC_OFFSET_CNTL__CRTC_TILE_EN_MASK 0x00008000L
+#define CRTC_OFFSET_CNTL__CRTC_TILE_EN 0x00008000L
+#define CRTC_OFFSET_CNTL__CRTC_OFFSET_FLIP_CNTL_MASK 0x00010000L
+#define CRTC_OFFSET_CNTL__CRTC_OFFSET_FLIP_CNTL 0x00010000L
+#define CRTC_OFFSET_CNTL__CRTC_STEREO_OFFSET_EN_MASK 0x00020000L
+#define CRTC_OFFSET_CNTL__CRTC_STEREO_OFFSET_EN 0x00020000L
+#define CRTC_OFFSET_CNTL__CRTC_STEREO_SYNC_EN_MASK 0x000c0000L
+#define CRTC_OFFSET_CNTL__CRTC_STEREO_SYNC_OUT_EN_MASK 0x00100000L
+#define CRTC_OFFSET_CNTL__CRTC_STEREO_SYNC_OUT_EN 0x00100000L
+#define CRTC_OFFSET_CNTL__CRTC_STEREO_SYNC_MASK 0x00200000L
+#define CRTC_OFFSET_CNTL__CRTC_STEREO_SYNC 0x00200000L
+#define CRTC_OFFSET_CNTL__CRTC_GUI_TRIG_OFFSET_LEFT_EN_MASK 0x10000000L
+#define CRTC_OFFSET_CNTL__CRTC_GUI_TRIG_OFFSET_LEFT_EN 0x10000000L
+#define CRTC_OFFSET_CNTL__CRTC_GUI_TRIG_OFFSET_RIGHT_EN_MASK 0x20000000L
+#define CRTC_OFFSET_CNTL__CRTC_GUI_TRIG_OFFSET_RIGHT_EN 0x20000000L
+#define CRTC_OFFSET_CNTL__CRTC_GUI_TRIG_OFFSET_MASK 0x40000000L
+#define CRTC_OFFSET_CNTL__CRTC_GUI_TRIG_OFFSET 0x40000000L
+#define CRTC_OFFSET_CNTL__CRTC_OFFSET_LOCK_MASK 0x80000000L
+#define CRTC_OFFSET_CNTL__CRTC_OFFSET_LOCK 0x80000000L
+
+// CRTC_GEN_CNTL
+#define CRTC_GEN_CNTL__CRTC_DBL_SCAN_EN_MASK 0x00000001L
+#define CRTC_GEN_CNTL__CRTC_DBL_SCAN_EN 0x00000001L
+#define CRTC_GEN_CNTL__CRTC_INTERLACE_EN_MASK 0x00000002L
+#define CRTC_GEN_CNTL__CRTC_INTERLACE_EN 0x00000002L
+#define CRTC_GEN_CNTL__CRTC_C_SYNC_EN_MASK 0x00000010L
+#define CRTC_GEN_CNTL__CRTC_C_SYNC_EN 0x00000010L
+#define CRTC_GEN_CNTL__CRTC_PIX_WIDTH_MASK 0x00000f00L
+#define CRTC_GEN_CNTL__CRTC_ICON_EN_MASK 0x00008000L
+#define CRTC_GEN_CNTL__CRTC_ICON_EN 0x00008000L
+#define CRTC_GEN_CNTL__CRTC_CUR_EN_MASK 0x00010000L
+#define CRTC_GEN_CNTL__CRTC_CUR_EN 0x00010000L
+#define CRTC_GEN_CNTL__CRTC_VSTAT_MODE_MASK 0x00060000L
+#define CRTC_GEN_CNTL__CRTC_CUR_MODE_MASK 0x00700000L
+#define CRTC_GEN_CNTL__CRTC_EXT_DISP_EN_MASK 0x01000000L
+#define CRTC_GEN_CNTL__CRTC_EXT_DISP_EN 0x01000000L
+#define CRTC_GEN_CNTL__CRTC_EN_MASK 0x02000000L
+#define CRTC_GEN_CNTL__CRTC_EN 0x02000000L
+#define CRTC_GEN_CNTL__CRTC_DISP_REQ_EN_B_MASK 0x04000000L
+#define CRTC_GEN_CNTL__CRTC_DISP_REQ_EN_B 0x04000000L
+
+// CRTC2_GEN_CNTL
+#define CRTC2_GEN_CNTL__CRTC2_DBL_SCAN_EN_MASK 0x00000001L
+#define CRTC2_GEN_CNTL__CRTC2_DBL_SCAN_EN 0x00000001L
+#define CRTC2_GEN_CNTL__CRTC2_INTERLACE_EN_MASK 0x00000002L
+#define CRTC2_GEN_CNTL__CRTC2_INTERLACE_EN 0x00000002L
+#define CRTC2_GEN_CNTL__CRTC2_SYNC_TRISTATE_MASK 0x00000010L
+#define CRTC2_GEN_CNTL__CRTC2_SYNC_TRISTATE 0x00000010L
+#define CRTC2_GEN_CNTL__CRTC2_HSYNC_TRISTATE_MASK 0x00000020L
+#define CRTC2_GEN_CNTL__CRTC2_HSYNC_TRISTATE 0x00000020L
+#define CRTC2_GEN_CNTL__CRTC2_VSYNC_TRISTATE_MASK 0x00000040L
+#define CRTC2_GEN_CNTL__CRTC2_VSYNC_TRISTATE 0x00000040L
+#define CRTC2_GEN_CNTL__CRT2_ON_MASK 0x00000080L
+#define CRTC2_GEN_CNTL__CRT2_ON 0x00000080L
+#define CRTC2_GEN_CNTL__CRTC2_PIX_WIDTH_MASK 0x00000f00L
+#define CRTC2_GEN_CNTL__CRTC2_ICON_EN_MASK 0x00008000L
+#define CRTC2_GEN_CNTL__CRTC2_ICON_EN 0x00008000L
+#define CRTC2_GEN_CNTL__CRTC2_CUR_EN_MASK 0x00010000L
+#define CRTC2_GEN_CNTL__CRTC2_CUR_EN 0x00010000L
+#define CRTC2_GEN_CNTL__CRTC2_CUR_MODE_MASK 0x00700000L
+#define CRTC2_GEN_CNTL__CRTC2_DISPLAY_DIS_MASK 0x00800000L
+#define CRTC2_GEN_CNTL__CRTC2_DISPLAY_DIS 0x00800000L
+#define CRTC2_GEN_CNTL__CRTC2_EN_MASK 0x02000000L
+#define CRTC2_GEN_CNTL__CRTC2_EN 0x02000000L
+#define CRTC2_GEN_CNTL__CRTC2_DISP_REQ_EN_B_MASK 0x04000000L
+#define CRTC2_GEN_CNTL__CRTC2_DISP_REQ_EN_B 0x04000000L
+#define CRTC2_GEN_CNTL__CRTC2_C_SYNC_EN_MASK 0x08000000L
+#define CRTC2_GEN_CNTL__CRTC2_C_SYNC_EN 0x08000000L
+#define CRTC2_GEN_CNTL__CRTC2_HSYNC_DIS_MASK 0x10000000L
+#define CRTC2_GEN_CNTL__CRTC2_HSYNC_DIS 0x10000000L
+#define CRTC2_GEN_CNTL__CRTC2_VSYNC_DIS_MASK 0x20000000L
+#define CRTC2_GEN_CNTL__CRTC2_VSYNC_DIS 0x20000000L
+
+// AGP_CNTL
+#define AGP_CNTL__MAX_IDLE_CLK_MASK 0x000000ffL
+#define AGP_CNTL__HOLD_RD_FIFO_MASK 0x00000100L
+#define AGP_CNTL__HOLD_RD_FIFO 0x00000100L
+#define AGP_CNTL__HOLD_RQ_FIFO_MASK 0x00000200L
+#define AGP_CNTL__HOLD_RQ_FIFO 0x00000200L
+#define AGP_CNTL__EN_2X_STBB_MASK 0x00000400L
+#define AGP_CNTL__EN_2X_STBB 0x00000400L
+#define AGP_CNTL__FORCE_FULL_SBA_MASK 0x00000800L
+#define AGP_CNTL__FORCE_FULL_SBA 0x00000800L
+#define AGP_CNTL__SBA_DIS_MASK 0x00001000L
+#define AGP_CNTL__SBA_DIS 0x00001000L
+#define AGP_CNTL__AGP_REV_ID_MASK 0x00002000L
+#define AGP_CNTL__AGP_REV_ID 0x00002000L
+#define AGP_CNTL__REG_CRIPPLE_AGP4X_MASK 0x00004000L
+#define AGP_CNTL__REG_CRIPPLE_AGP4X 0x00004000L
+#define AGP_CNTL__REG_CRIPPLE_AGP2X4X_MASK 0x00008000L
+#define AGP_CNTL__REG_CRIPPLE_AGP2X4X 0x00008000L
+#define AGP_CNTL__FORCE_INT_VREF_MASK 0x00010000L
+#define AGP_CNTL__FORCE_INT_VREF 0x00010000L
+#define AGP_CNTL__PENDING_SLOTS_VAL_MASK 0x00060000L
+#define AGP_CNTL__PENDING_SLOTS_SEL_MASK 0x00080000L
+#define AGP_CNTL__PENDING_SLOTS_SEL 0x00080000L
+#define AGP_CNTL__EN_EXTENDED_AD_STB_2X_MASK 0x00100000L
+#define AGP_CNTL__EN_EXTENDED_AD_STB_2X 0x00100000L
+#define AGP_CNTL__DIS_QUEUED_GNT_FIX_MASK 0x00200000L
+#define AGP_CNTL__DIS_QUEUED_GNT_FIX 0x00200000L
+#define AGP_CNTL__EN_RDATA2X4X_MULTIRESET_MASK 0x00400000L
+#define AGP_CNTL__EN_RDATA2X4X_MULTIRESET 0x00400000L
+#define AGP_CNTL__EN_RBFCALM_MASK 0x00800000L
+#define AGP_CNTL__EN_RBFCALM 0x00800000L
+#define AGP_CNTL__FORCE_EXT_VREF_MASK 0x01000000L
+#define AGP_CNTL__FORCE_EXT_VREF 0x01000000L
+#define AGP_CNTL__DIS_RBF_MASK 0x02000000L
+#define AGP_CNTL__DIS_RBF 0x02000000L
+#define AGP_CNTL__DELAY_FIRST_SBA_EN_MASK 0x04000000L
+#define AGP_CNTL__DELAY_FIRST_SBA_EN 0x04000000L
+#define AGP_CNTL__DELAY_FIRST_SBA_VAL_MASK 0x38000000L
+#define AGP_CNTL__AGP_MISC_MASK 0xc0000000L
+
+// AGP_CNTL
+#define AGP_CNTL__MAX_IDLE_CLK__SHIFT 0x00000000
+#define AGP_CNTL__HOLD_RD_FIFO__SHIFT 0x00000008
+#define AGP_CNTL__HOLD_RQ_FIFO__SHIFT 0x00000009
+#define AGP_CNTL__EN_2X_STBB__SHIFT 0x0000000a
+#define AGP_CNTL__FORCE_FULL_SBA__SHIFT 0x0000000b
+#define AGP_CNTL__SBA_DIS__SHIFT 0x0000000c
+#define AGP_CNTL__AGP_REV_ID__SHIFT 0x0000000d
+#define AGP_CNTL__REG_CRIPPLE_AGP4X__SHIFT 0x0000000e
+#define AGP_CNTL__REG_CRIPPLE_AGP2X4X__SHIFT 0x0000000f
+#define AGP_CNTL__FORCE_INT_VREF__SHIFT 0x00000010
+#define AGP_CNTL__PENDING_SLOTS_VAL__SHIFT 0x00000011
+#define AGP_CNTL__PENDING_SLOTS_SEL__SHIFT 0x00000013
+#define AGP_CNTL__EN_EXTENDED_AD_STB_2X__SHIFT 0x00000014
+#define AGP_CNTL__DIS_QUEUED_GNT_FIX__SHIFT 0x00000015
+#define AGP_CNTL__EN_RDATA2X4X_MULTIRESET__SHIFT 0x00000016
+#define AGP_CNTL__EN_RBFCALM__SHIFT 0x00000017
+#define AGP_CNTL__FORCE_EXT_VREF__SHIFT 0x00000018
+#define AGP_CNTL__DIS_RBF__SHIFT 0x00000019
+#define AGP_CNTL__DELAY_FIRST_SBA_EN__SHIFT 0x0000001a
+#define AGP_CNTL__DELAY_FIRST_SBA_VAL__SHIFT 0x0000001b
+#define AGP_CNTL__AGP_MISC__SHIFT 0x0000001e
+
+// DISP_MISC_CNTL
+#define DISP_MISC_CNTL__SOFT_RESET_GRPH_PP_MASK 0x00000001L
+#define DISP_MISC_CNTL__SOFT_RESET_GRPH_PP 0x00000001L
+#define DISP_MISC_CNTL__SOFT_RESET_SUBPIC_PP_MASK 0x00000002L
+#define DISP_MISC_CNTL__SOFT_RESET_SUBPIC_PP 0x00000002L
+#define DISP_MISC_CNTL__SOFT_RESET_OV0_PP_MASK 0x00000004L
+#define DISP_MISC_CNTL__SOFT_RESET_OV0_PP 0x00000004L
+#define DISP_MISC_CNTL__SOFT_RESET_GRPH_SCLK_MASK 0x00000010L
+#define DISP_MISC_CNTL__SOFT_RESET_GRPH_SCLK 0x00000010L
+#define DISP_MISC_CNTL__SOFT_RESET_SUBPIC_SCLK_MASK 0x00000020L
+#define DISP_MISC_CNTL__SOFT_RESET_SUBPIC_SCLK 0x00000020L
+#define DISP_MISC_CNTL__SOFT_RESET_OV0_SCLK_MASK 0x00000040L
+#define DISP_MISC_CNTL__SOFT_RESET_OV0_SCLK 0x00000040L
+#define DISP_MISC_CNTL__SYNC_STRENGTH_MASK 0x00000300L
+#define DISP_MISC_CNTL__SYNC_PAD_FLOP_EN_MASK 0x00000400L
+#define DISP_MISC_CNTL__SYNC_PAD_FLOP_EN 0x00000400L
+#define DISP_MISC_CNTL__SOFT_RESET_GRPH2_PP_MASK 0x00001000L
+#define DISP_MISC_CNTL__SOFT_RESET_GRPH2_PP 0x00001000L
+#define DISP_MISC_CNTL__SOFT_RESET_GRPH2_SCLK_MASK 0x00008000L
+#define DISP_MISC_CNTL__SOFT_RESET_GRPH2_SCLK 0x00008000L
+#define DISP_MISC_CNTL__SOFT_RESET_LVDS_MASK 0x00010000L
+#define DISP_MISC_CNTL__SOFT_RESET_LVDS 0x00010000L
+#define DISP_MISC_CNTL__SOFT_RESET_TMDS_MASK 0x00020000L
+#define DISP_MISC_CNTL__SOFT_RESET_TMDS 0x00020000L
+#define DISP_MISC_CNTL__SOFT_RESET_DIG_TMDS_MASK 0x00040000L
+#define DISP_MISC_CNTL__SOFT_RESET_DIG_TMDS 0x00040000L
+#define DISP_MISC_CNTL__SOFT_RESET_TV_MASK 0x00080000L
+#define DISP_MISC_CNTL__SOFT_RESET_TV 0x00080000L
+#define DISP_MISC_CNTL__PALETTE2_MEM_RD_MARGIN_MASK 0x00f00000L
+#define DISP_MISC_CNTL__PALETTE_MEM_RD_MARGIN_MASK 0x0f000000L
+#define DISP_MISC_CNTL__RMX_BUF_MEM_RD_MARGIN_MASK 0xf0000000L
+
+// DISP_PWR_MAN
+#define DISP_PWR_MAN__DISP_PWR_MAN_D3_CRTC_EN_MASK 0x00000001L
+#define DISP_PWR_MAN__DISP_PWR_MAN_D3_CRTC_EN 0x00000001L
+#define DISP_PWR_MAN__DISP2_PWR_MAN_D3_CRTC2_EN_MASK 0x00000010L
+#define DISP_PWR_MAN__DISP2_PWR_MAN_D3_CRTC2_EN 0x00000010L
+#define DISP_PWR_MAN__DISP_PWR_MAN_DPMS_MASK 0x00000300L
+#define DISP_PWR_MAN__DISP_D3_RST_MASK 0x00010000L
+#define DISP_PWR_MAN__DISP_D3_RST 0x00010000L
+#define DISP_PWR_MAN__DISP_D3_REG_RST_MASK 0x00020000L
+#define DISP_PWR_MAN__DISP_D3_REG_RST 0x00020000L
+#define DISP_PWR_MAN__DISP_D3_GRPH_RST_MASK 0x00040000L
+#define DISP_PWR_MAN__DISP_D3_GRPH_RST 0x00040000L
+#define DISP_PWR_MAN__DISP_D3_SUBPIC_RST_MASK 0x00080000L
+#define DISP_PWR_MAN__DISP_D3_SUBPIC_RST 0x00080000L
+#define DISP_PWR_MAN__DISP_D3_OV0_RST_MASK 0x00100000L
+#define DISP_PWR_MAN__DISP_D3_OV0_RST 0x00100000L
+#define DISP_PWR_MAN__DISP_D1D2_GRPH_RST_MASK 0x00200000L
+#define DISP_PWR_MAN__DISP_D1D2_GRPH_RST 0x00200000L
+#define DISP_PWR_MAN__DISP_D1D2_SUBPIC_RST_MASK 0x00400000L
+#define DISP_PWR_MAN__DISP_D1D2_SUBPIC_RST 0x00400000L
+#define DISP_PWR_MAN__DISP_D1D2_OV0_RST_MASK 0x00800000L
+#define DISP_PWR_MAN__DISP_D1D2_OV0_RST 0x00800000L
+#define DISP_PWR_MAN__DIG_TMDS_ENABLE_RST_MASK 0x01000000L
+#define DISP_PWR_MAN__DIG_TMDS_ENABLE_RST 0x01000000L
+#define DISP_PWR_MAN__TV_ENABLE_RST_MASK 0x02000000L
+#define DISP_PWR_MAN__TV_ENABLE_RST 0x02000000L
+#define DISP_PWR_MAN__AUTO_PWRUP_EN_MASK 0x04000000L
+#define DISP_PWR_MAN__AUTO_PWRUP_EN 0x04000000L
+
+// MC_IND_INDEX
+#define MC_IND_INDEX__MC_IND_ADDR_MASK 0x0000001fL
+#define MC_IND_INDEX__MC_IND_WR_EN_MASK 0x00000100L
+#define MC_IND_INDEX__MC_IND_WR_EN 0x00000100L
+
+// MC_IND_DATA
+#define MC_IND_DATA__MC_IND_DATA_MASK 0xffffffffL
+
+// MC_CHP_IO_CNTL_A1
+#define MC_CHP_IO_CNTL_A1__MEM_SLEWN_CKA__SHIFT 0x00000000
+#define MC_CHP_IO_CNTL_A1__MEM_SLEWN_AA__SHIFT 0x00000001
+#define MC_CHP_IO_CNTL_A1__MEM_SLEWN_DQMA__SHIFT 0x00000002
+#define MC_CHP_IO_CNTL_A1__MEM_SLEWN_DQSA__SHIFT 0x00000003
+#define MC_CHP_IO_CNTL_A1__MEM_SLEWP_CKA__SHIFT 0x00000004
+#define MC_CHP_IO_CNTL_A1__MEM_SLEWP_AA__SHIFT 0x00000005
+#define MC_CHP_IO_CNTL_A1__MEM_SLEWP_DQMA__SHIFT 0x00000006
+#define MC_CHP_IO_CNTL_A1__MEM_SLEWP_DQSA__SHIFT 0x00000007
+#define MC_CHP_IO_CNTL_A1__MEM_PREAMP_AA__SHIFT 0x00000008
+#define MC_CHP_IO_CNTL_A1__MEM_PREAMP_DQMA__SHIFT 0x00000009
+#define MC_CHP_IO_CNTL_A1__MEM_PREAMP_DQSA__SHIFT 0x0000000a
+#define MC_CHP_IO_CNTL_A1__MEM_IO_MODEA__SHIFT 0x0000000c
+#define MC_CHP_IO_CNTL_A1__MEM_REC_CKA__SHIFT 0x0000000e
+#define MC_CHP_IO_CNTL_A1__MEM_REC_AA__SHIFT 0x00000010
+#define MC_CHP_IO_CNTL_A1__MEM_REC_DQMA__SHIFT 0x00000012
+#define MC_CHP_IO_CNTL_A1__MEM_REC_DQSA__SHIFT 0x00000014
+#define MC_CHP_IO_CNTL_A1__MEM_SYNC_PHASEA__SHIFT 0x00000016
+#define MC_CHP_IO_CNTL_A1__MEM_SYNC_CENTERA__SHIFT 0x00000017
+#define MC_CHP_IO_CNTL_A1__MEM_SYNC_ENA__SHIFT 0x00000018
+#define MC_CHP_IO_CNTL_A1__MEM_CLK_SELA__SHIFT 0x0000001a
+#define MC_CHP_IO_CNTL_A1__MEM_CLK_INVA__SHIFT 0x0000001c
+#define MC_CHP_IO_CNTL_A1__MEM_DATA_ENIMP_A__SHIFT 0x0000001e
+#define MC_CHP_IO_CNTL_A1__MEM_CNTL_ENIMP_A__SHIFT 0x0000001f
+
+// MC_CHP_IO_CNTL_B1
+#define MC_CHP_IO_CNTL_B1__MEM_SLEWN_CKB__SHIFT 0x00000000
+#define MC_CHP_IO_CNTL_B1__MEM_SLEWN_AB__SHIFT 0x00000001
+#define MC_CHP_IO_CNTL_B1__MEM_SLEWN_DQMB__SHIFT 0x00000002
+#define MC_CHP_IO_CNTL_B1__MEM_SLEWN_DQSB__SHIFT 0x00000003
+#define MC_CHP_IO_CNTL_B1__MEM_SLEWP_CKB__SHIFT 0x00000004
+#define MC_CHP_IO_CNTL_B1__MEM_SLEWP_AB__SHIFT 0x00000005
+#define MC_CHP_IO_CNTL_B1__MEM_SLEWP_DQMB__SHIFT 0x00000006
+#define MC_CHP_IO_CNTL_B1__MEM_SLEWP_DQSB__SHIFT 0x00000007
+#define MC_CHP_IO_CNTL_B1__MEM_PREAMP_AB__SHIFT 0x00000008
+#define MC_CHP_IO_CNTL_B1__MEM_PREAMP_DQMB__SHIFT 0x00000009
+#define MC_CHP_IO_CNTL_B1__MEM_PREAMP_DQSB__SHIFT 0x0000000a
+#define MC_CHP_IO_CNTL_B1__MEM_IO_MODEB__SHIFT 0x0000000c
+#define MC_CHP_IO_CNTL_B1__MEM_REC_CKB__SHIFT 0x0000000e
+#define MC_CHP_IO_CNTL_B1__MEM_REC_AB__SHIFT 0x00000010
+#define MC_CHP_IO_CNTL_B1__MEM_REC_DQMB__SHIFT 0x00000012
+#define MC_CHP_IO_CNTL_B1__MEM_REC_DQSB__SHIFT 0x00000014
+#define MC_CHP_IO_CNTL_B1__MEM_SYNC_PHASEB__SHIFT 0x00000016
+#define MC_CHP_IO_CNTL_B1__MEM_SYNC_CENTERB__SHIFT 0x00000017
+#define MC_CHP_IO_CNTL_B1__MEM_SYNC_ENB__SHIFT 0x00000018
+#define MC_CHP_IO_CNTL_B1__MEM_CLK_SELB__SHIFT 0x0000001a
+#define MC_CHP_IO_CNTL_B1__MEM_CLK_INVB__SHIFT 0x0000001c
+#define MC_CHP_IO_CNTL_B1__MEM_DATA_ENIMP_B__SHIFT 0x0000001e
+#define MC_CHP_IO_CNTL_B1__MEM_CNTL_ENIMP_B__SHIFT 0x0000001f
+
+// MC_CHP_IO_CNTL_A1
+#define MC_CHP_IO_CNTL_A1__MEM_SLEWN_CKA_MASK 0x00000001L
+#define MC_CHP_IO_CNTL_A1__MEM_SLEWN_CKA 0x00000001L
+#define MC_CHP_IO_CNTL_A1__MEM_SLEWN_AA_MASK 0x00000002L
+#define MC_CHP_IO_CNTL_A1__MEM_SLEWN_AA 0x00000002L
+#define MC_CHP_IO_CNTL_A1__MEM_SLEWN_DQMA_MASK 0x00000004L
+#define MC_CHP_IO_CNTL_A1__MEM_SLEWN_DQMA 0x00000004L
+#define MC_CHP_IO_CNTL_A1__MEM_SLEWN_DQSA_MASK 0x00000008L
+#define MC_CHP_IO_CNTL_A1__MEM_SLEWN_DQSA 0x00000008L
+#define MC_CHP_IO_CNTL_A1__MEM_SLEWP_CKA_MASK 0x00000010L
+#define MC_CHP_IO_CNTL_A1__MEM_SLEWP_CKA 0x00000010L
+#define MC_CHP_IO_CNTL_A1__MEM_SLEWP_AA_MASK 0x00000020L
+#define MC_CHP_IO_CNTL_A1__MEM_SLEWP_AA 0x00000020L
+#define MC_CHP_IO_CNTL_A1__MEM_SLEWP_DQMA_MASK 0x00000040L
+#define MC_CHP_IO_CNTL_A1__MEM_SLEWP_DQMA 0x00000040L
+#define MC_CHP_IO_CNTL_A1__MEM_SLEWP_DQSA_MASK 0x00000080L
+#define MC_CHP_IO_CNTL_A1__MEM_SLEWP_DQSA 0x00000080L
+#define MC_CHP_IO_CNTL_A1__MEM_PREAMP_AA_MASK 0x00000100L
+#define MC_CHP_IO_CNTL_A1__MEM_PREAMP_AA 0x00000100L
+#define MC_CHP_IO_CNTL_A1__MEM_PREAMP_DQMA_MASK 0x00000200L
+#define MC_CHP_IO_CNTL_A1__MEM_PREAMP_DQMA 0x00000200L
+#define MC_CHP_IO_CNTL_A1__MEM_PREAMP_DQSA_MASK 0x00000400L
+#define MC_CHP_IO_CNTL_A1__MEM_PREAMP_DQSA 0x00000400L
+#define MC_CHP_IO_CNTL_A1__MEM_IO_MODEA_MASK 0x00003000L
+#define MC_CHP_IO_CNTL_A1__MEM_REC_CKA_MASK 0x0000c000L
+#define MC_CHP_IO_CNTL_A1__MEM_REC_AA_MASK 0x00030000L
+#define MC_CHP_IO_CNTL_A1__MEM_REC_DQMA_MASK 0x000c0000L
+#define MC_CHP_IO_CNTL_A1__MEM_REC_DQSA_MASK 0x00300000L
+#define MC_CHP_IO_CNTL_A1__MEM_SYNC_PHASEA_MASK 0x00400000L
+#define MC_CHP_IO_CNTL_A1__MEM_SYNC_PHASEA 0x00400000L
+#define MC_CHP_IO_CNTL_A1__MEM_SYNC_CENTERA_MASK 0x00800000L
+#define MC_CHP_IO_CNTL_A1__MEM_SYNC_CENTERA 0x00800000L
+#define MC_CHP_IO_CNTL_A1__MEM_SYNC_ENA_MASK 0x03000000L
+#define MC_CHP_IO_CNTL_A1__MEM_CLK_SELA_MASK 0x0c000000L
+#define MC_CHP_IO_CNTL_A1__MEM_CLK_INVA_MASK 0x10000000L
+#define MC_CHP_IO_CNTL_A1__MEM_CLK_INVA 0x10000000L
+#define MC_CHP_IO_CNTL_A1__MEM_DATA_ENIMP_A_MASK 0x40000000L
+#define MC_CHP_IO_CNTL_A1__MEM_DATA_ENIMP_A 0x40000000L
+#define MC_CHP_IO_CNTL_A1__MEM_CNTL_ENIMP_A_MASK 0x80000000L
+#define MC_CHP_IO_CNTL_A1__MEM_CNTL_ENIMP_A 0x80000000L
+
+// MC_CHP_IO_CNTL_B1
+#define MC_CHP_IO_CNTL_B1__MEM_SLEWN_CKB_MASK 0x00000001L
+#define MC_CHP_IO_CNTL_B1__MEM_SLEWN_CKB 0x00000001L
+#define MC_CHP_IO_CNTL_B1__MEM_SLEWN_AB_MASK 0x00000002L
+#define MC_CHP_IO_CNTL_B1__MEM_SLEWN_AB 0x00000002L
+#define MC_CHP_IO_CNTL_B1__MEM_SLEWN_DQMB_MASK 0x00000004L
+#define MC_CHP_IO_CNTL_B1__MEM_SLEWN_DQMB 0x00000004L
+#define MC_CHP_IO_CNTL_B1__MEM_SLEWN_DQSB_MASK 0x00000008L
+#define MC_CHP_IO_CNTL_B1__MEM_SLEWN_DQSB 0x00000008L
+#define MC_CHP_IO_CNTL_B1__MEM_SLEWP_CKB_MASK 0x00000010L
+#define MC_CHP_IO_CNTL_B1__MEM_SLEWP_CKB 0x00000010L
+#define MC_CHP_IO_CNTL_B1__MEM_SLEWP_AB_MASK 0x00000020L
+#define MC_CHP_IO_CNTL_B1__MEM_SLEWP_AB 0x00000020L
+#define MC_CHP_IO_CNTL_B1__MEM_SLEWP_DQMB_MASK 0x00000040L
+#define MC_CHP_IO_CNTL_B1__MEM_SLEWP_DQMB 0x00000040L
+#define MC_CHP_IO_CNTL_B1__MEM_SLEWP_DQSB_MASK 0x00000080L
+#define MC_CHP_IO_CNTL_B1__MEM_SLEWP_DQSB 0x00000080L
+#define MC_CHP_IO_CNTL_B1__MEM_PREAMP_AB_MASK 0x00000100L
+#define MC_CHP_IO_CNTL_B1__MEM_PREAMP_AB 0x00000100L
+#define MC_CHP_IO_CNTL_B1__MEM_PREAMP_DQMB_MASK 0x00000200L
+#define MC_CHP_IO_CNTL_B1__MEM_PREAMP_DQMB 0x00000200L
+#define MC_CHP_IO_CNTL_B1__MEM_PREAMP_DQSB_MASK 0x00000400L
+#define MC_CHP_IO_CNTL_B1__MEM_PREAMP_DQSB 0x00000400L
+#define MC_CHP_IO_CNTL_B1__MEM_IO_MODEB_MASK 0x00003000L
+#define MC_CHP_IO_CNTL_B1__MEM_REC_CKB_MASK 0x0000c000L
+#define MC_CHP_IO_CNTL_B1__MEM_REC_AB_MASK 0x00030000L
+#define MC_CHP_IO_CNTL_B1__MEM_REC_DQMB_MASK 0x000c0000L
+#define MC_CHP_IO_CNTL_B1__MEM_REC_DQSB_MASK 0x00300000L
+#define MC_CHP_IO_CNTL_B1__MEM_SYNC_PHASEB_MASK 0x00400000L
+#define MC_CHP_IO_CNTL_B1__MEM_SYNC_PHASEB 0x00400000L
+#define MC_CHP_IO_CNTL_B1__MEM_SYNC_CENTERB_MASK 0x00800000L
+#define MC_CHP_IO_CNTL_B1__MEM_SYNC_CENTERB 0x00800000L
+#define MC_CHP_IO_CNTL_B1__MEM_SYNC_ENB_MASK 0x03000000L
+#define MC_CHP_IO_CNTL_B1__MEM_CLK_SELB_MASK 0x0c000000L
+#define MC_CHP_IO_CNTL_B1__MEM_CLK_INVB_MASK 0x10000000L
+#define MC_CHP_IO_CNTL_B1__MEM_CLK_INVB 0x10000000L
+#define MC_CHP_IO_CNTL_B1__MEM_DATA_ENIMP_B_MASK 0x40000000L
+#define MC_CHP_IO_CNTL_B1__MEM_DATA_ENIMP_B 0x40000000L
+#define MC_CHP_IO_CNTL_B1__MEM_CNTL_ENIMP_B_MASK 0x80000000L
+#define MC_CHP_IO_CNTL_B1__MEM_CNTL_ENIMP_B 0x80000000L
+
+// MEM_SDRAM_MODE_REG
+#define MEM_SDRAM_MODE_REG__MEM_MODE_REG_MASK 0x00007fffL
+#define MEM_SDRAM_MODE_REG__MEM_WR_LATENCY_MASK 0x000f0000L
+#define MEM_SDRAM_MODE_REG__MEM_CAS_LATENCY_MASK 0x00700000L
+#define MEM_SDRAM_MODE_REG__MEM_CMD_LATENCY_MASK 0x00800000L
+#define MEM_SDRAM_MODE_REG__MEM_CMD_LATENCY 0x00800000L
+#define MEM_SDRAM_MODE_REG__MEM_STR_LATENCY_MASK 0x01000000L
+#define MEM_SDRAM_MODE_REG__MEM_STR_LATENCY 0x01000000L
+#define MEM_SDRAM_MODE_REG__MEM_FALL_OUT_CMD_MASK 0x02000000L
+#define MEM_SDRAM_MODE_REG__MEM_FALL_OUT_CMD 0x02000000L
+#define MEM_SDRAM_MODE_REG__MEM_FALL_OUT_DATA_MASK 0x04000000L
+#define MEM_SDRAM_MODE_REG__MEM_FALL_OUT_DATA 0x04000000L
+#define MEM_SDRAM_MODE_REG__MEM_FALL_OUT_STR_MASK 0x08000000L
+#define MEM_SDRAM_MODE_REG__MEM_FALL_OUT_STR 0x08000000L
+#define MEM_SDRAM_MODE_REG__MC_INIT_COMPLETE_MASK 0x10000000L
+#define MEM_SDRAM_MODE_REG__MC_INIT_COMPLETE 0x10000000L
+#define MEM_SDRAM_MODE_REG__MEM_DDR_DLL_MASK 0x20000000L
+#define MEM_SDRAM_MODE_REG__MEM_DDR_DLL 0x20000000L
+#define MEM_SDRAM_MODE_REG__MEM_CFG_TYPE_MASK 0x40000000L
+#define MEM_SDRAM_MODE_REG__MEM_CFG_TYPE 0x40000000L
+#define MEM_SDRAM_MODE_REG__MEM_SDRAM_RESET_MASK 0x80000000L
+#define MEM_SDRAM_MODE_REG__MEM_SDRAM_RESET 0x80000000L
+
+// MEM_SDRAM_MODE_REG
+#define MEM_SDRAM_MODE_REG__MEM_MODE_REG__SHIFT 0x00000000
+#define MEM_SDRAM_MODE_REG__MEM_WR_LATENCY__SHIFT 0x00000010
+#define MEM_SDRAM_MODE_REG__MEM_CAS_LATENCY__SHIFT 0x00000014
+#define MEM_SDRAM_MODE_REG__MEM_CMD_LATENCY__SHIFT 0x00000017
+#define MEM_SDRAM_MODE_REG__MEM_STR_LATENCY__SHIFT 0x00000018
+#define MEM_SDRAM_MODE_REG__MEM_FALL_OUT_CMD__SHIFT 0x00000019
+#define MEM_SDRAM_MODE_REG__MEM_FALL_OUT_DATA__SHIFT 0x0000001a
+#define MEM_SDRAM_MODE_REG__MEM_FALL_OUT_STR__SHIFT 0x0000001b
+#define MEM_SDRAM_MODE_REG__MC_INIT_COMPLETE__SHIFT 0x0000001c
+#define MEM_SDRAM_MODE_REG__MEM_DDR_DLL__SHIFT 0x0000001d
+#define MEM_SDRAM_MODE_REG__MEM_CFG_TYPE__SHIFT 0x0000001e
+#define MEM_SDRAM_MODE_REG__MEM_SDRAM_RESET__SHIFT 0x0000001f
+
+// MEM_REFRESH_CNTL
+#define MEM_REFRESH_CNTL__MEM_REFRESH_RATE_MASK 0x000000ffL
+#define MEM_REFRESH_CNTL__MEM_REFRESH_DIS_MASK 0x00000100L
+#define MEM_REFRESH_CNTL__MEM_REFRESH_DIS 0x00000100L
+#define MEM_REFRESH_CNTL__MEM_DYNAMIC_CKE_MASK 0x00000200L
+#define MEM_REFRESH_CNTL__MEM_DYNAMIC_CKE 0x00000200L
+#define MEM_REFRESH_CNTL__MEM_TRFC_MASK 0x0000f000L
+#define MEM_REFRESH_CNTL__MEM_CLKA0_ENABLE_MASK 0x00010000L
+#define MEM_REFRESH_CNTL__MEM_CLKA0_ENABLE 0x00010000L
+#define MEM_REFRESH_CNTL__MEM_CLKA0b_ENABLE_MASK 0x00020000L
+#define MEM_REFRESH_CNTL__MEM_CLKA0b_ENABLE 0x00020000L
+#define MEM_REFRESH_CNTL__MEM_CLKA1_ENABLE_MASK 0x00040000L
+#define MEM_REFRESH_CNTL__MEM_CLKA1_ENABLE 0x00040000L
+#define MEM_REFRESH_CNTL__MEM_CLKA1b_ENABLE_MASK 0x00080000L
+#define MEM_REFRESH_CNTL__MEM_CLKA1b_ENABLE 0x00080000L
+#define MEM_REFRESH_CNTL__MEM_CLKAFB_ENABLE_MASK 0x00100000L
+#define MEM_REFRESH_CNTL__MEM_CLKAFB_ENABLE 0x00100000L
+#define MEM_REFRESH_CNTL__DLL_FB_SLCT_CKA_MASK 0x00c00000L
+#define MEM_REFRESH_CNTL__MEM_CLKB0_ENABLE_MASK 0x01000000L
+#define MEM_REFRESH_CNTL__MEM_CLKB0_ENABLE 0x01000000L
+#define MEM_REFRESH_CNTL__MEM_CLKB0b_ENABLE_MASK 0x02000000L
+#define MEM_REFRESH_CNTL__MEM_CLKB0b_ENABLE 0x02000000L
+#define MEM_REFRESH_CNTL__MEM_CLKB1_ENABLE_MASK 0x04000000L
+#define MEM_REFRESH_CNTL__MEM_CLKB1_ENABLE 0x04000000L
+#define MEM_REFRESH_CNTL__MEM_CLKB1b_ENABLE_MASK 0x08000000L
+#define MEM_REFRESH_CNTL__MEM_CLKB1b_ENABLE 0x08000000L
+#define MEM_REFRESH_CNTL__MEM_CLKBFB_ENABLE_MASK 0x10000000L
+#define MEM_REFRESH_CNTL__MEM_CLKBFB_ENABLE 0x10000000L
+#define MEM_REFRESH_CNTL__DLL_FB_SLCT_CKB_MASK 0xc0000000L
+
+// MC_STATUS
+#define MC_STATUS__MEM_PWRUP_COMPL_A_MASK 0x00000001L
+#define MC_STATUS__MEM_PWRUP_COMPL_A 0x00000001L
+#define MC_STATUS__MEM_PWRUP_COMPL_B_MASK 0x00000002L
+#define MC_STATUS__MEM_PWRUP_COMPL_B 0x00000002L
+#define MC_STATUS__MC_IDLE_MASK 0x00000004L
+#define MC_STATUS__MC_IDLE 0x00000004L
+#define MC_STATUS__IMP_N_VALUE_R_BACK_MASK 0x00000078L
+#define MC_STATUS__IMP_P_VALUE_R_BACK_MASK 0x00000780L
+#define MC_STATUS__TEST_OUT_R_BACK_MASK 0x00000800L
+#define MC_STATUS__TEST_OUT_R_BACK 0x00000800L
+#define MC_STATUS__DUMMY_OUT_R_BACK_MASK 0x00001000L
+#define MC_STATUS__DUMMY_OUT_R_BACK 0x00001000L
+#define MC_STATUS__IMP_N_VALUE_A_R_BACK_MASK 0x0001e000L
+#define MC_STATUS__IMP_P_VALUE_A_R_BACK_MASK 0x001e0000L
+#define MC_STATUS__IMP_N_VALUE_CK_R_BACK_MASK 0x01e00000L
+#define MC_STATUS__IMP_P_VALUE_CK_R_BACK_MASK 0x1e000000L
+
+// MDLL_CKO
+#define MDLL_CKO__MCKOA_SLEEP_MASK 0x00000001L
+#define MDLL_CKO__MCKOA_SLEEP 0x00000001L
+#define MDLL_CKO__MCKOA_RESET_MASK 0x00000002L
+#define MDLL_CKO__MCKOA_RESET 0x00000002L
+#define MDLL_CKO__MCKOA_RANGE_MASK 0x0000000cL
+#define MDLL_CKO__ERSTA_SOUTSEL_MASK 0x00000030L
+#define MDLL_CKO__MCKOA_FB_SEL_MASK 0x000000c0L
+#define MDLL_CKO__MCKOA_REF_SKEW_MASK 0x00000700L
+#define MDLL_CKO__MCKOA_FB_SKEW_MASK 0x00007000L
+#define MDLL_CKO__MCKOA_BP_SEL_MASK 0x00008000L
+#define MDLL_CKO__MCKOA_BP_SEL 0x00008000L
+#define MDLL_CKO__MCKOB_SLEEP_MASK 0x00010000L
+#define MDLL_CKO__MCKOB_SLEEP 0x00010000L
+#define MDLL_CKO__MCKOB_RESET_MASK 0x00020000L
+#define MDLL_CKO__MCKOB_RESET 0x00020000L
+#define MDLL_CKO__MCKOB_RANGE_MASK 0x000c0000L
+#define MDLL_CKO__ERSTB_SOUTSEL_MASK 0x00300000L
+#define MDLL_CKO__MCKOB_FB_SEL_MASK 0x00c00000L
+#define MDLL_CKO__MCKOB_REF_SKEW_MASK 0x07000000L
+#define MDLL_CKO__MCKOB_FB_SKEW_MASK 0x70000000L
+#define MDLL_CKO__MCKOB_BP_SEL_MASK 0x80000000L
+#define MDLL_CKO__MCKOB_BP_SEL 0x80000000L
+
+// MDLL_RDCKA
+#define MDLL_RDCKA__MRDCKA0_SLEEP_MASK 0x00000001L
+#define MDLL_RDCKA__MRDCKA0_SLEEP 0x00000001L
+#define MDLL_RDCKA__MRDCKA0_RESET_MASK 0x00000002L
+#define MDLL_RDCKA__MRDCKA0_RESET 0x00000002L
+#define MDLL_RDCKA__MRDCKA0_RANGE_MASK 0x0000000cL
+#define MDLL_RDCKA__MRDCKA0_REF_SEL_MASK 0x00000030L
+#define MDLL_RDCKA__MRDCKA0_FB_SEL_MASK 0x000000c0L
+#define MDLL_RDCKA__MRDCKA0_REF_SKEW_MASK 0x00000700L
+#define MDLL_RDCKA__MRDCKA0_SINSEL_MASK 0x00000800L
+#define MDLL_RDCKA__MRDCKA0_SINSEL 0x00000800L
+#define MDLL_RDCKA__MRDCKA0_FB_SKEW_MASK 0x00007000L
+#define MDLL_RDCKA__MRDCKA0_BP_SEL_MASK 0x00008000L
+#define MDLL_RDCKA__MRDCKA0_BP_SEL 0x00008000L
+#define MDLL_RDCKA__MRDCKA1_SLEEP_MASK 0x00010000L
+#define MDLL_RDCKA__MRDCKA1_SLEEP 0x00010000L
+#define MDLL_RDCKA__MRDCKA1_RESET_MASK 0x00020000L
+#define MDLL_RDCKA__MRDCKA1_RESET 0x00020000L
+#define MDLL_RDCKA__MRDCKA1_RANGE_MASK 0x000c0000L
+#define MDLL_RDCKA__MRDCKA1_REF_SEL_MASK 0x00300000L
+#define MDLL_RDCKA__MRDCKA1_FB_SEL_MASK 0x00c00000L
+#define MDLL_RDCKA__MRDCKA1_REF_SKEW_MASK 0x07000000L
+#define MDLL_RDCKA__MRDCKA1_SINSEL_MASK 0x08000000L
+#define MDLL_RDCKA__MRDCKA1_SINSEL 0x08000000L
+#define MDLL_RDCKA__MRDCKA1_FB_SKEW_MASK 0x70000000L
+#define MDLL_RDCKA__MRDCKA1_BP_SEL_MASK 0x80000000L
+#define MDLL_RDCKA__MRDCKA1_BP_SEL 0x80000000L
+
+// MDLL_RDCKB
+#define MDLL_RDCKB__MRDCKB0_SLEEP_MASK 0x00000001L
+#define MDLL_RDCKB__MRDCKB0_SLEEP 0x00000001L
+#define MDLL_RDCKB__MRDCKB0_RESET_MASK 0x00000002L
+#define MDLL_RDCKB__MRDCKB0_RESET 0x00000002L
+#define MDLL_RDCKB__MRDCKB0_RANGE_MASK 0x0000000cL
+#define MDLL_RDCKB__MRDCKB0_REF_SEL_MASK 0x00000030L
+#define MDLL_RDCKB__MRDCKB0_FB_SEL_MASK 0x000000c0L
+#define MDLL_RDCKB__MRDCKB0_REF_SKEW_MASK 0x00000700L
+#define MDLL_RDCKB__MRDCKB0_SINSEL_MASK 0x00000800L
+#define MDLL_RDCKB__MRDCKB0_SINSEL 0x00000800L
+#define MDLL_RDCKB__MRDCKB0_FB_SKEW_MASK 0x00007000L
+#define MDLL_RDCKB__MRDCKB0_BP_SEL_MASK 0x00008000L
+#define MDLL_RDCKB__MRDCKB0_BP_SEL 0x00008000L
+#define MDLL_RDCKB__MRDCKB1_SLEEP_MASK 0x00010000L
+#define MDLL_RDCKB__MRDCKB1_SLEEP 0x00010000L
+#define MDLL_RDCKB__MRDCKB1_RESET_MASK 0x00020000L
+#define MDLL_RDCKB__MRDCKB1_RESET 0x00020000L
+#define MDLL_RDCKB__MRDCKB1_RANGE_MASK 0x000c0000L
+#define MDLL_RDCKB__MRDCKB1_REF_SEL_MASK 0x00300000L
+#define MDLL_RDCKB__MRDCKB1_FB_SEL_MASK 0x00c00000L
+#define MDLL_RDCKB__MRDCKB1_REF_SKEW_MASK 0x07000000L
+#define MDLL_RDCKB__MRDCKB1_SINSEL_MASK 0x08000000L
+#define MDLL_RDCKB__MRDCKB1_SINSEL 0x08000000L
+#define MDLL_RDCKB__MRDCKB1_FB_SKEW_MASK 0x70000000L
+#define MDLL_RDCKB__MRDCKB1_BP_SEL_MASK 0x80000000L
+#define MDLL_RDCKB__MRDCKB1_BP_SEL 0x80000000L
+
+#define pllVCLK_ECP_CNTL 0x0008
+#define pllDISP_TEST_MACRO_RW_WRITE 0x001A
+#define pllDISP_TEST_MACRO_RW_READ 0x001B
+#define pllDISP_TEST_MACRO_RW_DATA 0x001C
+#define pllDISP_TEST_MACRO_RW_CNTL 0x001D
+#define pllPIXCLKS_CNTL 0x002D
+#define pllPPLL_DIV_0 0x0004
+#define pllPPLL_DIV_1 0x0005
+#define pllPPLL_DIV_2 0x0006
+#define pllPPLL_DIV_3 0x0007
+#define pllHTOTAL_CNTL 0x0009
+#define pllPLL_TEST_CNTL_M6 0x0013
+#define pllP2PLL_DIV_0 0x002C
+#define pllHTOTAL2_CNTL 0x002E
+#define pllCLK_PIN_CNTL 0x0001
+#define pllPPLL_CNTL 0x0002
+#define pllPPLL_REF_DIV 0x0003
+#define pllSPLL_CNTL 0x000C
+#define pllSPLL_AUX_CNTL 0x0024
+#define pllSCLK_CNTL_M6 0x000D
+#define pllAGP_PLL_CNTL 0x000B
+#define pllTV_PLL_FINE_CNTL 0x0020
+#define pllTV_PLL_CNTL 0x0021
+#define pllTV_PLL_CNTL1 0x0022
+#define pllTV_DTO_INCREMENTS 0x0023
+#define pllP2PLL_CNTL 0x002A
+#define pllP2PLL_REF_DIV 0x002B
+#define pllSSPLL_CNTL 0x0030
+#define pllSSPLL_REF_DIV 0x0031
+#define pllSSPLL_DIV_0 0x0032
+#define pllSS_INT_CNTL 0x0033
+#define pllSS_TST_CNTL 0x0034
+#define pllSCLK_MORE_CNTL 0x0035
+#define pllCLK_PWRMGT_CNTL_M6 0x0014
+#define pllPLL_PWRMGT_CNTL 0x0015
+#define pllM_SPLL_REF_FB_DIV 0x000A
+#define pllMPLL_CNTL 0x000E
+#define pllMPLL_AUX_CNTL 0x0025
+#define pllMDLL_CKO 0x000F
+#define pllMDLL_RDCKA 0x0010
+#define pllMDLL_RDCKB 0x0011
+#define pllMCLK_CNTL_M6 0x0012
+#define pllMCLK_MISC 0x001F
+#define pllCG_TEST_MACRO_RW_WRITE 0x0016
+#define pllCG_TEST_MACRO_RW_READ 0x0017
+#define pllCG_TEST_MACRO_RW_DATA 0x0018
+#define pllCG_TEST_MACRO_RW_CNTL 0x0019
+
+#define ixMC_PERF_CNTL 0x0000
+#define ixMC_PERF_SEL 0x0001
+#define ixMC_PERF_REGION_0 0x0002
+#define ixMC_PERF_REGION_1 0x0003
+#define ixMC_PERF_COUNT_0 0x0004
+#define ixMC_PERF_COUNT_1 0x0005
+#define ixMC_PERF_COUNT_2 0x0006
+#define ixMC_PERF_COUNT_3 0x0007
+#define ixMC_PERF_COUNT_MEMCH_A 0x0008
+#define ixMC_PERF_COUNT_MEMCH_B 0x0009
+#define ixMC_IMP_CNTL 0x000A
+#define ixMC_CHP_IO_CNTL_A0 0x000B
+#define ixMC_CHP_IO_CNTL_A1 0x000C
+#define ixMC_CHP_IO_CNTL_B0 0x000D
+#define ixMC_CHP_IO_CNTL_B1 0x000E
+#define ixMC_IMP_CNTL_0 0x000F
+#define ixTC_MISMATCH_1 0x0010
+#define ixTC_MISMATCH_2 0x0011
+#define ixMC_BIST_CTRL 0x0012
+#define ixREG_COLLAR_WRITE 0x0013
+#define ixREG_COLLAR_READ 0x0014
+
+
+
+
#endif /* _RADEON_H */