Package org.jnode.driver.video.nvidia

Source Code of org.jnode.driver.video.nvidia.NVidiaCore

/*
* $Id$
*
* Copyright (C) 2003-2014 JNode.org
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; If not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package org.jnode.driver.video.nvidia;

import java.awt.Color;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import java.awt.image.ColorModel;
import java.awt.image.Raster;

import javax.naming.NameNotFoundException;

import org.apache.log4j.Logger;
import org.jnode.awt.util.BitmapGraphics;
import org.jnode.driver.DriverException;
import org.jnode.driver.bus.pci.PCIBaseAddress;
import org.jnode.driver.bus.pci.PCIDevice;
import org.jnode.driver.bus.pci.PCIHeaderType0;
import org.jnode.driver.video.FrameBufferConfiguration;
import org.jnode.driver.video.ddc.DisplayDataChannelAPI;
import org.jnode.driver.video.spi.DpmsState;
import org.jnode.driver.video.util.AbstractSurface;
import org.jnode.driver.video.vgahw.DisplayMode;
import org.jnode.naming.InitialNaming;
import org.jnode.system.resource.MemoryResource;
import org.jnode.system.resource.ResourceManager;
import org.jnode.system.resource.ResourceNotFreeException;
import org.jnode.util.NumberUtils;
import org.vmmagic.unboxed.Address;

/**
* @author Ewout Prangsma (epr@users.sourceforge.net)
*/
public class NVidiaCore extends AbstractSurface implements NVidiaConstants, DisplayDataChannelAPI {
    /** Acceleration functions */
    private final NVidiaAcceleration acc;
    private final int architecture;
    private BitmapGraphics bitmapGraphics;
    private int bitsPerPixel = 32;
    private int bytesPerLine;
    private FrameBufferConfiguration config;
    private final int CrystalFreqKHz;
    private final int DDCBase = 0x3e;
    private final NVidiaDriver driver;
    /** Hardware cursor implementation */
    private final NVidiaHardwareCursor hwCursor;
    /** My logger */
    private static final Logger log = Logger.getLogger(NVidiaCore.class);
    private final int MaxVClockFreqKHz;
    /** Size of card memory in MB */
    private final int memSize;
    private final MemoryResource mmio;
    private final NVidiaVgaState oldVgaState = new NVidiaVgaState();
    /** Should acceleration be used */
    private final boolean useAcc = true;
    private final NVidiaVgaIO vgaIO;
    private final MemoryResource videoRam;

    /**
     * @param driver
     * @param architecture
     * @param model
     * @param device
     */
    public NVidiaCore(NVidiaDriver driver, int architecture, String model, PCIDevice device)
        throws ResourceNotFreeException, DriverException {
        super(640, 480);
        this.driver = driver;
        this.architecture = architecture;
        final PCIHeaderType0 pciCfg = device.getConfig().asHeaderType0();
        final PCIBaseAddress ioAddr = pciCfg.getBaseAddresses()[0];
        final PCIBaseAddress fbAddr = pciCfg.getBaseAddresses()[1];
        log.info("Found NVidia " + model + ", chipset 0x" + NumberUtils.hex(pciCfg.getRevision()));
        try {
            final ResourceManager rm = InitialNaming.lookup(ResourceManager.NAME);
            final int ioBase = (int) ioAddr.getMemoryBase() & 0xFF800000;
            final int ioSize = ioAddr.getSize();
            final int fbBase = (int) fbAddr.getMemoryBase() & 0xFF800000;
            final int fbSize = fbAddr.getSize();

            log.debug("Found NVidia, FB at 0x" + NumberUtils.hex(fbBase) + "s0x" +
                    NumberUtils.hex(fbSize) + ", MMIO at 0x" + NumberUtils.hex(ioBase));

            this.mmio =
                    rm.claimMemoryResource(device, Address.fromIntZeroExtend(ioBase), ioSize,
                            ResourceManager.MEMMODE_NORMAL);
            this.videoRam =
                    rm.claimMemoryResource(device, Address.fromIntZeroExtend(fbBase), fbSize,
                            ResourceManager.MEMMODE_NORMAL);
            this.vgaIO = new NVidiaVgaIO(mmio, videoRam);

        } catch (NameNotFoundException ex) {
            throw new ResourceNotFreeException(ex);
        }
        this.hwCursor = new NVidiaHardwareCursor(vgaIO, architecture);
        this.acc = new NVidiaAcceleration(vgaIO, architecture);
        this.memSize = getMemorySize();
        int bootInfo;
       
        switch (architecture) {
            case NV04A:
                bootInfo = vgaIO.getReg32(NV32_NVSTRAPINFO2);
                CrystalFreqKHz = ((bootInfo & 0x00000040) != 0) ? 14318 : 13500;
                MaxVClockFreqKHz = 250000;
                break;
            case NV10A:
                bootInfo = vgaIO.getReg32(NV32_NVSTRAPINFO2);
                CrystalFreqKHz = ((bootInfo & 0x00000040) != 0) ? 14318 : 13500;
                MaxVClockFreqKHz = 350000;
                break;
            case NV28M:
                bootInfo = vgaIO.getReg32(NV32_NVSTRAPINFO2);
                CrystalFreqKHz = ((bootInfo & 0x00000040) != 0) ? 14318 : 13500;
                MaxVClockFreqKHz = 200000;
                break;
            default:
                throw new DriverException("Unknown architecture " + architecture);
        }
        log.debug("Memory size     =" + memSize + "MB");
        log.debug("CrystalFreqKHz  =" + CrystalFreqKHz);
        log.debug("MaxVClockFreqKHz=" + MaxVClockFreqKHz);
    }

    /**
     * Calculate the best VClock settings
     *
     * @param clockIn
     * @return The best values in the form of { M, N, P, clock }
     */
    private int[] calcVCLock(int clockIn) {
        int DeltaOld = Integer.MAX_VALUE;
        final int VClk = clockIn;
        final int lowM;
        final int highM;
        final boolean isNV3 = (architecture < NV04A);
        if (CrystalFreqKHz == 14318) {
            lowM = 8;
            highM = 14 - (isNV3 ? 1 : 0);
        } else {
            lowM = 7;
            highM = 13 - (isNV3 ? 1 : 0);
        }
        final int highP = 4 - (isNV3 ? 1 : 0);
        final int best[] = new int[4];
        for (int P = 0; P <= highP; P++) {
            int Freq = VClk << P;
            if ((Freq >= 128000) && (Freq <= MaxVClockFreqKHz)) {
                for (int M = lowM; M <= highM; M++) {
                    final int N = (VClk * M / CrystalFreqKHz) << P;
                    final int DeltaNew;
                    Freq = (CrystalFreqKHz * N / M) >> P;
                    if (Freq > VClk) {
                        DeltaNew = Freq - VClk;
                    } else {
                        DeltaNew = VClk - Freq;
                    }
                    if (DeltaNew < DeltaOld) {
                        best[0] = M;
                        best[1] = N;
                        best[2] = P;
                        best[3] = Freq;
                        DeltaOld = DeltaNew;
                    }
                }
            }
        }
        if (DeltaOld == Integer.MAX_VALUE) {
            throw new RuntimeException("Cannot find a suitable VClock");
        } else {
            return best;
        }
    }

    /**
     * Close the SVGA screen
     *
     * @see org.jnode.driver.video.Surface#close()
     */
    public synchronized void close() {
        log.debug("close");
        hwCursor.closeCursor();
        final DpmsState dpmsState = getDpms();
        log.debug("Old DPMS state: " + dpmsState);
        setDpms(DpmsState.OFF);
        vgaIO.unlock();
        log.debug("restore old VGA state");
        oldVgaState.restoreToVGA(vgaIO);
        log.debug("restore DPMS state");
        setDpms(dpmsState);

        // For debugging purposes
        // final NVidiaVgaState debugState = new NVidiaVgaState();
        // debugState.saveFromVGA(vgaIO);
        // log.debug("Restored state: " + debugState);
        // End of debugging purposes

        driver.close(this);
        super.close();
        log.debug("End of close");
    }

    /**
     * Terminate a DDC1 readout
     */
    public void closeDDC1() {
        // Disable access to extended registers
        // vgaIO.lock();
    }

    /**
     * @see org.jnode.driver.video.util.AbstractSurface#convertColor(java.awt.Color)
     */
    protected int convertColor(Color color) {
        return color.getRGB();
    }

    /**
     * @see org.jnode.driver.video.Surface#copyArea(int, int, int, int, int,
     *      int)
     */
    public void copyArea(int x, int y, int width, int height, int dx, int dy) {
        bitmapGraphics.copyArea(x, y, width, height, dx, dy);
    }

    /**
     * @see org.jnode.driver.video.Surface#drawCompatibleRaster(java.awt.image.Raster,
     *      int, int, int, int, int, int, java.awt.Color)
     */
    public final void drawCompatibleRaster(Raster raster, int srcX, int srcY, int dstX, int dstY,
            int width, int height, Color bgColor) {
        if (bgColor == null) {
            bitmapGraphics.drawImage(raster, srcX, srcY, dstX, dstY, width, height);
        } else {
            bitmapGraphics.drawImage(raster, srcX, srcY, dstX, dstY, width, height,
                    convertColor(bgColor));
        }
    }

    /**
     * @see org.jnode.driver.video.util.AbstractSurface#drawPixel(int, int, int,
     *      int)
     */
    public final void drawPixel(int x, int y, int color, int mode) {
        bitmapGraphics.drawPixels(x, y, 1, color, mode);
    }

    /**
     * @see org.jnode.driver.video.util.AbstractSurface#fillRect(int, int, int,
     *      int, int, int)
     */
    public void fillRect(int x, int y, int w, int h, int color, int mode) {
        final int screenWidth = config.getScreenWidth();
        if (x + w >= screenWidth) {
            w = screenWidth - x;
        }
        if (useAcc && (mode == PAINT_MODE)) {
            acc.setupRectangle(color);
            acc.fillRectangle(x, y, w, h);
        } else {
            if ((x == 0) && (w == screenWidth)) {
                bitmapGraphics.drawPixels(0, y, screenWidth * height, color, mode);
            } else {
                super.fillRect(x, y, w, h, color, mode);
            }
        }
    }

    /**
     * @see org.jnode.driver.video.Surface#getColorModel()
     */
    public ColorModel getColorModel() {
        return config.getColorModel();
    }

    /**
     * @see org.jnode.driver.video.ddc.DisplayDataChannelAPI#getDDC1Bit()
     */
    public boolean getDDC1Bit() {
        /* wait for Vsync */
        while ((vgaIO.getSTAT() & 0x08) != 0) { /* wait */
        }
        while ((vgaIO.getSTAT() & 0x08) == 0) { /* wait */
        }

        /* Get the result */
        final int val = vgaIO.getCRT(DDCBase);
        // log.debug("getDDC1Bit: val=0x" + NumberUtils.hex(val, 2));
        return ((val & DDC_SDA_READ_MASK) != 0);
    }

    /**
     * Gets the current DPMS state
     *
     * @return
     */
    private DpmsState getDpms() {
        final boolean display = ((vgaIO.getSEQ(NVSEQX_CLKMODE) & 0x20) == 0);
        final int repaint1 = vgaIO.getCRT(NVCRTCX_REPAINT1);
        final boolean hsync = ((repaint1 & 0x80) == 0);
        final boolean vsync = ((repaint1 & 0x40) == 0);
        return new DpmsState(display, hsync, vsync);
    }

    /**
     * Gets the hardware cursor implementation
     */
    public NVidiaHardwareCursor getHardwareCursor() {
        return hwCursor;
    }

    /**
     * Detect the size of installed memory.
     *
     * @return Size in MB.
     */
    private final int getMemorySize() {
        final int size;
        if (architecture == NV04A) {
            final int strapinfo = vgaIO.getReg32(NV32_NV4STRAPINFO);

            if ((strapinfo & 0x00000100) != 0) {
                /* Unified memory architecture used */
                log.debug("INFO: NV4 architecture chip with UMA detected");
                size = ((((strapinfo & 0x0000f000) >> 12) * 2) + 2);

            } else {
                /* private memory architecture used */
                switch (strapinfo & 0x00000003) {
                    case 0:
                        size = 32;
                        break;
                    case 1:
                        size = 4;
                        break;
                    case 2:
                        size = 8;
                        break;
                    case 3:
                        size = 16;
                        break;
                    default:
                        // Cannot get here, but just to keep the compiler
                        // silent.
                        size = 8;
                }
            }
        } else {
            // NV10, NV20
            // final int dev_manID = CFGR(DEVID);
            final int strapinfo = vgaIO.getReg32(NV32_NV10STRAPINFO);

            // case 0x01a010de: /* Nvidia GeForce2 Integrated GPU */
            // size = (((CFGR(GF2IGPU) & 0x000007c0) >> 6) + 1);
            // break;
            // case 0x01f010de: /* Nvidia GeForce4 MX Integrated GPU */
            // size = (((CFGR(GF4MXIGPU) & 0x000007f0) >> 4) + 1);
            // remove this line if det. is OK: int amt = pciReadLong(pciTag(0,
            // 0, 1), 0x84);
            // break;
            log.info("strapinfo " + strapinfo);
            switch ((strapinfo & 0x0ff00000) >> 20) {
                case 2:
                    size = 2;
                    break;
                case 4:
                    size = 4;
                    break;
                case 8:
                    size = 8;
                    break;
                case 16:
                    size = 16;
                    break;
                case 32:
                    size = 32;
                    break;
                case 64:
                    size = 64;
                    break;
                case 128:
                    size = 128;
                    break;
                default:
                    size = 16;
                    log
                            .info("NV10/20 architecture chip with unknown RAM amount detected, setting 16Mb");
                    break;
            }
        }
        return size;
    }

    /**
     * Gets the start address of the video memory
     */
    final int getVideoStartAddress() {
        int startadd = 0;
        if (architecture < NV10A) {
            /* upto 32Mb RAM adressing: must be used this way on pre-NV10! */

            /* set standard registers */
            /* (NVidia: startadress in 32bit words (b2 - b17) */
            startadd |= ((vgaIO.getCRT(NVCRTCX_FBSTADDL) & 0xFF) << 2);
            startadd |= ((vgaIO.getCRT(NVCRTCX_FBSTADDH) & 0xFF) << 10);

            /* set extended registers */
            /* NV4 extended bits: (b18-22) */
            int temp = vgaIO.getCRT(NVCRTCX_REPAINT0) & 0x1f;
            startadd |= (temp << 18);
            /* NV4 extended bits: (b23-24) */
            temp = vgaIO.getCRT(NVCRTCX_HEB) & 0x60;
            startadd |= (temp << 18);
        } else {
            /* upto 4Gb RAM adressing: must be used on NV10 and later! */
            /*
             * NOTE: While this register also exists on pre-NV10 cards, it will
             * wrap-around at 16Mb boundaries!!
             */

            /* 30bit adress in 32bit words */
            startadd = vgaIO.getReg32(NV32_NV10FBSTADD32) & 0xfffffffc;
        }
        return startadd;
    }

    /**
     * Open the given configuration
     *
     * @param config
     */
    final void open(NVidiaConfiguration config) {
        this.config = config;
        // Save the current state
        oldVgaState.saveFromVGA(vgaIO);
        // log.debug("Old VGA State: " + oldVgaState);
        // log.debug("Old start address:0x" +
        // NumberUtils.hex(getVideoStartAddress()));

        // Enabled access to extended registers
        vgaIO.unlock();

        // Turn off the screen
        final DpmsState dpmsState = getDpms();
        // log.debug("Old DPMS state: " + dpmsState);
        setDpms(DpmsState.OFF);

        /* power-up all nvidia hardware function blocks */
        /*
         * bit 28: OVERLAY ENGINE (BES), bit 25: CRTC2, (> NV04A) bit 24: CRTC1,
         * bit 20: framebuffer, bit 16: PPMI, bit 12: PGRAPH, bit 8: PFIFO, bit
         * 4: PMEDIA, bit 0: TVOUT. (> NV04A)
         */
        // log.debug("PWRUPCTRL=0x" +
        // NumberUtils.hex(mmio.getInt(NV32_PWRUPCTRL)));
        mmio.setInt(NV32_PWRUPCTRL, 0x13111111);

        // Set the new configuration
        this.bitsPerPixel = config.getBitsPerPixel();
        this.width = config.getScreenWidth();
        this.height = config.getScreenHeight();
        final int pixelDepth = (this.bitsPerPixel + 1) / 8;
        this.bytesPerLine = width * pixelDepth;
        final int startAddress = 2048;
        try {
            final NVidiaVgaState newState = config.getVgaState();
            newState.calcForConfiguration(config, architecture, vgaIO);
            newState.restoreToVGA(vgaIO);
            setPLL(config.getMode());
            // setColourDepth
            setPalette(1.0f);
            // setDacMode
            setPitch(bytesPerLine);
            setVideoStartAddress(startAddress);
            setTiming(config.getMode());
            hwCursor.initCursor();
            // Setup accelration
            acc.accInit(startAddress, bytesPerLine, memSize, bitsPerPixel);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        // Create the graphics helper & clear the screen
        final int pixels = width * height;
        switch (bitsPerPixel) {
            case 8:
                bitmapGraphics =
                        BitmapGraphics.create8bppInstance(videoRam, width, height, bytesPerLine,
                                startAddress);
                videoRam.setByte(startAddress, (byte) 0, pixels);
                break;
            case 16:
                bitmapGraphics =
                        BitmapGraphics.create16bppInstance(videoRam, width, height, bytesPerLine,
                                startAddress);
                videoRam.setShort(startAddress, (byte) 0, pixels);
                break;
            case 24:
                bitmapGraphics =
                        BitmapGraphics.create24bppInstance(videoRam, width, height, bytesPerLine,
                                startAddress);
                videoRam.setInt24(startAddress, 0, pixels);
                break;
            case 32:
                bitmapGraphics =
                        BitmapGraphics.create32bppInstance(videoRam, width, height, bytesPerLine,
                                startAddress);
                videoRam.setInt(startAddress, 0, pixels);
                break;
        }

        // Turn the screen back on
        setDpms(dpmsState);

    }

    /**
     * Release all resources
     */
    final void release() {
        mmio.release();
        videoRam.release();
    }

    private void setDpms(DpmsState state) {
        // log.debug("Setting DPMS to " + state);
        /* start synchronous reset: required before turning screen off! */
        vgaIO.setSEQ(NVSEQX_RESET, 0x01);

        /* turn screen off */
        int clkmode = vgaIO.getSEQ(NVSEQX_CLKMODE);
        if (state.isDisplay()) {
            vgaIO.setSEQ(NVSEQX_CLKMODE, clkmode & ~0x20);
            /* end synchronous reset if display should be enabled */
            vgaIO.setSEQ(NVSEQX_RESET, 0x03);
        } else {
            vgaIO.setSEQ(NVSEQX_CLKMODE, clkmode | 0x20);
        }

        int repaint1 = vgaIO.getCRT(NVCRTCX_REPAINT1);
        if (state.isHsync()) {
            repaint1 &= 0x7f;
        } else {
            repaint1 |= 0x80;
        }
        if (state.isVsync()) {
            repaint1 &= 0xbf;
        } else {
            repaint1 |= 0x40;
        }
        vgaIO.setCRT(NVCRTCX_REPAINT1, repaint1);
    }

    private final void setPalette(float brightness) {
        vgaIO.setReg8(NV8_PALMASK, 0xff);
        for (int i = 0; i < 256; i++) {
            int v = (int) (i * brightness);
            if (v > 255) {
                v = 255;
            }
            vgaIO.setDACWriteIndex(i);
            vgaIO.setDACData(v); // r
            vgaIO.setDACData(v); // g
            vgaIO.setDACData(v); // b
        }
    }

    private void setPitch(int bytesPerLine) {
        final int offset = bytesPerLine / 8;
        // log.info("setPitch: offset 0x" + NumberUtils.hex(offset) + "
        // bytesPerLine 0x" + NumberUtils.hex(bytesPerLine));
        // program the card!
        vgaIO.setCRT(NVCRTCX_PITCHL, offset & 0x00ff);
        final int temp = vgaIO.getCRT(NVCRTCX_REPAINT0);
        vgaIO.setCRT(NVCRTCX_REPAINT0, (temp & 0x1f) | ((offset & 0x0700) >> 3));
    }

    private void setPLL(DisplayMode mode) {
        final int[] best = calcVCLock(mode.getFreq());
        final int m = best[0];
        final int n = best[1];
        final int p = best[2];
        final int freq = best[3];
        log.debug("Programming PLL to M" + NumberUtils.hex(m, 2) + " N" + NumberUtils.hex(n, 2) +
                " P" + NumberUtils.hex(p, 2) + " at " + freq + "KHz");

        // select pixelPLL registerset C
        vgaIO.setReg32(NVDAC_PLLSEL, 0x10000700);

        // program new frequency
        vgaIO.setReg32(NVDAC_PIXPLLC, ((p << 16) | (n << 8) | m));
    }

    private void setTiming(DisplayMode mode) {
        log.debug("Setting timing to " + mode);
        // Modify parameters as required by standard VGA
        final int htotal = ((mode.getHTotal() >> 3) - 5);
        final int hdisp_e = ((mode.getWidth() >> 3) - 1);
        final int hblnk_s = hdisp_e;
        final int hblnk_e = (htotal + 4); // 0;
        final int hsync_s = (mode.getHsyncStart() >> 3);
        final int hsync_e = (mode.getHsyncEnd() >> 3);

        final int vtotal = mode.getVTotal() - 2;
        final int vdisp_e = mode.getHeight() - 1;
        final int vblnk_s = vdisp_e;
        final int vblnk_e = (vtotal + 1);
        final int vsync_s = mode.getVsyncStart(); // -1;
        final int vsync_e = mode.getVsyncEnd(); // -1;

        log.debug("HOR:" + htotal + " " + hdisp_e + " " + hblnk_s + " " + hblnk_e + " " + hsync_s +
                " " + hsync_e);
        log.debug("VER:" + vtotal + " " + vdisp_e + " " + vblnk_s + " " + vblnk_e + " " + vsync_s +
                " " + vsync_e);

        /*
         * prevent memory adress counter from being reset (linecomp may not
         * occur)
         */
        final int linecomp = 0x3ff; // mode.getHeight();

        // fixme: flatpanel 'don't touch' update needed for 'Go' cards!?!
        if (true) {
            /* actually program the card! */
            /* unlock CRTC registers at index 0-7 */
            // vgaIO.setCRT(NVCRTCX_LOCK, 0x57);
            vgaIO.unlock();
            /* horizontal standard VGA regs */
            vgaIO.setCRT(NVCRTCX_HTOTAL, (htotal & 0xff));
            vgaIO.setCRT(NVCRTCX_HDISPE, (hdisp_e & 0xff));
            vgaIO.setCRT(NVCRTCX_HBLANKS, (hblnk_s & 0xff));
            /* also unlock vertical retrace registers in advance */
            vgaIO.setCRT(NVCRTCX_HBLANKE, ((hblnk_e & 0x1f) | 0x80));
            vgaIO.setCRT(NVCRTCX_HSYNCS, (hsync_s & 0xff));
            vgaIO.setCRT(NVCRTCX_HSYNCE, ((hsync_e & 0x1f) | ((hblnk_e & 0x20) << 2)));

            /* vertical standard VGA regs */
            vgaIO.setCRT(NVCRTCX_VTOTAL, (vtotal & 0xff));
            int overflow = 0;
            overflow |= ((vtotal & 0x100) >> (8 - 0)); // VDT_8
            overflow |= ((vdisp_e & 0x100) >> (8 - 1)); // VDE_8
            overflow |= ((vsync_s & 0x100) >> (8 - 2)); // VRS_8
            overflow |= ((vblnk_s & 0x100) >> (8 - 3)); // VBS_8
            overflow |= ((vtotal & 0x200) >> (9 - 5)); // VDT_9
            overflow |= ((vdisp_e & 0x200) >> (9 - 6)); // VDE_9
            overflow |= ((vsync_s & 0x200) >> (9 - 7)); // VRS_9
            vgaIO.setCRT(NVCRTCX_OVERFLOW, overflow);
            vgaIO.setCRT(NVCRTCX_PRROWSCN, 0x00); /* not used */

            int maxsclin = 0;
            maxsclin |= ((vblnk_s & 0x200) >> (9 - 5)); // VBS_9
            maxsclin |= ((linecomp & 0x200) >> (9 - 6)); // LC_9
            vgaIO.setCRT(NVCRTCX_MAXSCLIN, maxsclin);
            vgaIO.setCRT(NVCRTCX_VSYNCS, (vsync_s & 0xff));
            vgaIO
                    .setCRT(NVCRTCX_VSYNCE,
                            ((vgaIO.getCRT(NVCRTCX_VSYNCE) & 0x70) | (vsync_e & 0x0f)));
            vgaIO.setCRT(NVCRTCX_VDISPE, (vdisp_e & 0xff));
            vgaIO.setCRT(NVCRTCX_VBLANKS, (vblnk_s & 0xff));
            vgaIO.setCRT(NVCRTCX_VBLANKE, (vblnk_e & 0xff));
            vgaIO.setCRT(NVCRTCX_LINECOMP, (linecomp & 0xff));

            /* horizontal extended regs */
            int heb = vgaIO.getCRT(NVCRTCX_HEB) & 0xe0;
            heb |= ((htotal & 0x100) >> (8 - 0)); // HDT_8
            heb |= ((hdisp_e & 0x100) >> (8 - 1)); // HDE_8
            heb |= ((hblnk_s & 0x100) >> (8 - 2)); // HBS_8
            heb |= ((hsync_s & 0x100) >> (8 - 3)); // HRS_8
            heb |= ((linecomp & 0x100) >> (8 - 4)); // ILC_8
            vgaIO.setCRT(NVCRTCX_HEB, heb);

            /* (mostly) vertical extended regs */
            int lsr = vgaIO.getCRT(NVCRTCX_LSR) & 0xc0;
            lsr |= ((vtotal & 0x400) >> (10 - 0)); // VDT_10
            lsr |= ((vdisp_e & 0x400) >> (10 - 1)); // VDE_10
            lsr |= ((vsync_s & 0x400) >> (10 - 2)); // VRS_10
            lsr |= ((vblnk_s & 0x400) >> (10 - 3)); // VRBS_10
            lsr |= ((hblnk_e & 0x040) >> (6 - 4)); // HBE_6
            vgaIO.setCRT(NVCRTCX_LSR, lsr);

            // extra
            int ebr = 0;
            ebr |= ((vtotal & 0x800) >> (11 - 0)); // VDT_11
            ebr |= ((vdisp_e & 0x800) >> (11 - 2)); // VDE_11
            ebr |= ((vsync_s & 0x800) >> (11 - 4)); // VRS_11
            ebr |= ((vblnk_s & 0x800) >> (11 - 8)); // VBS_11
            vgaIO.setCRT(NVCRTCX_EBR, ebr);

            /* setup 'large screen' mode */
            final int repaint1 = vgaIO.getCRT(NVCRTCX_REPAINT1);
            if (mode.getWidth() >= 1280) {
                vgaIO.setCRT(NVCRTCX_REPAINT1, (repaint1 & 0xfb));
            } else {
                vgaIO.setCRT(NVCRTCX_REPAINT1, (repaint1 | 0x04));
            }

            /* setup HSYNC & VSYNC polarity */
            /*
             * LOG(2, ("CRTC: sync polarity: ")); int temp =
             * vgaIO.getReg8(NV8_MISCR); if (target.timing.flags &
             * B_POSITIVE_HSYNC) { LOG(2, ("H:pos ")); temp &= ~0x40; } else {
             * LOG(2, ("H:neg ")); temp |= 0x40; } if (target.timing.flags &
             * B_POSITIVE_VSYNC) { LOG(2, ("V:pos ")); temp &= ~0x80; } else {
             * LOG(2, ("V:neg ")); temp |= 0x80; }
             */
        }
    }

    /**
     * Start a DDC1 readout
     */
    public void setupDDC1() {
        // Enable access to extended registers
        // vgaIO.unlock();
        vgaIO.setCRT(NVCRTCX_LOCK, 0x57);
    }

    /**
     * Sets the start address of the video memory
     *
     * @param startadd
     */
    private void setVideoStartAddress(int startadd) {
        if (architecture < NV10A) {
            /* upto 32Mb RAM adressing: must be used this way on pre-NV10! */

            /* set standard registers */
            /* (NVidia: startadress in 32bit words (b2 - b17) */
            vgaIO.setCRT(NVCRTCX_FBSTADDL, (startadd >> 2) & 0xFF);
            vgaIO.setCRT(NVCRTCX_FBSTADDH, (startadd >> 10) & 0xFF);

            /* set extended registers */
            /* NV4 extended bits: (b18-22) */
            int temp = vgaIO.getCRT(NVCRTCX_REPAINT0) & 0xE0;
            vgaIO.setCRT(NVCRTCX_REPAINT0, temp | ((startadd >> 18) & 0x1f));
            /* NV4 extended bits: (b23-24) */
            temp = vgaIO.getCRT(NVCRTCX_HEB) & 0xdf;
            vgaIO.setCRT(NVCRTCX_HEB, temp | ((startadd >> 18) & 0x20));
            // temp = (CRTCR(HEB) & 0x9f);
            // CRTCW(HEB, (temp | ((startadd & 0x01800000) >> 18)));
        } else {
            /* upto 4Gb RAM adressing: must be used on NV10 and later! */
            /*
             * NOTE: While this register also exists on pre-NV10 cards, it will
             * wrap-around at 16Mb boundaries!!
             */

            /* 30bit adress in 32bit words */
            vgaIO.setReg32(NV32_NV10FBSTADD32, startadd & 0xfffffffc);
        }

        int temp = vgaIO.getATT(NVATBX_HORPIXPAN) & 0xf9;
        vgaIO.setATT(NVATBX_HORPIXPAN, temp | ((startadd & 3) << 1));
    }

    /**
     * @see org.jnode.driver.video.Surface#drawAlphaRaster(java.awt.image.Raster,
     *      java.awt.geom.AffineTransform, int, int, int, int, int, int,
     *      java.awt.Color)
     */
    public void drawAlphaRaster(Raster raster, AffineTransform tx, int srcX, int srcY, int dstX,
            int dstY, int width, int height, Color color) {
        bitmapGraphics.drawAlphaRaster(raster, tx, srcX, srcY, dstX, dstY, width, height,
                convertColor(color));
    }

    @Override
    public int getRGBPixel(int x, int y) {
        return bitmapGraphics.doGetPixel(x, y);
    }

    @Override
    public int[] getRGBPixels(Rectangle region) {
        return bitmapGraphics.doGetPixels(region);
    }
}
TOP

Related Classes of org.jnode.driver.video.nvidia.NVidiaCore

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.