Date: Sun, 6 Apr 2014 21:48:46 +0000 (UTC) From: Justin Hibbits <jhibbits@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r264205 - head/sys/powerpc/powermac Message-ID: <201404062148.s36Lmk33009036@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: jhibbits Date: Sun Apr 6 21:48:45 2014 New Revision: 264205 URL: http://svnweb.freebsd.org/changeset/base/264205 Log: Fix the ATI backlight driver off/on handling. Now this driver works correctly with the ATI Radeon 9700 in the PowerBook G4 1.67GHz. Code shamelessly taken in spirit from the radeonkms driver, which I hope will make this driver redundant in the future. MFC after: 2 weeks Modified: head/sys/powerpc/powermac/atibl.c Modified: head/sys/powerpc/powermac/atibl.c ============================================================================== --- head/sys/powerpc/powermac/atibl.c Sun Apr 6 21:45:38 2014 (r264204) +++ head/sys/powerpc/powermac/atibl.c Sun Apr 6 21:48:45 2014 (r264205) @@ -57,6 +57,12 @@ __FBSDID("$FreeBSD$"); #define RADEON_LVDS_PLL_RESET (1 << 17) #define RADEON_PIXCLKS_CNTL 0x002d #define RADEON_PIXCLK_LVDS_ALWAYS_ONb (1 << 14) +#define RADEON_DISP_PWR_MAN 0x0d08 +#define RADEON_AUTO_PWRUP_EN (1 << 26) +#define RADEON_CLOCK_CNTL_DATA 0x000c +#define RADEON_CLOCK_CNTL_INDEX 0x0008 +#define RADEON_PLL_WR_EN (1 << 7) +#define RADEON_CRTC_GEN_CNTL 0x0050 struct atibl_softc { struct resource *sc_memr; @@ -151,12 +157,56 @@ atibl_attach(device_t dev) return (0); } +static uint32_t __inline +atibl_pll_rreg(struct atibl_softc *sc, uint32_t reg) +{ + uint32_t data, save, tmp; + + bus_write_1(sc->sc_memr, RADEON_CLOCK_CNTL_INDEX, + ((reg & 0x3f) | RADEON_PLL_WR_EN)); + (void)bus_read_4(sc->sc_memr, RADEON_CLOCK_CNTL_DATA); + (void)bus_read_4(sc->sc_memr, RADEON_CRTC_GEN_CNTL); + + data = bus_read_4(sc->sc_memr, RADEON_CLOCK_CNTL_DATA); + + /* Only necessary on R300, bt won't hurt others. */ + save = bus_read_4(sc->sc_memr, RADEON_CLOCK_CNTL_INDEX); + tmp = save & (~0x3f | RADEON_PLL_WR_EN); + bus_write_4(sc->sc_memr, RADEON_CLOCK_CNTL_INDEX, tmp); + tmp = bus_read_4(sc->sc_memr, RADEON_CLOCK_CNTL_DATA); + bus_write_4(sc->sc_memr, RADEON_CLOCK_CNTL_INDEX, save); + + return data; +} + +static void __inline +atibl_pll_wreg(struct atibl_softc *sc, uint32_t reg, uint32_t val) +{ + uint32_t save, tmp; + + bus_write_1(sc->sc_memr, RADEON_CLOCK_CNTL_INDEX, + ((reg & 0x3f) | RADEON_PLL_WR_EN)); + (void)bus_read_4(sc->sc_memr, RADEON_CLOCK_CNTL_DATA); + (void)bus_read_4(sc->sc_memr, RADEON_CRTC_GEN_CNTL); + + bus_write_4(sc->sc_memr, RADEON_CLOCK_CNTL_DATA, val); + DELAY(5000); + + /* Only necessary on R300, bt won't hurt others. */ + save = bus_read_4(sc->sc_memr, RADEON_CLOCK_CNTL_INDEX); + tmp = save & (~0x3f | RADEON_PLL_WR_EN); + bus_write_4(sc->sc_memr, RADEON_CLOCK_CNTL_INDEX, tmp); + tmp = bus_read_4(sc->sc_memr, RADEON_CLOCK_CNTL_DATA); + bus_write_4(sc->sc_memr, RADEON_CLOCK_CNTL_INDEX, save); +} + static int atibl_setlevel(struct atibl_softc *sc, int newlevel) { uint32_t lvds_gen_cntl; uint32_t lvds_pll_cntl; uint32_t pixclks_cntl; + uint32_t disp_pwr_reg; if (newlevel > 100) newlevel = 100; @@ -168,11 +218,15 @@ atibl_setlevel(struct atibl_softc *sc, i if (newlevel > 0) { newlevel = (newlevel * 5) / 2 + 5; + disp_pwr_reg = bus_read_4(sc->sc_memr, RADEON_DISP_PWR_MAN); + disp_pwr_reg |= RADEON_AUTO_PWRUP_EN; + bus_write_4(sc->sc_memr, RADEON_DISP_PWR_MAN, disp_pwr_reg); lvds_pll_cntl = bus_read_4(sc->sc_memr, RADEON_LVDS_PLL_CNTL); lvds_pll_cntl |= RADEON_LVDS_PLL_EN; bus_write_4(sc->sc_memr, RADEON_LVDS_PLL_CNTL, lvds_pll_cntl); lvds_pll_cntl &= ~RADEON_LVDS_PLL_RESET; bus_write_4(sc->sc_memr, RADEON_LVDS_PLL_CNTL, lvds_pll_cntl); + DELAY(1000); lvds_gen_cntl &= ~(RADEON_LVDS_DISPLAY_DIS | RADEON_LVDS_BL_MOD_LEVEL_MASK); @@ -181,20 +235,21 @@ atibl_setlevel(struct atibl_softc *sc, i lvds_gen_cntl |= (newlevel << RADEON_LVDS_BL_MOD_LEVEL_SHIFT) & RADEON_LVDS_BL_MOD_LEVEL_MASK; lvds_gen_cntl |= RADEON_LVDS_BL_MOD_EN; - DELAY(2000); + DELAY(2000000); bus_write_4(sc->sc_memr, RADEON_LVDS_GEN_CNTL, lvds_gen_cntl); } else { - pixclks_cntl = bus_read_4(sc->sc_memr, RADEON_PIXCLKS_CNTL); - bus_write_4(sc->sc_memr, RADEON_PIXCLKS_CNTL, + pixclks_cntl = atibl_pll_rreg(sc, RADEON_PIXCLKS_CNTL); + atibl_pll_wreg(sc, RADEON_PIXCLKS_CNTL, pixclks_cntl & ~RADEON_PIXCLK_LVDS_ALWAYS_ONb); lvds_gen_cntl |= RADEON_LVDS_DISPLAY_DIS; - lvds_gen_cntl &= RADEON_LVDS_BL_MOD_EN; + lvds_gen_cntl &= ~RADEON_LVDS_BL_MOD_EN; bus_write_4(sc->sc_memr, RADEON_LVDS_GEN_CNTL, lvds_gen_cntl); lvds_gen_cntl &= ~(RADEON_LVDS_ON | RADEON_LVDS_EN); - DELAY(2000); + DELAY(2000000); bus_write_4(sc->sc_memr, RADEON_LVDS_GEN_CNTL, lvds_gen_cntl); - bus_write_4(sc->sc_memr, RADEON_PIXCLKS_CNTL, pixclks_cntl); + atibl_pll_wreg(sc, RADEON_PIXCLKS_CNTL, pixclks_cntl); + DELAY(2000000); } return (0);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201404062148.s36Lmk33009036>