diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2010-08-27 12:48:55 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2010-08-27 12:48:55 +0000 |
commit | fbe234cad3c8ce40c1e0b5a682ed155282e533ae (patch) | |
tree | ea45a174792cb161348c0198a1a5e028b509b938 /sys/arch/loongson/dev | |
parent | 5719511d3db175875d06d611a135165cf71c3455 (diff) |
screen blanking code for SM502, and some smfb code cleanup.
Diffstat (limited to 'sys/arch/loongson/dev')
-rw-r--r-- | sys/arch/loongson/dev/smfb.c | 196 | ||||
-rw-r--r-- | sys/arch/loongson/dev/smfbreg.h | 4 | ||||
-rw-r--r-- | sys/arch/loongson/dev/voyagerreg.h | 91 |
3 files changed, 185 insertions, 106 deletions
diff --git a/sys/arch/loongson/dev/smfb.c b/sys/arch/loongson/dev/smfb.c index 0580fa6e875..1547bd4483d 100644 --- a/sys/arch/loongson/dev/smfb.c +++ b/sys/arch/loongson/dev/smfb.c @@ -1,4 +1,4 @@ -/* $OpenBSD: smfb.c,v 1.8 2010/08/26 18:57:14 miod Exp $ */ +/* $OpenBSD: smfb.c,v 1.9 2010/08/27 12:48:54 miod Exp $ */ /* * Copyright (c) 2009, 2010 Miodrag Vallat. @@ -17,7 +17,10 @@ */ /* - * Minimal SiliconMotion SM502 and SM712 frame buffer driver. + * SiliconMotion SM502 and SM712 frame buffer driver. + * + * Assumes its video output is an LCD panel, in 5:6:5 mode, and fixed + * 1024x600 resolution. */ #include <sys/param.h> @@ -43,12 +46,6 @@ #include <loongson/dev/voyagervar.h> #include <loongson/dev/smfbreg.h> -#define DPR_READ(fb, reg) (fb)->dpr[(reg) / 4] -#define DPR_WRITE(fb, reg, val) (fb)->dpr[(reg) / 4] = (val) - -#define REG_READ(fb, reg) (fb)->regs[(reg) / 4] -#define REG_WRITE(fb, reg, val) (fb)->regs[(reg) / 4] = (val) - struct smfb_softc; /* minimal frame buffer information, suitable for early console */ @@ -57,23 +54,33 @@ struct smfb { struct rasops_info ri; int is5xx; - volatile uint32_t *regs; - volatile uint32_t *dpr; - volatile uint8_t *mmio; + /* DPR registers */ + bus_space_tag_t dprt; + bus_space_handle_t dprh; + /* MMIO space (SM7xx) or control registers (SM5xx) */ + bus_space_tag_t mmiot; + bus_space_handle_t mmioh; + /* DCR registers (SM5xx) */ + bus_space_tag_t dcrt; + bus_space_handle_t dcrh; + struct wsscreen_descr wsd; }; +#define DCR_READ(fb, reg) \ + bus_space_read_4((fb)->dcrt, (fb)->dcrh, (reg)) +#define DCR_WRITE(fb, reg, val) \ + bus_space_write_4((fb)->dcrt, (fb)->dcrh, (reg), (val)) +#define DPR_READ(fb, reg) \ + bus_space_read_4((fb)->dprt, (fb)->dprh, (reg)) +#define DPR_WRITE(fb, reg, val) \ + bus_space_write_4((fb)->dprt, (fb)->dprh, (reg), (val)) + struct smfb_softc { struct device sc_dev; struct smfb *sc_fb; struct smfb sc_fb_store; - bus_space_tag_t sc_memt; - bus_space_handle_t sc_memh; - - bus_space_tag_t sc_regt; - bus_space_handle_t sc_regh; - struct wsscreen_list sc_wsl; struct wsscreen_descr *sc_scrlist[1]; int sc_nscr; @@ -117,7 +124,8 @@ struct wsdisplay_accessops smfb_accessops = { smfb_burner }; -int smfb_setup(struct smfb *, vaddr_t, vaddr_t); +int smfb_setup(struct smfb *, bus_space_tag_t, bus_space_handle_t, + bus_space_tag_t, bus_space_handle_t); void smfb_copyrect(struct smfb *, int, int, int, int, int, int); void smfb_fillrect(struct smfb *, int, int, int, int, int); @@ -128,10 +136,12 @@ int smfb_erasecols(void *, int, int, int, long); int smfb_eraserows(void *, int, int, long); int smfb_wait(struct smfb *); -uint8_t smfb_mmio_read(struct smfb *, uint); -void smfb_mmio_write(struct smfb *, uint, uint8_t); +void smfb_wait_panel_vsync(struct smfb *, int); +uint8_t smfb_vgats_read(struct smfb *, uint); +void smfb_vgats_write(struct smfb *, uint, uint8_t); -void smfb_attach_common(struct smfb_softc *, int); +void smfb_attach_common(struct smfb_softc *, int, bus_space_tag_t, + bus_space_handle_t, bus_space_tag_t, bus_space_handle_t); static struct smfb smfbcn; @@ -161,15 +171,16 @@ smfb_pci_attach(struct device *parent, struct device *self, void *aux) { struct smfb_softc *sc = (struct smfb_softc *)self; struct pci_attach_args *pa = (struct pci_attach_args *)aux; + bus_space_tag_t memt; + bus_space_handle_t memh; if (pci_mapreg_map(pa, PCI_MAPREG_START, PCI_MAPREG_TYPE_MEM, - BUS_SPACE_MAP_LINEAR, &sc->sc_memt, &sc->sc_memh, - NULL, NULL, 0) != 0) { + BUS_SPACE_MAP_LINEAR, &memt, &memh, NULL, NULL, 0) != 0) { printf(": can't map frame buffer\n"); return; } - smfb_attach_common(sc, 0); + smfb_attach_common(sc, 0, memt, memh, memt, memh); } void @@ -178,19 +189,15 @@ smfb_voyager_attach(struct device *parent, struct device *self, void *aux) struct smfb_softc *sc = (struct smfb_softc *)self; struct voyager_attach_args *vaa = (struct voyager_attach_args *)aux; - sc->sc_memt = vaa->vaa_fbt; - sc->sc_memh = vaa->vaa_fbh; - sc->sc_regt = vaa->vaa_mmiot; - sc->sc_regh = vaa->vaa_mmioh; - - smfb_attach_common(sc, 1); + smfb_attach_common(sc, 1, vaa->vaa_fbt, vaa->vaa_fbh, vaa->vaa_mmiot, + vaa->vaa_mmioh); } void -smfb_attach_common(struct smfb_softc *sc, int is5xx) +smfb_attach_common(struct smfb_softc *sc, int is5xx, bus_space_tag_t memt, + bus_space_handle_t memh, bus_space_tag_t mmiot, bus_space_handle_t mmioh) { struct wsemuldisplaydev_attach_args waa; - vaddr_t fbbase, regbase; int console; console = smfbcn.ri.ri_hw != NULL; @@ -201,14 +208,7 @@ smfb_attach_common(struct smfb_softc *sc, int is5xx) } else { sc->sc_fb = &sc->sc_fb_store; sc->sc_fb->is5xx = is5xx; - fbbase = (vaddr_t)bus_space_vaddr(sc->sc_memt, sc->sc_memh); - if (is5xx) { - regbase = (vaddr_t)bus_space_vaddr(sc->sc_regt, - sc->sc_regh); - } else { - regbase = 0; - } - if (smfb_setup(sc->sc_fb, fbbase, regbase) != 0) { + if (smfb_setup(sc->sc_fb, memt, memh, mmiot, mmioh) != 0) { printf(": can't setup frame buffer\n"); return; } @@ -319,16 +319,33 @@ smfb_burner(void *v, uint on, uint flg) struct smfb *fb = sc->sc_fb; if (fb->is5xx) { - /* XXX TBD */ + if (on) { + /* + * Wait for a few cycles after restoring power, + * to prevent white flickering. + */ + DCR_WRITE(fb, DCR_PANEL_DISPLAY_CONTROL, + DCR_READ(fb, DCR_PANEL_DISPLAY_CONTROL) | PDC_VDD); + smfb_wait_panel_vsync(fb, 4); + DCR_WRITE(fb, DCR_PANEL_DISPLAY_CONTROL, + DCR_READ(fb, DCR_PANEL_DISPLAY_CONTROL) | PDC_DATA); + smfb_wait_panel_vsync(fb, 4); + DCR_WRITE(fb, DCR_PANEL_DISPLAY_CONTROL, + DCR_READ(fb, DCR_PANEL_DISPLAY_CONTROL) | + (PDC_BIAS | PDC_EN)); + } else + DCR_WRITE(fb, DCR_PANEL_DISPLAY_CONTROL, + DCR_READ(fb, DCR_PANEL_DISPLAY_CONTROL) & + ~(PDC_EN | PDC_BIAS | PDC_DATA | PDC_VDD)); } else { if (on) { - smfb_mmio_write(fb, 0x31, - smfb_mmio_read(fb, 0x31) | 0x01); + smfb_vgats_write(fb, 0x31, + smfb_vgats_read(fb, 0x31) | 0x01); } else { - smfb_mmio_write(fb, 0x21, - smfb_mmio_read(fb, 0x21) | 0x30); - smfb_mmio_write(fb, 0x31, - smfb_mmio_read(fb, 0x31) & ~0x01); + smfb_vgats_write(fb, 0x21, + smfb_vgats_read(fb, 0x21) | 0x30); + smfb_vgats_write(fb, 0x31, + smfb_vgats_read(fb, 0x31) & ~0x01); } } } @@ -338,10 +355,12 @@ smfb_burner(void *v, uint on, uint flg) */ int -smfb_setup(struct smfb *fb, vaddr_t fbbase, vaddr_t regbase) +smfb_setup(struct smfb *fb, bus_space_tag_t memt, bus_space_handle_t memh, + bus_space_tag_t mmiot, bus_space_handle_t mmioh) { struct rasops_info *ri; int accel = 0; + int rc; ri = &fb->ri; ri->ri_width = 1024; @@ -349,7 +368,7 @@ smfb_setup(struct smfb *fb, vaddr_t fbbase, vaddr_t regbase) ri->ri_depth = 16; ri->ri_stride = (ri->ri_width * ri->ri_depth) / 8; ri->ri_flg = RI_CENTER | RI_CLEAR | RI_FULLCLEAR; - ri->ri_bits = (void *)fbbase; + ri->ri_bits = (void *)bus_space_vaddr(memt, memh); ri->ri_hw = fb; #ifdef __MIPSEL__ @@ -373,14 +392,28 @@ smfb_setup(struct smfb *fb, vaddr_t fbbase, vaddr_t regbase) fb->wsd.capabilities = ri->ri_caps; if (fb->is5xx) { - fb->dpr = (volatile uint32_t *)(regbase + SM5XX_DPR_BASE); - fb->mmio = NULL; - fb->regs = (volatile uint32_t *)(regbase + SM5XX_MMIO_BASE); + fb->dcrt = mmiot; + if ((rc = bus_space_subregion(mmiot, mmioh, SM5XX_DCR_BASE, + SM5XX_DCR_SIZE, &fb->dcrh)) != 0) + return rc; + fb->dprt = mmiot; + if ((rc = bus_space_subregion(mmiot, mmioh, SM5XX_DPR_BASE, + SMXXX_DPR_SIZE, &fb->dprh)) != 0) + return rc; + fb->mmiot = mmiot; + if ((rc = bus_space_subregion(mmiot, mmioh, SM5XX_MMIO_BASE, + SM5XX_MMIO_SIZE, &fb->mmioh)) != 0) + return rc; accel = 1; } else { - fb->dpr = (volatile uint32_t *)(fbbase + SM7XX_DPR_BASE); - fb->mmio = (volatile uint8_t *)(fbbase + SM7XX_MMIO_BASE); - fb->regs = NULL; + fb->dprt = memt; + if ((rc = bus_space_subregion(memt, memh, SM7XX_DPR_BASE, + SMXXX_DPR_SIZE, &fb->dprh)) != 0) + return rc; + fb->mmiot = memt; + if ((rc = bus_space_subregion(memt, memh, SM7XX_MMIO_BASE, + SM7XX_MMIO_SIZE, &fb->mmioh)) != 0) + return rc; accel = 1; } @@ -549,12 +582,13 @@ smfb_wait(struct smfb *fb) i = 10000; while (i-- != 0) { if (fb->is5xx) { - reg = REG_READ(fb, VOYAGER_SYSTEM_CONTROL); + reg = bus_space_read_4(fb->mmiot, fb->mmioh, + VOYAGER_SYSTEM_CONTROL); if ((reg & (VSC_FIFO_EMPTY | VSC_2DENGINE_BUSY)) == VSC_FIFO_EMPTY) return 0; } else { - reg = smfb_mmio_read(fb, 0x16); + reg = smfb_vgats_read(fb, 0x16); if ((reg & 0x18) == 0x10) return 0; } @@ -564,21 +598,40 @@ smfb_wait(struct smfb *fb) return EBUSY; } +/* + * wait for a few panel vertical retrace cycles (5xx only) + */ +void +smfb_wait_panel_vsync(struct smfb *fb, int ncycles) +{ + while (ncycles-- != 0) { + /* wait for end of retrace-in-progress */ + while (ISSET(bus_space_read_4(fb->mmiot, fb->mmioh, + VOYAGER_COMMANDLIST_STATUS), VCS_SP)) + delay(10); + /* wait for start of retrace */ + while (!ISSET(bus_space_read_4(fb->mmiot, fb->mmioh, + VOYAGER_COMMANDLIST_STATUS), VCS_SP)) + delay(10); + } +} + +/* + * vga sequencer access through mmio space (non-5xx only) + */ + uint8_t -smfb_mmio_read(struct smfb *fb, uint regno) +smfb_vgats_read(struct smfb *fb, uint regno) { - fb->mmio[IO_VGA + VGA_TS_INDEX] = regno; - (void)fb->mmio[IO_VGA + VGA_TS_INDEX]; /* posted write */ - return fb->mmio[IO_VGA + VGA_TS_DATA]; + bus_space_write_1(fb->mmiot, fb->mmioh, IO_VGA + VGA_TS_INDEX, regno); + return bus_space_read_1(fb->mmiot, fb->mmioh, IO_VGA + VGA_TS_DATA); } void -smfb_mmio_write(struct smfb *fb, uint regno, uint8_t value) +smfb_vgats_write(struct smfb *fb, uint regno, uint8_t value) { - fb->mmio[IO_VGA + VGA_TS_INDEX] = regno; - (void)fb->mmio[IO_VGA + VGA_TS_INDEX]; /* posted write */ - fb->mmio[IO_VGA + VGA_TS_DATA] = value; - (void)fb->mmio[IO_VGA + VGA_TS_DATA]; /* posted write */ + bus_space_write_1(fb->mmiot, fb->mmioh, IO_VGA + VGA_TS_INDEX, regno); + bus_space_write_1(fb->mmiot, fb->mmioh, IO_VGA + VGA_TS_DATA, value); } /* @@ -593,8 +646,7 @@ smfb_cnattach(bus_space_tag_t memt, bus_space_tag_t iot, pcitag_t tag, { long defattr; struct rasops_info *ri; - bus_space_handle_t fbh, regh; - vaddr_t fbbase, regbase; + bus_space_handle_t fbh, mmioh; pcireg_t bar; int rc, is5xx; @@ -619,22 +671,20 @@ smfb_cnattach(bus_space_tag_t memt, bus_space_tag_t iot, pcitag_t tag, BUS_SPACE_MAP_LINEAR, &fbh); if (rc != 0) return rc; - fbbase = (vaddr_t)bus_space_vaddr(memt, fbh); if (smfbcn.is5xx) { bar = pci_conf_read_early(tag, PCI_MAPREG_START + 0x04); if (PCI_MAPREG_TYPE(bar) != PCI_MAPREG_TYPE_MEM) return EINVAL; rc = bus_space_map(memt, PCI_MAPREG_MEM_ADDR(bar), 1 /* XXX */, - BUS_SPACE_MAP_LINEAR, ®h); + BUS_SPACE_MAP_LINEAR, &mmioh); if (rc != 0) return rc; - regbase = (vaddr_t)bus_space_vaddr(memt, regh); } else { - regbase = 0; + mmioh = fbh; } - rc = smfb_setup(&smfbcn, fbbase, regbase); + rc = smfb_setup(&smfbcn, memt, fbh, memt, mmioh); if (rc != 0) return rc; diff --git a/sys/arch/loongson/dev/smfbreg.h b/sys/arch/loongson/dev/smfbreg.h index 92cbd81b120..019ab4e777c 100644 --- a/sys/arch/loongson/dev/smfbreg.h +++ b/sys/arch/loongson/dev/smfbreg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: smfbreg.h,v 1.4 2010/02/18 22:45:28 miod Exp $ */ +/* $OpenBSD: smfbreg.h,v 1.5 2010/08/27 12:48:54 miod Exp $ */ /* * Copyright (c) 2009, 2010 Miodrag Vallat. @@ -28,6 +28,7 @@ #define SM5XX_DPR_BASE 0x00100000 #define SM7XX_DPR_BASE 0x00408000 +#define SMXXX_DPR_SIZE 0x00004000 #define DPR_SRC_COORDS 0x00 #define DPR_DST_COORDS 0x04 @@ -70,3 +71,4 @@ */ #define SM7XX_MMIO_BASE 0x00700000 +#define SM7XX_MMIO_SIZE 0x00004000 diff --git a/sys/arch/loongson/dev/voyagerreg.h b/sys/arch/loongson/dev/voyagerreg.h index 364635639bd..237517614a4 100644 --- a/sys/arch/loongson/dev/voyagerreg.h +++ b/sys/arch/loongson/dev/voyagerreg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: voyagerreg.h,v 1.2 2010/02/26 14:53:11 miod Exp $ */ +/* $OpenBSD: voyagerreg.h,v 1.3 2010/08/27 12:48:54 miod Exp $ */ /* * Copyright (c) 2010 Miodrag Vallat. @@ -21,26 +21,40 @@ */ #define SM5XX_MMIO_BASE 0x000000 +#define SM5XX_MMIO_SIZE 0x010000 -#define VOYAGER_SYSTEM_CONTROL 0x000000 +#define VOYAGER_SYSTEM_CONTROL 0x0000 #define VSC_DPMS_VSYNC_DISABLE 0x80000000 #define VSC_DPMS_HSYNC_DISABLE 0x40000000 #define VSC_COLOR_CONVERSION_BUSY 0x10000000 #define VSC_FIFO_EMPTY 0x00100000 #define VSC_2DENGINE_BUSY 0x00080000 #define VSC_2DENGINE_ABORT 0x00003000 /* not a typo */ -#define VOYAGER_MISC_CONTROL 0x000004 -#define VOYAGER_GPIOL_CONTROL 0x000008 -#define VOYAGER_GPIOH_CONTROL 0x00000c -#define VOYAGER_DRAM_CONTROL 0x000010 -#define VOYAGER_ARB_CONTROL 0x000014 +#define VOYAGER_MISC_CONTROL 0x0004 +#define VOYAGER_GPIOL_CONTROL 0x0008 +#define VOYAGER_GPIOH_CONTROL 0x000c +#define VOYAGER_DRAM_CONTROL 0x0010 +#define VOYAGER_ARB_CONTROL 0x0014 -#define VOYAGER_COMMANDLIST_CONTROL 0x000018 -#define VOYAGER_COMMANDLIST_CONDITION 0x00001c -#define VOYAGER_COMMANDLIST_RETURN 0x000020 -#define VOYAGER_COMMANDLIST_STATUS 0x000024 +#define VOYAGER_COMMANDLIST_CONTROL 0x0018 +#define VOYAGER_COMMANDLIST_CONDITION 0x001c +#define VOYAGER_COMMANDLIST_RETURN 0x0020 +#define VOYAGER_COMMANDLIST_STATUS 0x0024 +#define VCS_2M 0x00100000 +#define VCS_CF 0x00080000 +#define VCS_2C 0x00040000 +#define VCS_DM 0x00020000 +#define VCS_CS 0x00010000 +#define VCS_VF 0x00008000 +#define VCS_VS 0x00004000 +#define VCS_PS 0x00002000 +#define VCS_SC 0x00001000 +#define VCS_SP 0x00000800 +#define VCS_2S 0x00000004 +#define VCS_2F 0x00000002 +#define VCS_2E 0x00000001 -#define VOYAGER_RAW_ISR 0x000028 +#define VOYAGER_RAW_ISR 0x0028 #define VOYAGER_RAWINTR_ZV1 6 #define VOYAGER_RAWINTR_USB_PLUGIN 5 #define VOYAGER_RAWINTR_ZV0 4 @@ -48,8 +62,8 @@ #define VOYAGER_RAWINTR_USB_SLAVE 2 #define VOYAGER_RAWINTR_PANEL_VSYNC 1 #define VOYAGER_RAWINTR_COMMAND_INTERPRETER 0 -#define VOYAGER_RAW_ICR 0x000028 -#define VOYAGER_ISR 0x00002c +#define VOYAGER_RAW_ICR 0x0028 +#define VOYAGER_ISR 0x002c #define VOYAGER_INTR_USB_PLUGIN 31 #define VOYAGER_INTR_GPIO54 30 #define VOYAGER_INTR_GPIO53 29 @@ -77,26 +91,26 @@ #define VOYAGER_INTR_ZV0 2 #define VOYAGER_INTR_PANEL_VSYNC 1 #define VOYAGER_INTR_COMMAND_INTERPRETER 0 -#define VOYAGER_IMR 0x000030 -#define VOYAGER_DEBUG 0x000034 +#define VOYAGER_IMR 0x0030 +#define VOYAGER_DEBUG 0x0034 -#define VOYAGER_PM_CURRENT_GATE 0x000038 -#define VOYAGER_PM_CURRENT_CLOCK 0x00003c -#define VOYAGER_PM_MODE0_GATE 0x000040 -#define VOYAGER_PM_MODE0_CLOCK 0x000044 -#define VOYAGER_PM_MODE1_GATE 0x000048 -#define VOYAGER_PM_MODE1_CLOCK 0x00004c -#define VOYAGER_PM_SLEEP_GATE 0x000050 -#define VOYAGER_PM_CONTROL 0x000054 +#define VOYAGER_PM_CURRENT_GATE 0x0038 +#define VOYAGER_PM_CURRENT_CLOCK 0x003c +#define VOYAGER_PM_MODE0_GATE 0x0040 +#define VOYAGER_PM_MODE0_CLOCK 0x0044 +#define VOYAGER_PM_MODE1_GATE 0x0048 +#define VOYAGER_PM_MODE1_CLOCK 0x004c +#define VOYAGER_PM_SLEEP_GATE 0x0050 +#define VOYAGER_PM_CONTROL 0x0054 -#define VOYAGER_MASTER_PCI_BASE 0x000058 -#define VOYAGER_ENDIAN_CONTROL 0x00005c -#define VOYAGER_DEVICE_ID 0x000060 -#define VOYAGER_PLL_COUNT 0x000064 -#define VOYAGER_MISC 0x000068 -#define VOYAGER_SDRAM_CLOCK 0x00006c -#define VOYAGER_NON_CACHE_ADDRESS 0x000070 -#define VOYAGER_PLL_CONTROL 0x000074 +#define VOYAGER_MASTER_PCI_BASE 0x0058 +#define VOYAGER_ENDIAN_CONTROL 0x005c +#define VOYAGER_DEVICE_ID 0x0060 +#define VOYAGER_PLL_COUNT 0x0064 +#define VOYAGER_MISC 0x0068 +#define VOYAGER_SDRAM_CLOCK 0x006c +#define VOYAGER_NON_CACHE_ADDRESS 0x0070 +#define VOYAGER_PLL_CONTROL 0x0074 /* * GPIO @@ -113,3 +127,16 @@ #define VOYAGER_OHCI_BASE 0x040000 #define VOYAGER_OHCI_SIZE 0x020000 + +/* + * Display Controller + */ + +#define SM5XX_DCR_BASE 0x080000 +#define SM5XX_DCR_SIZE 0x010000 + +#define DCR_PANEL_DISPLAY_CONTROL 0x0000 +#define PDC_EN 0x08000000 +#define PDC_BIAS 0x04000000 +#define PDC_DATA 0x02000000 +#define PDC_VDD 0x01000000 |