diff -ur linux-source-2.6.15-orig/drivers/video/aty/aty128fb.c linux-source-2.6.15/drivers/video/aty/aty128fb.c
--- linux-source-2.6.15-orig/drivers/video/aty/aty128fb.c	2006-03-02 21:18:38.000000000 +0000
+++ linux-source-2.6.15/drivers/video/aty/aty128fb.c	2006-07-10 11:28:23.000000000 +0100
@@ -395,6 +395,14 @@
 	struct aty128_crtc crtc;
 	struct aty128_pll pll;
 	struct aty128_ddafifo fifo_reg;
+
+#ifdef CONFIG_PPC_PMAC
+    struct aty128_crtc crtc2;
+    struct aty128_pll pll2;
+    struct aty128_ddafifo fifo_reg2;
+#endif
+
+
 	u32 accel_flags;
 	struct aty128_constants constants;  /* PLL and others      */
 	void __iomem *regbase;              /* remapped mmio       */
@@ -998,6 +1006,26 @@
 	aty_st_pll(PPLL_CNTL, aty_ld_pll(PPLL_CNTL) & ~(0x00030000));
 }
 
+#ifdef CONFIG_PPC_PMAC
+static void
+aty128_set_crtc2(const struct aty128_crtc *crtc,
+	const struct aty128fb_par *par)
+{
+
+    aty_st_le32(CRTC2_GEN_CNTL, crtc->gen_cntl);
+
+    /* FIXME - Hardcoded */
+    aty_st_le32(CRTC2_H_TOTAL_DISP, crtc->h_total & ~0xf | 0xa );
+    aty_st_le32(CRTC2_H_SYNC_STRT_WID, crtc->h_sync_strt_wid & ~0xff | 0x10 );
+
+    aty_st_le32(CRTC2_V_TOTAL_DISP, crtc->v_total);
+    aty_st_le32(CRTC2_V_SYNC_STRT_WID, crtc->v_sync_strt_wid);
+    aty_st_le32(CRTC2_PITCH, crtc->pitch);
+    aty_st_le32(CRTC2_OFFSET, crtc->offset);
+    aty_st_le32(CRTC2_OFFSET_CNTL, crtc->offset_cntl);
+
+}
+#endif
 
 static int aty128_var_to_crtc(const struct fb_var_screeninfo *var,
 			      struct aty128_crtc *crtc,
@@ -1249,10 +1277,14 @@
 static void aty128_set_crt_enable(struct aty128fb_par *par, int on)
 {
 	if (on) {
-		aty_st_le32(CRTC_EXT_CNTL, aty_ld_le32(CRTC_EXT_CNTL) | CRT_CRTC_ON);
-		aty_st_le32(DAC_CNTL, (aty_ld_le32(DAC_CNTL) | DAC_PALETTE2_SNOOP_EN));
+		aty_st_le32(CRTC_EXT_CNTL, 
+			    aty_ld_le32(CRTC_EXT_CNTL) | CRT_CRTC_ON);
+		aty_st_le32(DAC_CNTL, (aty_ld_le32(DAC_CNTL) | 
+				       DAC_PALETTE2_SNOOP_EN | DAC_CLK_SEL));
+
 	} else
-		aty_st_le32(CRTC_EXT_CNTL, aty_ld_le32(CRTC_EXT_CNTL) & ~CRT_CRTC_ON);
+		aty_st_le32(CRTC_EXT_CNTL,
+			    aty_ld_le32(CRTC_EXT_CNTL) & ~CRT_CRTC_ON);
 }
 
 static void aty128_set_lcd_enable(struct aty128fb_par *par, int on)
@@ -1319,7 +1351,49 @@
 	aty_st_pll(PPLL_CNTL, aty_ld_pll(PPLL_CNTL) & ~PPLL_RESET);
 }
 
+#ifdef CONFIG_PPC_PMAC
+static void
+aty128_set_pll2(struct aty128_pll *pll, const struct aty128fb_par *par)
+{
+    u32 div;
+
+    unsigned char post_conv[] =	/* register values for post dividers */
+        { 2, 0, 1, 4, 2, 2, 6, 2, 3, 2, 2, 2, 7 };
+
+    /* reset PLL */
+    aty_st_pll(P2PLL_CNTL,
+		aty_ld_pll(P2PLL_CNTL) | PPLL_RESET | PPLL_ATOMIC_UPDATE_EN);
+
+    /* write the reference divider */
+    aty_pll_wait_readupdate(par);
+    aty_st_pll(P2PLL_REF_DIV, par->constants.ref_divider & 0x3ff);
+    aty_pll_writeupdate(par);
+
+    div = aty_ld_pll(P2PLL_DIV_0);
+    div &= ~XPLL_FB_DIV_MASK;
+    div |= pll->feedback_divider;
+    div |= post_conv[pll->post_divider] << 16;
+    div |= 0x00040000; /* magic value */
+
+    /* write feedback and post dividers */
+    aty_pll_wait_readupdate(par);
+    aty_st_pll(P2PLL_DIV_0, div);
+    aty_pll_writeupdate(par);
+
+    aty_pll_wait_readupdate(par);
+    aty_st_pll(HTOTAL_CNTL, 0);	/* no horiz crtc adjustment */
+    aty_pll_writeupdate(par);
+
+
+    /* clear the reset, just in case */
+    aty_st_pll(P2PLL_CNTL, aty_ld_pll(P2PLL_CNTL) & ~PPLL_RESET);
+
+}
+#endif 
+
 
+
+			
 static int aty128_var_to_pll(u32 period_in_ps, struct aty128_pll *pll,
 			     const struct aty128fb_par *par)
 {
@@ -1378,6 +1452,20 @@
 }
 
 
+#ifdef CONFIG_PPC_PMAC
+static void
+aty128_set_fifo2(const struct aty128_ddafifo *dsp,
+			const struct aty128fb_par *par)
+{
+    /* FIXME - Hardcoded */
+  /*    aty_st_le32(DDA2_CONFIG, dsp->dda_config);
+	aty_st_le32(DDA2_ON_OFF, dsp->dda_on_off);*/
+  aty_st_le32(DDA2_CONFIG, 0x010502aa);
+  aty_st_le32(DDA2_ON_OFF, 0x11805a74);
+
+}
+#endif
+
 static int aty128_ddafifo(struct aty128_ddafifo *dsp,
 			  const struct aty128_pll *pll,
 			  u32 depth,
@@ -1469,6 +1557,14 @@
 	aty128_set_crtc(&par->crtc, par);
 	aty128_set_pll(&par->pll, par);
 	aty128_set_fifo(&par->fifo_reg, par);
+#ifdef CONFIG_PPC_PMAC
+    if(par->chip_gen == rage_M3) {
+       aty128_set_crtc2(&par->crtc2, par);
+       aty128_set_pll2(&par->pll2, par);
+       aty128_set_fifo2(&par->fifo_reg2, par);
+    }
+#endif
+
 
 	config = aty_ld_le32(CONFIG_CNTL) & ~3;
 
@@ -1511,9 +1607,9 @@
 static int aty128_decode_var(struct fb_var_screeninfo *var, struct aty128fb_par *par)
 {
 	int err;
-	struct aty128_crtc crtc;
-	struct aty128_pll pll;
-	struct aty128_ddafifo fifo_reg;
+	struct aty128_crtc crtc, crtc2;
+	struct aty128_pll pll, pll2;
+	struct aty128_ddafifo fifo_reg, fifo_reg2;
 
 	if ((err = aty128_var_to_crtc(var, &crtc, par)))
 		return err;
@@ -1523,12 +1619,30 @@
 
 	if ((err = aty128_ddafifo(&fifo_reg, &pll, crtc.depth, par)))
 		return err;
+#ifdef CONFIG_PPC_PMAC
+
+    if ((err = aty128_var_to_crtc(var, &crtc2, par)))
+	return err;
+
+    if ((err = aty128_var_to_pll(var->pixclock, &pll2, par)))
+	return err;
+
+    if ((err = aty128_ddafifo(&fifo_reg2, &pll2, crtc2.depth, par)))
+	return err;
+#endif
+
 
 	par->crtc = crtc;
 	par->pll = pll;
 	par->fifo_reg = fifo_reg;
 	par->accel_flags = var->accel_flags;
+#ifdef CONFIG_PPC_PMAC
+
+        par->crtc2 = crtc2;
+        par->pll2 = pll2;
+        par->fifo_reg2 = fifo_reg2;
 
+#endif
 	return 0;
 }
 
@@ -1608,7 +1722,7 @@
 			  struct aty128fb_par *par)
 {
 	if (par->chip_gen == rage_M3) {
-#if 0
+#if CONFIG_PPC_PMAC
 		/* Note: For now, on M3, we set palette on both heads, which may
 		 * be useless. Can someone with a M3 check this ?
 		 * 
@@ -1616,11 +1730,13 @@
 		 * do mirroring
 		 */
 
-		aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) | DAC_PALETTE_ACCESS_CNTL);
+		aty_st_le32(DAC_CNTL,
+			    aty_ld_le32(DAC_CNTL) | DAC_PALETTE_ACCESS_CNTL);
 		aty_st_8(PALETTE_INDEX, regno);
 		aty_st_le32(PALETTE_DATA, (red<<16)|(green<<8)|blue);
 #endif
-		aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) & ~DAC_PALETTE_ACCESS_CNTL);
+		aty_st_le32(DAC_CNTL, 
+			    aty_ld_le32(DAC_CNTL) & ~DAC_PALETTE_ACCESS_CNTL);
 	}
 
 	aty_st_8(PALETTE_INDEX, regno);
diff -ur linux-source-2.6.15-orig/include/video/aty128.h linux-source-2.6.15/include/video/aty128.h
--- linux-source-2.6.15-orig/include/video/aty128.h	2006-03-02 21:18:42.000000000 +0000
+++ linux-source-2.6.15/include/video/aty128.h	2006-07-10 11:28:23.000000000 +0100
@@ -258,7 +258,7 @@
 #define PLL_TEST_CNTL				0x0013
 #define P2PLL_CNTL				0x002a
 #define P2PLL_REF_DIV				0x002b
-#define P2PLL_DIV_0				0x002b
+#define P2PLL_DIV_0				0x002c
 #define POWER_MANAGEMENT			0x002f
 
 #define PPLL_RESET				0x01

