implement WSDISPLAYIO_{GET|PUT}CMAP ioctl()s
while there: - unmap registers and vram only in WSDISPLAYIO_MODE_MAPPED ( so DRM can map them ) but not in WSDISPLAYIO_MODE_DUMBFB ( so wsfb can do things that require hardware access, like palette and cursor ioctl()s ) - reject ioctl()s that need hardware access if registers are unmapped ( so we don't crash instead ) - use the same bit order in cursor sprite images as the other drivers do with all this, Xorg with wsfb works properly on top of radeonfb tested on i386 and macppc ( fingers crossed for alpha ;) )
This commit is contained in:
parent
708b399e9d
commit
4f788ce7bc
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: radeonfb.c,v 1.81 2014/01/14 09:46:42 macallan Exp $ */
|
||||
/* $NetBSD: radeonfb.c,v 1.82 2014/01/22 07:57:33 macallan Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2006 Itronix Inc.
|
||||
@ -70,7 +70,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: radeonfb.c,v 1.81 2014/01/14 09:46:42 macallan Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: radeonfb.c,v 1.82 2014/01/22 07:57:33 macallan Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
@ -140,6 +140,9 @@ static int radeonfb_set_cursor(struct radeonfb_display *,
|
||||
struct wsdisplay_cursor *);
|
||||
static int radeonfb_set_curpos(struct radeonfb_display *,
|
||||
struct wsdisplay_curpos *);
|
||||
static void radeonfb_putpal(struct radeonfb_display *, int, int, int, int);
|
||||
static int radeonfb_putcmap(struct radeonfb_display *, struct wsdisplay_cmap *);
|
||||
static int radeonfb_getcmap(struct radeonfb_display *, struct wsdisplay_cmap *);
|
||||
|
||||
/* acceleration support */
|
||||
static void radeonfb_rectfill(struct radeonfb_display *, int dstx, int dsty,
|
||||
@ -1075,6 +1078,21 @@ radeonfb_ioctl(void *v, void *vs,
|
||||
dp = (struct radeonfb_display *)vd->cookie;
|
||||
sc = dp->rd_softc;
|
||||
|
||||
/* can't do these without registers being mapped */
|
||||
if (!sc->sc_mapped) {
|
||||
switch (cmd) {
|
||||
case WSDISPLAYIO_GVIDEO:
|
||||
case WSDISPLAYIO_SVIDEO:
|
||||
case WSDISPLAYIO_GETCMAP:
|
||||
case WSDISPLAYIO_PUTCMAP:
|
||||
case WSDISPLAYIO_SCURSOR:
|
||||
case WSDISPLAYIO_GCURPOS:
|
||||
case WSDISPLAYIO_SCURPOS:
|
||||
case WSDISPLAYIO_SETPARAM:
|
||||
return EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
switch (cmd) {
|
||||
case WSDISPLAYIO_GTYPE:
|
||||
*(unsigned *)d = WSDISPLAY_TYPE_PCIMISC;
|
||||
@ -1104,19 +1122,15 @@ radeonfb_ioctl(void *v, void *vs,
|
||||
return 0;
|
||||
|
||||
case WSDISPLAYIO_GETCMAP:
|
||||
#if 0
|
||||
if (dp->rd_bpp == 8)
|
||||
return radeonfb_getcmap(sc,
|
||||
return radeonfb_getcmap(dp,
|
||||
(struct wsdisplay_cmap *)d);
|
||||
#endif
|
||||
return EINVAL;
|
||||
|
||||
case WSDISPLAYIO_PUTCMAP:
|
||||
#if 0
|
||||
if (dp->rd_bpp == 8)
|
||||
return radeonfb_putcmap(sc,
|
||||
return radeonfb_putcmap(dp,
|
||||
(struct wsdisplay_cmap *)d);
|
||||
#endif
|
||||
return EINVAL;
|
||||
|
||||
case WSDISPLAYIO_LINEBYTES:
|
||||
@ -1126,9 +1140,12 @@ radeonfb_ioctl(void *v, void *vs,
|
||||
case WSDISPLAYIO_SMODE:
|
||||
if (*(int *)d != dp->rd_wsmode) {
|
||||
dp->rd_wsmode = *(int *)d;
|
||||
if ((dp->rd_wsmode == WSDISPLAYIO_MODE_EMUL) ||
|
||||
(dp->rd_wsmode == WSDISPLAYIO_MODE_DUMBFB))
|
||||
radeonfb_map(sc);
|
||||
|
||||
if ((dp->rd_wsmode == WSDISPLAYIO_MODE_EMUL) &&
|
||||
(dp->rd_vd.active)) {
|
||||
radeonfb_map(sc);
|
||||
radeonfb_engine_init(dp);
|
||||
glyphcache_wipe(&dp->rd_gc);
|
||||
radeonfb_init_palette(dp);
|
||||
@ -1136,9 +1153,9 @@ radeonfb_ioctl(void *v, void *vs,
|
||||
radeonfb_rectfill(dp, 0, 0, dp->rd_virtx,
|
||||
dp->rd_virty, dp->rd_bg);
|
||||
vcons_redraw_screen(dp->rd_vd.active);
|
||||
} else {
|
||||
radeonfb_unmap(sc);
|
||||
}
|
||||
if (dp->rd_wsmode == WSDISPLAYIO_MODE_MAPPED)
|
||||
radeonfb_unmap(sc);
|
||||
}
|
||||
return 0;
|
||||
|
||||
@ -2549,20 +2566,12 @@ radeonfb_init_misc(struct radeonfb_softc *sc)
|
||||
PUT32(sc, RADEON_GEN_INT_STATUS, GET32(sc, RADEON_GEN_INT_STATUS));
|
||||
}
|
||||
|
||||
/*
|
||||
* This loads a linear color map for true color.
|
||||
*/
|
||||
void
|
||||
radeonfb_init_palette(struct radeonfb_display *dp)
|
||||
static void
|
||||
radeonfb_putpal(struct radeonfb_display *dp, int idx, int r, int g, int b)
|
||||
{
|
||||
struct radeonfb_softc *sc = dp->rd_softc;
|
||||
int i, cc;
|
||||
int crtc, cc;
|
||||
uint32_t vclk;
|
||||
int crtc;
|
||||
|
||||
#define DAC_WIDTH ((1 << 10) - 1)
|
||||
#define CLUT_WIDTH ((1 << 8) - 1)
|
||||
#define CLUT_COLOR(i) ((i * DAC_WIDTH * 2 / CLUT_WIDTH + 1) / 2)
|
||||
|
||||
vclk = GETPLL(sc, RADEON_VCLK_ECP_CNTL);
|
||||
PUTPLL(sc, RADEON_VCLK_ECP_CNTL, vclk & ~RADEON_PIXCLK_DAC_ALWAYS_ONb);
|
||||
@ -2577,55 +2586,124 @@ radeonfb_init_palette(struct radeonfb_display *dp)
|
||||
else
|
||||
CLR32(sc, RADEON_DAC_CNTL2, RADEON_DAC2_PALETTE_ACC_CTL);
|
||||
|
||||
PUT32(sc, RADEON_PALETTE_INDEX, 0);
|
||||
|
||||
if (dp->rd_bpp == 8) {
|
||||
|
||||
/* R3G3B2 palette */
|
||||
int j = 0;
|
||||
uint32_t tmp, r, g, b;
|
||||
|
||||
for (i = 0; i <= CLUT_WIDTH; ++i) {
|
||||
tmp = i & 0xe0;
|
||||
/*
|
||||
* replicate bits so 0xe0 maps to a red value of 0xff
|
||||
* in order to make white look actually white
|
||||
*/
|
||||
tmp |= (tmp >> 3) | (tmp >> 6);
|
||||
r = tmp;
|
||||
|
||||
tmp = (i & 0x1c) << 3;
|
||||
tmp |= (tmp >> 3) | (tmp >> 6);
|
||||
g = tmp;
|
||||
|
||||
tmp = (i & 0x03) << 6;
|
||||
tmp |= tmp >> 2;
|
||||
tmp |= tmp >> 4;
|
||||
b = tmp;
|
||||
|
||||
PUT32(sc, RADEON_PALETTE_30_DATA,
|
||||
(r << 22) |
|
||||
(g << 12) |
|
||||
(b << 2));
|
||||
j += 3;
|
||||
}
|
||||
} else {
|
||||
/* linear ramp */
|
||||
for (i = 0; i <= CLUT_WIDTH; ++i) {
|
||||
PUT32(sc, RADEON_PALETTE_30_DATA,
|
||||
(CLUT_COLOR(i) << 10) |
|
||||
(CLUT_COLOR(i) << 20) |
|
||||
(CLUT_COLOR(i)));
|
||||
}
|
||||
}
|
||||
PUT32(sc, RADEON_PALETTE_INDEX, idx);
|
||||
PUT32(sc, RADEON_PALETTE_30_DATA,
|
||||
(r << 22) | (g << 12) | (b << 2));
|
||||
}
|
||||
|
||||
CLR32(sc, RADEON_DAC_CNTL2, RADEON_DAC2_PALETTE_ACC_CTL);
|
||||
PRINTREG(RADEON_DAC_CNTL2);
|
||||
|
||||
PUTPLL(sc, RADEON_VCLK_ECP_CNTL, vclk);
|
||||
}
|
||||
|
||||
/*
|
||||
* This loads a linear color map for true color.
|
||||
*/
|
||||
void
|
||||
radeonfb_init_palette(struct radeonfb_display *dp)
|
||||
{
|
||||
int i;
|
||||
|
||||
#define DAC_WIDTH ((1 << 10) - 1)
|
||||
#define CLUT_WIDTH ((1 << 8) - 1)
|
||||
#define CLUT_COLOR(i) ((i * DAC_WIDTH * 2 / CLUT_WIDTH + 1) / 2)
|
||||
|
||||
if (dp->rd_bpp == 8) {
|
||||
|
||||
/* R3G3B2 palette */
|
||||
uint32_t tmp, r, g, b;
|
||||
|
||||
for (i = 0; i <= CLUT_WIDTH; ++i) {
|
||||
tmp = i & 0xe0;
|
||||
|
||||
/*
|
||||
* replicate bits so 0xe0 maps to a red value of 0xff
|
||||
* in order to make white look actually white
|
||||
*/
|
||||
tmp |= (tmp >> 3) | (tmp >> 6);
|
||||
r = tmp;
|
||||
|
||||
tmp = (i & 0x1c) << 3;
|
||||
tmp |= (tmp >> 3) | (tmp >> 6);
|
||||
g = tmp;
|
||||
|
||||
tmp = (i & 0x03) << 6;
|
||||
tmp |= tmp >> 2;
|
||||
tmp |= tmp >> 4;
|
||||
b = tmp;
|
||||
|
||||
radeonfb_putpal(dp, i, r, g, b);
|
||||
}
|
||||
} else {
|
||||
/* linear ramp */
|
||||
for (i = 0; i <= CLUT_WIDTH; ++i) {
|
||||
radeonfb_putpal(dp, i, i, i, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
radeonfb_putcmap(struct radeonfb_display *dp, struct wsdisplay_cmap *cm)
|
||||
{
|
||||
u_char *r, *g, *b;
|
||||
u_int index = cm->index;
|
||||
u_int count = cm->count;
|
||||
int i, error;
|
||||
u_char rbuf[256], gbuf[256], bbuf[256];
|
||||
|
||||
#ifdef GENFB_DEBUG
|
||||
aprint_debug("putcmap: %d %d\n",index, count);
|
||||
#endif
|
||||
if (cm->index >= 256 || cm->count > 256 ||
|
||||
(cm->index + cm->count) > 256)
|
||||
return EINVAL;
|
||||
error = copyin(cm->red, &rbuf[index], count);
|
||||
if (error)
|
||||
return error;
|
||||
error = copyin(cm->green, &gbuf[index], count);
|
||||
if (error)
|
||||
return error;
|
||||
error = copyin(cm->blue, &bbuf[index], count);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
memcpy(&dp->rd_cmap_red[index], &rbuf[index], count);
|
||||
memcpy(&dp->rd_cmap_green[index], &gbuf[index], count);
|
||||
memcpy(&dp->rd_cmap_blue[index], &bbuf[index], count);
|
||||
|
||||
r = &dp->rd_cmap_red[index];
|
||||
g = &dp->rd_cmap_green[index];
|
||||
b = &dp->rd_cmap_blue[index];
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
radeonfb_putpal(dp, index, *r, *g, *b);
|
||||
index++;
|
||||
r++, g++, b++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
radeonfb_getcmap(struct radeonfb_display *dp, struct wsdisplay_cmap *cm)
|
||||
{
|
||||
u_int index = cm->index;
|
||||
u_int count = cm->count;
|
||||
int error;
|
||||
|
||||
if (index >= 255 || count > 256 || index + count > 256)
|
||||
return EINVAL;
|
||||
|
||||
error = copyout(&dp->rd_cmap_red[index], cm->red, count);
|
||||
if (error)
|
||||
return error;
|
||||
error = copyout(&dp->rd_cmap_green[index], cm->green, count);
|
||||
if (error)
|
||||
return error;
|
||||
error = copyout(&dp->rd_cmap_blue[index], cm->blue, count);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Bugs in some R300 hardware requires this when accessing CLOCK_CNTL_INDEX.
|
||||
*/
|
||||
@ -3498,6 +3576,22 @@ radeonfb_set_cursor(struct radeonfb_display *dp, struct wsdisplay_cursor *wc)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
radeonfb_backwards(uint8_t d)
|
||||
{
|
||||
uint8_t l;
|
||||
|
||||
l = d << 7;
|
||||
l |= ((d & 0x02) << 5);
|
||||
l |= ((d & 0x04) << 3);
|
||||
l |= ((d & 0x08) << 1);
|
||||
l |= ((d & 0x10) >> 1);
|
||||
l |= ((d & 0x20) >> 3);
|
||||
l |= ((d & 0x40) >> 5);
|
||||
l |= ((d & 0x80) >> 7);
|
||||
return l;
|
||||
}
|
||||
|
||||
/*
|
||||
* Change the cursor shape. Call this with the cursor locked to avoid
|
||||
* flickering/tearing.
|
||||
@ -3563,6 +3657,11 @@ radeonfb_cursor_shape(struct radeonfb_display *dp)
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < 512; i++) {
|
||||
and[i] = radeonfb_backwards(and[i]);
|
||||
xor[i] = radeonfb_backwards(xor[i]);
|
||||
}
|
||||
|
||||
/* copy the image into place */
|
||||
for (i = 0; i < 64; i++) {
|
||||
memcpy((uint8_t *)dp->rd_curptr + (i * 16),
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: radeonfbvar.h,v 1.18 2013/03/28 17:25:10 macallan Exp $ */
|
||||
/* $NetBSD: radeonfbvar.h,v 1.19 2014/01/22 07:57:33 macallan Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2006 Itronix Inc.
|
||||
@ -196,11 +196,9 @@ struct radeonfb_display {
|
||||
void (*rd_putchar)(void *, int, int, u_int, long);
|
||||
glyphcache rd_gc;
|
||||
|
||||
#if 0
|
||||
uint8_t rd_cmap_red[256];
|
||||
uint8_t rd_cmap_green[256];
|
||||
uint8_t rd_cmap_blue[256];
|
||||
#endif
|
||||
|
||||
#ifdef SPLASHSCREEN
|
||||
struct splash_info rd_splash;
|
||||
|
Loading…
Reference in New Issue
Block a user