don't hardcode inverted backlight levels needed on some macppc models

This commit is contained in:
macallan 2007-02-09 21:12:00 +00:00
parent 4909469d5d
commit 94ed04fa15
2 changed files with 86 additions and 64 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: radeonfb.c,v 1.9 2007/01/03 19:47:17 macallan Exp $ */
/* $NetBSD: radeonfb.c,v 1.10 2007/02/09 21:12:00 macallan Exp $ */
/*-
* Copyright (c) 2006 Itronix Inc.
@ -29,7 +29,7 @@
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
*/
/*
* ATI Technologies Inc. ("ATI") has not assisted in the creation of, and
@ -70,7 +70,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: radeonfb.c,v 1.9 2007/01/03 19:47:17 macallan Exp $");
__KERNEL_RCSID(0, "$NetBSD: radeonfb.c,v 1.10 2007/02/09 21:12:00 macallan Exp $");
#define RADEONFB_DEFAULT_DEPTH 32
@ -171,7 +171,7 @@ static struct videomode *radeonfb_best_refresh(struct videomode *,
struct videomode *);
static void radeonfb_pickres(struct radeonfb_display *, uint16_t *,
uint16_t *, int);
static const struct videomode *radeonfb_port_mode(struct radeonfb_softc *,
static const struct videomode *radeonfb_port_mode(struct radeonfb_softc *,
struct radeonfb_port *, int, int);
@ -193,7 +193,6 @@ int radeon_debug = 1;
#ifndef RADEON_DEFAULT_MODE
/* any reasonably modern display should handle this */
#define RADEON_DEFAULT_MODE "1024x768x60"
//#define RADEON_DEFAULT_MODE "1280x1024x60"
#endif
const char *radeonfb_default_mode = RADEON_DEFAULT_MODE;
@ -235,7 +234,7 @@ static struct {
uint16_t devid;
uint16_t family;
uint16_t flags;
} radeonfb_devices[] =
} radeonfb_devices[] =
{
/* R100 family */
{ PCI_PRODUCT_ATI_RADEON_R100_QD, RADEON_R100, 0 },
@ -444,6 +443,8 @@ radeonfb_attach(struct device *parent, struct device *dev, void *aux)
aprint_naive("\n");
aprint_normal(": %s\n", sc->sc_devinfo);
DPRINTF((prop_dictionary_externalize(device_properties(dev))));
KASSERT(radeonfb_devices[i].devid != 0);
sc->sc_pt = pa->pa_tag;
sc->sc_pc = pa->pa_pc;
@ -491,6 +492,22 @@ radeonfb_attach(struct device *parent, struct device *dev, void *aux)
break;
}
if ((sc->sc_family == RADEON_RV200) ||
(sc->sc_family == RADEON_RV250) ||
(sc->sc_family == RADEON_RV280) ||
(sc->sc_family == RADEON_RV350)) {
int inverted = 0;
/* backlight level is linear */
DPRINTF(("found RV* chip, backlight is supposedly linear\n"));
prop_dictionary_get_bool(device_properties(&sc->sc_dev),
"backlight_level_reverted", &inverted);
if (inverted) {
DPRINTF(("nope, it's inverted\n"));
sc->sc_flags |= RFB_INV_BLIGHT;
}
} else
sc->sc_flags |= RFB_INV_BLIGHT;
/*
* XXX: to support true multihead, this must change.
*/
@ -626,7 +643,7 @@ radeonfb_attach(struct device *parent, struct device *dev, void *aux)
v |= RADEON_DAC_MASK_ALL | RADEON_DAC_8BIT_EN;
PUT32(sc, RADEON_DAC_CNTL, v);
PRINTREG(RADEON_DAC_CNTL);
/* XXX: this may need more investigation */
PUT32(sc, RADEON_TV_DAC_CNTL, 0x00280203);
PRINTREG(RADEON_TV_DAC_CNTL);
@ -687,7 +704,7 @@ radeonfb_attach(struct device *parent, struct device *dev, void *aux)
struct rasops_info *ri;
long defattr;
struct wsemuldisplaydev_attach_args aa;
/*
* Figure out how many "displays" (desktops) we are going to
* support. If more than one, then each CRTC gets its own
@ -870,7 +887,7 @@ radeonfb_attach(struct device *parent, struct device *dev, void *aux)
config_found(&sc->sc_dev, &aa, wsemuldisplaydevprint);
radeonfb_blank(dp, 0);
/* Initialise delayed lvds operations for backlight. */
callout_init(&dp->rd_bl_lvds_co);
callout_setfunc(&dp->rd_bl_lvds_co,
@ -912,8 +929,8 @@ radeonfb_ioctl(void *v, void *vs,
if (vd->active != NULL) {
struct wsdisplay_fbinfo *fb;
fb = (struct wsdisplay_fbinfo *)d;
fb->width = dp->rd_virtx;
fb->height = dp->rd_virty;
fb->width = dp->rd_virtx;
fb->height = dp->rd_virty;
fb->depth = dp->rd_bpp;
fb->cmsize = 256;
return 0;
@ -938,7 +955,7 @@ radeonfb_ioctl(void *v, void *vs,
(struct wsdisplay_cmap *)d);
#endif
return EINVAL;
case WSDISPLAYIO_PUTCMAP:
#if 0
if (dp->rd_bpp == 8)
@ -946,7 +963,7 @@ radeonfb_ioctl(void *v, void *vs,
(struct wsdisplay_cmap *)d);
#endif
return EINVAL;
case WSDISPLAYIO_LINEBYTES:
*(unsigned *)d = dp->rd_stride;
return 0;
@ -1062,25 +1079,25 @@ radeonfb_mmap(void *v, void *vs, off_t offset, int prot)
}
}
if ((offset >= sc->sc_regaddr) &&
if ((offset >= sc->sc_regaddr) &&
(offset < sc->sc_regaddr + sc->sc_regsz)) {
return bus_space_mmap(sc->sc_regt, offset, 0, prot,
return bus_space_mmap(sc->sc_regt, offset, 0, prot,
BUS_SPACE_MAP_LINEAR);
}
if ((offset >= sc->sc_memaddr) &&
if ((offset >= sc->sc_memaddr) &&
(offset < sc->sc_memaddr + sc->sc_memsz)) {
return bus_space_mmap(sc->sc_memt, offset, 0, prot,
return bus_space_mmap(sc->sc_memt, offset, 0, prot,
BUS_SPACE_MAP_LINEAR);
}
#ifdef macppc
/* allow mapping of IO space */
if ((offset >= 0xf2000000) && (offset < 0xf2800000)) {
pa = bus_space_mmap(sc->sc_iot, offset-0xf2000000, 0, prot,
BUS_SPACE_MAP_LINEAR);
pa = bus_space_mmap(sc->sc_iot, offset-0xf2000000, 0, prot,
BUS_SPACE_MAP_LINEAR);
return pa;
}
}
#endif /* macppc */
#endif /* RADEONFB_MMAP_BARS */
@ -1322,7 +1339,7 @@ radeonfb_getclocks(struct radeonfb_softc *sc)
*/
if (refdiv < 2)
refdiv = 12;
} else {
/* Legacy BIOS */
ptr = GETBIOS16(sc, 0x48);
@ -1582,7 +1599,7 @@ radeonfb_gettmds(struct radeonfb_softc *sc)
ptr = GETBIOS16(sc, 0x48);
ptr = GETBIOS16(sc, ptr + 0x34);
DPRINTF(("DFP table revision %d\n", GETBIOS8(sc, ptr)));
if (GETBIOS8(sc, ptr) == 3) {
if (GETBIOS8(sc, ptr) == 3) {
/* revision three table */
n = GETBIOS8(sc, ptr + 5) + 1;
n = min(n, 4);
@ -1687,7 +1704,7 @@ radeonfb_program_vclk(struct radeonfb_softc *sc, int dotclock, int crtc)
PATCHPLL(sc, RADEON_VCLK_ECP_CNTL,
RADEON_VCLK_SRC_SEL_CPUCLK,
~RADEON_VCLK_SRC_SEL_MASK);
/* put vclk into reset, use atomic updates */
SETPLL(sc, RADEON_PPLL_CNTL,
RADEON_PPLL_REFCLK_SEL |
@ -1704,7 +1721,7 @@ radeonfb_program_vclk(struct radeonfb_softc *sc, int dotclock, int crtc)
PATCH32(sc, RADEON_CLOCK_CNTL_INDEX, 0,
~RADEON_PLL_DIV_SEL);
#endif
/* XXX: R300 family -- program divider differently? */
/* program reference divider */
@ -1918,7 +1935,7 @@ radeonfb_setcrtc(struct radeonfb_display *dp, int index)
if (crtc == 1)
v |= RADEON_CRTC2_VSYNC_TRISTAT;
}
PUT32(sc, gencntl, v);
DPRINTF(("CRTC%s_GEN_CNTL = %08x\n", crtc ? "2" : "", v));
@ -2008,7 +2025,7 @@ radeonfb_setcrtc(struct radeonfb_display *dp, int index)
CLR32(sc, RADEON_CRTC2_GEN_CNTL,
RADEON_CRTC2_VSYNC_DIS |
RADEON_CRTC2_HSYNC_DIS |
RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_DISP_REQ_EN_B);
RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_DISP_REQ_EN_B);
PRINTREG(RADEON_CRTC2_GEN_CNTL);
break;
}
@ -2050,7 +2067,7 @@ radeonfb_blank(struct radeonfb_display *dp, int blank)
fpreg = RADEON_FP_GEN_CNTL;
fpval = RADEON_FP_FPON;
}
if (blank) {
SET32(sc, reg, mask);
CLR32(sc, fpreg, fpval);
@ -2141,7 +2158,7 @@ radeonfb_set_fbloc(struct radeonfb_softc *sc)
if (HAS_CRTC2(sc)) {
gen2 = GET32(sc, RADEON_CRTC2_GEN_CNTL);
PUT32(sc, RADEON_CRTC2_GEN_CNTL,
PUT32(sc, RADEON_CRTC2_GEN_CNTL,
gen2 | RADEON_CRTC2_DISP_REQ_EN_B);
}
@ -2396,10 +2413,10 @@ radeonfb_cursor(void *cookie, int on, int row, int col)
struct vcons_screen *scr = ri->ri_hw;
struct radeonfb_display *dp = scr->scr_cookie;
int x, y, wi, he;
wi = ri->ri_font->fontwidth;
he = ri->ri_font->fontheight;
if (dp->rd_wsmode == WSDISPLAYIO_MODE_EMUL) {
x = ri->ri_ccol * wi + ri->ri_xorigin;
y = ri->ri_crow * he + ri->ri_yorigin;
@ -2448,21 +2465,21 @@ radeonfb_setup_mono(struct radeonfb_display *dp, int xd, int yd, int width,
uint32_t gmc;
uint32_t padded_width = (width+7) & 0xfff8;
uint32_t topleft, bottomright;
gmc = dp->rd_format << RADEON_GMC_DST_DATATYPE_SHIFT;
if (width != padded_width) {
radeonfb_wait_fifo(sc, 2);
topleft = ((yd << 16) & 0x1fff0000) | (xd & 0x1fff);
bottomright = (((yd + height) << 16) & 0x1fff0000) |
bottomright = (((yd + height) << 16) & 0x1fff0000) |
((xd + width) & 0x1fff);
PUT32(sc, RADEON_SC_TOP_LEFT, topleft);
PUT32(sc, RADEON_SC_BOTTOM_RIGHT, bottomright);
}
radeonfb_wait_fifo(sc, 5);
PUT32(sc, RADEON_DP_GUI_MASTER_CNTL,
RADEON_GMC_BRUSH_NONE |
RADEON_GMC_SRC_DATATYPE_MONO_FG_BG |
@ -2479,7 +2496,7 @@ radeonfb_setup_mono(struct radeonfb_display *dp, int xd, int yd, int width,
PUT32(sc, RADEON_DST_X_Y, (xd << 16) | yd);
PUT32(sc, RADEON_DST_WIDTH_HEIGHT, (padded_width << 16) | height);
}
static void
@ -2489,7 +2506,7 @@ radeonfb_feed_bytes(struct radeonfb_display *dp, int count, uint8_t *data)
int i;
uint32_t latch = 0;
int shift = 0;
for (i = 0; i < count; i++) {
latch |= (data[i] << shift);
if (shift == 24) {
@ -2563,7 +2580,7 @@ radeonfb_bitblt(struct radeonfb_display *dp, int srcx, int srcy,
}
gmc = dp->rd_format << RADEON_GMC_DST_DATATYPE_SHIFT;
radeonfb_wait_fifo(sc, 6);
PUT32(sc, RADEON_DP_GUI_MASTER_CNTL,
@ -2817,7 +2834,7 @@ radeonfb_set_cursor(struct radeonfb_display *dp, struct wsdisplay_cursor *wc)
if (flags & WSDISPLAY_CURSOR_DOCMAP) {
index = wc->cmap.index;
count = wc->cmap.count;
if (index >= 2 || (index + count) > 2)
return EINVAL;
@ -3063,7 +3080,7 @@ radeonfb_cursor_visible(struct radeonfb_display *dp)
gencntl = RADEON_CRTC_GEN_CNTL;
bit = RADEON_CRTC_CUR_EN;
}
if (dp->rd_cursor.rc_visible)
SET32(dp->rd_softc, gencntl, bit);
else
@ -3144,7 +3161,7 @@ radeonfb_port_mode(struct radeonfb_softc *sc, struct radeonfb_port *rp,
/* fallback to safe mode */
return radeonfb_modelookup(sc->sc_defaultmode);
}
/* always choose the preferred mode first! */
if (ep->edid_preferred_mode) {
@ -3330,10 +3347,16 @@ radeonfb_pickres(struct radeonfb_display *dp, uint16_t *x, uint16_t *y,
}
}
/*
* backlight levels are linear on:
* - RV200, RV250, RV280, RV350
* - but NOT on PowerBook4,3 6,3 6,5
* according to Linux' radeonfb
*/
/* Get the current backlight level for the display. */
static int
static int
radeonfb_get_backlight(struct radeonfb_display *dp)
{
int s;
@ -3345,22 +3368,21 @@ radeonfb_get_backlight(struct radeonfb_display *dp)
level &= RADEON_LVDS_BL_MOD_LEV_MASK;
level >>= RADEON_LVDS_BL_MOD_LEV_SHIFT;
/*
* On some chips, we should negate the backlight level.
* XXX Find out on which chips.
/*
* On some chips, we should negate the backlight level.
* XXX Find out on which chips.
*/
#ifdef RADEONFB_BACKLIGHT_NEGATED
level = RADEONFB_BACKLIGHT_MAX - level;
#endif /* RADEONFB_BACKLIGHT_NEGATED */
if (dp->rd_softc->sc_flags & RFB_INV_BLIGHT)
level = RADEONFB_BACKLIGHT_MAX - level;
splx(s);
return level;
}
}
/* Set the backlight to the given level for the display. */
static int
static int
radeonfb_set_backlight(struct radeonfb_display *dp, int level)
{
struct radeonfb_softc *sc;
@ -3368,7 +3390,7 @@ radeonfb_set_backlight(struct radeonfb_display *dp, int level)
uint32_t lvds;
s = spltty();
if (level < 0)
level = 0;
else if (level >= RADEONFB_BACKLIGHT_MAX)
@ -3377,24 +3399,23 @@ radeonfb_set_backlight(struct radeonfb_display *dp, int level)
sc = dp->rd_softc;
/* On some chips, we should negate the backlight level. */
#ifdef RADEONFB_BACKLIGHT_NEGATED
rlevel = RADEONFB_BACKLIGHT_MAX - level;
#else
rlevel = level;
#endif /* RADEONFB_BACKLIGHT_NEGATED */
if (dp->rd_softc->sc_flags & RFB_INV_BLIGHT) {
rlevel = RADEONFB_BACKLIGHT_MAX - level;
} else
rlevel = level;
callout_stop(&dp->rd_bl_lvds_co);
radeonfb_engine_idle(sc);
/*
/*
* Turn off the display if the backlight is set to 0, since the
* display is useless without backlight anyway.
* display is useless without backlight anyway.
*/
if (level == 0)
radeonfb_blank(dp, 1);
else if (radeonfb_get_backlight(dp) == 0)
radeonfb_blank(dp, 0);
lvds = radeonfb_get32(sc, RADEON_LVDS_GEN_CNTL);
lvds &= ~RADEON_LVDS_DISPLAY_DIS;
if (!(lvds & RADEON_LVDS_BLON) || !(lvds & RADEON_LVDS_ON)) {
@ -3410,19 +3431,19 @@ radeonfb_set_backlight(struct radeonfb_display *dp, int level)
lvds |= rlevel << RADEON_LVDS_BL_MOD_LEV_SHIFT;
radeonfb_put32(sc, RADEON_LVDS_GEN_CNTL, lvds);
}
dp->rd_bl_lvds_val &= ~RADEON_LVDS_STATE_MASK;
dp->rd_bl_lvds_val |= lvds & RADEON_LVDS_STATE_MASK;
/* XXX What is the correct delay? */
callout_schedule(&dp->rd_bl_lvds_co, 200 * hz);
callout_schedule(&dp->rd_bl_lvds_co, 200 * hz);
splx(s);
return 0;
}
/*
* Callout function for delayed operations on the LVDS_GEN_CNTL register.
/*
* Callout function for delayed operations on the LVDS_GEN_CNTL register.
* Set the delayed bits in the register, and clear the stored delayed
* value.
*/
@ -3434,7 +3455,7 @@ static void radeonfb_lvds_callout(void *arg)
s = splhigh();
radeonfb_mask32(dp->rd_softc, RADEON_LVDS_GEN_CNTL, ~0,
radeonfb_mask32(dp->rd_softc, RADEON_LVDS_GEN_CNTL, ~0,
dp->rd_bl_lvds_val);
dp->rd_bl_lvds_val = 0;

View File

@ -1,4 +1,4 @@
/* $NetBSD: radeonfbvar.h,v 1.3 2007/01/03 19:47:17 macallan Exp $ */
/* $NetBSD: radeonfbvar.h,v 1.4 2007/02/09 21:12:00 macallan Exp $ */
/*-
* Copyright (c) 2006 Itronix Inc.
@ -29,7 +29,7 @@
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
*/
/*
* ATI Technologies Inc. ("ATI") has not assisted in the creation of, and
@ -303,6 +303,7 @@ struct radeonfb_softc {
#define RFB_R300 (1 << 5) /* R300 variants -- newer parts */
#define RFB_RV100 (1 << 6) /* RV100 variants -- previous gen */
#define RFB_ATOM (1 << 7) /* ATOM bios */
#define RFB_INV_BLIGHT (1 << 8) /* backlight level inverted */
#define IS_MOBILITY(sc) ((sc)->sc_flags & RFB_MOB)
#define HAS_CRTC2(sc) (((sc)->sc_flags & RFB_NCRTC2) == 0)