summaryrefslogtreecommitdiffstats
path: root/sys/dev/fb/machfb.c
diff options
context:
space:
mode:
authormarius <marius@FreeBSD.org>2005-07-10 11:43:20 +0000
committermarius <marius@FreeBSD.org>2005-07-10 11:43:20 +0000
commit99f3cd87d0cf545cf425c60177d56a0c625c1146 (patch)
tree8854259cd51e7720f6da404085ccb3ebcd4c5e6a /sys/dev/fb/machfb.c
parentcaf07ad5af89e0aaff0ba7bcb3caa4abbfac1857 (diff)
downloadFreeBSD-src-99f3cd87d0cf545cf425c60177d56a0c625c1146.zip
FreeBSD-src-99f3cd87d0cf545cf425c60177d56a0c625c1146.tar.gz
- Declare lookup tables etc. const. [1]
- Add a missing "ATI" in one of the device descriptions. - In machfb_init_engine() adjust a wait_for_fifo() call to the actual number of operations. - As a speed optimization cache setting the foreground and back- ground colors. - I got the meaning of V_DISPLAY_BLANK wrong, it's blank like turn off and not blank like turn on and clear the screen. So move clearing the screen to machfb_clear() were it hopefully belongs. - Properly implement V_DISPLAY_BLANK, V_DISPLAY_STAND_BY and V_DISPLAY_SUSPEND. This makes blank_saver.ko and green_saver.ko work. [1] - Implement machfb_load_palette() and machfb_save_palette() and set the V_ADP_PALETTE flag. This makes fade_saver.ko work. [2] - Install our 16-color color map only once and with an offset of 16 as the OBP driver expects white to be at index 0 and black at 255. This fixes the inversion of the colors back at the boot prompt after shutting down FreeBSD. This will also be handy if we ever want to implement breaking into OFW. Unfortunately there doesn't seem to be a better way to achieve this as e.g. bypassing the color map isn't supported by all Mach64 chips. - Move invalidating the cache variables to machfb_set_mode() and set the V_ADP_MODECHANGE flag. This causes machfb_set_mode() to be called when the X server shuts down. This hopefully will fix the screen corruption happening occasionally when shutting down the X server and which is present until switching to another VTY. Inspired by: NetBSD [1] Based on: Xorg [2] Approved by: re (scottl)
Diffstat (limited to 'sys/dev/fb/machfb.c')
-rw-r--r--sys/dev/fb/machfb.c216
1 files changed, 148 insertions, 68 deletions
diff --git a/sys/dev/fb/machfb.c b/sys/dev/fb/machfb.c
index 440f955..f97480b 100644
--- a/sys/dev/fb/machfb.c
+++ b/sys/dev/fb/machfb.c
@@ -135,15 +135,12 @@ struct machfb_softc {
int sc_mclk_post_div;
int sc_mclk_fb_div;
- int sc_dacw;
- uint8_t sc_cmap_red[256];
- uint8_t sc_cmap_green[256];
- uint8_t sc_cmap_blue[256];
-
u_char *sc_font;
int sc_cbwidth;
vm_offset_t sc_curoff;
+ int sc_bg_cache;
+ int sc_fg_cache;
int sc_draw_cache;
#define MACHFB_DRAW_CHAR (1 << 0)
#define MACHFB_DRAW_FILLRECT (1 << 1)
@@ -154,7 +151,7 @@ struct machfb_softc {
#define MACHFB_DSP (1 << 2)
};
-static struct {
+static const struct {
uint16_t chip_id;
const char *name;
uint32_t ramdac_freq;
@@ -166,7 +163,7 @@ static struct {
{ ATI_RAGE_XC_PCI66, "ATI Rage XL (PCI66)", 230000 },
{ ATI_RAGE_XL_AGP, "ATI Rage XL (AGP)", 230000 },
{ ATI_RAGE_XC_AGP, "ATI Rage XC (AGP)", 230000 },
- { ATI_RAGE_XL_PCI66, "Rage XL (PCI66)", 230000 },
+ { ATI_RAGE_XL_PCI66, "ATI Rage XL (PCI66)", 230000 },
{ ATI_RAGE_PRO_PCI_P, "ATI 3D Rage Pro", 230000 },
{ ATI_RAGE_PRO_PCI_L, "ATI 3D Rage Pro (limited 3D)", 230000 },
{ ATI_RAGE_XL_PCI, "ATI Rage XL", 230000 },
@@ -192,7 +189,7 @@ static struct {
{ ATI_MACH64_VT4, "ATI Mach64 VT4", 230000 }
};
-static struct machfb_cmap {
+static const struct machfb_cmap {
uint8_t red;
uint8_t green;
uint8_t blue;
@@ -215,7 +212,9 @@ static struct machfb_cmap {
{0xff, 0xff, 0xff} /* white */
};
-static u_char machfb_mouse_pointer_bits[64][8] = {
+#define MACHFB_CMAP_OFF 16
+
+static const u_char machfb_mouse_pointer_bits[64][8] = {
{ 0x00, 0x00, }, /* ............ */
{ 0x80, 0x00, }, /* *........... */
{ 0xc0, 0x00, }, /* **.......... */
@@ -244,12 +243,12 @@ static u_char machfb_mouse_pointer_bits[64][8] = {
* Lookup table to perform a bit-swap of the mouse pointer bits,
* map set bits to CUR_CLR0 and unset bits to transparent.
*/
-static u_char machfb_mouse_pointer_lut[] = {
+static const u_char machfb_mouse_pointer_lut[] = {
0xaa, 0x2a, 0x8a, 0x0a, 0xa2, 0x22, 0x82, 0x02,
0xa8, 0x28, 0x88, 0x08, 0xa0, 0x20, 0x80, 0x00
};
-static char *machfb_memtype_names[] = {
+static const char *machfb_memtype_names[] = {
"(N/A)", "DRAM", "EDO DRAM", "EDO DRAM", "SDRAM", "SGRAM", "WRAM",
"(unknown type)"
};
@@ -289,8 +288,6 @@ static void machfb_init_engine(struct machfb_softc *);
#if 0
static void machfb_adjust_frame(struct machfb_softc *, int, int);
#endif
-static void machfb_putpalreg(struct machfb_softc *, uint8_t, uint8_t, uint8_t,
- uint8_t);
static void machfb_shutdown_final(void *);
static void machfb_shutdown_reset(void *);
@@ -439,6 +436,34 @@ wait_for_idle(struct machfb_softc *sc)
}
/*
+ * Inline functions for setting the background and foreground colors.
+ */
+static inline void machfb_setbg(struct machfb_softc *sc, int bg);
+static inline void machfb_setfg(struct machfb_softc *sc, int fg);
+
+static inline void
+machfb_setbg(struct machfb_softc *sc, int bg)
+{
+
+ if (bg == sc->sc_bg_cache)
+ return;
+ sc->sc_bg_cache = bg;
+ wait_for_fifo(sc, 1);
+ regw(sc, DP_BKGD_CLR, bg + MACHFB_CMAP_OFF);
+}
+
+static inline void
+machfb_setfg(struct machfb_softc *sc, int fg)
+{
+
+ if (fg == sc->sc_fg_cache)
+ return;
+ sc->sc_fg_cache = fg;
+ wait_for_fifo(sc, 1);
+ regw(sc, DP_FRGD_CLR, fg + MACHFB_CMAP_OFF);
+}
+
+/*
* video driver interface
*/
static int
@@ -522,7 +547,8 @@ machfb_init(int unit, video_adapter_t *adp, int flags)
phandle_t options;
video_info_t *vi;
char buf[32];
- int i, j;
+ int i;
+ uint8_t dac_mask, dac_rindex, dac_windex;
sc = (struct machfb_softc *)adp;
vi = &adp->va_info;
@@ -566,7 +592,6 @@ machfb_init(int unit, video_adapter_t *adp, int flags)
vi->vi_flags = V_INFO_COLOR;
vi->vi_mem_model = V_INFO_MM_OTHER;
- sc->sc_draw_cache = -1;
sc->sc_font = gallant12x22_data;
sc->sc_cbwidth = howmany(vi->vi_cwidth, 8); /* width in bytes */
sc->sc_xmargin = (sc->sc_width - (vi->vi_width * vi->vi_cwidth)) / 2;
@@ -605,18 +630,40 @@ machfb_init(int unit, video_adapter_t *adp, int flags)
#if 0
mach64_adjust_frame(0, 0);
#endif
+ machfb_set_mode(adp, 0);
- sc->sc_dacw = -1;
- for (i = 0; i < 16; i++)
- for (j = 0; j < 16; j++)
- machfb_putpalreg(sc, (i * 16) + j,
- machfb_default_cmap[j].red,
- machfb_default_cmap[j].green,
- machfb_default_cmap[j].blue);
+ /*
+ * Install our 16-color color map. This is done only once and with
+ * an offset of 16 on sparc64 as there the OBP driver expects white
+ * to be at index 0 and black at 255 (some versions also use 1 - 8
+ * for color text support or the full palette for the boot banner
+ * logo but no versions seems to use the ISO 6429-1983 color map).
+ * Otherwise the colors are inverted when back in the OFW.
+ */
+ dac_rindex = regrb(sc, DAC_RINDEX);
+ dac_windex = regrb(sc, DAC_WINDEX);
+ dac_mask = regrb(sc, DAC_MASK);
+ regwb(sc, DAC_MASK, 0xff);
+ regwb(sc, DAC_WINDEX, MACHFB_CMAP_OFF);
+ for (i = 0; i < 16; i++) {
+ regwb(sc, DAC_DATA, machfb_default_cmap[i].red);
+ regwb(sc, DAC_DATA, machfb_default_cmap[i].green);
+ regwb(sc, DAC_DATA, machfb_default_cmap[i].blue);
+ }
+ regwb(sc, DAC_MASK, dac_mask);
+ regwb(sc, DAC_RINDEX, dac_rindex);
+ regwb(sc, DAC_WINDEX, dac_windex);
- machfb_blank_display(adp, V_DISPLAY_BLANK);
+ machfb_blank_display(adp, V_DISPLAY_ON);
+ machfb_clear(adp);
- adp->va_flags |= V_ADP_COLOR | V_ADP_BORDER | V_ADP_INITIALIZED;
+ /*
+ * Setting V_ADP_MODECHANGE serves as hack so machfb_set_mode()
+ * (which will invalidate our caches) is called as a precaution
+ * when the X server shuts down.
+ */
+ adp->va_flags |= V_ADP_COLOR | V_ADP_MODECHANGE | V_ADP_PALETTE |
+ V_ADP_BORDER | V_ADP_INITIALIZED;
if (vid_register(adp) < 0)
return (ENXIO);
adp->va_flags |= V_ADP_REGISTERED;
@@ -643,8 +690,15 @@ machfb_query_mode(video_adapter_t *adp, video_info_t *info)
static int
machfb_set_mode(video_adapter_t *adp, int mode)
{
+ struct machfb_softc *sc;
- return (ENODEV);
+ sc = (struct machfb_softc *)adp;
+
+ sc->sc_bg_cache = -1;
+ sc->sc_fg_cache = -1;
+ sc->sc_draw_cache = -1;
+
+ return (0);
}
static int
@@ -673,15 +727,47 @@ machfb_show_font(video_adapter_t *adp, int page)
static int
machfb_save_palette(video_adapter_t *adp, u_char *palette)
{
+ struct machfb_softc *sc;
+ int i;
+ uint8_t dac_mask, dac_rindex, dac_windex;
- return (ENODEV);
+ sc = (struct machfb_softc *)adp;
+
+ dac_rindex = regrb(sc, DAC_RINDEX);
+ dac_windex = regrb(sc, DAC_WINDEX);
+ dac_mask = regrb(sc, DAC_MASK);
+ regwb(sc, DAC_MASK, 0xff);
+ regwb(sc, DAC_RINDEX, 0x0);
+ for (i = 0; i < 256 * 3; i++)
+ palette[i] = regrb(sc, DAC_DATA);
+ regwb(sc, DAC_MASK, dac_mask);
+ regwb(sc, DAC_RINDEX, dac_rindex);
+ regwb(sc, DAC_WINDEX, dac_windex);
+
+ return (0);
}
static int
machfb_load_palette(video_adapter_t *adp, u_char *palette)
{
+ struct machfb_softc *sc;
+ int i;
+ uint8_t dac_mask, dac_rindex, dac_windex;
- return (ENODEV);
+ sc = (struct machfb_softc *)adp;
+
+ dac_rindex = regrb(sc, DAC_RINDEX);
+ dac_windex = regrb(sc, DAC_WINDEX);
+ dac_mask = regrb(sc, DAC_MASK);
+ regwb(sc, DAC_MASK, 0xff);
+ regwb(sc, DAC_WINDEX, 0x0);
+ for (i = 0; i < 256 * 3; i++)
+ regwb(sc, DAC_DATA, palette[i]);
+ regwb(sc, DAC_MASK, dac_mask);
+ regwb(sc, DAC_RINDEX, dac_rindex);
+ regwb(sc, DAC_WINDEX, dac_windex);
+
+ return (0);
}
static int
@@ -751,17 +837,27 @@ static int
machfb_blank_display(video_adapter_t *adp, int mode)
{
struct machfb_softc *sc;
+ uint32_t crtc_gen_cntl;
sc = (struct machfb_softc *)adp;
- if (mode == V_DISPLAY_ON || mode == V_DISPLAY_BLANK)
- regw(sc, CRTC_GEN_CNTL, (regr(sc, CRTC_GEN_CNTL) | CRTC_EN |
- CRTC_EXT_DISP_EN) & ~CRTC_DISPLAY_DIS);
- else
- regw(sc, CRTC_GEN_CNTL, regr(sc, CRTC_GEN_CNTL) & ~CRTC_EN);
- if (mode == V_DISPLAY_BLANK)
- machfb_fill_rect(adp, (SC_NORM_ATTR >> 4) & 0xf, 0, 0,
- sc->sc_width, sc->sc_height);
+ crtc_gen_cntl = (regr(sc, CRTC_GEN_CNTL) | CRTC_EXT_DISP_EN | CRTC_EN) &
+ ~(CRTC_HSYNC_DIS | CRTC_VSYNC_DIS | CRTC_DISPLAY_DIS);
+ switch (mode) {
+ case V_DISPLAY_ON:
+ break;
+ case V_DISPLAY_BLANK:
+ crtc_gen_cntl |= CRTC_HSYNC_DIS | CRTC_VSYNC_DIS |
+ CRTC_DISPLAY_DIS;
+ break;
+ case V_DISPLAY_STAND_BY:
+ crtc_gen_cntl |= CRTC_HSYNC_DIS | CRTC_DISPLAY_DIS;
+ break;
+ case V_DISPLAY_SUSPEND:
+ crtc_gen_cntl |= CRTC_VSYNC_DIS | CRTC_DISPLAY_DIS;
+ break;
+ }
+ regw(sc, CRTC_GEN_CNTL, crtc_gen_cntl);
return (0);
}
@@ -841,8 +937,14 @@ machfb_ioctl(video_adapter_t *adp, u_long cmd, caddr_t data)
static int
machfb_clear(video_adapter_t *adp)
{
+ struct machfb_softc *sc;
- return (ENODEV);
+ sc = (struct machfb_softc *)adp;
+
+ machfb_fill_rect(adp, (SC_NORM_ATTR >> 4) & 0xf, 0, 0, sc->sc_width,
+ sc->sc_height);
+
+ return (0);
}
static int
@@ -863,8 +965,8 @@ machfb_fill_rect(video_adapter_t *adp, int val, int x, int y, int cx, int cy)
regw(sc, DST_CNTL, DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM);
sc->sc_draw_cache = MACHFB_DRAW_FILLRECT;
}
- wait_for_fifo(sc, 5);
- regw(sc, DP_FRGD_CLR, val);
+ machfb_setfg(sc, val);
+ wait_for_fifo(sc, 4);
regw(sc, SRC_Y_X, (x << 16) | y);
regw(sc, SRC_WIDTH1, cx);
regw(sc, DST_Y_X, (x << 16) | y);
@@ -943,10 +1045,9 @@ machfb_putc(video_adapter_t *adp, vm_offset_t off, uint8_t c, uint8_t a)
regw(sc, HOST_CNTL, HOST_BYTE_ALIGN);
sc->sc_draw_cache = MACHFB_DRAW_CHAR;
}
- p = sc->sc_font + (c * adp->va_info.vi_cheight * sc->sc_cbwidth);
- wait_for_fifo(sc, 6 + (adp->va_info.vi_cheight / sc->sc_cbwidth));
- regw(sc, DP_BKGD_CLR, (a >> 4) & 0xf);
- regw(sc, DP_FRGD_CLR, a & 0xf);
+ machfb_setbg(sc, (a >> 4) & 0xf);
+ machfb_setfg(sc, a & 0xf);
+ wait_for_fifo(sc, 4 + (adp->va_info.vi_cheight / sc->sc_cbwidth));
regw(sc, SRC_Y_X, 0);
regw(sc, SRC_WIDTH1, adp->va_info.vi_cwidth);
regw(sc, DST_Y_X, ((((off % adp->va_info.vi_width) *
@@ -955,6 +1056,7 @@ machfb_putc(video_adapter_t *adp, vm_offset_t off, uint8_t c, uint8_t a)
sc->sc_ymargin));
regw(sc, DST_HEIGHT_WIDTH, (adp->va_info.vi_cwidth << 16) |
adp->va_info.vi_cheight);
+ p = sc->sc_font + (c * adp->va_info.vi_cheight * sc->sc_cbwidth);
for (i = 0; i < adp->va_info.vi_cheight * sc->sc_cbwidth; i += 4)
regw(sc, HOST_DATA0 + i, (p[i + 3] << 24 | p[i + 2] << 16 |
p[i + 1] << 8 | p[i]));
@@ -1302,8 +1404,9 @@ machfb_cursor_install(struct machfb_softc *sc)
machfb_cursor_enable(sc, 0);
regw(sc, CUR_OFFSET, sc->sc_curoff >> 3);
fg = SC_NORM_ATTR & 0xf;
- regw(sc, CUR_CLR0, sc->sc_cmap_red[fg] << 24 |
- sc->sc_cmap_green[fg] << 16 | sc->sc_cmap_blue[fg] << 8 | fg);
+ regw(sc, CUR_CLR0, machfb_default_cmap[fg].red << 24 |
+ machfb_default_cmap[fg].green << 16 |
+ machfb_default_cmap[fg].blue << 8);
p = (uint16_t *)(sc->sc_va.va_buffer + sc->sc_curoff);
for (i = 0; i < 64; i++)
for (j = 0; j < 8; j++)
@@ -1435,7 +1538,7 @@ machfb_init_engine(struct machfb_softc *sc)
#endif
}
- wait_for_fifo(sc, 5);
+ wait_for_fifo(sc, 2);
regw(sc, CRTC_INT_CNTL, regr(sc, CRTC_INT_CNTL) & ~0x20);
regw(sc, GUI_TRAJ_CNTL, DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM);
@@ -1456,29 +1559,6 @@ machfb_adjust_frame(struct machfb_softc *sc, int x, int y)
#endif
static void
-machfb_putpalreg(struct machfb_softc *sc, uint8_t index, uint8_t r, uint8_t g,
- uint8_t b)
-{
-
- sc->sc_cmap_red[index] = r;
- sc->sc_cmap_green[index] = g;
- sc->sc_cmap_blue[index] = b;
- /*
- * Writing the DAC index takes a while, in theory we can poll some
- * register to see when it's ready - but we better avoid writing it
- * unnecessarily.
- */
- if (index != sc->sc_dacw) {
- regwb(sc, DAC_MASK, 0xff);
- regwb(sc, DAC_WINDEX, index);
- }
- sc->sc_dacw = index + 1;
- regwb(sc, DAC_DATA, r);
- regwb(sc, DAC_DATA, g);
- regwb(sc, DAC_DATA, b);
-}
-
-static void
machfb_shutdown_final(void *v)
{
struct machfb_softc *sc = v;
OpenPOWER on IntegriCloud