diff options
Diffstat (limited to 'src/ffb_dac.c')
-rw-r--r-- | src/ffb_dac.c | 612 |
1 files changed, 612 insertions, 0 deletions
diff --git a/src/ffb_dac.c b/src/ffb_dac.c new file mode 100644 index 0000000..01b746e --- /dev/null +++ b/src/ffb_dac.c @@ -0,0 +1,612 @@ +/* + * Acceleration for the Creator and Creator3D framebuffer - DAC programming. + * + * Copyright (C) 2000 David S. Miller (davem@redhat.com) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * DAVID MILLER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sunffb/ffb_dac.c,v 1.4 2002/12/06 02:44:03 tsi Exp $ */ + +#include "ffb.h" +#include "ffb_rcache.h" +#include "ffb_fifo.h" + +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86_ansic.h" + +#include "xf86DDC.h" + +/* + * Used for stabilize time after playing with power management on the display + */ + +#ifndef DPMS_SPIN_COUNT +#define DPMS_SPIN_COUNT 100 +#endif /* DPMS_SPIN_COUNT */ + +/* Cursor programming */ + +void +FFBDacLoadCursorPos(FFBPtr pFfb, int x, int y) +{ + ffb_dacPtr dac = pFfb->dac; + int posval; + + posval = ((y & 0xffff) << 16) | (x & 0xffff); + posval &= (FFBDAC_CUR_POS_Y_SIGN | + FFBDAC_CUR_POS_Y | + FFBDAC_CUR_POS_X_SIGN | + FFBDAC_CUR_POS_X); + + DACCUR_WRITE(dac, FFBDAC_CUR_POS, posval); +} + +void +FFBDacLoadCursorColor(FFBPtr pFfb, int fg, int bg) +{ + ffb_dacPtr dac = pFfb->dac; + + dac->cur = FFBDAC_CUR_COLOR1; + dac->curdata = bg; + dac->curdata = fg; +} + +void +FFBDacCursorEnableDisable(FFBPtr pFfb, int enable) +{ + ffb_dac_info_t *p = &pFfb->dac_info; + ffb_dacPtr dac = pFfb->dac; + int val; + + val = 0; + if (!enable) + val = (FFBDAC_CUR_CTRL_P0 | FFBDAC_CUR_CTRL_P1); + + /* PAC1 ramdacs with manufacturing revision less than + * '3' invert these control bits, wheee... + */ + if (p->flags & FFB_DAC_ICURCTL) + val ^= (FFBDAC_CUR_CTRL_P0 | FFBDAC_CUR_CTRL_P1); + + DACCUR_WRITE(dac, FFBDAC_CUR_CTRL, val); +} + +void +FFBDacCursorLoadBitmap(FFBPtr pFfb, int xshift, int yshift, unsigned int *bitmap) +{ + ffb_dacPtr dac = pFfb->dac; + int i, j; + + dac->cur = FFBDAC_CUR_BITMAP_P0; + for (j = 0; j < 2; j++) { + bitmap += yshift * 2; + if (!xshift) { + for (i = yshift * 2; i < 128; i++) + dac->curdata = *bitmap++; + } else if (xshift < 32) { + for (i = yshift; i < 64; i++, bitmap += 2) { + dac->curdata = (bitmap[0] << xshift) | + (bitmap[1] >> (32 - xshift)); + dac->curdata = bitmap[1] << xshift; + } + } else { + for (i = yshift; i < 64; i++, bitmap += 2) { + dac->curdata = bitmap[1] << (xshift - 32); + dac->curdata = 0; + } + } + + for (i = 0; i < yshift * 2; i++) + dac->curdata = 0; + } +} + +/* Config space programming */ + +/* XF86 LoadPalette callback. */ + +void +FFBDacLoadPalette(ScrnInfoPtr pScrn, int ncolors, int *indices, LOCO *colors, VisualPtr pVisual) +{ + FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn); + ffb_dac_info_t *p = &pFfb->dac_info; + ffb_dacPtr dac = pFfb->dac; + unsigned int *cluts; + int i, index, palette; + + if ((pVisual->nplanes != 8 && pVisual->class != DirectColor) || + (pVisual->nplanes == 8 && pVisual->class == StaticGray)) + return; + + palette = 0; + if (p->flags & FFB_DAC_PAC2) { + if (pVisual->class == PseudoColor) + palette = 0; + if (pVisual->class == GrayScale) + palette = 1; + if (pVisual->class == DirectColor) + palette = 2; + } + + cluts = &p->x_dac_state.clut[256 * palette]; + for (i = 0; i < ncolors; i++) { + unsigned int regval; + + index = indices[i]; + if (pVisual->class == GrayScale) { + regval = cluts[index] = + ((colors[index].red << FFBDAC_COLOR_RED_SHFT) | + (colors[index].red << FFBDAC_COLOR_GREEN_SHFT) | + (colors[index].red << FFBDAC_COLOR_BLUE_SHFT)); + } else { + regval = cluts[index] = + ((colors[index].red << FFBDAC_COLOR_RED_SHFT) | + (colors[index].green << FFBDAC_COLOR_GREEN_SHFT) | + (colors[index].blue << FFBDAC_COLOR_BLUE_SHFT)); + } + + FFBLOG(("FFBDacLoadPalette: visclass(%d) index(%d) val[%08x]\n", + pVisual->class, index, regval)); + + /* Now update the hardware copy. */ + dac->cfg = FFBDAC_CFG_CLUP(palette) + index; + dac->cfgdata = regval; + } +} + +/* WARNING: Very dangerous function, use with extreme care. */ +static void +dac_stop(FFBPtr pFfb) +{ + ffb_dacPtr dac = pFfb->dac; + unsigned int tgctrl; + + tgctrl = DACCFG_READ(dac, FFBDAC_CFG_TGEN); + if (tgctrl & FFBDAC_CFG_TGEN_TGE) { + long limit = 1000000; + + /* We try to shut off the timing generation + * precisely at the beginning of a vertical + * retrace. This is really just to make it + * look nice, it's not a functional necessity. + * + * The limit is so that malfunctioning hardware + * does not end up hanging the server. + */ + while (limit--) { + unsigned int vctr = DACCFG_READ(dac, FFBDAC_CFG_TGVC); + + if (vctr == 0) + break; + } + + DACCFG_WRITE(dac, FFBDAC_CFG_TGEN, 0); + } +} + +/* This is made slightly complex because the ordering matters + * between several operations. We have to stop the DAC while + * restoring the timing registers so that some intermediate + * state does not emit wild retrace signals to the monitor. + * + * Another further complication is that we need to mess with + * some portions of the FFB framebuffer config registers to + * do this all properly. + */ +static void +dac_state_restore(FFBPtr pFfb, ffb_dac_hwstate_t *state) +{ + ffb_dac_info_t *p = &pFfb->dac_info; + ffb_dacPtr dac = pFfb->dac; + ffb_fbcPtr ffb = pFfb->regs; + int i, nluts; + + /* Step 1: Shut off all pixel timing generation. */ + dac_stop(pFfb); + ffb->fbcfg0 = 0; + + /* Step 2: Restore timing settings. */ + DACCFG_WRITE(dac, FFBDAC_CFG_VBNP, state->vbnp); + DACCFG_WRITE(dac, FFBDAC_CFG_VBAP, state->vbap); + DACCFG_WRITE(dac, FFBDAC_CFG_VSNP, state->vsnp); + DACCFG_WRITE(dac, FFBDAC_CFG_VSAP, state->vsap); + DACCFG_WRITE(dac, FFBDAC_CFG_HSNP, state->hsnp); + DACCFG_WRITE(dac, FFBDAC_CFG_HBNP, state->hbnp); + DACCFG_WRITE(dac, FFBDAC_CFG_HBAP, state->hbap); + DACCFG_WRITE(dac, FFBDAC_CFG_HSYNCNP, state->hsyncnp); + DACCFG_WRITE(dac, FFBDAC_CFG_HSYNCAP, state->hsyncap); + DACCFG_WRITE(dac, FFBDAC_CFG_HSCENNP, state->hscennp); + DACCFG_WRITE(dac, FFBDAC_CFG_HSCENAP, state->hscenap); + DACCFG_WRITE(dac, FFBDAC_CFG_EPNP, state->epnp); + DACCFG_WRITE(dac, FFBDAC_CFG_EINP, state->einp); + DACCFG_WRITE(dac, FFBDAC_CFG_EIAP, state->eiap); + + /* Step 3: Restore rest of DAC hw state. */ + DACCFG_WRITE(dac, FFBDAC_CFG_PPLLCTRL, state->ppllctrl); + DACCFG_WRITE(dac, FFBDAC_CFG_GPLLCTRL, state->gpllctrl); + DACCFG_WRITE(dac, FFBDAC_CFG_PFCTRL, state->pfctrl); + DACCFG_WRITE(dac, FFBDAC_CFG_UCTRL, state->uctrl); + + nluts = (p->flags & FFB_DAC_PAC1) ? 256 : (4 * 256); + dac->cfg = FFBDAC_CFG_CLUP_BASE; + for (i = 0; i < nluts; i++) + dac->cfgdata = state->clut[i]; + + if (p->flags & FFB_DAC_PAC2) { + dac->cfg = FFBDAC_PAC2_AOVWLUT0; + for (i = 0; i < 4; i++) + dac->cfgdata = state->ovluts[i]; + } + + DACCFG_WRITE(dac, FFBDAC_CFG_WTCTRL, state->wtctrl); + DACCFG_WRITE(dac, FFBDAC_CFG_TMCTRL, state->tmctrl); + DACCFG_WRITE(dac, FFBDAC_CFG_TCOLORKEY, state->tcolorkey); + if (p->flags & FFB_DAC_PAC2) + DACCFG_WRITE(dac, FFBDAC_CFG_WAMASK, state->wamask); + + if (p->flags & FFB_DAC_PAC1) { + dac->cfg = FFBDAC_PAC1_APWLUT_BASE; + for (i = 0; i < 32; i++) + dac->cfgdata = state->pwluts[i]; + } else { + dac->cfg = FFBDAC_PAC2_APWLUT_BASE; + for (i = 0; i < 64; i++) + dac->cfgdata = state->pwluts[i]; + } + + DACCFG_WRITE(dac, FFBDAC_CFG_DACCTRL, state->dacctrl); + + /* Step 4: Restore FFB framebuffer config state. */ + if (pFfb->ffb_type == ffb2_vertical_plus || + pFfb->ffb_type == ffb2_horizontal_plus || + pFfb->ffb_type == afb_m3 || + pFfb->ffb_type == afb_m6) + ffb->passin = p->ffb_passin_ctrl; + ffb->fbcfg0 = p->ffbcfg0; + ffb->fbcfg2 = p->ffbcfg2; + + /* Step 5: Restore the timing generator control reg. */ + DACCFG_WRITE(dac, FFBDAC_CFG_TGEN, state->tgen); + + /* Step 6: Pause for a bit. */ + for (i = 0; i < 100; i++) + (void) DACCFG_READ(dac, FFBDAC_CFG_TGVC); +} + +static void +dac_state_save(FFBPtr pFfb, ffb_dac_hwstate_t *state) +{ + ffb_dac_info_t *p = &pFfb->dac_info; + ffb_dacPtr dac = pFfb->dac; + int i, nluts; + + state->ppllctrl = DACCFG_READ(dac, FFBDAC_CFG_PPLLCTRL); + state->gpllctrl = DACCFG_READ(dac, FFBDAC_CFG_GPLLCTRL); + state->pfctrl = DACCFG_READ(dac, FFBDAC_CFG_PFCTRL); + state->uctrl = DACCFG_READ(dac, FFBDAC_CFG_UCTRL); + + nluts = (p->flags & FFB_DAC_PAC1) ? 256 : (4 * 256); + dac->cfg = FFBDAC_CFG_CLUP_BASE; + for (i = 0; i < nluts; i++) + state->clut[i] = dac->cfgdata; + + if (p->flags & FFB_DAC_PAC2) { + dac->cfg = FFBDAC_PAC2_AOVWLUT0; + for (i = 0; i < 4; i++) + state->ovluts[i] = dac->cfgdata; + } + + state->wtctrl = DACCFG_READ(dac, FFBDAC_CFG_WTCTRL); + state->tmctrl = DACCFG_READ(dac, FFBDAC_CFG_TMCTRL); + state->tcolorkey = DACCFG_READ(dac, FFBDAC_CFG_TCOLORKEY); + if (p->flags & FFB_DAC_PAC2) + state->wamask = DACCFG_READ(dac, FFBDAC_CFG_WAMASK); + + if (p->flags & FFB_DAC_PAC1) { + dac->cfg = FFBDAC_PAC1_APWLUT_BASE; + for (i = 0; i < 32; i++) + state->pwluts[i] = dac->cfgdata; + } else { + dac->cfg = FFBDAC_PAC2_APWLUT_BASE; + for (i = 0; i < 64; i++) + state->pwluts[i] = dac->cfgdata; + } + + state->dacctrl = DACCFG_READ(dac, FFBDAC_CFG_DACCTRL); + + state->tgen = DACCFG_READ(dac, FFBDAC_CFG_TGEN); + state->vbnp = DACCFG_READ(dac, FFBDAC_CFG_VBNP); + state->vbap = DACCFG_READ(dac, FFBDAC_CFG_VBAP); + state->vsnp = DACCFG_READ(dac, FFBDAC_CFG_VSNP); + state->vsap = DACCFG_READ(dac, FFBDAC_CFG_VSAP); + state->hsnp = DACCFG_READ(dac, FFBDAC_CFG_HSNP); + state->hbnp = DACCFG_READ(dac, FFBDAC_CFG_HBNP); + state->hbap = DACCFG_READ(dac, FFBDAC_CFG_HBAP); + state->hsyncnp = DACCFG_READ(dac, FFBDAC_CFG_HSYNCNP); + state->hsyncap = DACCFG_READ(dac, FFBDAC_CFG_HSYNCAP); + state->hscennp = DACCFG_READ(dac, FFBDAC_CFG_HSCENNP); + state->hscenap = DACCFG_READ(dac, FFBDAC_CFG_HSCENAP); + state->epnp = DACCFG_READ(dac, FFBDAC_CFG_EPNP); + state->einp = DACCFG_READ(dac, FFBDAC_CFG_EINP); + state->eiap = DACCFG_READ(dac, FFBDAC_CFG_EIAP); +} + +static void +init_dac_flags(FFBPtr pFfb) +{ + ffb_dac_info_t *p = &pFfb->dac_info; + ffb_dacPtr dac = pFfb->dac; + unsigned int did, manuf_rev, partnum; + char *device; + + /* Fetch kernel WID. */ + p->kernel_wid = *((volatile unsigned char *)pFfb->dfb8x); + + /* For AFB, assume it is PAC2 which also implies not having + * the inverted cursor control attribute. + */ + if (pFfb->ffb_type == afb_m3 || pFfb->ffb_type == afb_m6) { + p->flags = FFB_DAC_PAC2; + manuf_rev = 4; + } else { + p->flags = 0; + + did = DACCFG_READ(dac, FFBDAC_CFG_DID); + + manuf_rev = DACCFG_READ(dac, FFBDAC_CFG_UCTRL); + manuf_rev = (manuf_rev & FFBDAC_UCTRL_MANREV) >> 8; + + partnum = ((did & FFBDAC_CFG_DID_PNUM) >> 12); + if (partnum == 0x236e) + p->flags |= FFB_DAC_PAC2; + else + p->flags |= FFB_DAC_PAC1; + } + + device = pFfb->psdp->device; + if ((p->flags & FFB_DAC_PAC1) != 0) { + if (manuf_rev < 3) { + p->flags |= FFB_DAC_ICURCTL; + xf86Msg(X_INFO, "%s: BT9068 (PAC1) ramdac detected (with " + "inverted cursor control)\n", device); + } else { + xf86Msg(X_INFO, "%s: BT9068 (PAC1) ramdac detected (with " + "normal cursor control)\n", device); + } + } else { + xf86Msg(X_INFO, "%s: BT498 (PAC2) ramdac detected\n", device); + } +} + +/* The registers of the chip must be mapped, and the FFB/AFB + * board type must be probed before this is invoked. + */ +Bool +FFBDacInit(FFBPtr pFfb) +{ + ffb_dac_info_t *p = &pFfb->dac_info; + ffb_fbcPtr ffb = pFfb->regs; + + init_dac_flags(pFfb); + + p->ffbcfg0 = ffb->fbcfg0; + p->ffbcfg2 = ffb->fbcfg2; + if (pFfb->ffb_type == ffb2_vertical_plus || + pFfb->ffb_type == ffb2_horizontal_plus || + pFfb->ffb_type == afb_m3 || + pFfb->ffb_type == afb_m6) + p->ffb_passin_ctrl = ffb->passin; + + /* Save the kernel DAC state. We also save to the + * X server state here as well even though we have + * not modified anything yet. + */ + dac_state_save(pFfb, &p->kern_dac_state); + dac_state_save(pFfb, &p->x_dac_state); + + /* Fire up the WID layer. */ + FFBWidPoolInit(pFfb); + + return TRUE; +} + +/* We need to reset the A buffer X planes to the value 0xff + * when giving the hardware back to the kernel too, thus... + * Also need to do this for the B buffer X planes when double + * buffering is available. + */ +static void +restore_kernel_xchannel(FFBPtr pFfb) +{ + ffb_fbcPtr ffb = pFfb->regs; + unsigned int fbc, ppc, ppc_mask, drawop, wid; + + wid = pFfb->dac_info.kernel_wid; + + if (pFfb->has_double_buffer) + fbc = FFB_FBC_WB_AB; + else + fbc = FFB_FBC_WB_A; + + fbc |= (FFB_FBC_WM_COMBINED | FFB_FBC_RB_A | FFB_FBC_SB_BOTH | + FFB_FBC_ZE_OFF | FFB_FBC_YE_OFF | + FFB_FBC_XE_ON | FFB_FBC_RGBE_MASK); + + ppc = (FFB_PPC_APE_DISABLE | FFB_PPC_CS_CONST | FFB_PPC_XS_WID); + ppc_mask = (FFB_PPC_APE_MASK | FFB_PPC_CS_MASK | FFB_PPC_XS_MASK); + + drawop = FFB_DRAWOP_RECTANGLE; + + FFB_ATTR_RAW(pFfb, ppc, ppc_mask, ~0, + (FFB_ROP_EDIT_BIT | GXcopy)|(FFB_ROP_NEW<<8), + drawop, 0x0, fbc, wid); + + FFBFifo(pFfb, 4); + FFB_WRITE64(&ffb->by, 0, 0); + FFB_WRITE64_2(&ffb->bh, pFfb->psdp->height, pFfb->psdp->width); + pFfb->rp_active = 1; + FFBWait(pFfb, ffb); +} + +void +FFBDacFini(FFBPtr pFfb) +{ + ffb_dac_info_t *p = &pFfb->dac_info; + + /* Just restore the kernel ramdac/x-channel state. */ + dac_state_restore(pFfb, &p->kern_dac_state); + restore_kernel_xchannel(pFfb); +} + + +/* Restore X server DAC state. */ +void +FFBDacEnterVT(FFBPtr pFfb) +{ + ffb_dac_info_t *p = &pFfb->dac_info; + + /* Save kernel DAC state. */ + dac_state_save(pFfb, &p->kern_dac_state); + + /* Restore X DAC state. */ + dac_state_restore(pFfb, &p->x_dac_state); +} + +/* Restore kernel DAC state. */ +void +FFBDacLeaveVT(FFBPtr pFfb) +{ + ffb_dac_info_t *p = &pFfb->dac_info; + + /* Save X DAC state. */ + dac_state_save(pFfb, &p->x_dac_state); + + /* Restore kernel DAC and x-channel state. */ + dac_state_restore(pFfb, &p->kern_dac_state); + restore_kernel_xchannel(pFfb); +} + +/* DPMS stuff, courtesy of a hint from David S. Miller. + * 05.xii.01, FEM + */ + +/* + * I don't know why, if at all, this is needed, but JJ or DSM do it + * on restore. I observe that when just blanking/unblanking, everything + * works fine without it, but that sometimes DPMS -> Standby actually + * results in Off. Maybe related? + */ +static void +SPIN(ffb_dacPtr d, int count) { + while(count-- > 0) { + (void) DACCFG_READ(d, FFBDAC_CFG_TGVC); + } + return; +} + +/* Screen save (blank) restore */ +Bool +FFBDacSaveScreen(FFBPtr pFfb, int mode) { + int tmp; + ffb_dacPtr dac; + if(!pFfb) return FALSE; /* Is there any way at all this could happen? */ + else dac = pFfb -> dac; + + tmp = DACCFG_READ(dac, FFBDAC_CFG_TGEN); /* Get the timing information */ + + switch(mode) { + case SCREEN_SAVER_ON: + case SCREEN_SAVER_CYCLE: + tmp &= ~FFBDAC_CFG_TGEN_VIDE; /* Kill the video */ + break; + + case SCREEN_SAVER_OFF: + case SCREEN_SAVER_FORCER: + tmp |= FFBDAC_CFG_TGEN_VIDE; /* Turn the video on */ + break; + + default: + return FALSE; /* Don't know what to do; gently fail. */ + } + DACCFG_WRITE(dac, FFBDAC_CFG_TGEN, tmp); /* Restore timing register, video set as asked */ + SPIN(dac, DPMS_SPIN_COUNT/10); + return TRUE; +} + +/* DPMS Control, also hinted at by David Miller. + + The rule seems to be: + + StandBy = -HSYNC +VSYNC -VIDEO + Suspend = +HSYNC -VSYNC -VIDEO + Off = -HSYNC -VSYNC -VIDEO + On = +HSYNC +VSINC +VIDEO + + If you don't force video off, someone periodically tries to turn the + monitor on for some reason. I don't know who or why, so I kill the video + when trying to go into some sort of energy saving mode. (In real life, + 'xset s blank s xx' could well have taken care of this.) + + Also, on MY monitor, StandBy as above defined (-H+V-Vid) in fact + gives the same as Off, which I don't want. Hence, I just do (-Vid) + + 05.xii.01, FEM + 08.xii.01, FEM +*/ +void +FFBDacDPMSMode(FFBPtr pFfb, int DPMSMode, int flags) { + int tmp; + ffb_dacPtr dac = pFfb -> dac; + + tmp = DACCFG_READ(dac, FFBDAC_CFG_TGEN); /* Get timing control */ + + switch(DPMSMode) { + + case DPMSModeOn: + tmp &= ~(FFBDAC_CFG_TGEN_VSD | FFBDAC_CFG_TGEN_HSD); /* Turn off VSYNC, HSYNC + disable bits */ + tmp |= FFBDAC_CFG_TGEN_VIDE; /* Turn the video on */ + break; + + case DPMSModeStandby: +#ifdef DPMS_TRUE_STANDBY + tmp |= FFBDAC_CFG_TGEN_HSD; /* HSYNC = OFF */ +#endif /* DPMS_TRUE_STANDBY */ + tmp &= ~FFBDAC_CFG_TGEN_VSD; /* VSYNC = ON */ + tmp &= ~FFBDAC_CFG_TGEN_VIDE; /* Kill the video */ + break; + + case DPMSModeSuspend: + tmp |= FFBDAC_CFG_TGEN_VSD; /* VSYNC = OFF */ + tmp &= ~FFBDAC_CFG_TGEN_HSD; /* HSYNC = ON */ + tmp &= ~FFBDAC_CFG_TGEN_VIDE; /* Kill the video */ + break; + + case DPMSModeOff: + tmp |= (FFBDAC_CFG_TGEN_VSD | FFBDAC_CFG_TGEN_HSD); /* Kill HSYNC, VSYNC both */ + tmp &= ~FFBDAC_CFG_TGEN_VIDE; /* Kill the video */ + break; + + default: + return; /* If we get here, we really should log an error */ + } + DACCFG_WRITE(dac, FFBDAC_CFG_TGEN,tmp); /* Restore timing register, video set as asked */ + SPIN(dac, DPMS_SPIN_COUNT); /* Is this necessary? Why? */ +} |