Module Name:    src
Committed By:   macallan
Date:           Fri Aug 25 22:45:33 UTC 2017

Modified Files:
        src/sys/dev/pci: radeonfb.c

Log Message:
Radeon PLLs can't have odd post dividers when used with digital outputs -
add a flag to track this in relevant functions.
Now DVI output works properly on my Mini 2
Needs testing on Mini 1 and other hardware...


To generate a diff of this commit:
cvs rdiff -u -r1.91 -r1.92 src/sys/dev/pci/radeonfb.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/pci/radeonfb.c
diff -u src/sys/dev/pci/radeonfb.c:1.91 src/sys/dev/pci/radeonfb.c:1.92
--- src/sys/dev/pci/radeonfb.c:1.91	Wed Aug 23 19:47:39 2017
+++ src/sys/dev/pci/radeonfb.c	Fri Aug 25 22:45:33 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: radeonfb.c,v 1.91 2017/08/23 19:47:39 macallan Exp $ */
+/*	$NetBSD: radeonfb.c,v 1.92 2017/08/25 22:45:33 macallan Exp $ */
 
 /*-
  * Copyright (c) 2006 Itronix Inc.
@@ -70,7 +70,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: radeonfb.c,v 1.91 2017/08/23 19:47:39 macallan Exp $");
+__KERNEL_RCSID(0, "$NetBSD: radeonfb.c,v 1.92 2017/08/25 22:45:33 macallan Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -120,13 +120,16 @@ static uintmax_t radeonfb_getprop_num(st
 static int radeonfb_getclocks(struct radeonfb_softc *);
 static int radeonfb_gettmds(struct radeonfb_softc *);
 static int radeonfb_calc_dividers(struct radeonfb_softc *, uint32_t,
-    uint32_t *, uint32_t *);
+    uint32_t *, uint32_t *, int);
+/* flags for radeonfb_calc_dividers */
+#define NO_ODD_FBDIV	1
+    
 static int radeonfb_getconnectors(struct radeonfb_softc *);
 static const struct videomode *radeonfb_modelookup(const char *);
 static void radeonfb_init_screen(void *, struct vcons_screen *, int, long *);
 static void radeonfb_pllwriteupdate(struct radeonfb_softc *, int);
 static void radeonfb_pllwaitatomicread(struct radeonfb_softc *, int);
-static void radeonfb_program_vclk(struct radeonfb_softc *, int, int);
+static void radeonfb_program_vclk(struct radeonfb_softc *, int, int, int);
 static void radeonfb_modeswitch(struct radeonfb_display *);
 static void radeonfb_setcrtc(struct radeonfb_display *, int);
 static void radeonfb_init_misc(struct radeonfb_softc *);
@@ -580,9 +583,12 @@ radeonfb_attach(device_t parent, device_
 	PRINTREG(RADEON_TMDS_TRANSMITTER_CNTL);
 	PRINTREG(RADEON_TMDS_PLL_CNTL);
 	PRINTREG(RADEON_LVDS_GEN_CNTL);
-	PRINTREG(RADEON_FP_HORZ_STRETCH);
-	PRINTREG(RADEON_FP_VERT_STRETCH);
 	PRINTREG(RADEON_DISP_HW_DEBUG);
+	PRINTREG(RADEON_PIXCLKS_CNTL);
+	PRINTREG(RADEON_CRTC_H_SYNC_STRT_WID);
+	PRINTREG(RADEON_FP_H_SYNC_STRT_WID);
+	PRINTREG(RADEON_CRTC2_H_SYNC_STRT_WID);
+	PRINTREG(RADEON_FP_H2_SYNC_STRT_WID);
 	if (IS_RV100(sc))
 		PUT32(sc, RADEON_TMDS_PLL_CNTL, 0xa27);
 
@@ -1041,6 +1047,7 @@ radeonfb_attach(device_t parent, device_
 	PRINTREG(RADEON_TMDS_CNTL);
 	PRINTREG(RADEON_TMDS_TRANSMITTER_CNTL);
 	PRINTREG(RADEON_TMDS_PLL_CNTL);
+	PRINTREG(RADEON_PIXCLKS_CNTL);
 
 	return;
 
@@ -1625,7 +1632,7 @@ dontprobe:
 
 int
 radeonfb_calc_dividers(struct radeonfb_softc *sc, uint32_t dotclock,
-    uint32_t *postdivbit, uint32_t *feedbackdiv)
+    uint32_t *postdivbit, uint32_t *feedbackdiv, int flags)
 {
 	int		i;
 	uint32_t	outfreq;
@@ -1633,6 +1640,7 @@ radeonfb_calc_dividers(struct radeonfb_s
 
 	DPRINTF(("dot clock: %u\n", dotclock));
 	for (i = 0; (div = radeonfb_dividers[i].divider) != 0; i++) {
+		if ((flags & NO_ODD_FBDIV) && ((div & 1) != 0)) continue;
 		outfreq = div * dotclock;
 		if ((outfreq >= sc->sc_minpll) &&
 		    (outfreq <= sc->sc_maxpll)) {
@@ -2021,13 +2029,13 @@ radeonfb_pllwaitatomicread(struct radeon
 }
 
 void
-radeonfb_program_vclk(struct radeonfb_softc *sc, int dotclock, int crtc)
+radeonfb_program_vclk(struct radeonfb_softc *sc, int dotclock, int crtc, int flags)
 {
 	uint32_t	pbit = 0;
 	uint32_t	feed = 0;
 	uint32_t	data, refdiv, div0;
 
-	radeonfb_calc_dividers(sc, dotclock, &pbit, &feed);
+	radeonfb_calc_dividers(sc, dotclock, &pbit, &feed, flags);
 
 	if (crtc == 0) {
 
@@ -2190,6 +2198,21 @@ radeonfb_modeswitch(struct radeonfb_disp
 	for (i = 0; i < dp->rd_ncrtcs; i++)
 		radeonfb_setcrtc(dp, i);
 
+#if 0
+	/*
+	 * DVO chip voodoo from xf86-video-radeon
+	 * apparently this is needed for some powerbooks with DVI outputs
+	 */
+
+	uint8_t data[5][2] = {{0x8, 0x030}, {0x9, 0}, {0xa, 0x90}, {0xc, 0x89}, {0x8, 0x3b}};
+	int n = 0;
+	iic_acquire_bus(&sc->sc_i2c[0].ric_controller, 0);
+	for (i = 0; i < 5; i++)
+		n += iic_exec(&sc->sc_i2c[0].ric_controller, I2C_OP_WRITE, 0x38, data[i], 2, NULL, 0, 0);
+	iic_release_bus(&sc->sc_i2c[0].ric_controller, 0);
+	printf("n = %d\n", n);
+#endif
+
 	/* activate the display */
 	radeonfb_blank(dp, 0);
 }
@@ -2197,7 +2220,7 @@ radeonfb_modeswitch(struct radeonfb_disp
 void
 radeonfb_setcrtc(struct radeonfb_display *dp, int index)
 {
-	int			crtc;
+	int			crtc, flags = 0;
 	struct videomode	*mode;
 	struct radeonfb_softc	*sc;
 	struct radeonfb_crtc	*cp;
@@ -2214,6 +2237,12 @@ radeonfb_setcrtc(struct radeonfb_display
 	uint32_t		pitch;
 
 	sc = dp->rd_softc;
+
+	if ((sc->sc_ports[index].rp_tmds_type == RADEON_TMDS_INT) ||
+	    (sc->sc_ports[index].rp_tmds_type == RADEON_TMDS_EXT)) {
+		flags |= NO_ODD_FBDIV;
+	}
+
 	cp = &dp->rd_crtcs[index];
 	crtc = cp->rc_number;
 	mode = &cp->rc_videomode;
@@ -2231,6 +2260,7 @@ radeonfb_setcrtc(struct radeonfb_display
 		hsyncstrt = RADEON_CRTC_H_SYNC_STRT_WID;
 		vtotaldisp = RADEON_CRTC_V_TOTAL_DISP;
 		vsyncstrt = RADEON_CRTC_V_SYNC_STRT_WID;
+		/* should probably leave those alone on non-LVDS */
 		fpvsyncstrt = RADEON_FP_V_SYNC_STRT_WID;
 		fphsyncstrt = RADEON_FP_H_SYNC_STRT_WID;
 		fpvtotaldisp = RADEON_FP_CRTC_V_TOTAL_DISP;
@@ -2244,8 +2274,9 @@ radeonfb_setcrtc(struct radeonfb_display
 		vsyncstrt = RADEON_CRTC2_V_SYNC_STRT_WID;
 		fpvsyncstrt = RADEON_FP_V2_SYNC_STRT_WID;
 		fphsyncstrt = RADEON_FP_H2_SYNC_STRT_WID;
-		fpvtotaldisp = RADEON_FP_CRTC2_V_TOTAL_DISP;
-		fphtotaldisp = RADEON_FP_CRTC2_H_TOTAL_DISP;
+		/* XXX these registers don't seem to exist */
+		fpvtotaldisp = 0;//RADEON_FP_CRTC2_V_TOTAL_DISP;
+		fphtotaldisp = 0;//RADEON_FP_CRTC2_H_TOTAL_DISP;
 		break;
 	default:
 		panic("Bad CRTC!");
@@ -2302,9 +2333,10 @@ radeonfb_setcrtc(struct radeonfb_display
 	v |= (mode->htotal / 8) - 1;
 	PUT32(sc, htotaldisp, v);
 	DPRINTF(("CRTC%s_H_TOTAL_DISP = %08x\n", crtc ? "2" : "", v));
-	PUT32(sc, fphtotaldisp, v);
-	DPRINTF(("FP_H%s_TOTAL_DISP = %08x\n", crtc ? "2" : "", v));
-
+	if (fphtotaldisp) {
+		PUT32(sc, fphtotaldisp, v);
+		DPRINTF(("FP_H%s_TOTAL_DISP = %08x\n", crtc ? "2" : "", v));
+	}
 	/*
 	 * H_SYNC_STRT_WID
 	 */
@@ -2314,8 +2346,10 @@ radeonfb_setcrtc(struct radeonfb_display
 		v |= RADEON_CRTC_H_SYNC_POL;
 	PUT32(sc, hsyncstrt, v);
 	DPRINTF(("CRTC%s_H_SYNC_STRT_WID = %08x\n", crtc ? "2" : "", v));
-	PUT32(sc, fphsyncstrt, v);
-	DPRINTF(("FP_H%s_SYNC_STRT_WID = %08x\n", crtc ? "2" : "", v));
+	if (fphsyncstrt) {
+		PUT32(sc, fphsyncstrt, v);
+		DPRINTF(("FP_H%s_SYNC_STRT_WID = %08x\n", crtc ? "2" : "", v));
+	}
 
 	/*
 	 * V_TOTAL_DISP
@@ -2324,8 +2358,10 @@ radeonfb_setcrtc(struct radeonfb_display
 	v |= (mode->vtotal - 1);
 	PUT32(sc, vtotaldisp, v);
 	DPRINTF(("CRTC%s_V_TOTAL_DISP = %08x\n", crtc ? "2" : "", v));
-	PUT32(sc, fpvtotaldisp, v);
-	DPRINTF(("FP_V%s_TOTAL_DISP = %08x\n", crtc ? "2" : "", v));
+	if (fpvtotaldisp) {
+		PUT32(sc, fpvtotaldisp, v);
+		DPRINTF(("FP_V%s_TOTAL_DISP = %08x\n", crtc ? "2" : "", v));
+	}
 
 	/*
 	 * V_SYNC_STRT_WID
@@ -2336,10 +2372,12 @@ radeonfb_setcrtc(struct radeonfb_display
 		v |= RADEON_CRTC_V_SYNC_POL;
 	PUT32(sc, vsyncstrt, v);
 	DPRINTF(("CRTC%s_V_SYNC_STRT_WID = %08x\n", crtc ? "2" : "", v));
-	PUT32(sc, fpvsyncstrt, v);
-	DPRINTF(("FP_V%s_SYNC_STRT_WID = %08x\n", crtc ? "2" : "", v));
+	if (fpvsyncstrt) {
+		PUT32(sc, fpvsyncstrt, v);
+		DPRINTF(("FP_V%s_SYNC_STRT_WID = %08x\n", crtc ? "2" : "", v));
+	}
 
-	radeonfb_program_vclk(sc, mode->dot_clock, crtc);
+	radeonfb_program_vclk(sc, mode->dot_clock, crtc, flags);
 
 	switch (crtc) {
 	case 0:
@@ -2644,7 +2682,6 @@ radeonfb_putpal(struct radeonfb_display 
 	/* initialize the palette for every CRTC used by this display */
 	for (cc = 0; cc < dp->rd_ncrtcs; cc++) {
 		crtc = dp->rd_crtcs[cc].rc_number;
-		DPRINTF(("%s: doing crtc %d %d\n", __func__, cc, crtc));
 
 		if (crtc)
 			SET32(sc, RADEON_DAC_CNTL2, RADEON_DAC2_PALETTE_ACC_CTL);

Reply via email to