[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#298075: kernel-image-2.6.8-powerpc: Video to external monitor/projector is corrupted



Package: kernel-image-2.6.8-powerpc
Version: 2.6.8-9
Severity: normal
Tags: patch

On an iBook G3, the output to an external VGA monitor has high spatial
frequency waves drifting across it. The patch accompanying this report
is Owen Stampflee's 2.4 patch ported to 2.6 and fixes the problem. It
probably needs at least a once over from someone more familiar with the
workings of the kernel before it's released into the wild.

N.B. The kernel reported in the system information below is my patched
copy built from the Debian kernel sources package.


-- System Information:
Debian Release: 3.1
  APT prefers testing
  APT policy: (500, 'testing')
Architecture: powerpc (ppc)
Kernel: Linux 2.6.8vga-fix
Locale: LANG=en_GB, LC_CTYPE=en_GB (charmap=ISO-8859-1)

Versions of packages kernel-image-2.6.8-powerpc depends on:
ii  initrd-tools                  0.1.77     tools to create initrd image for p
ii  module-init-tools             3.2-pre1-2 tools for managing Linux kernel mo

-- no debconf information
diff -ru kernel-source-2.6.8/drivers/video/aty/aty128fb.c kernel-source-2.6.8-patched/drivers/video/aty/aty128fb.c
--- kernel-source-2.6.8/drivers/video/aty/aty128fb.c	2004-08-14 06:36:57.000000000 +0100
+++ kernel-source-2.6.8-patched/drivers/video/aty/aty128fb.c	2005-02-15 16:19:11.000000000 +0000
@@ -395,6 +395,14 @@
 	struct aty128_crtc crtc;
 	struct aty128_pll pll;
 	struct aty128_ddafifo fifo_reg;
+
+#ifdef CONFIG_PMAC_PBOOK
+    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 *regbase;                      /* remapped mmio       */
@@ -1036,6 +1044,26 @@
 	aty_st_pll(PPLL_CNTL, aty_ld_pll(PPLL_CNTL) & ~(0x00030000));
 }
 
+#ifdef CONFIG_PMAC_PBOOK
+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,
@@ -1289,7 +1317,9 @@
 {
 	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(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);
 }
@@ -1359,7 +1389,49 @@
 	aty_st_pll(PPLL_CNTL, aty_ld_pll(PPLL_CNTL) & ~PPLL_RESET);
 }
 
+#ifdef CONFIG_PMAC_PBOOK
+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)
 {
@@ -1418,6 +1490,17 @@
 }
 
 
+#ifdef CONFIG_PMAC_PBOOK
+static void
+aty128_set_fifo2(const struct aty128_ddafifo *dsp,
+			const struct aty128fb_par *par)
+{
+    /* FIXME - Hardcoded */
+    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,
@@ -1509,6 +1592,14 @@
 	aty128_set_crtc(&par->crtc, par);
 	aty128_set_pll(&par->pll, par);
 	aty128_set_fifo(&par->fifo_reg, par);
+#ifdef CONFIG_PMAC_PBOOK
+    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;
 
@@ -1553,9 +1644,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;
@@ -1565,12 +1656,30 @@
 
 	if ((err = aty128_ddafifo(&fifo_reg, &pll, crtc.depth, par)))
 		return err;
+#ifdef CONFIG_PMAC_PBOOK
+
+    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_PMAC_PBOOK
 
+        par->crtc2 = crtc2;
+        par->pll2 = pll2;
+        par->fifo_reg2 = fifo_reg2;
+
+#endif
 	return 0;
 }
 
@@ -1650,7 +1759,7 @@
 			  struct aty128fb_par *par)
 {
 	if (par->chip_gen == rage_M3) {
-#if 0
+#if CONFIG_PMAC_PBOOK
 		/* Note: For now, on M3, we set palette on both heads, which may
 		 * be useless. Can someone with a M3 check this ?
 		 * 
diff -ru kernel-source-2.6.8/include/video/aty128.h kernel-source-2.6.8-patched/include/video/aty128.h
--- kernel-source-2.6.8/include/video/aty128.h	2004-08-14 06:36:56.000000000 +0100
+++ kernel-source-2.6.8-patched/include/video/aty128.h	2005-02-15 14:54:05.000000000 +0000
@@ -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

Reply to: