diff --git a/sys/dev/fb/machfb.c b/sys/dev/fb/machfb.c new file mode 100644 index 000000000000..2fc32efe1016 --- /dev/null +++ b/sys/dev/fb/machfb.c @@ -0,0 +1,1490 @@ +/*- + * Copyright (c) 2002 Bang Jun-Young + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, 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. + * + * from: NetBSD: machfb.c,v 1.23 2005/03/07 21:45:24 martin Exp + */ +/*- + * Copyright (c) 2005 Marius Strobl + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification, immediately at the beginning of the file. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 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. + */ + +#include +__FBSDID("$FreeBSD$"); + +/* + * Driver for ATI Mach64 graphics chips. Some code is derived from the + * ATI Rage Pro and Derivatives Programmer's Guide. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +/* #define MACHFB_DEBUG */ + +#define MACHFB_DRIVER_NAME "machfb" + +#define MACH64_REG_OFF 0x7ffc00 +#define MACH64_REG_SIZE 1024 + +struct machfb_softc { + video_adapter_t sc_va; /* must be first */ + + phandle_t sc_node; + uint16_t sc_chip_id; + uint8_t sc_chip_rev; + + int sc_memrid; + int sc_viorid; + int sc_vmemrid; + struct resource *sc_memres; + struct resource *sc_viores; + struct resource *sc_vmemres; + bus_space_tag_t sc_memt; + bus_space_tag_t sc_regt; + bus_space_tag_t sc_viot; + bus_space_tag_t sc_vmemt; + bus_space_handle_t sc_memh; + bus_space_handle_t sc_regh; + bus_space_handle_t sc_vioh; + bus_space_handle_t sc_vmemh; + + int sc_height; + int sc_width; + int sc_depth; + int sc_xmargin; + int sc_ymargin; + + size_t sc_memsize; + int sc_memtype; + int sc_mem_freq; + int sc_ramdac_freq; + int sc_ref_freq; + + int sc_ref_div; + 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_draw_cache; +#define MACHFB_DRAW_CHAR (1 << 0) +#define MACHFB_DRAW_FILLRECT (1 << 1) + + int sc_flags; +#define MACHFB_CONSOLE (1 << 0) +#define MACHFB_CUREN (1 << 1) +#define MACHFB_DSP (1 << 2) +}; + +static struct { + uint16_t chip_id; + const char *name; + uint32_t ramdac_freq; +} machfb_info[] = { + { ATI_MACH64_CT, "ATI Mach64 CT", 135000 }, + { ATI_RAGE_PRO_AGP, "ATI 3D Rage Pro (AGP)", 230000 }, + { ATI_RAGE_PRO_AGP1X, "ATI 3D Rage Pro (AGP 1x)", 230000 }, + { ATI_RAGE_PRO_PCI_B, "ATI 3D Rage Pro Turbo", 230000 }, + { 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_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 }, + { ATI_RAGE_XC_PCI, "ATI Rage XC", 230000 }, + { ATI_RAGE_II, "ATI 3D Rage I/II", 135000 }, + { ATI_RAGE_IIP, "ATI 3D Rage II+", 200000 }, + { ATI_RAGE_IIC_PCI, "ATI 3D Rage IIC", 230000 }, + { ATI_RAGE_IIC_AGP_B, "ATI 3D Rage IIC (AGP)", 230000 }, + { ATI_RAGE_IIC_AGP_P, "ATI 3D Rage IIC (AGP)", 230000 }, + { ATI_RAGE_LT_PRO_AGP, "ATI 3D Rage LT Pro (AGP 133MHz)", 230000 }, + { ATI_RAGE_MOB_M3_PCI, "ATI Rage Mobility M3", 230000 }, + { ATI_RAGE_MOB_M3_AGP, "ATI Rage Mobility M3 (AGP)", 230000 }, + { ATI_RAGE_LT, "ATI 3D Rage LT", 230000 }, + { ATI_RAGE_LT_PRO_PCI, "ATI 3D Rage LT Pro", 230000 }, + { ATI_RAGE_MOBILITY, "ATI Rage Mobility", 230000 }, + { ATI_RAGE_L_MOBILITY, "ATI Rage L Mobility", 230000 }, + { ATI_RAGE_LT_PRO, "ATI 3D Rage LT Pro", 230000 }, + { ATI_RAGE_LT_PRO2, "ATI 3D Rage LT Pro", 230000 }, + { ATI_RAGE_MOB_M1_PCI, "ATI Rage Mobility M1 (PCI)", 230000 }, + { ATI_RAGE_L_MOB_M1_PCI, "ATI Rage L Mobility (PCI)", 230000 }, + { ATI_MACH64_VT, "ATI Mach64 VT", 170000 }, + { ATI_MACH64_VTB, "ATI Mach64 VTB", 200000 }, + { ATI_MACH64_VT4, "ATI Mach64 VT4", 230000 } +}; + +static struct machfb_cmap { + uint8_t red; + uint8_t green; + uint8_t blue; +} machfb_default_cmap[16] = { + {0x00, 0x00, 0x00}, /* black */ + {0x00, 0x00, 0xff}, /* blue */ + {0x00, 0xff, 0x00}, /* green */ + {0x00, 0xc0, 0xc0}, /* cyan */ + {0xff, 0x00, 0x00}, /* red */ + {0xc0, 0x00, 0xc0}, /* magenta */ + {0xc0, 0xc0, 0x00}, /* brown */ + {0xc0, 0xc0, 0xc0}, /* light grey */ + {0x80, 0x80, 0x80}, /* dark grey */ + {0x80, 0x80, 0xff}, /* light blue */ + {0x80, 0xff, 0x80}, /* light green */ + {0x80, 0xff, 0xff}, /* light cyan */ + {0xff, 0x80, 0x80}, /* light red */ + {0xff, 0x80, 0xff}, /* light magenta */ + {0xff, 0xff, 0x80}, /* yellow */ + {0xff, 0xff, 0xff} /* white */ +}; + +static u_char machfb_mouse_pointer_bits[64][8] = { + { 0x00, 0x00, }, /* ............ */ + { 0x80, 0x00, }, /* *........... */ + { 0xc0, 0x00, }, /* **.......... */ + { 0xe0, 0x00, }, /* ***......... */ + { 0xf0, 0x00, }, /* ****........ */ + { 0xf8, 0x00, }, /* *****....... */ + { 0xfc, 0x00, }, /* ******...... */ + { 0xfe, 0x00, }, /* *******..... */ + { 0xff, 0x00, }, /* ********.... */ + { 0xff, 0x80, }, /* *********... */ + { 0xfc, 0xc0, }, /* ******..**.. */ + { 0xdc, 0x00, }, /* **.***...... */ + { 0x8e, 0x00, }, /* *...***..... */ + { 0x0e, 0x00, }, /* ....***..... */ + { 0x07, 0x00, }, /* .....***.... */ + { 0x04, 0x00, }, /* .....*...... */ + { 0x00, 0x00, }, /* ............ */ + { 0x00, 0x00, }, /* ............ */ + { 0x00, 0x00, }, /* ............ */ + { 0x00, 0x00, }, /* ............ */ + { 0x00, 0x00, }, /* ............ */ + { 0x00, 0x00, }, /* ............ */ +}; + +/* + * 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[] = { + 0xaa, 0x2a, 0x8a, 0x0a, 0xa2, 0x22, 0x82, 0x02, + 0xa8, 0x28, 0x88, 0x08, 0xa0, 0x20, 0x80, 0x00 +}; + +static char *machfb_memtype_names[] = { + "(N/A)", "DRAM", "EDO DRAM", "EDO DRAM", "SDRAM", "SGRAM", "WRAM", + "(unknown type)" +}; + +static struct machfb_softc machfb_softc; +static struct bus_space_tag machfb_bst_store[1]; + +static device_probe_t machfb_pci_probe; +static device_attach_t machfb_pci_attach; +static device_detach_t machfb_pci_detach; + +static device_method_t machfb_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, machfb_pci_probe), + DEVMETHOD(device_attach, machfb_pci_attach), + DEVMETHOD(device_detach, machfb_pci_detach), + + { 0, 0 } +}; + +static driver_t machfb_pci_driver = { + MACHFB_DRIVER_NAME, + machfb_methods, + sizeof(struct machfb_softc), +}; + +static devclass_t machfb_devclass; + +DRIVER_MODULE(machfb, pci, machfb_pci_driver, machfb_devclass, 0, 0); +MODULE_DEPEND(machfb, pci, 1, 1, 1); + +static void machfb_cursor_enable(struct machfb_softc *, int); +static int machfb_cursor_install(struct machfb_softc *); +static int machfb_get_memsize(struct machfb_softc *); +static void machfb_reset_engine(struct machfb_softc *); +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 *v); +static void machfb_shutdown_reset(void *v); + +static int machfb_configure(int flags); + +static vi_probe_t machfb_probe; +static vi_init_t machfb_init; +static vi_get_info_t machfb_get_info; +static vi_query_mode_t machfb_query_mode; +static vi_set_mode_t machfb_set_mode; +static vi_save_font_t machfb_save_font; +static vi_load_font_t machfb_load_font; +static vi_show_font_t machfb_show_font; +static vi_save_palette_t machfb_save_palette; +static vi_load_palette_t machfb_load_palette; +static vi_set_border_t machfb_set_border; +static vi_save_state_t machfb_save_state; +static vi_load_state_t machfb_load_state; +static vi_set_win_org_t machfb_set_win_org; +static vi_read_hw_cursor_t machfb_read_hw_cursor; +static vi_set_hw_cursor_t machfb_set_hw_cursor; +static vi_set_hw_cursor_shape_t machfb_set_hw_cursor_shape; +static vi_blank_display_t machfb_blank_display; +static vi_mmap_t machfb_mmap; +static vi_ioctl_t machfb_ioctl; +static vi_clear_t machfb_clear; +static vi_fill_rect_t machfb_fill_rect; +static vi_bitblt_t machfb_bitblt; +static vi_diag_t machfb_diag; +static vi_save_cursor_palette_t machfb_save_cursor_palette; +static vi_load_cursor_palette_t machfb_load_cursor_palette; +static vi_copy_t machfb_copy; +static vi_putp_t machfb_putp; +static vi_putc_t machfb_putc; +static vi_puts_t machfb_puts; +static vi_putm_t machfb_putm; + +static video_switch_t machfbvidsw = { + .probe = machfb_probe, + .init = machfb_init, + .get_info = machfb_get_info, + .query_mode = machfb_query_mode, + .set_mode = machfb_set_mode, + .save_font = machfb_save_font, + .load_font = machfb_load_font, + .show_font = machfb_show_font, + .save_palette = machfb_save_palette, + .load_palette = machfb_load_palette, + .set_border = machfb_set_border, + .save_state = machfb_save_state, + .load_state = machfb_load_state, + .set_win_org = machfb_set_win_org, + .read_hw_cursor = machfb_read_hw_cursor, + .set_hw_cursor = machfb_set_hw_cursor, + .set_hw_cursor_shape = machfb_set_hw_cursor_shape, + .blank_display = machfb_blank_display, + .mmap = machfb_mmap, + .ioctl = machfb_ioctl, + .clear = machfb_clear, + .fill_rect = machfb_fill_rect, + .bitblt = machfb_bitblt, + NULL, + NULL, + .diag = machfb_diag, + .save_cursor_palette = machfb_save_cursor_palette, + .load_cursor_palette = machfb_load_cursor_palette, + .copy = machfb_copy, + .putp = machfb_putp, + .putc = machfb_putc, + .puts = machfb_puts, + .putm = machfb_putm +}; + +VIDEO_DRIVER(machfb, machfbvidsw, machfb_configure); + +extern sc_rndr_sw_t txtrndrsw; +RENDERER(machfb, 0, txtrndrsw, gfb_set); + +RENDERER_MODULE(machfb, gfb_set); + +/* + * Inline functions for getting access to register aperture. + */ +static inline uint32_t regr(struct machfb_softc *, uint32_t); +static inline uint8_t regrb(struct machfb_softc *, uint32_t); +static inline void regw(struct machfb_softc *, uint32_t, uint32_t); +static inline void regwb(struct machfb_softc *, uint32_t, uint8_t); +static inline void regwb_pll(struct machfb_softc *, uint32_t, uint8_t); + +static inline uint32_t +regr(struct machfb_softc *sc, uint32_t index) +{ + + return bus_space_read_4(sc->sc_regt, sc->sc_regh, index); +} + +static inline uint8_t +regrb(struct machfb_softc *sc, uint32_t index) +{ + + return bus_space_read_1(sc->sc_regt, sc->sc_regh, index); +} + +static inline void +regw(struct machfb_softc *sc, uint32_t index, uint32_t data) +{ + + bus_space_write_4(sc->sc_regt, sc->sc_regh, index, data); + bus_space_barrier(sc->sc_regt, sc->sc_regh, index, 4, + BUS_SPACE_BARRIER_WRITE); +} + +static inline void +regwb(struct machfb_softc *sc, uint32_t index, uint8_t data) +{ + + bus_space_write_1(sc->sc_regt, sc->sc_regh, index, data); + bus_space_barrier(sc->sc_regt, sc->sc_regh, index, 1, + BUS_SPACE_BARRIER_WRITE); +} + +static inline void +regwb_pll(struct machfb_softc *sc, uint32_t index, uint8_t data) +{ + + regwb(sc, CLOCK_CNTL + 1, (index << 2) | PLL_WR_EN); + regwb(sc, CLOCK_CNTL + 2, data); + regwb(sc, CLOCK_CNTL + 1, (index << 2) & ~PLL_WR_EN); +} + +static inline void +wait_for_fifo(struct machfb_softc *sc, uint8_t v) +{ + + while ((regr(sc, FIFO_STAT) & 0xffff) > (0x8000 >> v)) + ; +} + +static inline void +wait_for_idle(struct machfb_softc *sc) +{ + + wait_for_fifo(sc, 16); + while ((regr(sc, GUI_STAT) & 1) != 0) + ; +} + +/* + * video driver interface + */ +static int +machfb_configure(int flags) +{ + struct machfb_softc *sc; + phandle_t chosen, output; + ihandle_t stdout; + bus_addr_t addr; + uint32_t id; + int i, space; + + sc = &machfb_softc; + + if ((chosen = OF_finddevice("/chosen")) == -1) /* Quis contra nos? */ + return (0); + if (OF_getprop(chosen, "stdout", &stdout, sizeof(stdout)) == -1) + return (0); + if ((output = OF_instance_to_package(stdout)) == -1) + return (0); + if ((OF_getprop(output, "vendor-id", &id, sizeof(id)) == -1) || + id != ATI_VENDOR) + return (0); + if (OF_getprop(output, "device-id", &id, sizeof(id)) == -1) + return (0); + for (i = 0; i < sizeof(machfb_info) / sizeof(machfb_info[0]); i++) { + if (id == machfb_info[i].chip_id) { + /* + * When being called a second time, i.e. during + * sc_probe_unit(), just return at this point. + * Note that the polarity of the VIO_PROBE_ONLY + * flag is somewhat non-intuitive. + */ + if (!(flags & VIO_PROBE_ONLY)) + goto found; + sc->sc_flags = MACHFB_CONSOLE; + sc->sc_node = output; + sc->sc_chip_id = id; + break; + } + } + if (!(sc->sc_flags & MACHFB_CONSOLE)) + return (0); + + if (OF_getprop(output, "revision-id", &sc->sc_chip_rev, + sizeof(sc->sc_chip_rev)) == -1) + return (0); + if (OF_decode_addr(output, 0, &space, &addr) != 0) + return (0); + sc->sc_memt = &machfb_bst_store[0]; + sc->sc_memh = sparc64_fake_bustag(space, addr, sc->sc_memt); + sc->sc_regt = sc->sc_memt; + bus_space_subregion(sc->sc_regt, sc->sc_memh, MACH64_REG_OFF, + MACH64_REG_SIZE, &sc->sc_regh); + + if (machfb_init(0, &sc->sc_va, 0) < 0) + return (0); + + found: + /* Return number of found adapters. */ + return (1); +} + +static int +machfb_probe(int unit, video_adapter_t **adpp, void *arg, int flags) +{ + + return (0); +} + +static int +machfb_init(int unit, video_adapter_t *adp, int flags) +{ + struct machfb_softc *sc; + phandle_t options; + video_info_t *vi; + char buf[32]; + int i, j; + + sc = (struct machfb_softc *)adp; + vi = &adp->va_info; + + if ((regr(sc, CONFIG_CHIP_ID) & 0xffff) != sc->sc_chip_id) + return (ENXIO); + + sc->sc_ramdac_freq = 0; + for (i = 0; i < sizeof(machfb_info) / sizeof(machfb_info[0]); i++) { + if (sc->sc_chip_id == machfb_info[i].chip_id) { + sc->sc_ramdac_freq = machfb_info[i].ramdac_freq; + break; + } + } + if (sc->sc_ramdac_freq == 0) + return (ENXIO); + if (sc->sc_chip_id == ATI_RAGE_II && sc->sc_chip_rev & 0x07) + sc->sc_ramdac_freq = 170000; + + vid_init_struct(adp, MACHFB_DRIVER_NAME, -1, unit); + + if (OF_getprop(sc->sc_node, "height", &sc->sc_height, + sizeof(sc->sc_height)) == -1) + return (ENXIO); + if (OF_getprop(sc->sc_node, "width", &sc->sc_width, + sizeof(sc->sc_width)) == -1) + return (ENXIO); + if (OF_getprop(sc->sc_node, "depth", &sc->sc_depth, + sizeof(sc->sc_depth)) == -1) + return (ENXIO); + if ((options = OF_finddevice("/options")) == -1) + return (ENXIO); + if (OF_getprop(options, "screen-#rows", buf, sizeof(buf)) == -1) + return (ENXIO); + vi->vi_height = strtol(buf, NULL, 10); + if (OF_getprop(options, "screen-#columns", buf, sizeof(buf)) == -1) + return (ENXIO); + vi->vi_width = strtol(buf, NULL, 10); + vi->vi_cwidth = 12; + vi->vi_cheight = 22; + 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; + sc->sc_ymargin = (sc->sc_height - (vi->vi_height * vi->vi_cheight)) / 2; + + if (sc->sc_chip_id != ATI_MACH64_CT && + !((sc->sc_chip_id == ATI_MACH64_VT || + sc->sc_chip_id == ATI_RAGE_II) && + (sc->sc_chip_rev & 0x07) == 0)) + sc->sc_flags |= MACHFB_DSP; + + sc->sc_memsize = machfb_get_memsize(sc); + if (sc->sc_memsize == 8192) + /* The last page is used as register aperture. */ + sc->sc_memsize -= 4; + sc->sc_memtype = regr(sc, CONFIG_STAT0) & 0x07; + + if ((sc->sc_chip_id >= ATI_RAGE_XC_PCI66 && + sc->sc_chip_id <= ATI_RAGE_XL_PCI66) || + (sc->sc_chip_id >= ATI_RAGE_XL_PCI && + sc->sc_chip_id <= ATI_RAGE_XC_PCI)) + sc->sc_ref_freq = 29498; + else + sc->sc_ref_freq = 14318; + + regwb(sc, CLOCK_CNTL + 1, PLL_REF_DIV << 2); + sc->sc_ref_div = regrb(sc, CLOCK_CNTL + 2); + regwb(sc, CLOCK_CNTL + 1, MCLK_FB_DIV << 2); + sc->sc_mclk_fb_div = regrb(sc, CLOCK_CNTL + 2); + sc->sc_mem_freq = (2 * sc->sc_ref_freq * sc->sc_mclk_fb_div) / + (sc->sc_ref_div * 2); + sc->sc_mclk_post_div = (sc->sc_mclk_fb_div * 2 * sc->sc_ref_freq) / + (sc->sc_mem_freq * sc->sc_ref_div); + + machfb_init_engine(sc); +#if 0 + mach64_adjust_frame(0, 0); +#endif + + 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); + + machfb_blank_display(adp, V_DISPLAY_BLANK); + + adp->va_flags |= V_ADP_COLOR | V_ADP_BORDER | V_ADP_INITIALIZED; + if (vid_register(adp) < 0) + return (ENXIO); + adp->va_flags |= V_ADP_REGISTERED; + + return (0); +} + +static int +machfb_get_info(video_adapter_t *adp, int mode, video_info_t *info) +{ + + bcopy(&adp->va_info, info, sizeof(*info)); + + return (0); +} + +static int +machfb_query_mode(video_adapter_t *adp, video_info_t *info) +{ + + return (ENODEV); +} + +static int +machfb_set_mode(video_adapter_t *adp, int mode) +{ + + return (ENODEV); +} + +static int +machfb_save_font(video_adapter_t *adp, int page, int size, u_char *data, + int c, int count) +{ + + return (ENODEV); +} + +static int +machfb_load_font(video_adapter_t *adp, int page, int size, u_char *data, + int c, int count) +{ + + return (ENODEV); +} + +static int +machfb_show_font(video_adapter_t *adp, int page) +{ + + return (ENODEV); +} + +static int +machfb_save_palette(video_adapter_t *adp, u_char *palette) +{ + + return (ENODEV); +} + +static int +machfb_load_palette(video_adapter_t *adp, u_char *palette) +{ + + return (ENODEV); +} + +static int +machfb_set_border(video_adapter_t *adp, int border) +{ + struct machfb_softc *sc; + + sc = (struct machfb_softc *)adp; + + machfb_fill_rect(adp, border, 0, 0, sc->sc_width, sc->sc_ymargin); + machfb_fill_rect(adp, border, 0, sc->sc_height - sc->sc_ymargin, + sc->sc_width, sc->sc_ymargin); + machfb_fill_rect(adp, border, 0, 0, sc->sc_xmargin, sc->sc_height); + machfb_fill_rect(adp, border, sc->sc_width - sc->sc_xmargin, 0, + sc->sc_xmargin, sc->sc_height); + + return (0); +} + +static int +machfb_save_state(video_adapter_t *adp, void *p, size_t size) +{ + + return (ENODEV); +} + +static int +machfb_load_state(video_adapter_t *adp, void *p) +{ + + return (ENODEV); +} + +static int +machfb_set_win_org(video_adapter_t *adp, off_t offset) +{ + + return (ENODEV); +} + +static int +machfb_read_hw_cursor(video_adapter_t *adp, int *col, int *row) +{ + + *col = 0; + *row = 0; + + return (0); +} + +static int +machfb_set_hw_cursor(video_adapter_t *adp, int col, int row) +{ + + return (ENODEV); +} + +static int +machfb_set_hw_cursor_shape(video_adapter_t *adp, int base, int height, + int celsize, int blink) +{ + + return (ENODEV); +} + +static int +machfb_blank_display(video_adapter_t *adp, int mode) +{ + struct machfb_softc *sc; + + 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); + + return (0); +} + +static int +machfb_mmap(video_adapter_t *adp, vm_offset_t offset, vm_paddr_t *paddr, + int prot) +{ + struct machfb_softc *sc; + + sc = (struct machfb_softc *)adp; + + if (adp->va_io_base != 0 && offset >= adp->va_io_base && + offset < adp->va_io_base + adp->va_io_size) { + *paddr = sc->sc_vioh + offset - adp->va_io_size; + return (0); + } + + if (adp->va_mem_base != 0 && offset >= adp->va_mem_base && + offset < adp->va_mem_base + adp->va_mem_size) { + *paddr = sc->sc_vmemh + offset - adp->va_mem_base; + return (0); + } + + if (offset >= adp->va_registers && + offset < adp->va_registers + adp->va_registers_size) { + *paddr = sc->sc_memh + offset - adp->va_registers; + return (0); + } + + /* 'regular' framebuffer mmap()ing */ + if (offset < adp->va_window_size) { + *paddr = adp->va_window + offset; + return (0); + } + + return (EINVAL); +} + +static int +machfb_ioctl(video_adapter_t *adp, u_long cmd, caddr_t data) +{ + struct machfb_softc *sc; + struct fbcursor *fbc; + struct fbtype *fb; + + sc = (struct machfb_softc *)adp; + + switch (cmd) { + case FBIOGTYPE: + fb = (struct fbtype *)data; + fb->fb_type = FBTYPE_PCIMISC; + fb->fb_height = sc->sc_height; + fb->fb_width = sc->sc_width; + fb->fb_depth = sc->sc_depth; + if (sc->sc_depth <= 1 || sc->sc_depth > 8) + fb->fb_cmsize = 0; + else + fb->fb_cmsize = 1 << sc->sc_depth; + fb->fb_size = adp->va_buffer_size; + break; + case FBIOSCURSOR: + fbc = (struct fbcursor *)data; + if (fbc->set & FB_CUR_SETCUR) { + if (fbc->enable == 0) { + machfb_cursor_enable(sc, 0); + sc->sc_flags &= ~MACHFB_CUREN; + } else + return (ENODEV); + } + break; + default: + return (fb_commonioctl(adp, cmd, data)); + } + + return (0); +} + +static int +machfb_clear(video_adapter_t *adp) +{ + + return (ENODEV); +} + +static int +machfb_fill_rect(video_adapter_t *adp, int val, int x, int y, int cx, int cy) +{ + struct machfb_softc *sc; + + sc = (struct machfb_softc *)adp; + + if (sc->sc_draw_cache != MACHFB_DRAW_FILLRECT) { + wait_for_fifo(sc, 7); + regw(sc, DP_WRITE_MASK, 0xff); + regw(sc, DP_PIX_WIDTH, DST_8BPP | SRC_8BPP | HOST_8BPP); + regw(sc, DP_SRC, FRGD_SRC_FRGD_CLR); + regw(sc, DP_MIX, MIX_SRC << 16); + regw(sc, CLR_CMP_CNTL, 0); /* no transparency */ + regw(sc, SRC_CNTL, SRC_LINE_X_LEFT_TO_RIGHT); + 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); + regw(sc, SRC_Y_X, (x << 16) | y); + regw(sc, SRC_WIDTH1, cx); + regw(sc, DST_Y_X, (x << 16) | y); + regw(sc, DST_HEIGHT_WIDTH, (cx << 16) | cy); + + return (0); +} + +static int +machfb_bitblt(video_adapter_t *adp, ...) +{ + + return (ENODEV); +} + +static int +machfb_diag(video_adapter_t *adp, int level) +{ + video_info_t info; + + fb_dump_adp_info(adp->va_name, adp, level); + machfb_get_info(adp, 0, &info); + fb_dump_mode_info(adp->va_name, adp, &info, level); + + return (0); +} + +static int +machfb_save_cursor_palette(video_adapter_t *adp, u_char *palette) +{ + + return (ENODEV); +} + +static int +machfb_load_cursor_palette(video_adapter_t *adp, u_char *palette) +{ + + return (ENODEV); +} + +static int +machfb_copy(video_adapter_t *adp, vm_offset_t src, vm_offset_t dst, int n) +{ + + return (ENODEV); +} + +static int +machfb_putp(video_adapter_t *adp, vm_offset_t off, uint32_t p, uint32_t a, + int size, int bpp, int bit_ltor, int byte_ltor) +{ + + return (ENODEV); +} + +static int +machfb_putc(video_adapter_t *adp, vm_offset_t off, uint8_t c, uint8_t a) +{ + struct machfb_softc *sc; + uint8_t *p; + int i; + + sc = (struct machfb_softc *)adp; + + if (sc->sc_draw_cache != MACHFB_DRAW_CHAR) { + wait_for_fifo(sc, 8); + regw(sc, DP_WRITE_MASK, 0xff); /* XXX only good for 8 bit */ + regw(sc, DP_PIX_WIDTH, DST_8BPP | SRC_1BPP | HOST_1BPP); + regw(sc, DP_SRC, MONO_SRC_HOST | BKGD_SRC_BKGD_CLR | + FRGD_SRC_FRGD_CLR); + regw(sc, DP_MIX ,((MIX_SRC & 0xffff) << 16) | MIX_SRC); + regw(sc, CLR_CMP_CNTL, 0); /* no transparency */ + regw(sc, SRC_CNTL, SRC_LINE_X_LEFT_TO_RIGHT); + regw(sc, DST_CNTL, DST_Y_TOP_TO_BOTTOM | DST_X_LEFT_TO_RIGHT); + 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); + 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) * + adp->va_info.vi_cwidth) + sc->sc_xmargin) << 16) | + (((off / adp->va_info.vi_width) * adp->va_info.vi_cheight) + + sc->sc_ymargin)); + regw(sc, DST_HEIGHT_WIDTH, (adp->va_info.vi_cwidth << 16) | + adp->va_info.vi_cheight); + 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])); + + return (0); +} + +static int +machfb_puts(video_adapter_t *adp, vm_offset_t off, uint16_t *s, int len) +{ + struct machfb_softc *sc; + int blanks, i, x1, x2, y1, y2; + uint8_t a, c, color1, color2; + + sc = (struct machfb_softc *)adp; + +#define MACHFB_BLANK machfb_fill_rect(adp, color1, x1, y1, \ + blanks * adp->va_info.vi_cwidth, \ + adp->va_info.vi_cheight) + + blanks = color1 = x1 = y1 = 0; + for (i = 0; i < len; i++) { + /* + * Accelerate continuous blanks by drawing a respective + * rectangle instead. Drawing a rectangle of any size + * takes about the same number of operations as drawing + * a single character. + */ + c = s[i] & 0xff; + a = (s[i] & 0xff00) >> 8; + if (c == 0x00 || c == 0x20 || c == 0xdb || c == 0xff) { + color2 = (a >> (c == 0xdb ? 0 : 4) & 0xf); + x2 = (((off + i) % adp->va_info.vi_width) * + adp->va_info.vi_cwidth) + sc->sc_xmargin; + y2 = (((off + i) / adp->va_info.vi_width) * + adp->va_info.vi_cheight) + sc->sc_ymargin; + if (blanks == 0) { + color1 = color2; + x1 = x2; + y1 = y2; + blanks++; + } else if (color1 != color2 || y1 != y2) { + MACHFB_BLANK; + color1 = color2; + x1 = x2; + y1 = y2; + blanks = 1; + } else + blanks++; + } else { + if (blanks != 0) { + MACHFB_BLANK; + blanks = 0; + } + (*vidsw[adp->va_index]->putc)(adp, off + i, c, a); + } + } + if (blanks != 0) + MACHFB_BLANK; + +#undef MACHFB_BLANK + + return (0); +} + +static int +machfb_putm(video_adapter_t *adp, int x, int y, uint8_t *pixel_image, + uint32_t pixel_mask, int size) +{ + struct machfb_softc *sc; + int error; + + sc = (struct machfb_softc *)adp; + + if ((!(sc->sc_flags & MACHFB_CUREN)) && + (error = machfb_cursor_install(sc)) < 0) + return (error); + else { + /* + * The hardware cursor always must be disabled when + * fiddling with its bits otherwise some artifacts + * may appear on the screen. + */ + machfb_cursor_enable(sc, 0); + } + + regw(sc, CUR_HORZ_VERT_OFF, 0); + if ((regr(sc, GEN_TEST_CNTL) & CRTC_DBL_SCAN_EN) != 0) + y <<= 1; + regw(sc, CUR_HORZ_VERT_POSN, ((y + sc->sc_ymargin) << 16) | + (x + sc->sc_xmargin)); + machfb_cursor_enable(sc, 1); + sc->sc_flags |= MACHFB_CUREN; + + return (0); +} + +/* + * PCI bus interface + */ +static int +machfb_pci_probe(device_t dev) +{ + int i; + + if (pci_get_class(dev) != PCIC_DISPLAY || + pci_get_subclass(dev) != PCIS_DISPLAY_VGA) + return (ENXIO); + + for (i = 0; i < sizeof(machfb_info) / sizeof(machfb_info[0]); i++) { + if (pci_get_device(dev) == machfb_info[i].chip_id) { + device_set_desc(dev, machfb_info[i].name); + return (BUS_PROBE_DEFAULT); + } + } + + return (ENXIO); +} + +static int +machfb_pci_attach(device_t dev) +{ + struct machfb_softc *sc; + video_adapter_t *adp; + video_switch_t *sw; + phandle_t node; + uint32_t *p32, saved_value; + uint8_t *p; + int error, i; + + node = ofw_bus_get_node(dev); + if ((sc = (struct machfb_softc *)vid_get_adapter(vid_find_adapter( + MACHFB_DRIVER_NAME, 0))) != NULL && sc->sc_node == node) { + device_printf(dev, "console\n"); + device_set_softc(dev, sc); + } else { + sc = device_get_softc(dev); + bzero(sc, sizeof(struct machfb_softc)); + + sc->sc_node = node; + sc->sc_chip_id = pci_get_device(dev); + sc->sc_chip_rev = pci_get_revid(dev); + } + adp = &sc->sc_va; + + /* + * Regardless whether we are the console and already allocated + * resources in machfb_configure() or not we have to allocate + * them here (again) in order for rman_get_virtual() to work. + */ + + /* Enable memory and IO access. */ + pci_write_config(dev, PCIR_COMMAND, + pci_read_config(dev, PCIR_COMMAND, 2) | PCIM_CMD_PORTEN | + PCIM_CMD_MEMEN, 2); + + sc->sc_memrid = PCIR_BAR(0); + if ((sc->sc_memres = bus_alloc_resource_any(dev, SYS_RES_MEMORY, + &sc->sc_memrid, RF_ACTIVE)) == NULL) { + device_printf(dev, "cannot allocate memory resources\n"); + return (ENXIO); + } + sc->sc_memt = rman_get_bustag(sc->sc_memres); + sc->sc_memh = rman_get_bushandle(sc->sc_memres); + adp->va_registers = rman_get_start(sc->sc_memres); + adp->va_registers_size = rman_get_size(sc->sc_memres); + sc->sc_regt = sc->sc_memt; + bus_space_subregion(sc->sc_regt, sc->sc_memh, MACH64_REG_OFF, + MACH64_REG_SIZE, &sc->sc_regh); + adp->va_buffer = (vm_offset_t)rman_get_virtual(sc->sc_memres); + adp->va_buffer_size = rman_get_size(sc->sc_memres); + + /* + * Depending on the firmware version the VGA I/O and/or memory + * resources of the Mach64 chips come up disabled. We generally + * enable them above (pci(4) actually already did this unless + * pci_enable_io_modes is not set) but this doesn't necessarily + * mean that we get valid ones. Invalid resources seem to have + * in common that they start at address 0. We don't allocate + * them in this case in order to avoid warnings in apb(4) and + * crashes when using these invalid resources. Xorg is aware + * of this and doesn't use the VGA resources in this case (but + * demands them if they are valid). + */ + sc->sc_viorid = PCIR_BAR(1); + if (bus_get_resource_start(dev, SYS_RES_IOPORT, sc->sc_viorid) != 0) { + if ((sc->sc_viores = bus_alloc_resource_any(dev, + SYS_RES_IOPORT, &sc->sc_viorid, RF_ACTIVE)) == NULL) { + device_printf(dev, + "cannot allocate VGA I/O resources\n"); + error = ENXIO; + goto fail_memres; + } + sc->sc_viot = rman_get_bustag(sc->sc_viores); + sc->sc_vioh = rman_get_bushandle(sc->sc_viores); + adp->va_io_base = rman_get_start(sc->sc_viores); + adp->va_io_size = rman_get_size(sc->sc_viores); + } + + sc->sc_vmemrid = PCIR_BAR(2); + if (bus_get_resource_start(dev, SYS_RES_MEMORY, sc->sc_vmemrid) != 0) { + if ((sc->sc_vmemres = bus_alloc_resource_any(dev, + SYS_RES_MEMORY, &sc->sc_vmemrid, RF_ACTIVE)) == NULL) { + device_printf(dev, + "cannot allocate VGA memory resources\n"); + error = ENXIO; + goto fail_viores; + } + sc->sc_vmemt = rman_get_bustag(sc->sc_vmemres); + sc->sc_vmemh = rman_get_bushandle(sc->sc_vmemres); + adp->va_mem_base = rman_get_start(sc->sc_vmemres); + adp->va_mem_size = rman_get_size(sc->sc_vmemres); + } + + device_printf(dev, + "%d MB aperture at 0x%08x, %d KB registers at 0x%08x\n", + (u_int)(adp->va_buffer_size / (1024 * 1024)), + (u_int)adp->va_buffer, MACH64_REG_SIZE / 1024, + (u_int)sc->sc_regh); + + if (!(sc->sc_flags & MACHFB_CONSOLE)) { + if ((sw = vid_get_switch(MACHFB_DRIVER_NAME)) == NULL) { + device_printf(dev, "cannot get video switch\n"); + error = ENODEV; + goto fail_vmemres; + } + /* + * During device configuration we don't necessarily probe + * the adapter which is the console first so we can't use + * the device unit number for the video adapter unit. The + * worst case would be that we use the video adapter unit + * 0 twice. As it doesn't really matter which unit number + * the corresponding video adapter has just use the next + * unused one. + */ + for (i = 0; i < devclass_get_maxunit(machfb_devclass); i++) + if (vid_find_adapter(MACHFB_DRIVER_NAME, i) < 0) + break; + if ((error = sw->init(i, adp, 0)) != 0) { + device_printf(dev, "cannot initialize adapter\n"); + goto fail_vmemres; + } + } + + device_printf(dev, + "%ld KB %s %d.%d MHz, maximum RAMDAC clock %d MHz, %sDSP\n", + (u_long)sc->sc_memsize, machfb_memtype_names[sc->sc_memtype], + sc->sc_mem_freq / 1000, sc->sc_mem_freq % 1000, + sc->sc_ramdac_freq / 1000, + (sc->sc_flags & MACHFB_DSP) ? "" : "no "); + device_printf(dev, "resolution %dx%d at %d bpp\n", + sc->sc_width, sc->sc_height, sc->sc_depth); + + /* + * Test whether the aperture is byte swapped or not, set + * va_window and va_window_size as appropriate. + */ + p32 = (uint32_t *)adp->va_buffer; + saved_value = *p32; + p = (uint8_t *)adp->va_buffer; + *p32 = 0x12345678; + if (!(p[0] == 0x12 && p[1] == 0x34 && p[2] == 0x56 && p[3] == 0x78)) { + adp->va_window = adp->va_buffer + 0x800000; + adp->va_window_size = adp->va_buffer_size - 0x800000; + } else { + adp->va_window = adp->va_buffer; + adp->va_window_size = adp->va_buffer_size; + } + *p32 = saved_value; + adp->va_window_gran = adp->va_window_size; + + /* + * Allocate one page for the mouse pointer image at the end of + * the little endian aperture, right before the memory mapped + * registers that might also reside there. Must be done after + * sc_memsize was set and possibly adjusted to account for the + * memory mapped registers. + */ + sc->sc_curoff = (sc->sc_memsize * 1024) - PAGE_SIZE; + sc->sc_memsize -= PAGE_SIZE / 1024; + machfb_cursor_enable(sc, 0); + /* Initialize with an all transparent image. */ + memset((void *)(adp->va_buffer + sc->sc_curoff), 0xaa, PAGE_SIZE); + + /* + * For cosmetics register a handler that turns off the mouse + * pointer on halt. Register a second handler that turns off + * the CRTC when resetting, otherwise the OFW boot command + * issued by cpu_reset() just doesn't work. + */ + EVENTHANDLER_REGISTER(shutdown_final, machfb_shutdown_final, sc, + SHUTDOWN_PRI_DEFAULT); + EVENTHANDLER_REGISTER(shutdown_reset, machfb_shutdown_reset, sc, + SHUTDOWN_PRI_DEFAULT); + + return (0); + + fail_vmemres: + if (sc->sc_vmemres != NULL) + bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_vmemrid, + sc->sc_vmemres); + fail_viores: + if (sc->sc_viores != NULL) + bus_release_resource(dev, SYS_RES_IOPORT, sc->sc_viorid, + sc->sc_viores); + fail_memres: + bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_memrid, sc->sc_memres); + + return (error); +} + +static int +machfb_pci_detach(device_t dev) +{ + + return (EINVAL); +} + +/* + * internal functions + */ +static void +machfb_cursor_enable(struct machfb_softc *sc, int onoff) +{ + + if (onoff) + regw(sc, GEN_TEST_CNTL, + regr(sc, GEN_TEST_CNTL) | HWCURSOR_ENABLE); + else + regw(sc, GEN_TEST_CNTL, + regr(sc, GEN_TEST_CNTL) &~ HWCURSOR_ENABLE); +} + +static int +machfb_cursor_install(struct machfb_softc *sc) +{ + uint16_t *p; + uint8_t fg; + int i, j; + + if (sc->sc_curoff == 0) + return (ENODEV); + + 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); + p = (uint16_t *)(sc->sc_va.va_buffer + sc->sc_curoff); + for (i = 0; i < 64; i++) + for (j = 0; j < 8; j++) + *(p++) = machfb_mouse_pointer_lut[ + machfb_mouse_pointer_bits[i][j] >> 4] | + machfb_mouse_pointer_lut[ + machfb_mouse_pointer_bits[i][j] & 0x0f] << 8; + + return (0); +} + +static int +machfb_get_memsize(struct machfb_softc *sc) +{ + int tmp, memsize; + int mem_tab[] = { + 512, 1024, 2048, 4096, 6144, 8192, 12288, 16384 + }; + + tmp = regr(sc, MEM_CNTL); +#ifdef MACHFB_DEBUG + printf("memcntl=0x%08x\n", tmp); +#endif + if (sc->sc_flags & MACHFB_DSP) { + tmp &= 0x0000000f; + if (tmp < 8) + memsize = (tmp + 1) * 512; + else if (tmp < 12) + memsize = (tmp - 3) * 1024; + else + memsize = (tmp - 7) * 2048; + } else + memsize = mem_tab[tmp & 0x07]; + + return (memsize); +} + +static void +machfb_reset_engine(struct machfb_softc *sc) +{ + + /* Reset engine.*/ + regw(sc, GEN_TEST_CNTL, regr(sc, GEN_TEST_CNTL) & ~GUI_ENGINE_ENABLE); + + /* Enable engine. */ + regw(sc, GEN_TEST_CNTL, regr(sc, GEN_TEST_CNTL) | GUI_ENGINE_ENABLE); + + /* + * Ensure engine is not locked up by clearing any FIFO or + * host errors. + */ + regw(sc, BUS_CNTL, regr(sc, BUS_CNTL) | BUS_HOST_ERR_ACK | + BUS_FIFO_ERR_ACK); +} + +static void +machfb_init_engine(struct machfb_softc *sc) +{ + uint32_t pitch_value; + + pitch_value = sc->sc_width; + + if (sc->sc_depth == 24) + pitch_value *= 3; + + machfb_reset_engine(sc); + + wait_for_fifo(sc, 14); + + regw(sc, CONTEXT_MASK, 0xffffffff); + + regw(sc, DST_OFF_PITCH, (pitch_value / 8) << 22); + + regw(sc, DST_Y_X, 0); + regw(sc, DST_HEIGHT, 0); + regw(sc, DST_BRES_ERR, 0); + regw(sc, DST_BRES_INC, 0); + regw(sc, DST_BRES_DEC, 0); + + regw(sc, DST_CNTL, DST_LAST_PEL | DST_X_LEFT_TO_RIGHT | + DST_Y_TOP_TO_BOTTOM); + + regw(sc, SRC_OFF_PITCH, (pitch_value / 8) << 22); + + regw(sc, SRC_Y_X, 0); + regw(sc, SRC_HEIGHT1_WIDTH1, 1); + regw(sc, SRC_Y_X_START, 0); + regw(sc, SRC_HEIGHT2_WIDTH2, 1); + + regw(sc, SRC_CNTL, SRC_LINE_X_LEFT_TO_RIGHT); + + wait_for_fifo(sc, 13); + regw(sc, HOST_CNTL, 0); + + regw(sc, PAT_REG0, 0); + regw(sc, PAT_REG1, 0); + regw(sc, PAT_CNTL, 0); + + regw(sc, SC_LEFT, 0); + regw(sc, SC_TOP, 0); + regw(sc, SC_BOTTOM, sc->sc_height - 1); + regw(sc, SC_RIGHT, pitch_value - 1); + + regw(sc, DP_BKGD_CLR, 0); + regw(sc, DP_FRGD_CLR, 0xffffffff); + regw(sc, DP_WRITE_MASK, 0xffffffff); + regw(sc, DP_MIX, (MIX_SRC << 16) | MIX_DST); + + regw(sc, DP_SRC, FRGD_SRC_FRGD_CLR); + + wait_for_fifo(sc, 3); + regw(sc, CLR_CMP_CLR, 0); + regw(sc, CLR_CMP_MASK, 0xffffffff); + regw(sc, CLR_CMP_CNTL, 0); + + wait_for_fifo(sc, 2); + switch (sc->sc_depth) { + case 8: + regw(sc, DP_PIX_WIDTH, HOST_8BPP | SRC_8BPP | DST_8BPP); + regw(sc, DP_CHAIN_MASK, DP_CHAIN_8BPP); + regw(sc, DAC_CNTL, regr(sc, DAC_CNTL) | DAC_8BIT_EN); + break; +#if 0 + case 32: + regw(sc, DP_PIX_WIDTH, HOST_32BPP | SRC_32BPP | DST_32BPP); + regw(sc, DP_CHAIN_MASK, DP_CHAIN_32BPP); + regw(sc, DAC_CNTL, regr(sc, DAC_CNTL) | DAC_8BIT_EN); + break; +#endif + } + + wait_for_fifo(sc, 5); + 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); + + wait_for_idle(sc); +} + +#if 0 +static void +machfb_adjust_frame(struct machfb_softc *sc, int x, int y) +{ + int offset; + + offset = ((x + y * sc->sc_width) * (sc->sc_depth >> 3)) >> 3; + + regw(sc, CRTC_OFF_PITCH, (regr(sc, CRTC_OFF_PITCH) & 0xfff00000) | + offset); +} +#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; + + machfb_cursor_enable(sc, 0); +} + +static void +machfb_shutdown_reset(void *v) +{ + struct machfb_softc *sc = v; + + machfb_blank_display(&sc->sc_va, V_DISPLAY_STAND_BY); +} diff --git a/sys/dev/fb/machfbreg.h b/sys/dev/fb/machfbreg.h new file mode 100644 index 000000000000..8990a4e3993a --- /dev/null +++ b/sys/dev/fb/machfbreg.h @@ -0,0 +1,458 @@ +/*- + * Copyright 1992,1993,1994,1995,1996,1997 by Kevin E. Martin, Chapel Hill, North Carolina. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of Kevin E. Martin not be + * used in advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. Kevin E. Martin + * makes no representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * KEVIN E. MARTIN, RICKARD E. FAITH, AND TIAGO GONS DISCLAIM ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE + * AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR + * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, + * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + * + * Modified for the Mach-8 by Rickard E. Faith (faith@cs.unc.edu) + * Modified for the Mach32 by Kevin E. Martin (martin@cs.unc.edu) + * Modified for the Mach64 by Kevin E. Martin (martin@cs.unc.edu) + * + * from: NetBSD: machfbreg.h,v 1.1 2002/10/24 18:15:57 junyoung Exp + * + * $FreeBSD$ + */ + +#ifndef _DEV_FB_MACHFB_H_ +#define _DEV_FB_MACHFB_H_ + +/* NON-GUI MEMORY MAPPED Registers - expressed in BYTE offsets */ + +#define CRTC_H_TOTAL_DISP 0x0000 /* Dword offset 00 */ +#define CRTC_H_SYNC_STRT_WID 0x0004 /* Dword offset 01 */ +#define CRTC_V_TOTAL_DISP 0x0008 /* Dword offset 02 */ +#define CRTC_V_SYNC_STRT_WID 0x000C /* Dword offset 03 */ +#define CRTC_VLINE_CRNT_VLINE 0x0010 /* Dword offset 04 */ +#define CRTC_OFF_PITCH 0x0014 /* Dword offset 05 */ +#define CRTC_INT_CNTL 0x0018 /* Dword offset 06 */ +#define CRTC_GEN_CNTL 0x001C /* Dword offset 07 */ + +#define DSP_CONFIG 0x0020 /* Dword offset 08 */ +#define DSP_ON_OFF 0x0024 /* Dword offset 09 */ + +#define SHARED_CNTL 0x0038 /* Dword offset 0E */ + +#define OVR_CLR 0x0040 /* Dword offset 10 */ +#define OVR_WID_LEFT_RIGHT 0x0044 /* Dword offset 11 */ +#define OVR_WID_TOP_BOTTOM 0x0048 /* Dword offset 12 */ + +#define CUR_CLR0 0x0060 /* Dword offset 18 */ +#define CUR_CLR1 0x0064 /* Dword offset 19 */ +#define CUR_OFFSET 0x0068 /* Dword offset 1A */ +#define CUR_HORZ_VERT_POSN 0x006C /* Dword offset 1B */ +#define CUR_HORZ_VERT_OFF 0x0070 /* Dword offset 1C */ + +#define HW_DEBUG 0x007C /* Dword offset 1F */ + +#define SCRATCH_REG0 0x0080 /* Dword offset 20 */ +#define SCRATCH_REG1 0x0084 /* Dword offset 21 */ + +#define CLOCK_CNTL 0x0090 /* Dword offset 24 */ + +#define BUS_CNTL 0x00A0 /* Dword offset 28 */ + +#define LCD_INDEX 0x00A4 /* Dword offset 29 (LTPro) */ +#define LCD_DATA 0x00A8 /* Dword offset 2A (LTPro) */ + +#define MEM_CNTL 0x00B0 /* Dword offset 2C */ + +#define MEM_VGA_WP_SEL 0x00B4 /* Dword offset 2D */ +#define MEM_VGA_RP_SEL 0x00B8 /* Dword offset 2E */ + +#define DAC_REGS 0x00C0 /* Dword offset 30 */ +#define DAC_WINDEX 0x00C0 /* Dword offset 30 */ +#define DAC_DATA 0x00C1 /* Dword offset 30 */ +#define DAC_MASK 0x00C2 /* Dword offset 30 */ +#define DAC_RINDEX 0x00C3 /* Dword offset 30 */ +#define DAC_CNTL 0x00C4 /* Dword offset 31 */ + +#define HORZ_STRETCHING 0x00C8 /* Dword offset 32 (LT) */ +#define VERT_STRETCHING 0x00CC /* Dword offset 33 (LT) */ + +#define GEN_TEST_CNTL 0x00D0 /* Dword offset 34 */ + +#define LCD_GEN_CNTL 0x00D4 /* Dword offset 35 (LT) */ +#define POWER_MANAGEMENT 0x00D8 /* Dword offset 36 (LT) */ + +#define CONFIG_CNTL 0x00DC /* Dword offset 37 (CT, ET, VT) */ +#define CONFIG_CHIP_ID 0x00E0 /* Dword offset 38 */ +#define CONFIG_STAT0 0x00E4 /* Dword offset 39 */ +#define CONFIG_STAT1 0x00E8 /* Dword offset 3A */ + + +/* GUI MEMORY MAPPED Registers */ + +#define DST_OFF_PITCH 0x0100 /* Dword offset 40 */ +#define DST_X 0x0104 /* Dword offset 41 */ +#define DST_Y 0x0108 /* Dword offset 42 */ +#define DST_Y_X 0x010C /* Dword offset 43 */ +#define DST_WIDTH 0x0110 /* Dword offset 44 */ +#define DST_HEIGHT 0x0114 /* Dword offset 45 */ +#define DST_HEIGHT_WIDTH 0x0118 /* Dword offset 46 */ +#define DST_X_WIDTH 0x011C /* Dword offset 47 */ +#define DST_BRES_LNTH 0x0120 /* Dword offset 48 */ +#define DST_BRES_ERR 0x0124 /* Dword offset 49 */ +#define DST_BRES_INC 0x0128 /* Dword offset 4A */ +#define DST_BRES_DEC 0x012C /* Dword offset 4B */ +#define DST_CNTL 0x0130 /* Dword offset 4C */ + +#define SRC_OFF_PITCH 0x0180 /* Dword offset 60 */ +#define SRC_X 0x0184 /* Dword offset 61 */ +#define SRC_Y 0x0188 /* Dword offset 62 */ +#define SRC_Y_X 0x018C /* Dword offset 63 */ +#define SRC_WIDTH1 0x0190 /* Dword offset 64 */ +#define SRC_HEIGHT1 0x0194 /* Dword offset 65 */ +#define SRC_HEIGHT1_WIDTH1 0x0198 /* Dword offset 66 */ +#define SRC_X_START 0x019C /* Dword offset 67 */ +#define SRC_Y_START 0x01A0 /* Dword offset 68 */ +#define SRC_Y_X_START 0x01A4 /* Dword offset 69 */ +#define SRC_WIDTH2 0x01A8 /* Dword offset 6A */ +#define SRC_HEIGHT2 0x01AC /* Dword offset 6B */ +#define SRC_HEIGHT2_WIDTH2 0x01B0 /* Dword offset 6C */ +#define SRC_CNTL 0x01B4 /* Dword offset 6D */ + +#define HOST_DATA0 0x0200 /* Dword offset 80 */ +#define HOST_DATA1 0x0204 /* Dword offset 81 */ +#define HOST_DATA2 0x0208 /* Dword offset 82 */ +#define HOST_DATA3 0x020C /* Dword offset 83 */ +#define HOST_DATA4 0x0210 /* Dword offset 84 */ +#define HOST_DATA5 0x0214 /* Dword offset 85 */ +#define HOST_DATA6 0x0218 /* Dword offset 86 */ +#define HOST_DATA7 0x021C /* Dword offset 87 */ +#define HOST_DATA8 0x0220 /* Dword offset 88 */ +#define HOST_DATA9 0x0224 /* Dword offset 89 */ +#define HOST_DATAA 0x0228 /* Dword offset 8A */ +#define HOST_DATAB 0x022C /* Dword offset 8B */ +#define HOST_DATAC 0x0230 /* Dword offset 8C */ +#define HOST_DATAD 0x0234 /* Dword offset 8D */ +#define HOST_DATAE 0x0238 /* Dword offset 8E */ +#define HOST_DATAF 0x023C /* Dword offset 8F */ +#define HOST_CNTL 0x0240 /* Dword offset 90 */ + +#define PAT_REG0 0x0280 /* Dword offset A0 */ +#define PAT_REG1 0x0284 /* Dword offset A1 */ +#define PAT_CNTL 0x0288 /* Dword offset A2 */ + +#define SC_LEFT 0x02A0 /* Dword offset A8 */ +#define SC_RIGHT 0x02A4 /* Dword offset A9 */ +#define SC_LEFT_RIGHT 0x02A8 /* Dword offset AA */ +#define SC_TOP 0x02AC /* Dword offset AB */ +#define SC_BOTTOM 0x02B0 /* Dword offset AC */ +#define SC_TOP_BOTTOM 0x02B4 /* Dword offset AD */ + +#define DP_BKGD_CLR 0x02C0 /* Dword offset B0 */ +#define DP_FRGD_CLR 0x02C4 /* Dword offset B1 */ +#define DP_WRITE_MASK 0x02C8 /* Dword offset B2 */ +#define DP_CHAIN_MASK 0x02CC /* Dword offset B3 */ +#define DP_PIX_WIDTH 0x02D0 /* Dword offset B4 */ +#define DP_MIX 0x02D4 /* Dword offset B5 */ +#define DP_SRC 0x02D8 /* Dword offset B6 */ + +#define CLR_CMP_CLR 0x0300 /* Dword offset C0 */ +#define CLR_CMP_MASK 0x0304 /* Dword offset C1 */ +#define CLR_CMP_CNTL 0x0308 /* Dword offset C2 */ + +#define FIFO_STAT 0x0310 /* Dword offset C4 */ + +#define CONTEXT_MASK 0x0320 /* Dword offset C8 */ +#define CONTEXT_LOAD_CNTL 0x032C /* Dword offset CB */ + +#define GUI_TRAJ_CNTL 0x0330 /* Dword offset CC */ +#define GUI_STAT 0x0338 /* Dword offset CE */ + + +/* CRTC control values */ + +#define CRTC_HSYNC_NEG 0x00200000 +#define CRTC_VSYNC_NEG 0x00200000 + +#define CRTC_DBL_SCAN_EN 0x00000001 +#define CRTC_INTERLACE_EN 0x00000002 +#define CRTC_HSYNC_DIS 0x00000004 +#define CRTC_VSYNC_DIS 0x00000008 +#define CRTC_CSYNC_EN 0x00000010 +#define CRTC_PIX_BY_2_EN 0x00000020 +#define CRTC_DISPLAY_DIS 0x00000040 +#define CRTC_VGA_XOVERSCAN 0x00000080 + +#define CRTC_PIX_WIDTH 0x00000700 +#define CRTC_PIX_WIDTH_4BPP 0x00000100 +#define CRTC_PIX_WIDTH_8BPP 0x00000200 +#define CRTC_PIX_WIDTH_15BPP 0x00000300 +#define CRTC_PIX_WIDTH_16BPP 0x00000400 +#define CRTC_PIX_WIDTH_24BPP 0x00000500 +#define CRTC_PIX_WIDTH_32BPP 0x00000600 + +#define CRTC_BYTE_PIX_ORDER 0x00000800 +#define CRTC_PIX_ORDER_MSN_LSN 0x00000000 +#define CRTC_PIX_ORDER_LSN_MSN 0x00000800 + +#define CRTC_FIFO_LWM 0x000f0000 +#define CRTC_LOCK_REGS 0x00400000 +#define CRTC_EXT_DISP_EN 0x01000000 +#define CRTC_EN 0x02000000 +#define CRTC_DISP_REQ_EN 0x04000000 +#define CRTC_VGA_LINEAR 0x08000000 +#define CRTC_VSYNC_FALL_EDGE 0x10000000 +#define CRTC_VGA_TEXT_132 0x20000000 +#define CRTC_CNT_EN 0x40000000 +#define CRTC_CUR_B_TEST 0x80000000 + +#define CRTC_CRNT_VLINE 0x07f00000 +#define CRTC_VBLANK 0x00000001 + +/* DAC control values */ + +#define DAC_EXT_SEL_RS2 0x01 +#define DAC_EXT_SEL_RS3 0x02 +#define DAC_8BIT_EN 0x00000100 +#define DAC_PIX_DLY_MASK 0x00000600 +#define DAC_PIX_DLY_0NS 0x00000000 +#define DAC_PIX_DLY_2NS 0x00000200 +#define DAC_PIX_DLY_4NS 0x00000400 +#define DAC_BLANK_ADJ_MASK 0x00001800 +#define DAC_BLANK_ADJ_0 0x00000000 +#define DAC_BLANK_ADJ_1 0x00000800 +#define DAC_BLANK_ADJ_2 0x00001000 + + +/* Mix control values */ + +#define MIX_NOT_DST 0x0000 +#define MIX_0 0x0001 +#define MIX_1 0x0002 +#define MIX_DST 0x0003 +#define MIX_NOT_SRC 0x0004 +#define MIX_XOR 0x0005 +#define MIX_XNOR 0x0006 +#define MIX_SRC 0x0007 +#define MIX_NAND 0x0008 +#define MIX_NOT_SRC_OR_DST 0x0009 +#define MIX_SRC_OR_NOT_DST 0x000a +#define MIX_OR 0x000b +#define MIX_AND 0x000c +#define MIX_SRC_AND_NOT_DST 0x000d +#define MIX_NOT_SRC_AND_DST 0x000e +#define MIX_NOR 0x000f + +/* Maximum engine dimensions */ +#define ENGINE_MIN_X 0 +#define ENGINE_MIN_Y 0 +#define ENGINE_MAX_X 4095 +#define ENGINE_MAX_Y 16383 + +/* Mach64 engine bit constants - these are typically ORed together */ + +/* HW_DEBUG register constants */ +/* For RagePro only... */ +#define AUTO_FF_DIS 0x000001000 +#define AUTO_BLKWRT_DIS 0x000002000 + +/* BUS_CNTL register constants */ +#define BUS_FIFO_ERR_ACK 0x00200000 +#define BUS_HOST_ERR_ACK 0x00800000 +#define BUS_APER_REG_DIS 0x00000010 + +/* GEN_TEST_CNTL register constants */ +#define GEN_OVR_OUTPUT_EN 0x20 +#define HWCURSOR_ENABLE 0x80 +#define GUI_ENGINE_ENABLE 0x100 +#define BLOCK_WRITE_ENABLE 0x200 + +/* DSP_CONFIG register constants */ +#define DSP_XCLKS_PER_QW 0x00003fff +#define DSP_LOOP_LATENCY 0x000f0000 +#define DSP_PRECISION 0x00700000 + +/* DSP_ON_OFF register constants */ +#define DSP_OFF 0x000007ff +#define DSP_ON 0x07ff0000 + +/* SHARED_CNTL register constants */ +#define CTD_FIFO5 0x01000000 + +/* CLOCK_CNTL register constants */ +#define CLOCK_SEL 0x0f +#define CLOCK_DIV 0x30 +#define CLOCK_DIV1 0x00 +#define CLOCK_DIV2 0x10 +#define CLOCK_DIV4 0x20 +#define CLOCK_STROBE 0x40 +#define PLL_WR_EN 0x02 + +/* PLL registers */ +#define PLL_MACRO_CNTL 0x01 +#define PLL_REF_DIV 0x02 +#define PLL_GEN_CNTL 0x03 +#define MCLK_FB_DIV 0x04 +#define PLL_VCLK_CNTL 0x05 +#define VCLK_POST_DIV 0x06 +#define VCLK0_FB_DIV 0x07 +#define VCLK1_FB_DIV 0x08 +#define VCLK2_FB_DIV 0x09 +#define VCLK3_FB_DIV 0x0A +#define PLL_XCLK_CNTL 0x0B +#define PLL_TEST_CTRL 0x0E +#define PLL_TEST_COUNT 0x0F + +/* Memory types for CT, ET, VT, GT */ +#define DRAM 1 +#define EDO_DRAM 2 +#define PSEUDO_EDO 3 +#define SDRAM 4 +#define SGRAM 5 +#define SGRAM32 6 + +#define DAC_INTERNAL 0x00 +#define DAC_IBMRGB514 0x01 +#define DAC_ATI68875 0x02 +#define DAC_TVP3026_A 0x72 +#define DAC_BT476 0x03 +#define DAC_BT481 0x04 +#define DAC_ATT20C491 0x14 +#define DAC_SC15026 0x24 +#define DAC_MU9C1880 0x34 +#define DAC_IMSG174 0x44 +#define DAC_ATI68860_B 0x05 +#define DAC_ATI68860_C 0x15 +#define DAC_TVP3026_B 0x75 +#define DAC_STG1700 0x06 +#define DAC_ATT498 0x16 +#define DAC_STG1702 0x07 +#define DAC_SC15021 0x17 +#define DAC_ATT21C498 0x27 +#define DAC_STG1703 0x37 +#define DAC_CH8398 0x47 +#define DAC_ATT20C408 0x57 + +#define CLK_ATI18818_0 0 +#define CLK_ATI18818_1 1 +#define CLK_STG1703 2 +#define CLK_CH8398 3 +#define CLK_INTERNAL 4 +#define CLK_ATT20C408 5 +#define CLK_IBMRGB514 6 + +/* DST_CNTL register constants */ +#define DST_X_RIGHT_TO_LEFT 0 +#define DST_X_LEFT_TO_RIGHT 1 +#define DST_Y_BOTTOM_TO_TOP 0 +#define DST_Y_TOP_TO_BOTTOM 2 +#define DST_X_MAJOR 0 +#define DST_Y_MAJOR 4 +#define DST_X_TILE 8 +#define DST_Y_TILE 0x10 +#define DST_LAST_PEL 0x20 +#define DST_POLYGON_ENABLE 0x40 +#define DST_24_ROTATION_ENABLE 0x80 + +/* SRC_CNTL register constants */ +#define SRC_PATTERN_ENABLE 1 +#define SRC_ROTATION_ENABLE 2 +#define SRC_LINEAR_ENABLE 4 +#define SRC_BYTE_ALIGN 8 +#define SRC_LINE_X_RIGHT_TO_LEFT 0 +#define SRC_LINE_X_LEFT_TO_RIGHT 0x10 + +/* HOST_CNTL register constants */ +#define HOST_BYTE_ALIGN 1 + +/* DP_CHAIN_MASK register constants */ +#define DP_CHAIN_4BPP 0x8888 +#define DP_CHAIN_7BPP 0xD2D2 +#define DP_CHAIN_8BPP 0x8080 +#define DP_CHAIN_8BPP_RGB 0x9292 +#define DP_CHAIN_15BPP 0x4210 +#define DP_CHAIN_16BPP 0x8410 +#define DP_CHAIN_24BPP 0x8080 +#define DP_CHAIN_32BPP 0x8080 + +/* DP_PIX_WIDTH register constants */ +#define DST_1BPP 0 +#define DST_4BPP 1 +#define DST_8BPP 2 +#define DST_15BPP 3 +#define DST_16BPP 4 +#define DST_32BPP 6 +#define SRC_1BPP 0 +#define SRC_4BPP 0x100 +#define SRC_8BPP 0x200 +#define SRC_15BPP 0x300 +#define SRC_16BPP 0x400 +#define SRC_32BPP 0x600 +#define HOST_1BPP 0 +#define HOST_4BPP 0x10000 +#define HOST_8BPP 0x20000 +#define HOST_15BPP 0x30000 +#define HOST_16BPP 0x40000 +#define HOST_32BPP 0x60000 +#define BYTE_ORDER_MSB_TO_LSB 0 +#define BYTE_ORDER_LSB_TO_MSB 0x1000000 + +/* DP_SRC register constants */ +#define BKGD_SRC_BKGD_CLR 0 +#define BKGD_SRC_FRGD_CLR 1 +#define BKGD_SRC_HOST 2 +#define BKGD_SRC_BLIT 3 +#define BKGD_SRC_PATTERN 4 +#define FRGD_SRC_BKGD_CLR 0 +#define FRGD_SRC_FRGD_CLR 0x100 +#define FRGD_SRC_HOST 0x200 +#define FRGD_SRC_BLIT 0x300 +#define FRGD_SRC_PATTERN 0x400 +#define MONO_SRC_ONE 0 +#define MONO_SRC_PATTERN 0x10000 +#define MONO_SRC_HOST 0x20000 +#define MONO_SRC_BLIT 0x30000 + +/* PCI IDs */ +#define ATI_VENDOR 0x1002 +#define ATI_MACH64_CT 0x4354 /* Mach64 CT */ +#define ATI_RAGE_PRO_AGP 0x4742 /* 3D Rage Pro (AGP) */ +#define ATI_RAGE_PRO_AGP1X 0x4744 /* 3D Rage Pro (AGP 1x) */ +#define ATI_RAGE_PRO_PCI_B 0x4749 /* 3D Rage Pro Turbo */ +#define ATI_RAGE_XC_PCI66 0x474c /* Rage XC (PCI66) */ +#define ATI_RAGE_XL_AGP 0x474d /* Rage XL (AGP) */ +#define ATI_RAGE_XC_AGP 0x474e /* Rage XC (AGP) */ +#define ATI_RAGE_XL_PCI66 0x474f /* Rage XL (PCI66) */ +#define ATI_RAGE_PRO_PCI_P 0x4750 /* 3D Rage Pro */ +#define ATI_RAGE_PRO_PCI_L 0x4751 /* 3D Rage Pro (limited 3D) */ +#define ATI_RAGE_XL_PCI 0x4752 /* Rage XL */ +#define ATI_RAGE_XC_PCI 0x4753 /* Rage XC */ +#define ATI_RAGE_II 0x4754 /* 3D Rage I/II */ +#define ATI_RAGE_IIP 0x4755 /* 3D Rage II+ */ +#define ATI_RAGE_IIC_PCI 0x4756 /* 3D Rage IIC */ +#define ATI_RAGE_IIC_AGP_B 0x4757 /* 3D Rage IIC (AGP) */ +#define ATI_RAGE_IIC_AGP_P 0x475a /* 3D Rage IIC (AGP) */ +#define ATI_RAGE_LT_PRO_AGP 0x4c42 /* 3D Rage LT Pro (AGP 133MHz) */ +#define ATI_RAGE_MOB_M3_PCI 0x4c45 /* Rage Mobility M3 */ +#define ATI_RAGE_MOB_M3_AGP 0x4c46 /* Rage Mobility M3 (AGP) */ +#define ATI_RAGE_LT 0x4c47 /* 3D Rage LT */ +#define ATI_RAGE_LT_PRO_PCI 0x4c49 /* 3D Rage LT Pro */ +#define ATI_RAGE_MOBILITY 0x4c4d /* Rage Mobility */ +#define ATI_RAGE_L_MOBILITY 0x4c4e /* Rage L Mobility */ +#define ATI_RAGE_LT_PRO 0x4c50 /* 3D Rage LT Pro */ +#define ATI_RAGE_LT_PRO2 0x4c51 /* 3D Rage LT Pro */ +#define ATI_RAGE_MOB_M1_PCI 0x4c52 /* Rage Mobility M1 (PCI) */ +#define ATI_RAGE_L_MOB_M1_PCI 0x4c53 /* Rage L Mobility (PCI) */ +#define ATI_MACH64_VT 0x5654 /* Mach64 VT */ +#define ATI_MACH64_VTB 0x5655 /* Mach64 VTB */ +#define ATI_MACH64_VT4 0x5656 /* Mach64 VT4 */ + +#endif /* !_DEV_FB_MACHFB_H_ */