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);