Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/pci Make R3xx actually work by wiring outputs, DACs ...
details: https://anonhg.NetBSD.org/src/rev/2405398de366
branches: trunk
changeset: 783577:2405398de366
user: macallan <macallan%NetBSD.org@localhost>
date: Sun Dec 30 09:45:05 2012 +0000
description:
Make R3xx actually work by wiring outputs, DACs and CRTCs sanely, add a bunch of R3xx-specific workarounds. Tested in xvr-100, iBook G4 and an RV350.
diffstat:
sys/dev/pci/radeonfb.c | 254 +++++++++++++++++++++++++++++++--------------
sys/dev/pci/radeonfbreg.h | 3 +-
2 files changed, 176 insertions(+), 81 deletions(-)
diffs (truncated from 467 to 300 lines):
diff -r 43d12c25dfba -r 2405398de366 sys/dev/pci/radeonfb.c
--- a/sys/dev/pci/radeonfb.c Sun Dec 30 09:19:24 2012 +0000
+++ b/sys/dev/pci/radeonfb.c Sun Dec 30 09:45:05 2012 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: radeonfb.c,v 1.68 2012/12/20 03:08:39 macallan Exp $ */
+/* $NetBSD: radeonfb.c,v 1.69 2012/12/30 09:45:05 macallan Exp $ */
/*-
* Copyright (c) 2006 Itronix Inc.
@@ -70,7 +70,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: radeonfb.c,v 1.68 2012/12/20 03:08:39 macallan Exp $");
+__KERNEL_RCSID(0, "$NetBSD: radeonfb.c,v 1.69 2012/12/30 09:45:05 macallan Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -380,13 +380,14 @@
int divider;
int mask;
} radeonfb_dividers[] = {
- { 1, 0 },
- { 2, 1 },
- { 3, 4 },
+ { 16, 5 },
+ { 12, 7 },
+ { 8, 3 },
+ { 6, 6 },
{ 4, 2 },
- { 6, 6 },
- { 8, 3 },
- { 12, 7 },
+ { 3, 4 },
+ { 2, 1 },
+ { 1, 0 },
{ 0, 0 }
};
@@ -561,6 +562,8 @@
PRINTREG(RADEON_CRTC2_GEN_CNTL);
PRINTREG(RADEON_DISP_OUTPUT_CNTL);
PRINTREG(RADEON_DAC_CNTL2);
+ PRINTREG(RADEON_FP_GEN_CNTL);
+ PRINTREG(RADEON_FP2_GEN_CNTL);
PRINTREG(RADEON_BIOS_4_SCRATCH);
PRINTREG(RADEON_FP_GEN_CNTL);
@@ -573,13 +576,22 @@
PRINTREG(RADEON_FP_HORZ_STRETCH);
PRINTREG(RADEON_FP_VERT_STRETCH);
- /* XXX: RV100 specific */
- PUT32(sc, RADEON_TMDS_PLL_CNTL, 0xa27);
-
- PATCH32(sc, RADEON_TMDS_TRANSMITTER_CNTL,
- RADEON_TMDS_TRANSMITTER_PLLEN,
- RADEON_TMDS_TRANSMITTER_PLLEN | RADEON_TMDS_TRANSMITTER_PLLRST);
-
+ if (IS_RV100(sc))
+ PUT32(sc, RADEON_TMDS_PLL_CNTL, 0xa27);
+
+ /* XXX
+ * according to xf86-video-radeon R3xx has this bit backwards
+ */
+ if (IS_R300(sc)) {
+ PATCH32(sc, RADEON_TMDS_TRANSMITTER_CNTL,
+ 0,
+ ~(RADEON_TMDS_TRANSMITTER_PLLEN | RADEON_TMDS_TRANSMITTER_PLLRST));
+ } else {
+ PATCH32(sc, RADEON_TMDS_TRANSMITTER_CNTL,
+ RADEON_TMDS_TRANSMITTER_PLLEN,
+ ~(RADEON_TMDS_TRANSMITTER_PLLEN | RADEON_TMDS_TRANSMITTER_PLLRST));
+ }
+
radeonfb_i2c_init(sc);
radeonfb_loadbios(sc, pa);
@@ -655,8 +667,32 @@
PATCH32(sc, RADEON_DISP_HW_DEBUG,
i ? 0 : RADEON_CRT2_DISP1_SEL,
~RADEON_CRT2_DISP1_SEL);
+ /* we're using CRTC2 for the 2nd port */
+ if (sc->sc_ports[i].rp_number == 99) {
+ PATCH32(sc, RADEON_DISP_OUTPUT_CNTL,
+ RADEON_DISP_DAC2_SOURCE_CRTC2,
+ ~RADEON_DISP_DAC2_SOURCE_MASK);
+ }
+
break;
}
+ switch (sc->sc_ports[i].rp_tmds_type) {
+ case RADEON_TMDS_INT:
+ /* point FP0 at the CRTC this port uses */
+ if (IS_R300(sc)) {
+ PATCH32(sc, RADEON_FP_GEN_CNTL,
+ sc->sc_ports[i].rp_number ?
+ R200_FP_SOURCE_SEL_CRTC2 :
+ R200_FP_SOURCE_SEL_CRTC1,
+ ~R200_FP_SOURCE_SEL_MASK);
+ } else {
+ PATCH32(sc, RADEON_FP_GEN_CNTL,
+ sc->sc_ports[i].rp_number ?
+ RADEON_FP_SEL_CRTC2 :
+ RADEON_FP_SEL_CRTC1,
+ ~RADEON_FP_SEL_MASK);
+ }
+ }
}
PRINTREG(RADEON_DAC_CNTL2);
PRINTREG(RADEON_DISP_HW_DEBUG);
@@ -682,14 +718,15 @@
* no idea why this is necessary - if I do not clear this bit on my
* iBook G4 the screen remains black, even though it's already clear.
* It needs to be set on my Sun XVR-100 for the DVI port to work
+ * TODO:
+ * see if this is still necessary now that CRTCs, DACs and outputs are
+ * getting wired up in a halfway sane way
*/
if (sc->sc_fp_gen_cntl & RADEON_FP_SEL_CRTC2) {
SET32(sc, RADEON_FP_GEN_CNTL, RADEON_FP_SEL_CRTC2);
- } else
+ } else {
CLR32(sc, RADEON_FP_GEN_CNTL, RADEON_FP_SEL_CRTC2);
-
- if (HAS_CRTC2(sc))
- SET32(sc, RADEON_FP2_GEN_CNTL, RADEON_FP2_SRC_SEL_CRTC2);
+ }
/*
* we use bus_space_map instead of pci_mapreg, because we don't
@@ -750,17 +787,17 @@
if (HAS_CRTC2(sc) && (sc->sc_ndisplays == 1)) {
DPRINTF(("dual crtcs!\n"));
dp->rd_ncrtcs = 2;
- dp->rd_crtcs[0].rc_number = 0;
- dp->rd_crtcs[1].rc_number = 1;
+ dp->rd_crtcs[0].rc_port =
+ &sc->sc_ports[0];
+ dp->rd_crtcs[0].rc_number = sc->sc_ports[0].rp_number;
+ dp->rd_crtcs[1].rc_port =
+ &sc->sc_ports[1];
+ dp->rd_crtcs[1].rc_number = sc->sc_ports[1].rp_number;
} else {
dp->rd_ncrtcs = 1;
- dp->rd_crtcs[0].rc_number = i;
- }
-
- /* set up port pointer */
- for (j = 0; j < dp->rd_ncrtcs; j++) {
- dp->rd_crtcs[j].rc_port =
- &sc->sc_ports[dp->rd_crtcs[j].rc_number];
+ dp->rd_crtcs[0].rc_port =
+ &sc->sc_ports[i];
+ dp->rd_crtcs[0].rc_number = sc->sc_ports[i].rp_number;
}
dp->rd_softc = sc;
@@ -946,7 +983,8 @@
radeonfb_init_palette(sc, 1);
CLR32(sc, RADEON_CRTC2_GEN_CNTL, RADEON_CRTC2_DISP_DIS);
}
-
+ CLR32(sc, RADEON_CRTC_EXT_CNTL, RADEON_CRTC_DISPLAY_DIS);
+ SET32(sc, RADEON_FP_GEN_CNTL, RADEON_FP_FPON);
pmf_event_register(dev, PMFE_DISPLAY_BRIGHTNESS_UP,
radeonfb_brightness_up, TRUE);
pmf_event_register(dev, PMFE_DISPLAY_BRIGHTNESS_DOWN,
@@ -959,6 +997,8 @@
PRINTREG(RADEON_CRTC2_GEN_CNTL);
PRINTREG(RADEON_DISP_OUTPUT_CNTL);
PRINTREG(RADEON_DAC_CNTL2);
+ PRINTREG(RADEON_FP_GEN_CNTL);
+ PRINTREG(RADEON_FP2_GEN_CNTL);
return;
@@ -1358,7 +1398,7 @@
uint32_t val;
s = splhigh();
- radeonfb_put32(sc, RADEON_CLOCK_CNTL_INDEX, idx & 0x3f);
+ radeonfb_put32(sc, RADEON_CLOCK_CNTL_INDEX, (idx & 0x3f));
val = radeonfb_get32(sc, RADEON_CLOCK_CNTL_DATA);
if (HAS_R300CG(sc))
radeonfb_r300cg_workaround(sc);
@@ -1439,6 +1479,15 @@
minpll = radeonfb_getprop_num(sc, "minpll", 0) & 0xffffffffU;
maxpll = radeonfb_getprop_num(sc, "maxpll", 0) & 0xffffffffU;
+ PRINTPLL(RADEON_PPLL_REF_DIV);
+ PRINTPLL(RADEON_PPLL_DIV_0);
+ PRINTPLL(RADEON_PPLL_DIV_1);
+ PRINTPLL(RADEON_PPLL_DIV_2);
+ PRINTPLL(RADEON_PPLL_DIV_3);
+ PRINTREG(RADEON_CLOCK_CNTL_INDEX);
+ PRINTPLL(RADEON_P2PLL_REF_DIV);
+ PRINTPLL(RADEON_P2PLL_DIV_0);
+
if (refclk && refdiv && minpll && maxpll)
goto dontprobe;
@@ -1452,7 +1501,13 @@
refclk = refclk ? refclk : 2700;
refdiv = refdiv ? refdiv : 12;
minpll = minpll ? minpll : 12500;
- maxpll = maxpll ? maxpll : 35000;
+ /* XXX
+ * Need to check if the firmware or something programmed a
+ * higher value than this, and if so, bump it.
+ * The RV280 in my iBook is unhappy if the PLL input is less
+ * than 360MHz
+ */
+ maxpll = maxpll ? maxpll : 40000/*35000*/;
} else if (IS_ATOM(sc)) {
/* ATOM BIOS */
ptr = GETBIOS16(sc, 0x48);
@@ -1476,9 +1531,18 @@
refdiv = 12;
} else {
+ uint32_t tmp = GETPLL(sc, RADEON_PPLL_REF_DIV);
/* Legacy BIOS */
ptr = GETBIOS16(sc, 0x48);
ptr = GETBIOS16(sc, ptr + 0x30);
+ if (IS_R300(sc)) {
+ refdiv = refdiv ? refdiv :
+ (tmp & R300_PPLL_REF_DIV_ACC_MASK) >>
+ R300_PPLL_REF_DIV_ACC_SHIFT;
+ } else {
+ refdiv = refdiv ? refdiv :
+ tmp & RADEON_PPLL_REF_DIV_MASK;
+ }
refclk = refclk ? refclk : GETBIOS16(sc, ptr + 0x0E);
refdiv = refdiv ? refdiv : GETBIOS16(sc, ptr + 0x10);
minpll = minpll ? minpll : GETBIOS32(sc, ptr + 0x12);
@@ -1653,6 +1717,7 @@
(tmds == RADEON_TMDS_INT))
sc->sc_ports[port].rp_tmds_type =
RADEON_TMDS_UNKNOWN;
+ sc->sc_ports[port].rp_number = i - 1;
found += (port + 1);
}
@@ -1661,18 +1726,37 @@
nobios:
if (!found) {
DPRINTF(("No connector info in BIOS!\n"));
- /* default, port 0 = internal TMDS, port 1 = CRT */
- sc->sc_ports[0].rp_mon_type = RADEON_MT_UNKNOWN;
- sc->sc_ports[0].rp_ddc_type = RADEON_DDC_DVI;
- sc->sc_ports[0].rp_dac_type = RADEON_DAC_TVDAC;
- sc->sc_ports[0].rp_conn_type = RADEON_CONN_DVI_D;
- sc->sc_ports[0].rp_tmds_type = RADEON_TMDS_INT;
-
- sc->sc_ports[1].rp_mon_type = RADEON_MT_UNKNOWN;
- sc->sc_ports[1].rp_ddc_type = RADEON_DDC_VGA;
- sc->sc_ports[1].rp_dac_type = RADEON_DAC_PRIMARY;
- sc->sc_ports[1].rp_conn_type = RADEON_CONN_CRT;
- sc->sc_ports[1].rp_tmds_type = RADEON_TMDS_EXT;
+ if IS_MOBILITY(sc) {
+ /* default, port 0 = internal TMDS, port 1 = CRT */
+ sc->sc_ports[0].rp_mon_type = RADEON_MT_UNKNOWN;
+ sc->sc_ports[0].rp_ddc_type = RADEON_DDC_DVI;
+ sc->sc_ports[0].rp_dac_type = RADEON_DAC_TVDAC;
+ sc->sc_ports[0].rp_conn_type = RADEON_CONN_DVI_D;
+ sc->sc_ports[0].rp_tmds_type = RADEON_TMDS_INT;
+ sc->sc_ports[0].rp_number = 0;
+
+ sc->sc_ports[1].rp_mon_type = RADEON_MT_UNKNOWN;
+ sc->sc_ports[1].rp_ddc_type = RADEON_DDC_VGA;
+ sc->sc_ports[1].rp_dac_type = RADEON_DAC_PRIMARY;
+ sc->sc_ports[1].rp_conn_type = RADEON_CONN_CRT;
+ sc->sc_ports[1].rp_tmds_type = RADEON_TMDS_EXT;
+ sc->sc_ports[1].rp_number = 1;
+ } else {
+ /* default, port 0 = DVI, port 1 = CRT */
+ sc->sc_ports[0].rp_mon_type = RADEON_MT_UNKNOWN;
+ sc->sc_ports[0].rp_ddc_type = RADEON_DDC_DVI;
+ sc->sc_ports[0].rp_dac_type = RADEON_DAC_TVDAC;
+ sc->sc_ports[0].rp_conn_type = RADEON_CONN_DVI_D;
+ sc->sc_ports[0].rp_tmds_type = RADEON_TMDS_INT;
+ sc->sc_ports[0].rp_number = 1;
+
+ sc->sc_ports[1].rp_mon_type = RADEON_MT_UNKNOWN;
+ sc->sc_ports[1].rp_ddc_type = RADEON_DDC_VGA;
+ sc->sc_ports[1].rp_dac_type = RADEON_DAC_PRIMARY;
+ sc->sc_ports[1].rp_conn_type = RADEON_CONN_CRT;
+ sc->sc_ports[1].rp_tmds_type = RADEON_TMDS_EXT;
+ sc->sc_ports[1].rp_number = 0;
+ }
}
/*
@@ -1698,17 +1782,18 @@
prop_data_t edid_data;
DPRINTF(("Port #%d:\n", i));
- DPRINTF((" conn = %d\n", sc->sc_ports[i].rp_conn_type));
+ DPRINTF((" conn = %d\n", sc->sc_ports[i].rp_conn_type));
Home |
Main Index |
Thread Index |
Old Index