summaryrefslogtreecommitdiff
path: root/src/gfx/disp_gu3.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gfx/disp_gu3.c')
-rw-r--r--src/gfx/disp_gu3.c2603
1 files changed, 2603 insertions, 0 deletions
diff --git a/src/gfx/disp_gu3.c b/src/gfx/disp_gu3.c
new file mode 100644
index 0000000..8fdbb27
--- /dev/null
+++ b/src/gfx/disp_gu3.c
@@ -0,0 +1,2603 @@
+/* Copyright (c) 2005 Advanced Micro Devices, Inc.
+ *
+ * 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 THE
+ * AUTHORS OR COPYRIGHT HOLDERS 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.
+ *
+ * Neither the name of the Advanced Micro Devices, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ */
+
+/*
+ * This file contains routines for the second generation display controller.
+ * */
+
+void gu3_enable_compression(void); /* private routine definition */
+void gu3_disable_compression(void); /* private routine definition */
+int gfx_set_display_control(int sync_polarities); /* private routine definition */
+void gfx_reset_video(void);
+int gu3_set_specified_mode(DISPLAYMODE * pMode, int bpp);
+
+ /*---------------------------------------------------------------------------
+ * WARNING!!!! INACCURATE DELAY MECHANISM
+ *
+ * In an effort to keep the code self contained and operating system
+ * independent, the delay loop just performs reads of a display controller
+ * register. This time will vary for faster processors. The delay can always
+ * be longer than intended, only effecting the time of the mode switch
+ * (obviously want it to still be under a second). Problems with the hardware
+ * only arise if the delay is not long enough.
+ *----------------------------------------------------------------------------
+ */
+
+#define CSTL_READS_PER_MILLISECOND 15000L
+
+#if GFX_DISPLAY_DYNAMIC
+void
+gu3_delay_milliseconds(unsigned long milliseconds)
+#else
+void
+gfx_delay_milliseconds(unsigned long milliseconds)
+#endif
+{
+ /* ASSUME 300 MHZ 20 CLOCKS PER READ */
+
+ unsigned long loop;
+
+ loop = milliseconds * CSTL_READS_PER_MILLISECOND;
+ while (loop-- > 0) {
+ READ_REG32(DC3_UNLOCK);
+ }
+}
+
+#if GFX_DISPLAY_DYNAMIC
+void
+gu3_delay_microseconds(unsigned long microseconds)
+#else
+void
+gfx_delay_microseconds(unsigned long microseconds)
+#endif
+{
+ /* ASSUME 300 MHz, 2 CLOCKS PER INCREMENT */
+
+ unsigned long loop_count = microseconds * 15;
+
+ while (loop_count-- > 0) {
+ READ_REG32(DC3_UNLOCK);
+ }
+}
+
+/*----------------------------------------------------------------------------
+ * GFX_SET_DISPLAY_BPP
+ *
+ * This routine programs the bpp in the display controller.
+ *----------------------------------------------------------------------------
+ */
+#if GFX_DISPLAY_DYNAMIC
+int
+gu3_set_display_bpp(unsigned short bpp)
+#else
+int
+gfx_set_display_bpp(unsigned short bpp)
+#endif
+{
+ unsigned long dcfg, lock;
+
+ dcfg =
+ READ_REG32(DC3_DISPLAY_CFG) & ~(DC3_DCFG_DISP_MODE_MASK |
+ DC3_DCFG_16BPP_MODE_MASK);
+ lock = READ_REG32(DC3_UNLOCK);
+
+ switch (bpp) {
+ case 12:
+ dcfg |= (DC3_DCFG_DISP_MODE_16BPP | DC3_DCFG_12BPP);
+ break;
+ case 15:
+ dcfg |= (DC3_DCFG_DISP_MODE_16BPP | DC3_DCFG_15BPP);
+ break;
+ case 16:
+ dcfg |= (DC3_DCFG_DISP_MODE_16BPP | DC3_DCFG_16BPP);
+ break;
+ case 32:
+ dcfg |= (DC3_DCFG_DISP_MODE_24BPP);
+ break;
+ case 8:
+ dcfg |= (DC3_DCFG_DISP_MODE_8BPP);
+ break;
+ default:
+ return GFX_STATUS_BAD_PARAMETER;
+ }
+
+ WRITE_REG32(DC3_UNLOCK, DC3_UNLOCK_VALUE);
+ WRITE_REG32(DC3_DISPLAY_CFG, dcfg);
+ WRITE_REG32(DC3_UNLOCK, lock);
+
+ /* SET BPP IN GRAPHICS PIPELINE */
+
+ gfx_set_bpp(bpp);
+
+ return 0;
+}
+
+/*----------------------------------------------------------------------------
+ * gu3_set_specified_mode (private routine)
+ * This routine uses the parameters in the specified display mode structure
+ * to program the display controller hardware.
+ *----------------------------------------------------------------------------
+ */
+int
+gu3_set_specified_mode(DISPLAYMODE * pMode, int bpp)
+{
+ Q_WORD msr_value;
+ unsigned long unlock, value;
+ unsigned long acfg, gcfg, dcfg;
+ unsigned long size, pitch;
+ unsigned long bpp_mask, temp, dv_size;
+
+ /* CHECK WHETHER TIMING CHANGE IS ALLOWED */
+ /* Flag used for locking also overrides timing change restriction */
+
+ if (gfx_timing_lock && !(pMode->flags & GFX_MODE_LOCK_TIMING))
+ return GFX_STATUS_ERROR;
+
+ /* CLEAR PANNING OFFSETS */
+
+ DeltaX = 0;
+ DeltaY = 0;
+ panelLeft = 0;
+ panelTop = 0;
+
+ /* SET GLOBAL FLAG */
+
+ if (pMode->flags & GFX_MODE_LOCK_TIMING)
+ gfx_timing_lock = 1;
+
+ /* CHECK FOR VALID BPP */
+ /* As this function can be called directly from */
+ /* gfx_set_display_timings, we must correct any */
+ /* invalid bpp settings. */
+
+ switch (bpp) {
+ case 12:
+ bpp_mask = 0x00000900;
+ break;
+ case 15:
+ bpp_mask = 0x00000500;
+ break;
+ case 16:
+ bpp_mask = 0x00000100;
+ break;
+ case 32:
+ bpp_mask = 0x00000200;
+ break;
+ default:
+ bpp_mask = 0x00000000;
+ bpp = 8;
+ break;
+ }
+
+ gbpp = bpp;
+
+ /* DISABLE COMPRESSION */
+
+ gu3_disable_compression();
+
+ /* ALSO DISABLE VIDEO */
+ /* Use private "reset video" routine to do all that is needed. */
+ /* SC1200, for example, also disables the alpha blending regions. */
+
+ gfx_reset_video();
+
+ /* UNLOCK THE DISPLAY CONTROLLER REGISTERS */
+
+ unlock = READ_REG32(DC3_UNLOCK);
+ WRITE_REG32(DC3_UNLOCK, DC3_UNLOCK_VALUE);
+
+ /* READ THE CURRENT REGISTER VALUES */
+
+ gcfg = READ_REG32(DC3_GENERAL_CFG);
+ dcfg = READ_REG32(DC3_DISPLAY_CFG);
+
+ /* BLANK THE DISPLAY IN THE DISPLAY FILTER */
+
+ gfx_set_crt_enable(0);
+
+ /* DISABLE THE TIMING GENERATOR */
+
+ dcfg &= ~(unsigned long)DC3_DCFG_TGEN;
+ WRITE_REG32(DC3_DISPLAY_CFG, dcfg);
+
+ /* DELAY: WAIT FOR PENDING MEMORY REQUESTS */
+ /* This delay is used to make sure that all pending requests to the */
+ /* memory controller have completed before disabling the FIFO load. */
+
+ gfx_delay_milliseconds(1);
+
+ /* DISABLE DISPLAY FIFO LOAD */
+
+ gcfg &= ~(unsigned long)DC3_GCFG_DFLE;
+ WRITE_REG32(DC3_GENERAL_CFG, gcfg);
+
+ /* PRESERVE VIDEO INFORMATION */
+
+ gcfg &= (unsigned long)(DC3_GCFG_YUVM | DC3_GCFG_VDSE);
+ dcfg = 0;
+
+ /* DISABLE VGA */
+ /* VGA *MUST* be turned off before TGEN is enabled. If not, a condition
+ * will result where VGA Enable is waiting for a VSync to be latched but
+ * a VSync will not be generated until VGA is disabled.
+ * */
+
+ WRITE_REG32(DC3_GENERAL_CFG, gcfg);
+
+ /* SET THE DOT CLOCK FREQUENCY */
+ /* Mask off the divide by two bit (bit 31) */
+
+ gfx_set_clock_frequency(pMode->frequency & 0x7FFFFFFF);
+
+ /* DELAY: WAIT FOR THE PLL TO SETTLE */
+ /* This allows the dot clock frequency that was just set to settle. */
+
+ gfx_delay_milliseconds(1);
+
+ /* SET THE GX DISPLAY CONTROLLER PARAMETERS */
+
+ WRITE_REG32(DC3_FB_ST_OFFSET, 0);
+ WRITE_REG32(DC3_CB_ST_OFFSET, 0);
+ WRITE_REG32(DC3_CURS_ST_OFFSET, 0);
+
+ /* SET LINE SIZE AND PITCH */
+ /* 1. Flat Panels must use the mode width and not */
+ /* the timing width to set the pitch. */
+ /* 2. Mode sets will use a pitch that is aligned */
+ /* on a 1K boundary to preserve legacy. The */
+ /* pitch can be overridden by a subsequent call */
+ /* to gfx_set_display_pitch. */
+
+ if (PanelEnable)
+ size = ModeWidth;
+ else
+ size = pMode->hactive;
+
+ if (bpp > 8)
+ size <<= 1;
+ if (bpp > 16)
+ size <<= 1;
+
+ pitch = 1024;
+ dv_size = DC3_DV_LINE_SIZE_1024;
+
+ if (size > 1024) {
+ pitch = 2048;
+ dv_size = DC3_DV_LINE_SIZE_2048;
+ }
+
+ if (size > 2048) {
+ pitch = 4096;
+ dv_size = DC3_DV_LINE_SIZE_4096;
+ }
+
+ if (size > 4096) {
+ pitch = 8192;
+ dv_size = DC3_DV_LINE_SIZE_8192;
+ }
+
+ WRITE_REG32(DC3_GFX_PITCH, pitch >> 3);
+
+ /* WRITE DIRTY/VALID CONTROL WITH LINE LENGTH */
+
+ temp = READ_REG32(DC3_DV_CTL);
+ WRITE_REG32(DC3_DV_CTL, (temp & ~DC3_DV_LINE_SIZE_MASK) | dv_size);
+
+ if (PanelEnable) {
+ size = pMode->hactive;
+ if (bpp > 8)
+ size <<= 1;
+ if (bpp > 16)
+ size <<= 1;
+ }
+
+ WRITE_REG32(DC3_LINE_SIZE, ((size >> 3)));
+
+ /* ALWAYS ENABLE VIDEO AND GRAPHICS DATA */
+ /* These bits are relics from a previous design and */
+ /* should always be enabled. */
+
+ dcfg |= (unsigned long)(DC3_DCFG_VDEN | DC3_DCFG_GDEN);
+
+ /* SET PIXEL FORMAT */
+
+ dcfg |= bpp_mask;
+
+ /* ENABLE TIMING GENERATOR, TIM. REG. UPDATES, PALETTE BYPASS */
+ /* AND VERT. INT. SELECT */
+
+ dcfg |=
+ (unsigned long)(DC3_DCFG_TGEN | DC3_DCFG_TRUP | DC3_DCFG_PALB |
+ DC3_DCFG_VISL);
+
+ /* SET FIFO PRIORITIES AND DISPLAY FIFO LOAD ENABLE */
+
+ gcfg |= 0x0000BA01;
+ dcfg |= 0x000EA000;
+ acfg = 0x001A0000;
+
+ /* SET THE DISPLAY CHARACTERISTICS FOR HIGH BANDWIDTH CASES */
+
+ gfx_msr_read(RC_ID_VG, DC3_VG_SPARE_MSR, &msr_value);
+ msr_value.low &=
+ ~(VG_SPARE_DISABLE_CFIFO_HGO | VG_SPARE_VFIFO_ARB_SELECT |
+ VG_SPARE_LOAD_WM_LPEN_MASK | VG_SPARE_WM_LPEN_OVRD |
+ VG_SPARE_DISABLE_INIT_VID_PRI | VG_SPARE_DISABLE_VFIFO_WM);
+ msr_value.low |= VG_SPARE_DISABLE_CFIFO_HGO | VG_SPARE_VFIFO_ARB_SELECT;
+ gfx_msr_write(RC_ID_VG, DC3_VG_SPARE_MSR, &msr_value);
+ WRITE_REG32(DC3_ARB_CFG, acfg);
+
+ /* ENABLE FLAT PANEL CENTERING */
+ /* For panel modes having a resolution smaller than the */
+ /* panel resolution, turn on data centering. */
+
+ if (PanelEnable && ModeWidth < PanelWidth)
+ dcfg |= DC3_DCFG_DCEN;
+
+ /* SET THE GRAPHICS SCALE */
+ /* We do not support graphics scaling, but we need to ensure that the */
+ /* scale is set correctly none the less. */
+
+ WRITE_REG32(DC3_GFX_SCALE, 0x40004000);
+ WRITE_REG32(DC3_IRQ_CTL, 0);
+
+ /* COMBINE AND SET TIMING VALUES */
+
+ value = (unsigned long)(pMode->hactive - 1) |
+ (((unsigned long)(pMode->htotal - 1)) << 16);
+ WRITE_REG32(DC3_H_ACTIVE_TIMING, value);
+ value = (unsigned long)(pMode->hblankstart - 1) |
+ (((unsigned long)(pMode->hblankend - 1)) << 16);
+ WRITE_REG32(DC3_H_BLANK_TIMING, value);
+ value = (unsigned long)(pMode->hsyncstart - 1) |
+ (((unsigned long)(pMode->hsyncend - 1)) << 16);
+ WRITE_REG32(DC3_H_SYNC_TIMING, value);
+ value = (unsigned long)(pMode->vactive - 1) |
+ (((unsigned long)(pMode->vtotal - 1)) << 16);
+ WRITE_REG32(DC3_V_ACTIVE_TIMING, value);
+ value = (unsigned long)(pMode->vblankstart - 1) |
+ (((unsigned long)(pMode->vblankend - 1)) << 16);
+ WRITE_REG32(DC3_V_BLANK_TIMING, value);
+ value = (unsigned long)(pMode->vsyncstart - 1) |
+ (((unsigned long)(pMode->vsyncend - 1)) << 16);
+ WRITE_REG32(DC3_V_SYNC_TIMING, value);
+
+ WRITE_REG32(DC3_DISPLAY_CFG, dcfg);
+ WRITE_REG32(DC3_GENERAL_CFG, gcfg);
+
+ /* CONFIGURE DISPLAY OUTPUT FROM VIDEO PROCESSOR */
+
+ gfx_set_display_control(((pMode->flags & GFX_MODE_NEG_HSYNC) ? 1 : 0) |
+ ((pMode->flags & GFX_MODE_NEG_VSYNC) ? 2 : 0));
+
+ /* RESTORE VALUE OF DC3_UNLOCK */
+
+ WRITE_REG32(DC3_UNLOCK, unlock);
+
+ /* RESET THE PITCH VALUES IN THE GP */
+
+ gfx_reset_pitch((unsigned short)pitch);
+
+ gfx_set_bpp((unsigned short)bpp);
+
+ return GFX_STATUS_OK;
+}
+
+ /*---------------------------------------------------------------------------
+ * GFX_IS_DISPLAY_MODE_SUPPORTED
+ *
+ * This routine sets the specified display mode.
+ *
+ * Returns 1 if successful, 0 if mode could not be set.
+ *----------------------------------------------------------------------------
+ */
+#if GFX_DISPLAY_DYNAMIC
+int
+gu3_is_display_mode_supported(int xres, int yres, int bpp, int hz)
+#else
+int
+gfx_is_display_mode_supported(int xres, int yres, int bpp, int hz)
+#endif
+{
+ unsigned int mode;
+ unsigned long hz_flag = 0, bpp_flag = 0;
+
+ /* SET FLAGS TO MATCH REFRESH RATE */
+ gfx_mode_hz_conversion
+ /* SET BPP FLAGS TO LIMIT MODE SELECTION */
+ gfx_mode_bpp_conversion
+ /* LOOP THROUGH THE AVAILABLE MODES TO FIND A MATCH */
+ for (mode = 0; mode < NUM_RC_DISPLAY_MODES; mode++) {
+ if ((DisplayParams[mode].hactive == (unsigned short)xres) &&
+ (DisplayParams[mode].vactive == (unsigned short)yres) &&
+ (DisplayParams[mode].flags & hz_flag) &&
+ (DisplayParams[mode].flags & bpp_flag)) {
+
+ /* CASTLE DOES NOT SUPPORT EMULATED VGA MODES */
+
+ if ((DisplayParams[mode].flags & GFX_MODE_PIXEL_DOUBLE) ||
+ (DisplayParams[mode].flags & GFX_MODE_LINE_DOUBLE))
+ continue;
+
+ /* SET THE DISPLAY CONTROLLER FOR THE SELECTED MODE */
+
+ return (mode);
+ }
+ }
+ return (-1);
+}
+
+/*----------------------------------------------------------------------------
+ * gfx_set_display_mode
+ *
+ * This routine sets the specified display mode.
+ *
+ * Returns 1 if successful, 0 if mode could not be set.
+ *----------------------------------------------------------------------------
+ */
+#if GFX_DISPLAY_DYNAMIC
+int
+gu3_set_display_mode(int xres, int yres, int bpp, int hz)
+#else
+int
+gfx_set_display_mode(int xres, int yres, int bpp, int hz)
+#endif
+{
+ int mode;
+
+ /* DISABLE FLAT PANEL */
+ /* Flat Panel settings are enabled by the function gfx_set_fixed_timings
+ * and disabled by gfx_set_display_mode.
+ * */
+
+ PanelEnable = 0;
+
+ mode = gfx_is_display_mode_supported(xres, yres, bpp, hz);
+ if (mode >= 0) {
+ if (gu3_set_specified_mode(&DisplayParams[mode],
+ bpp) == GFX_STATUS_OK)
+ return (1);
+ }
+ return (0);
+}
+
+/*----------------------------------------------------------------------------
+ * GFX_SET_DISPLAY_TIMINGS
+ *
+ * This routine sets the display controller mode using the specified timing
+ * values (as opposed to using the tables internal to Durango).
+ *
+ * Returns GFX_STATUS_OK ON SUCCESS, GFX_STATUS_ERROR otherwise.
+ *----------------------------------------------------------------------------
+ */
+#if GFX_DISPLAY_DYNAMIC
+int
+gu3_set_display_timings(unsigned short bpp, unsigned short flags,
+ unsigned short hactive, unsigned short hblankstart,
+ unsigned short hsyncstart, unsigned short hsyncend,
+ unsigned short hblankend, unsigned short htotal,
+ unsigned short vactive, unsigned short vblankstart,
+ unsigned short vsyncstart, unsigned short vsyncend,
+ unsigned short vblankend, unsigned short vtotal, unsigned long frequency)
+#else
+int
+gfx_set_display_timings(unsigned short bpp, unsigned short flags,
+ unsigned short hactive, unsigned short hblankstart,
+ unsigned short hsyncstart, unsigned short hsyncend,
+ unsigned short hblankend, unsigned short htotal,
+ unsigned short vactive, unsigned short vblankstart,
+ unsigned short vsyncstart, unsigned short vsyncend,
+ unsigned short vblankend, unsigned short vtotal, unsigned long frequency)
+#endif
+{
+ /* SET MODE STRUCTURE WITH SPECIFIED VALUES */
+
+ gfx_display_mode.flags = 0;
+ if (flags & 1)
+ gfx_display_mode.flags |= GFX_MODE_NEG_HSYNC;
+ if (flags & 2)
+ gfx_display_mode.flags |= GFX_MODE_NEG_VSYNC;
+ if (flags & 0x1000)
+ gfx_display_mode.flags |= GFX_MODE_LOCK_TIMING;
+ gfx_display_mode.hactive = hactive;
+ gfx_display_mode.hblankstart = hblankstart;
+ gfx_display_mode.hsyncstart = hsyncstart;
+ gfx_display_mode.hsyncend = hsyncend;
+ gfx_display_mode.hblankend = hblankend;
+ gfx_display_mode.htotal = htotal;
+ gfx_display_mode.vactive = vactive;
+ gfx_display_mode.vblankstart = vblankstart;
+ gfx_display_mode.vsyncstart = vsyncstart;
+ gfx_display_mode.vsyncend = vsyncend;
+ gfx_display_mode.vblankend = vblankend;
+ gfx_display_mode.vtotal = vtotal;
+ gfx_display_mode.frequency = frequency;
+
+ /* CALL ROUTINE TO SET MODE */
+
+ return (gu3_set_specified_mode(&gfx_display_mode, bpp));
+}
+
+/*----------------------------------------------------------------------------
+ * GFX_SET_VTOTAL
+ *
+ * This routine sets the display controller vertical total to
+ * "vtotal". As a side effect it also sets vertical blank end.
+ * It should be used when only this value needs to be changed,
+ * due to speed considerations.
+ *
+ * Note: it is the caller's responsibility to make sure that
+ * a legal vtotal is used, i.e. that "vtotal" is greater than or
+ * equal to vsync end.
+ *
+ * Always returns 0.
+ *----------------------------------------------------------------------------
+ */
+#if GFX_DISPLAY_DYNAMIC
+int
+gu3_set_vtotal(unsigned short vtotal)
+#else
+int
+gfx_set_vtotal(unsigned short vtotal)
+#endif
+{
+ unsigned long unlock, dcfg, vactive, vblank;
+
+ /* UNLOCK THE DISPLAY CONTROLLER REGISTERS */
+
+ unlock = READ_REG32(DC3_UNLOCK);
+ WRITE_REG32(DC3_UNLOCK, DC3_UNLOCK_VALUE);
+
+ /* READ THE CURRENT RC VALUES */
+
+ dcfg = READ_REG32(DC3_DISPLAY_CFG);
+ vactive = READ_REG32(DC3_V_ACTIVE_TIMING);
+ vblank = READ_REG32(DC3_V_BLANK_TIMING);
+
+ /* DISABLE TIMING REGISTER UPDATES */
+
+ WRITE_REG32(DC3_DISPLAY_CFG, dcfg & ~(unsigned long)DC3_DCFG_TRUP);
+
+ /* WRITE NEW TIMING VALUES */
+
+ WRITE_REG32(DC3_V_ACTIVE_TIMING,
+ (vactive & DC3_VAT_VA_MASK) | (unsigned long)(vtotal - 1) << 16);
+ WRITE_REG32(DC3_V_BLANK_TIMING,
+ (vblank & DC3_VBT_VBS_MASK) | (unsigned long)(vtotal - 1) << 16);
+
+ /* RESTORE OLD RC VALUES */
+
+ WRITE_REG32(DC3_DISPLAY_CFG, dcfg);
+ WRITE_REG32(DC3_UNLOCK, unlock);
+
+ return (0);
+}
+
+/*---------------------------------------------------------------------------
+ * gfx_set_display_pitch
+ *
+ * This routine sets the pitch of the frame buffer to the specified value.
+ *---------------------------------------------------------------------------
+ */
+#if GFX_DISPLAY_DYNAMIC
+void
+gu3_set_display_pitch(unsigned short pitch)
+#else
+void
+gfx_set_display_pitch(unsigned short pitch)
+#endif
+{
+ unsigned long value = 0;
+ unsigned long lock = READ_REG32(DC3_UNLOCK);
+
+ value = READ_REG32(DC3_GFX_PITCH) & 0xFFFF0000;
+ value |= (pitch >> 3);
+ WRITE_REG32(DC3_UNLOCK, DC3_UNLOCK_VALUE);
+ WRITE_REG32(DC3_GFX_PITCH, value);
+
+ /* SET RENDERING PITCHES TO MATCH */
+
+ gfx_reset_pitch(pitch);
+
+ /* SET THE FRAME DIRTY MODE */
+ /* Non-standard pitches, i.e. pitches that */
+ /* are not 1K, 2K or 4K must mark the entire */
+ /* frame as dirty when writing to the frame */
+ /* buffer. */
+
+ value = READ_REG32(DC3_GENERAL_CFG);
+
+ if (pitch == 1024 || pitch == 2048 || pitch == 4096 || pitch == 8192)
+ value &= ~(unsigned long)(DC3_GCFG_FDTY);
+ else
+ value |= (unsigned long)(DC3_GCFG_FDTY);
+
+ WRITE_REG32(DC3_GENERAL_CFG, value);
+ WRITE_REG32(DC3_UNLOCK, lock);
+}
+
+/*---------------------------------------------------------------------------
+ * gfx_set_display_offset
+ *
+ * This routine sets the start address of the frame buffer. It is
+ * typically used to pan across a virtual desktop (frame buffer larger than
+ * the displayed screen) or to flip the display between multiple buffers.
+ *---------------------------------------------------------------------------
+ */
+#if GFX_DISPLAY_DYNAMIC
+void
+gu3_set_display_offset(unsigned long offset)
+#else
+void
+gfx_set_display_offset(unsigned long offset)
+#endif
+{
+ /* UPDATE FRAME BUFFER OFFSET */
+ unsigned long lock;
+
+ lock = READ_REG32(DC3_UNLOCK);
+ WRITE_REG32(DC3_UNLOCK, DC3_UNLOCK_VALUE);
+
+ /* START ADDRESS EFFECTS DISPLAY COMPRESSION */
+ /* Disable compression for non-zero start addresss values. */
+ /* Enable compression if offset is zero and comression is intended to */
+ /* be enabled from a previous call to "gfx_set_compression_enable". */
+ /* Compression should be disabled BEFORE the offset is changed */
+ /* and enabled AFTER the offset is changed. */
+
+ if (offset == 0) {
+ WRITE_REG32(DC3_FB_ST_OFFSET, offset);
+ if (gfx_compression_enabled) {
+ /* WAIT FOR THE OFFSET TO BE LATCHED */
+ gfx_wait_vertical_blank();
+ gu3_enable_compression();
+ }
+ } else {
+ /* ONLY DISABLE COMPRESSION ONCE */
+
+ if (gfx_compression_active)
+ gu3_disable_compression();
+
+ WRITE_REG32(DC3_FB_ST_OFFSET, offset);
+ }
+
+ WRITE_REG32(DC3_UNLOCK, lock);
+}
+
+/*---------------------------------------------------------------------------
+ * gfx_set_display_palette_entry
+ *
+ * This routine sets an palette entry in the display controller.
+ * A 32-bit X:R:G:B value.
+ *---------------------------------------------------------------------------
+ */
+#if GFX_DISPLAY_DYNAMIC
+int
+gu3_set_display_palette_entry(unsigned long index, unsigned long palette)
+#else
+int
+gfx_set_display_palette_entry(unsigned long index, unsigned long palette)
+#endif
+{
+ if (index > 0xFF)
+ return GFX_STATUS_BAD_PARAMETER;
+
+ WRITE_REG32(DC3_PAL_ADDRESS, index);
+ WRITE_REG32(DC3_PAL_DATA, palette);
+
+ return (0);
+}
+
+/*---------------------------------------------------------------------------
+ * gfx_set_display_palette
+ *
+ * This routine sets the entire palette in the display controller.
+ * A pointer is provided to a 256 entry table of 32-bit X:R:G:B values.
+ *---------------------------------------------------------------------------
+ */
+#if GFX_DISPLAY_DYNAMIC
+int
+gu3_set_display_palette(unsigned long *palette)
+#else
+int
+gfx_set_display_palette(unsigned long *palette)
+#endif
+{
+ unsigned long i;
+
+ WRITE_REG32(DC3_PAL_ADDRESS, 0);
+
+ if (palette) {
+ for (i = 0; i < 256; i++) {
+ WRITE_REG32(DC3_PAL_DATA, palette[i]);
+ }
+ }
+ return (0);
+}
+
+/*---------------------------------------------------------------------------
+ * gfx_set_cursor_enable
+ *
+ * This routine enables or disables the hardware cursor.
+ *
+ * WARNING: The cursor start offset must be set by setting the cursor
+ * position before calling this routine to assure that memory reads do not
+ * go past the end of graphics memory (this can hang GXm).
+ *---------------------------------------------------------------------------
+ */
+#if GFX_DISPLAY_DYNAMIC
+void
+gu3_set_cursor_enable(int enable)
+#else
+void
+gfx_set_cursor_enable(int enable)
+#endif
+{
+ unsigned long unlock, gcfg;
+
+ /* SET OR CLEAR CURSOR ENABLE BIT */
+
+ unlock = READ_REG32(DC3_UNLOCK);
+ gcfg = READ_REG32(DC3_GENERAL_CFG);
+ if (enable)
+ gcfg |= DC3_GCFG_CURE;
+ else
+ gcfg &= ~(DC3_GCFG_CURE);
+
+ /* WRITE NEW REGISTER VALUE */
+
+ WRITE_REG32(DC3_UNLOCK, DC3_UNLOCK_VALUE);
+ WRITE_REG32(DC3_GENERAL_CFG, gcfg);
+ WRITE_REG32(DC3_UNLOCK, unlock);
+}
+
+/*---------------------------------------------------------------------------
+ * gfx_set_cursor_colors
+ *
+ * This routine sets the colors of the hardware cursor.
+ *---------------------------------------------------------------------------
+ */
+#if GFX_DISPLAY_DYNAMIC
+void
+gu3_set_cursor_colors(unsigned long bkcolor, unsigned long fgcolor)
+#else
+void
+gfx_set_cursor_colors(unsigned long bkcolor, unsigned long fgcolor)
+#endif
+{
+ /* SET CURSOR COLORS */
+
+ WRITE_REG32(DC3_PAL_ADDRESS, 0x100);
+ WRITE_REG32(DC3_PAL_DATA, bkcolor);
+ WRITE_REG32(DC3_PAL_DATA, fgcolor);
+}
+
+/*---------------------------------------------------------------------------
+ * gfx_set_cursor_position
+ *
+ * This routine sets the position of the hardware cusror. The starting
+ * offset of the cursor buffer must be specified so that the routine can
+ * properly clip scanlines if the cursor is off the top of the screen.
+ *---------------------------------------------------------------------------
+ */
+#if GFX_DISPLAY_DYNAMIC
+void
+gu3_set_cursor_position(unsigned long memoffset,
+ unsigned short xpos, unsigned short ypos,
+ unsigned short xhotspot, unsigned short yhotspot)
+#else
+void
+gfx_set_cursor_position(unsigned long memoffset,
+ unsigned short xpos, unsigned short ypos,
+ unsigned short xhotspot, unsigned short yhotspot)
+#endif
+{
+ unsigned long unlock;
+
+ short x = (short)xpos - (short)xhotspot;
+ short y = (short)ypos - (short)yhotspot;
+ short xoffset = 0;
+ short yoffset = 0;
+
+ if (x < -63)
+ return;
+ if (y < -63)
+ return;
+
+ if (PanelEnable) {
+ if ((ModeWidth > PanelWidth) || (ModeHeight > PanelHeight)) {
+ gfx_enable_panning(xpos, ypos);
+ x = x - (unsigned short)panelLeft;
+ y = y - (unsigned short)panelTop;
+ }
+ }
+
+ /* ADJUST OFFSETS */
+ /* Cursor movement and panning work as follows: The cursor position */
+ /* refers to where the hotspot of the cursor is located. However, for */
+ /* non-zero hotspots, the cursor buffer actually begins before the */
+ /* specified position. */
+
+ if (x < 0) {
+ xoffset = -x;
+ x = 0;
+ }
+ if (y < 0) {
+ yoffset = -y;
+ y = 0;
+ }
+ memoffset += (unsigned long)yoffset << 4;
+
+ /* SET CURSOR POSITION */
+
+ unlock = READ_REG32(DC3_UNLOCK);
+ WRITE_REG32(DC3_UNLOCK, DC3_UNLOCK_VALUE);
+ WRITE_REG32(DC3_CURS_ST_OFFSET, memoffset);
+ WRITE_REG32(DC3_CURSOR_X, (unsigned long)x |
+ (((unsigned long)xoffset) << 11));
+ WRITE_REG32(DC3_CURSOR_Y, (unsigned long)y |
+ (((unsigned long)yoffset) << 11));
+ WRITE_REG32(DC3_UNLOCK, unlock);
+}
+
+/*---------------------------------------------------------------------------
+ * gfx_set_cursor_shape32
+ *
+ * This routine loads 32x32 cursor data into the cursor buffer in graphics
+ * memory.
+ * As the Castle cursor is actually 64x64, we must pad the outside of the
+ * cursor data with transparent pixels.
+ *---------------------------------------------------------------------------
+ */
+#if GFX_DISPLAY_DYNAMIC
+void
+gu3_set_cursor_shape32(unsigned long memoffset,
+ unsigned long *andmask, unsigned long *xormask)
+#else
+void
+gfx_set_cursor_shape32(unsigned long memoffset,
+ unsigned long *andmask, unsigned long *xormask)
+#endif
+{
+ int i;
+
+ for (i = 0; i < 32; i++) {
+ /* EVEN QWORDS CONTAIN THE AND MASK */
+
+ WRITE_FB32(memoffset, 0xFFFFFFFF);
+ WRITE_FB32(memoffset + 4, andmask[i]);
+
+ /* ODD QWORDS CONTAIN THE XOR MASK */
+
+ WRITE_FB32(memoffset + 8, 0x00000000);
+ WRITE_FB32(memoffset + 12, xormask[i]);
+
+ memoffset += 16;
+ }
+
+ /* FILL THE LOWER HALF OF THE BUFFER WITH TRANSPARENT PIXELS */
+
+ for (i = 0; i < 32; i++) {
+ WRITE_FB32(memoffset, 0xFFFFFFFF);
+ WRITE_FB32(memoffset + 4, 0xFFFFFFFF);
+ WRITE_FB32(memoffset + 8, 0x00000000);
+ WRITE_FB32(memoffset + 12, 0x00000000);
+
+ memoffset += 16;
+ }
+}
+
+/*---------------------------------------------------------------------------
+ * gfx_set_cursor_shape64
+ *
+ * This routine loads 64x64 cursor data into the cursor buffer in graphics
+ * memory.
+ *---------------------------------------------------------------------------
+ */
+#if GFX_DISPLAY_DYNAMIC
+void
+gu3_set_cursor_shape64(unsigned long memoffset,
+ unsigned long *andmask, unsigned long *xormask)
+#else
+void
+gfx_set_cursor_shape64(unsigned long memoffset,
+ unsigned long *andmask, unsigned long *xormask)
+#endif
+{
+ int i;
+
+ for (i = 0; i < 128; i += 2) {
+ /* EVEN QWORDS CONTAIN THE AND MASK */
+ /* We invert the dwords to prevent the calling */
+ /* application from having to think in terms of Qwords. */
+ /* The hardware data order is actually 63:0, or 31:0 of */
+ /* the second dword followed by 31:0 of the first dword. */
+
+ WRITE_FB32(memoffset, andmask[i + 1]);
+ WRITE_FB32(memoffset + 4, andmask[i]);
+
+ /* ODD QWORDS CONTAIN THE XOR MASK */
+
+ WRITE_FB32(memoffset + 8, xormask[i + 1]);
+ WRITE_FB32(memoffset + 12, xormask[i]);
+
+ memoffset += 16;
+ }
+}
+
+/*---------------------------------------------------------------------------
+ * gu3_enable_compression
+ *
+ * This is a private routine to this module (not exposed in the Durango API).
+ * It enables display compression.
+ *---------------------------------------------------------------------------
+ */
+void
+gu3_enable_compression(void)
+{
+ unsigned long unlock, gcfg, temp;
+
+ /* DO NOT ENABLE IF START ADDRESS IS NOT ZERO */
+
+ if (READ_REG32(DC3_FB_ST_OFFSET) & 0x0FFFFFFF)
+ return;
+
+ /* SET GLOBAL INDICATOR */
+
+ gfx_compression_active = 1;
+
+ /* CLEAR DIRTY/VALID BITS IN MEMORY CONTROLLER */
+ /* Software is required to do this before enabling compression. */
+ /* Don't want controller to think that old lines are still valid. */
+ /* Writing a 1 to bit 0 of the DV Control register will force the */
+ /* hardware to clear all the valid bits. */
+
+ unlock = READ_REG32(DC3_UNLOCK);
+ temp = READ_REG32(DC3_DV_CTL);
+ WRITE_REG32(DC3_UNLOCK, DC3_UNLOCK_VALUE);
+ WRITE_REG32(DC3_DV_CTL, temp | 0x00000001);
+
+ /* TURN ON COMPRESSION CONTROL BITS */
+
+ gcfg = READ_REG32(DC3_GENERAL_CFG);
+ gcfg |= DC3_GCFG_CMPE | DC3_GCFG_DECE;
+
+ WRITE_REG32(DC3_GENERAL_CFG, gcfg);
+ WRITE_REG32(DC3_UNLOCK, unlock);
+}
+
+/*---------------------------------------------------------------------------
+ * gu3_disable_compression
+ *
+ * This is a private routine to this module (not exposed in the Durango API).
+ * It disables display compression.
+ *---------------------------------------------------------------------------
+ */
+void
+gu3_disable_compression(void)
+{
+ unsigned long unlock, gcfg;
+
+ /* SET GLOBAL INDICATOR */
+
+ gfx_compression_active = 0;
+
+ /* TURN OFF COMPRESSION CONTROL BITS */
+
+ unlock = READ_REG32(DC3_UNLOCK);
+ gcfg = READ_REG32(DC3_GENERAL_CFG);
+ gcfg &= ~(DC3_GCFG_CMPE | DC3_GCFG_DECE);
+ WRITE_REG32(DC3_UNLOCK, DC3_UNLOCK_VALUE);
+ WRITE_REG32(DC3_GENERAL_CFG, gcfg);
+ WRITE_REG32(DC3_UNLOCK, unlock);
+}
+
+/*---------------------------------------------------------------------------
+ * gfx_set_compression_enable
+ *
+ * This routine enables or disables display compression.
+ *---------------------------------------------------------------------------
+ */
+#if GFX_DISPLAY_DYNAMIC
+int
+gu3_set_compression_enable(int enable)
+#else
+int
+gfx_set_compression_enable(int enable)
+#endif
+{
+ /* SET GLOBAL VARIABLE FOR INDENDED STATE */
+ /* Compression can only be enabled for non-zero start address values. */
+ /* Keep state to enable compression on start address changes. */
+
+ gfx_compression_enabled = enable;
+ if (enable)
+ gu3_enable_compression();
+ else
+ gu3_disable_compression();
+ return (0);
+}
+
+/*---------------------------------------------------------------------------
+ * gfx_set_compression_offset
+ *
+ * This routine sets the base offset for the compression buffer.
+ *---------------------------------------------------------------------------
+ */
+#if GFX_DISPLAY_DYNAMIC
+int
+gu3_set_compression_offset(unsigned long offset)
+#else
+int
+gfx_set_compression_offset(unsigned long offset)
+#endif
+{
+ unsigned long lock;
+
+ /* MUST BE 16-BYTE ALIGNED FOR CASTLE */
+
+ if (offset & 0x0F)
+ return (1);
+
+ /* SET REGISTER VALUE */
+
+ lock = READ_REG32(DC3_UNLOCK);
+ WRITE_REG32(DC3_UNLOCK, DC3_UNLOCK_VALUE);
+ WRITE_REG32(DC3_CB_ST_OFFSET, offset & 0x0FFFFFFF);
+ WRITE_REG32(DC3_UNLOCK, lock);
+
+ return (0);
+}
+
+/*---------------------------------------------------------------------------
+ * gfx_set_compression_pitch
+ *
+ * This routine sets the pitch, in bytes, of the compression buffer.
+ *---------------------------------------------------------------------------
+ */
+#if GFX_DISPLAY_DYNAMIC
+int
+gu3_set_compression_pitch(unsigned short pitch)
+#else
+int
+gfx_set_compression_pitch(unsigned short pitch)
+#endif
+{
+ unsigned long lock, line_delta;
+
+ lock = READ_REG32(DC3_UNLOCK);
+
+ /* SET REGISTER VALUE */
+
+ line_delta = READ_REG32(DC3_GFX_PITCH) & 0x0000FFFF;
+ line_delta |= (((unsigned long)pitch << 13) & 0xFFFF0000);
+ WRITE_REG32(DC3_UNLOCK, DC3_UNLOCK_VALUE);
+ WRITE_REG32(DC3_GFX_PITCH, line_delta);
+ WRITE_REG32(DC3_UNLOCK, lock);
+ return (0);
+}
+
+/*---------------------------------------------------------------------------
+ * gfx_set_compression_size
+ *
+ * This routine sets the line size of the compression buffer, which is the
+ * maximum number of bytes allowed to store a compressed line.
+ *---------------------------------------------------------------------------
+ */
+#if GFX_DISPLAY_DYNAMIC
+int
+gu3_set_compression_size(unsigned short size)
+#else
+int
+gfx_set_compression_size(unsigned short size)
+#endif
+{
+ unsigned long lock, buf_size;
+
+ /* SUBTRACT 32 FROM SIZE */
+ /* The display controller will actually write */
+ /* 4 extra QWords. So, if we assume that "size" */
+ /* refers to the allocated size, we must subtract */
+ /* 32 bytes. */
+
+ size -= 32;
+
+ /* SET REGISTER VALUE */
+
+ lock = READ_REG32(DC3_UNLOCK);
+ buf_size = READ_REG32(DC3_LINE_SIZE) & ~DC3_LINE_SIZE_CBLS_MASK;
+ buf_size |=
+ ((((unsigned long)size >> 3) + 1) & 0x7F) << DC3_LINE_SIZE_CB_SHIFT;
+ WRITE_REG32(DC3_UNLOCK, DC3_UNLOCK_VALUE);
+ WRITE_REG32(DC3_LINE_SIZE, buf_size);
+ WRITE_REG32(DC3_UNLOCK, lock);
+ return (0);
+}
+
+/*---------------------------------------------------------------------------
+ * gfx_set_display_video_color_key (PRIVATE ROUTINE - NOT PART OF API)
+ *
+ * This routine is called by "gfx_set_video_color_key". It abstracts the
+ * version of the display controller from the video overlay routines.
+ *---------------------------------------------------------------------------
+ */
+#if GFX_DISPLAY_DYNAMIC
+void
+gu3_set_display_video_color_key(unsigned long key, unsigned long mask,
+ int enable)
+#else
+void
+gfx_set_display_video_color_key(unsigned long key, unsigned long mask,
+ int enable)
+#endif
+{
+ unsigned long colorkey = 0;
+ unsigned long lock;
+
+ if (enable)
+ colorkey = (key & 0xFFFFFF) | DC3_CLR_KEY_ENABLE;
+
+ lock = READ_REG32(DC3_UNLOCK);
+ WRITE_REG32(DC3_UNLOCK, DC3_UNLOCK_VALUE);
+
+ WRITE_REG32(DC3_COLOR_KEY, colorkey);
+ WRITE_REG32(DC3_COLOR_MASK, (mask & 0xFFFFFF));
+
+ WRITE_REG32(DC3_UNLOCK, lock);
+}
+
+/*---------------------------------------------------------------------------
+ * gfx_set_display_video_format (PRIVATE ROUTINE - NOT PART OF API)
+ *
+ * This routine is called by "gfx_set_video_format". It abstracts the
+ * version of the display controller from the video overlay routines.
+ *---------------------------------------------------------------------------
+ */
+#if GFX_DISPLAY_DYNAMIC
+void
+gu3_set_display_video_format(unsigned long format)
+#else
+void
+gfx_set_display_video_format(unsigned long format)
+#endif
+{
+ unsigned long gcfg, lock;
+
+ lock = READ_REG32(DC3_UNLOCK);
+ gcfg = READ_REG32(DC3_GENERAL_CFG);
+
+ switch (format) {
+ case VIDEO_FORMAT_Y0Y1Y2Y3:
+ case VIDEO_FORMAT_Y3Y2Y1Y0:
+ case VIDEO_FORMAT_Y1Y0Y3Y2:
+ case VIDEO_FORMAT_Y1Y2Y3Y0:
+ gcfg |= DC3_GCFG_YUVM;
+ break;
+
+ default:
+ gcfg &= ~DC3_GCFG_YUVM;
+ break;
+ }
+
+ WRITE_REG32(DC3_UNLOCK, DC3_UNLOCK_VALUE);
+ WRITE_REG32(DC3_GENERAL_CFG, gcfg);
+ WRITE_REG32(DC3_UNLOCK, lock);
+}
+
+/*---------------------------------------------------------------------------
+ * gfx_set_display_video_enable (PRIVATE ROUTINE - NOT PART OF API)
+ *
+ * This routine is called by "gfx_set_video_enable". It abstracts the
+ * version of the display controller from the video overlay routines.
+ *---------------------------------------------------------------------------
+ */
+#if GFX_DISPLAY_DYNAMIC
+void
+gu3_set_display_video_enable(int enable)
+#else
+void
+gfx_set_display_video_enable(int enable)
+#endif
+{
+ unsigned long lock, gcfg, dcfg;
+
+ /* READ CURRENT VALUES */
+
+ lock = READ_REG32(DC3_UNLOCK);
+ gcfg = READ_REG32(DC3_GENERAL_CFG);
+ dcfg = READ_REG32(DC3_DISPLAY_CFG);
+
+ /* SET OR CLEAR VIDEO ENABLE IN GENERAL_CFG */
+
+ if (enable)
+ gcfg |= DC3_GCFG_VIDE;
+ else
+ gcfg &= ~DC3_GCFG_VIDE;
+
+ /* WRITE REGISTER */
+
+ WRITE_REG32(DC3_UNLOCK, DC3_UNLOCK_VALUE);
+ WRITE_REG32(DC3_GENERAL_CFG, gcfg);
+ WRITE_REG32(DC3_UNLOCK, lock);
+}
+
+/*---------------------------------------------------------------------------
+ * gfx_set_display_video_size (PRIVATE ROUTINE - NOT PART OF API)
+ *
+ * This routine is called by "gfx_set_video_size". It abstracts the
+ * version of the display controller from the video overlay routines.
+ *---------------------------------------------------------------------------
+ */
+#if GFX_DISPLAY_DYNAMIC
+void
+gu3_set_display_video_size(unsigned short width, unsigned short height)
+#else
+void
+gfx_set_display_video_size(unsigned short width, unsigned short height)
+#endif
+{
+ unsigned long lock, value, yuv_420;
+
+ /* READ CURRENT VALUES */
+
+ lock = READ_REG32(DC3_UNLOCK);
+ value = READ_REG32(DC3_LINE_SIZE) & ~DC3_LINE_SIZE_VLS_MASK;
+ yuv_420 = READ_REG32(DC3_GENERAL_CFG) & DC3_GCFG_YUVM;
+
+ /* LINE WIDTH IS 1/4 FOR 4:2:0 VIDEO */
+ /* All data must be 32-byte aligned. */
+
+ if (yuv_420) {
+ width >>= 1;
+ width = (width + 7) & 0xFFF8;
+ } else {
+ width <<= 1;
+ width = (width + 31) & 0xFFE0;
+ }
+
+ /* ONLY THE LINE SIZE IS PROGRAMMED IN THE DISPLAY CONTROLLER */
+ /* Shift by three less than the bit position to effect a divide by 8 */
+
+ value |=
+ ((unsigned long)width << (DC3_LINE_SIZE_VB_SHIFT -
+ 3)) & DC3_LINE_SIZE_VLS_MASK;
+
+ /* WRITE THE REGISTER */
+
+ WRITE_REG32(DC3_UNLOCK, DC3_UNLOCK_VALUE);
+ WRITE_REG32(DC3_LINE_SIZE, value);
+ WRITE_REG32(DC3_UNLOCK, lock);
+}
+
+/*---------------------------------------------------------------------------
+ * gfx_set_display_video_offset (PRIVATE ROUTINE - NOT PART OF API)
+ *
+ * This routine is called by "gfx_set_video_offset". It abstracts the
+ * version of the display controller from the video overlay routines.
+ *---------------------------------------------------------------------------
+ */
+#if GFX_DISPLAY_DYNAMIC
+void
+gu3_set_display_video_offset(unsigned long offset)
+#else
+void
+gfx_set_display_video_offset(unsigned long offset)
+#endif
+{
+ unsigned long lock;
+
+ lock = READ_REG32(DC3_UNLOCK);
+ WRITE_REG32(DC3_UNLOCK, DC3_UNLOCK_VALUE);
+ offset &= 0x0FFFFFF0;
+ WRITE_REG32(DC3_VID_Y_ST_OFFSET, offset);
+ WRITE_REG32(DC3_UNLOCK, lock);
+}
+
+/*---------------------------------------------------------------------------
+ * gfx_set_display_video_yuv_offsets (PRIVATE ROUTINE - NOT PART OF API)
+ *
+ * This routine is called by gfx_set_video_yuv_offsets. It abstracts the
+ * version of the display controller from the video overlay routines.
+ *---------------------------------------------------------------------------
+ */
+#if GFX_DISPLAY_DYNAMIC
+void
+gu3_set_display_video_yuv_offsets(unsigned long yoffset,
+ unsigned long uoffset, unsigned long voffset)
+#else
+void
+gfx_set_display_video_yuv_offsets(unsigned long yoffset,
+ unsigned long uoffset, unsigned long voffset)
+#endif
+{
+ unsigned long lock;
+
+ lock = READ_REG32(DC3_UNLOCK);
+
+ yoffset &= 0x0FFFFFF0;
+ uoffset &= 0x0FFFFFF8;
+ voffset &= 0x0FFFFFF8;
+
+ WRITE_REG32(DC3_UNLOCK, DC3_UNLOCK_VALUE);
+ WRITE_REG32(DC3_VID_Y_ST_OFFSET, yoffset);
+ WRITE_REG32(DC3_VID_U_ST_OFFSET, uoffset);
+ WRITE_REG32(DC3_VID_V_ST_OFFSET, voffset);
+ WRITE_REG32(DC3_UNLOCK, lock);
+}
+
+/*---------------------------------------------------------------------------
+ * gfx_set_display_video_yuv_pitch (PRIVATE ROUTINE - NOT PART OF API)
+ *
+ * This routine is called by gfx_set_video_yuv_pitch. It abstracts the
+ * version of the display controller from the video overlay routines.
+ *---------------------------------------------------------------------------
+ */
+#if GFX_DISPLAY_DYNAMIC
+void
+gu3_set_display_video_yuv_pitch(unsigned long ypitch, unsigned long uvpitch)
+#else
+void
+gfx_set_display_video_yuv_pitch(unsigned long ypitch, unsigned long uvpitch)
+#endif
+{
+ unsigned long lock, pitch;
+
+ lock = READ_REG32(DC3_UNLOCK);
+
+ pitch = ((uvpitch << 13) & 0xFFFF0000) | ((ypitch >> 3) & 0xFFFF);
+
+ WRITE_REG32(DC3_UNLOCK, DC3_UNLOCK_VALUE);
+ WRITE_REG32(DC3_VID_YUV_PITCH, pitch);
+ WRITE_REG32(DC3_UNLOCK, lock);
+}
+
+/*---------------------------------------------------------------------------
+ * gfx_test_timing_active
+ *---------------------------------------------------------------------------
+ */
+#if GFX_DISPLAY_DYNAMIC
+int
+gu3_test_timing_active(void)
+#else
+int
+gfx_test_timing_active(void)
+#endif
+{
+ if (READ_REG32(DC3_DISPLAY_CFG) & DC3_DCFG_TGEN)
+ return (1);
+ else
+ return (0);
+}
+
+/*---------------------------------------------------------------------------
+ * gfx_test_vertical_active
+ *---------------------------------------------------------------------------
+ */
+#if GFX_DISPLAY_DYNAMIC
+int
+gu3_test_vertical_active(void)
+#else
+int
+gfx_test_vertical_active(void)
+#endif
+{
+ if (READ_REG32(DC3_LINE_CNT_STATUS) & DC3_LNCNT_VNA)
+ return (0);
+
+ return (1);
+}
+
+/*---------------------------------------------------------------------------
+ * gfx_wait_vertical_blank
+ *---------------------------------------------------------------------------
+ */
+#if GFX_DISPLAY_DYNAMIC
+int
+gu3_wait_vertical_blank(void)
+#else
+int
+gfx_wait_vertical_blank(void)
+#endif
+{
+ if (gfx_test_timing_active()) {
+ while (!gfx_test_vertical_active()) ;
+ while (gfx_test_vertical_active()) ;
+ }
+ return (0);
+}
+
+/*---------------------------------------------------------------------------
+ * gfx_enable_panning
+ *
+ * This routine enables the panning when the Mode is bigger than the panel
+ * size.
+ *---------------------------------------------------------------------------
+ */
+#if GFX_DISPLAY_DYNAMIC
+void
+gu3_enable_panning(int x, int y)
+#else
+void
+gfx_enable_panning(int x, int y)
+#endif
+{
+ unsigned long modeBytesPerPixel;
+ unsigned long modeBytesPerScanline = 0;
+ unsigned long startAddress = 0;
+
+ modeBytesPerPixel = (gbpp + 7) / 8;
+ modeBytesPerScanline = (READ_REG32(DC3_GFX_PITCH) & 0x0000FFFF) << 3;
+
+ /* TEST FOR NO-WORK */
+
+ if (x >= DeltaX && x < ((int)PanelWidth + DeltaX) &&
+ y >= DeltaY && y < ((int)PanelHeight + DeltaY))
+ return;
+
+ /* ADJUST PANNING VARIABLES WHEN CURSOR EXCEEDS BOUNDARY */
+ /* Test the boundary conditions for each coordinate and update */
+ /* all variables and the starting offset accordingly. */
+
+ if (x < DeltaX)
+ DeltaX = x;
+
+ else if (x >= (DeltaX + (int)PanelWidth))
+ DeltaX = x - (int)PanelWidth + 1;
+
+ if (y < DeltaY)
+ DeltaY = y;
+
+ else if (y >= (DeltaY + (int)PanelHeight))
+ DeltaY = y - (int)PanelHeight + 1;
+
+ /* CALCULATE THE START OFFSET */
+
+ startAddress =
+ (DeltaX * modeBytesPerPixel) + (DeltaY * modeBytesPerScanline);
+
+ gfx_set_display_offset(startAddress);
+
+ /* SET PANEL COORDINATES */
+ /* Panel's x position must be DWORD aligned */
+
+ panelTop = DeltaY;
+ panelLeft = DeltaX * modeBytesPerPixel;
+
+ if (panelLeft & 3)
+ panelLeft = (panelLeft & 0xFFFFFFFC) + 4;
+
+ panelLeft /= modeBytesPerPixel;
+}
+
+/*---------------------------------------------------------------------------
+ * gfx_set_fixed_timings
+ *---------------------------------------------------------------------------
+ */
+
+#if GFX_DISPLAY_DYNAMIC
+int
+gu3_set_fixed_timings(int panelResX, int panelResY, unsigned short width,
+ unsigned short height, unsigned short bpp)
+#else
+int
+gfx_set_fixed_timings(int panelResX, int panelResY, unsigned short width,
+ unsigned short height, unsigned short bpp)
+#endif
+{
+ unsigned int mode;
+
+ ModeWidth = width;
+ ModeHeight = height;
+ PanelWidth = (unsigned short)panelResX;
+ PanelHeight = (unsigned short)panelResY;
+ PanelEnable = 1;
+
+ /* LOOP THROUGH THE AVAILABLE MODES TO FIND A MATCH */
+ for (mode = 0; mode < NUM_FIXED_TIMINGS_MODES; mode++) {
+ if ((FixedParams[mode].xres == width) &&
+ (FixedParams[mode].yres == height) &&
+ (FixedParams[mode].panelresx == panelResX) &&
+ (FixedParams[mode].panelresy == panelResY)) {
+
+ /* SET THE 92xx FOR THE SELECTED MODE */
+ FIXEDTIMINGS *fmode = &FixedParams[mode];
+
+ gfx_set_display_timings(bpp, 3, fmode->hactive,
+ fmode->hblankstart, fmode->hsyncstart, fmode->hsyncend,
+ fmode->hblankend, fmode->htotal, fmode->vactive,
+ fmode->vblankstart, fmode->vsyncstart, fmode->vsyncend,
+ fmode->vblankend, fmode->vtotal, fmode->frequency);
+
+ return (1);
+ } /* end if() */
+ } /* end for() */
+
+ return (-1);
+}
+
+/*---------------------------------------------------------------------------
+ * gfx_set_panel_present
+ *---------------------------------------------------------------------------
+ */
+#if GFX_DISPLAY_DYNAMIC
+int
+gu3_set_panel_present(int panelResX, int panelResY, unsigned short width,
+ unsigned short height, unsigned short bpp)
+#else
+int
+gfx_set_panel_present(int panelResX, int panelResY, unsigned short width,
+ unsigned short height, unsigned short bpp)
+#endif
+{
+ /* SET VALID BPP */
+ /* 16BPP is the default. */
+
+ if (bpp != 8 && bpp != 12 && bpp != 15 && bpp != 16 && bpp != 32)
+ bpp = 16;
+
+ /* RECORD PANEL PARAMETERS */
+ /* This routine does not touch any panel timings. It is used when custom
+ * panel settings are set up in advance by the BIOS or an application,
+ * but the application still requires access to other panel functionality
+ * provided by Durango (i.e. panning).
+ * */
+ ModeWidth = width;
+ ModeHeight = height;
+ PanelWidth = (unsigned short)panelResX;
+ PanelHeight = (unsigned short)panelResY;
+ PanelEnable = 1;
+ gbpp = bpp;
+
+ /* PROGRAM THE BPP IN THE DISPLAY CONTROLLER */
+
+ gfx_set_display_bpp(bpp);
+
+ return (GFX_STATUS_OK);
+}
+
+/* THE FOLLOWING READ ROUTINES ARE ALWAYS INCLUDED: */
+
+/*---------------------------------------------------------------------------
+ * gfx_get_display_pitch
+ *
+ * This routine returns the current pitch of the frame buffer, in bytes.
+ *---------------------------------------------------------------------------
+ */
+#if GFX_DISPLAY_DYNAMIC
+unsigned short
+gu3_get_display_pitch(void)
+#else
+unsigned short
+gfx_get_display_pitch(void)
+#endif
+{
+ return ((unsigned short)(READ_REG32(DC3_GFX_PITCH) & 0x0000FFFF) << 3);
+}
+
+/*----------------------------------------------------------------------------
+ * gfx_mode_frequency_supported
+ *
+ * This routine examines if the requested mode with pixel frequency is
+ * supported.
+ *
+ * Returns >0 if successful , <0 if freq. could not be found and matched.
+ *----------------------------------------------------------------------------
+ */
+#if GFX_DISPLAY_DYNAMIC
+int
+gu3_mode_frequency_supported(int xres, int yres, int bpp,
+ unsigned long frequency)
+#else
+int
+gfx_mode_frequency_supported(int xres, int yres, int bpp,
+ unsigned long frequency)
+#endif
+{
+ unsigned int index;
+ unsigned long value;
+ unsigned long bpp_flag = 0;
+
+ gfx_mode_bpp_conversion_def(bpp)
+
+ for (index = 0; index < NUM_RC_DISPLAY_MODES; index++) {
+ if ((DisplayParams[index].hactive == (unsigned int)xres) &&
+ (DisplayParams[index].vactive == (unsigned int)yres) &&
+ (DisplayParams[index].flags & bpp_flag) &&
+ (DisplayParams[index].frequency == frequency)) {
+ int hz = 0;
+
+ value = DisplayParams[index].flags;
+
+ if (value & GFX_MODE_56HZ)
+ hz = 56;
+ else if (value & GFX_MODE_60HZ)
+ hz = 60;
+ else if (value & GFX_MODE_70HZ)
+ hz = 70;
+ else if (value & GFX_MODE_72HZ)
+ hz = 72;
+ else if (value & GFX_MODE_75HZ)
+ hz = 75;
+ else if (value & GFX_MODE_85HZ)
+ hz = 85;
+ else if (value & GFX_MODE_90HZ)
+ hz = 90;
+ else if (value & GFX_MODE_100HZ)
+ hz = 100;
+ return (hz);
+ }
+ }
+
+ return (-1);
+}
+
+/*----------------------------------------------------------------------------
+ * gfx_refreshrate_from_frequency
+ *
+ * This routine maps the frequency to close match refresh rate
+ *----------------------------------------------------------------------------
+ */
+#if GFX_DISPLAY_DYNAMIC
+int
+gu3_get_refreshrate_from_frequency(int xres, int yres, int bpp, int *hz,
+ unsigned long frequency)
+#else
+int
+gfx_get_refreshrate_from_frequency(int xres, int yres, int bpp, int *hz,
+ unsigned long frequency)
+#endif
+{
+ unsigned int index, closematch = 0;
+ unsigned long value;
+ unsigned long bpp_flag = 0;
+ long min, diff;
+
+ *hz = 60;
+
+ gfx_mode_bpp_conversion_def(bpp)
+
+ /* FIND THE REGISTER VALUES FOR THE DESIRED FREQUENCY */
+ /* Search the table for the closest frequency (16.16 format). */
+ min = 0x7fffffff;
+ for (index = 0; index < NUM_RC_DISPLAY_MODES; index++) {
+ if ((DisplayParams[index].htotal == (unsigned int)xres) &&
+ (DisplayParams[index].vtotal == (unsigned int)yres) &&
+ (DisplayParams[index].flags & bpp_flag)) {
+ diff = (long)frequency - (long)DisplayParams[index].frequency;
+ if (diff < 0)
+ diff = -diff;
+
+ if (diff < min) {
+ min = diff;
+ closematch = index;
+ }
+ }
+ }
+
+ value = DisplayParams[closematch].flags;
+
+ if (value & GFX_MODE_56HZ)
+ *hz = 56;
+ else if (value & GFX_MODE_60HZ)
+ *hz = 60;
+ else if (value & GFX_MODE_70HZ)
+ *hz = 70;
+ else if (value & GFX_MODE_72HZ)
+ *hz = 72;
+ else if (value & GFX_MODE_75HZ)
+ *hz = 75;
+ else if (value & GFX_MODE_85HZ)
+ *hz = 85;
+ else if (value & GFX_MODE_90HZ)
+ *hz = 90;
+ else if (value & GFX_MODE_100HZ)
+ *hz = 100;
+
+ return (1);
+}
+
+/*----------------------------------------------------------------------------
+ * gfx_refreshrate_from_mode
+ *
+ * This routine is identical to the gfx_get_refreshrate_from_frequency,
+ * except that the active timing values are compared instead of the total
+ * values. Some modes (such as 70Hz and 72Hz) may be confused in this routine
+ *----------------------------------------------------------------------------
+ */
+#if GFX_DISPLAY_DYNAMIC
+int
+gu3_get_refreshrate_from_mode(int xres, int yres, int bpp, int *hz,
+ unsigned long frequency)
+#else
+int
+gfx_get_refreshrate_from_mode(int xres, int yres, int bpp, int *hz,
+ unsigned long frequency)
+#endif
+{
+ unsigned int index, closematch = 0;
+ unsigned long value;
+ unsigned long bpp_flag = 0;
+ long min, diff;
+
+ *hz = 60;
+
+ gfx_mode_bpp_conversion_def(bpp)
+
+ /* FIND THE REGISTER VALUES FOR THE DESIRED FREQUENCY */
+ /* Search the table for the closest frequency (16.16 format). */
+ min = 0x7fffffff;
+ for (index = 0; index < NUM_RC_DISPLAY_MODES; index++) {
+ if ((DisplayParams[index].hactive == (unsigned int)xres) &&
+ (DisplayParams[index].vactive == (unsigned int)yres) &&
+ (DisplayParams[index].flags & bpp_flag)) {
+ diff = (long)frequency - (long)DisplayParams[index].frequency;
+ if (diff < 0)
+ diff = -diff;
+
+ if (diff < min) {
+ min = diff;
+ closematch = index;
+ }
+ }
+ }
+
+ value = DisplayParams[closematch].flags;
+
+ if (value & GFX_MODE_56HZ)
+ *hz = 56;
+ else if (value & GFX_MODE_60HZ)
+ *hz = 60;
+ else if (value & GFX_MODE_70HZ)
+ *hz = 70;
+ else if (value & GFX_MODE_72HZ)
+ *hz = 72;
+ else if (value & GFX_MODE_75HZ)
+ *hz = 75;
+ else if (value & GFX_MODE_85HZ)
+ *hz = 85;
+ else if (value & GFX_MODE_90HZ)
+ *hz = 90;
+ else if (value & GFX_MODE_100HZ)
+ *hz = 100;
+
+ return (1);
+}
+
+/*----------------------------------------------------------------------------
+ * gfx_get_frequency_from_refreshrate
+ *
+ * This routine maps the refresh rate to the closest matching PLL frequency.
+ *----------------------------------------------------------------------------
+ */
+#if GFX_DISPLAY_DYNAMIC
+int
+gu3_get_frequency_from_refreshrate(int xres, int yres, int bpp, int hz,
+ int *frequency)
+#else
+int
+gfx_get_frequency_from_refreshrate(int xres, int yres, int bpp, int hz,
+ int *frequency)
+#endif
+{
+ unsigned int index;
+ int retval = -1;
+ unsigned long hz_flag = 0;
+ unsigned long bpp_flag = 0;
+
+ *frequency = 0;
+
+ gfx_mode_hz_conversion gfx_mode_bpp_conversion_def(bpp)
+
+ /* FIND THE REGISTER VALUES FOR THE DESIRED FREQUENCY */
+ /* Search the table for the closest frequency (16.16 format). */
+ for (index = 0; index < NUM_RC_DISPLAY_MODES; index++) {
+ if ((DisplayParams[index].hactive == (unsigned short)xres) &&
+ (DisplayParams[index].vactive == (unsigned short)yres) &&
+ (DisplayParams[index].flags & bpp_flag) &&
+ (DisplayParams[index].flags & hz_flag)) {
+ *frequency = (int)DisplayParams[index].frequency;
+ retval = 1;
+ }
+ }
+ return retval;
+}
+
+/*---------------------------------------------------------------------------
+ * gfx_get_max_supported_pixel_clock
+ *
+ * This routine returns the maximum recommended speed for the pixel clock. The
+ * return value is an integer of the format xxxyyy, where xxx.yyy is the
+ * maximum floating point pixel clock speed.
+ *---------------------------------------------------------------------------
+ */
+#if GFX_DISPLAY_DYNAMIC
+unsigned long
+gu3_get_max_supported_pixel_clock(void)
+#else
+unsigned long
+gfx_get_max_supported_pixel_clock(void)
+#endif
+{
+ return 229500;
+}
+
+/*----------------------------------------------------------------------------
+ * gfx_get_display_mode
+ *
+ * This routine gets the specified display mode.
+ *
+ * Returns >0 if successful and mode returned, <0 if mode could not be found.
+ *----------------------------------------------------------------------------
+ */
+#if GFX_DISPLAY_DYNAMIC
+int
+gu3_get_display_mode(int *xres, int *yres, int *bpp, int *hz)
+#else
+int
+gfx_get_display_mode(int *xres, int *yres, int *bpp, int *hz)
+#endif
+{
+ unsigned int mode = 0;
+ unsigned long pll_freq = 0, bpp_flag = 0;
+
+ *xres = gfx_get_hactive();
+ *yres = gfx_get_vactive();
+ *bpp = gfx_get_display_bpp();
+ pll_freq = gfx_get_clock_frequency();
+
+ /* SET BPP FLAGS TO LIMIT MODE SELECTION */
+ gfx_mode_bpp_conversion_def(bpp)
+
+ for (mode = 0; mode < NUM_RC_DISPLAY_MODES; mode++) {
+ if ((DisplayParams[mode].hactive == (unsigned int)*xres) &&
+ (DisplayParams[mode].vactive == (unsigned int)*yres) &&
+ (DisplayParams[mode].frequency == pll_freq) &&
+ (DisplayParams[mode].flags & bpp_flag)) {
+
+ pll_freq = DisplayParams[mode].flags;
+
+ if (pll_freq & GFX_MODE_56HZ)
+ *hz = 56;
+ else if (pll_freq & GFX_MODE_60HZ)
+ *hz = 60;
+ else if (pll_freq & GFX_MODE_70HZ)
+ *hz = 70;
+ else if (pll_freq & GFX_MODE_72HZ)
+ *hz = 72;
+ else if (pll_freq & GFX_MODE_75HZ)
+ *hz = 75;
+ else if (pll_freq & GFX_MODE_85HZ)
+ *hz = 85;
+ else if (pll_freq & GFX_MODE_90HZ)
+ *hz = 90;
+ else if (pll_freq & GFX_MODE_100HZ)
+ *hz = 100;
+
+ return (1);
+ }
+ }
+ return (-1);
+}
+
+/*----------------------------------------------------------------------------
+ * GFX_GET_DISPLAY_DETAILS
+ *
+ * This routine gets the specified display mode.
+ *
+ * Returns 1 if successful, 0 if mode could not be get.
+ *----------------------------------------------------------------------------
+ */
+#if GFX_DISPLAY_DYNAMIC
+int
+gu3_get_display_details(unsigned int mode, int *xres, int *yres, int *hz)
+#else
+int
+gfx_get_display_details(unsigned int mode, int *xres, int *yres, int *hz)
+#endif
+{
+ if (mode < NUM_RC_DISPLAY_MODES) {
+ if (DisplayParams[mode].flags & GFX_MODE_56HZ)
+ *hz = 56;
+ else if (DisplayParams[mode].flags & GFX_MODE_60HZ)
+ *hz = 60;
+ else if (DisplayParams[mode].flags & GFX_MODE_70HZ)
+ *hz = 70;
+ else if (DisplayParams[mode].flags & GFX_MODE_72HZ)
+ *hz = 72;
+ else if (DisplayParams[mode].flags & GFX_MODE_75HZ)
+ *hz = 75;
+ else if (DisplayParams[mode].flags & GFX_MODE_85HZ)
+ *hz = 85;
+ else if (DisplayParams[mode].flags & GFX_MODE_90HZ)
+ *hz = 90;
+ else if (DisplayParams[mode].flags & GFX_MODE_100HZ)
+ *hz = 100;
+
+ *xres = DisplayParams[mode].hactive;
+ *yres = DisplayParams[mode].vactive;
+
+ if (DisplayParams[mode].flags & GFX_MODE_PIXEL_DOUBLE)
+ *xres >>= 1;
+ if (DisplayParams[mode].flags & GFX_MODE_LINE_DOUBLE)
+ *yres >>= 1;
+
+ return (1);
+ }
+ return (0);
+}
+
+/*----------------------------------------------------------------------------
+ * GFX_GET_DISPLAY_MODE_COUNT
+ *
+ * This routine gets the number of available display modes.
+ *----------------------------------------------------------------------------
+ */
+#if GFX_DISPLAY_DYNAMIC
+int
+gu3_get_display_mode_count(void)
+#else
+int
+gfx_get_display_mode_count(void)
+#endif
+{
+ return (NUM_RC_DISPLAY_MODES);
+}
+
+/*----------------------------------------------------------------------------
+ * gfx_get_frame_buffer_line_size
+ *
+ * Returns the current frame buffer line size, in bytes
+ *----------------------------------------------------------------------------
+ */
+#if GFX_DISPLAY_DYNAMIC
+unsigned long
+gu3_get_frame_buffer_line_size(void)
+#else
+unsigned long
+gfx_get_frame_buffer_line_size(void)
+#endif
+{
+ return ((READ_REG32(DC3_LINE_SIZE) & 0x3FF) << 3);
+}
+
+/*---------------------------------------------------------------------------
+ * gfx_get_hactive
+ *---------------------------------------------------------------------------
+ */
+#if GFX_DISPLAY_DYNAMIC
+unsigned short
+gu3_get_hactive(void)
+#else
+unsigned short
+gfx_get_hactive(void)
+#endif
+{
+ return ((unsigned short)((READ_REG32(DC3_H_ACTIVE_TIMING) & 0x0FF8) + 8));
+}
+
+/*---------------------------------------------------------------------------
+ * gfx_get_hsync_start
+ *---------------------------------------------------------------------------
+ */
+#if GFX_DISPLAY_DYNAMIC
+unsigned short
+gu3_get_hsync_start(void)
+#else
+unsigned short
+gfx_get_hsync_start(void)
+#endif
+{
+ return ((unsigned short)((READ_REG32(DC3_H_SYNC_TIMING) & 0x0FF8) + 8));
+}
+
+/*---------------------------------------------------------------------------
+ * gfx_get_hsync_end
+ *---------------------------------------------------------------------------
+ */
+#if GFX_DISPLAY_DYNAMIC
+unsigned short
+gu3_get_hsync_end(void)
+#else
+unsigned short
+gfx_get_hsync_end(void)
+#endif
+{
+ return ((unsigned short)(((READ_REG32(DC3_H_SYNC_TIMING) >> 16) & 0x0FF8)
+ + 8));
+}
+
+/*---------------------------------------------------------------------------
+ * gfx_get_htotal
+ *---------------------------------------------------------------------------
+ */
+#if GFX_DISPLAY_DYNAMIC
+unsigned short
+gu3_get_htotal(void)
+#else
+unsigned short
+gfx_get_htotal(void)
+#endif
+{
+ return ((unsigned short)(((READ_REG32(DC3_H_ACTIVE_TIMING) >> 16) &
+ 0x0FF8) + 8));
+}
+
+/*---------------------------------------------------------------------------
+ * gfx_get_vactive
+ *---------------------------------------------------------------------------
+ */
+#if GFX_DISPLAY_DYNAMIC
+unsigned short
+gu3_get_vactive(void)
+#else
+unsigned short
+gfx_get_vactive(void)
+#endif
+{
+ return ((unsigned short)((READ_REG32(DC3_V_ACTIVE_TIMING) & 0x07FF) + 1));
+}
+
+/*---------------------------------------------------------------------------
+ * gfx_get_vsync_end
+ *---------------------------------------------------------------------------
+ */
+#if GFX_DISPLAY_DYNAMIC
+unsigned short
+gu3_get_vsync_end(void)
+#else
+unsigned short
+gfx_get_vsync_end(void)
+#endif
+{
+ return ((unsigned short)(((READ_REG32(DC3_V_SYNC_TIMING) >> 16) & 0x07FF)
+ + 1));
+}
+
+/*---------------------------------------------------------------------------
+ * gfx_get_vtotal
+ *---------------------------------------------------------------------------
+ */
+#if GFX_DISPLAY_DYNAMIC
+unsigned short
+gu3_get_vtotal(void)
+#else
+unsigned short
+gfx_get_vtotal(void)
+#endif
+{
+ return ((unsigned short)(((READ_REG32(DC3_V_ACTIVE_TIMING) >> 16) &
+ 0x07FF) + 1));
+}
+
+/*----------------------------------------------------------------------------
+ * gfx_get_display_bpp
+ *
+ * This routine returns the current color depth of the active display.
+ *----------------------------------------------------------------------------
+ */
+#if GFX_DISPLAY_DYNAMIC
+unsigned short
+gu3_get_display_bpp(void)
+#else
+unsigned short
+gfx_get_display_bpp(void)
+#endif
+{
+ unsigned long dcfg = READ_REG32(DC3_DISPLAY_CFG);
+
+ switch ((dcfg & DC3_DCFG_DISP_MODE_MASK) >> 8) {
+ case 0:
+ return (8);
+ case 2:
+ return (32);
+
+ case 1:
+
+ switch ((dcfg & DC3_DCFG_16BPP_MODE_MASK) >> 10) {
+ case 0:
+ return (16);
+ case 1:
+ return (15);
+ case 2:
+ return (12);
+ default:
+ return (0);
+ }
+ }
+
+ /* INVALID SETTING */
+
+ return (0);
+}
+
+/*---------------------------------------------------------------------------
+ * gfx_get_vline
+ *---------------------------------------------------------------------------
+ */
+#if GFX_DISPLAY_DYNAMIC
+unsigned short
+gu3_get_vline(void)
+#else
+unsigned short
+gfx_get_vline(void)
+#endif
+{
+ unsigned long current_scan_line;
+
+ /* Read similar value twice to ensure that the value is not transitioning
+ * */
+
+ do
+ current_scan_line =
+ (READ_REG32(DC3_LINE_CNT_STATUS) & DC3_LNCNT_V_LINE_CNT);
+ while (current_scan_line !=
+ (READ_REG32(DC3_LINE_CNT_STATUS) & DC3_LNCNT_V_LINE_CNT));
+
+ return ((unsigned short)(current_scan_line >> 16));
+}
+
+/*----------------------------------------------------------------------------
+ * gfx_get_display_offset
+ *----------------------------------------------------------------------------
+ */
+#if GFX_DISPLAY_DYNAMIC
+unsigned long
+gu3_get_display_offset(void)
+#else
+unsigned long
+gfx_get_display_offset(void)
+#endif
+{
+ return (READ_REG32(DC3_FB_ST_OFFSET) & 0x0FFFFFFF);
+}
+
+/*----------------------------------------------------------------------------
+ * gfx_get_cursor_offset
+ *----------------------------------------------------------------------------
+ */
+#if GFX_DISPLAY_DYNAMIC
+unsigned long
+gu3_get_cursor_offset(void)
+#else
+unsigned long
+gfx_get_cursor_offset(void)
+#endif
+{
+ return (READ_REG32(DC3_CURS_ST_OFFSET) & 0x0FFFFFFF);
+}
+
+#if GFX_READ_ROUTINES
+
+/*************************************************************/
+/* READ ROUTINES | INCLUDED FOR DIAGNOSTIC PURPOSES ONLY */
+/*************************************************************/
+
+/*---------------------------------------------------------------------------
+ * gfx_get_hblank_start
+ *---------------------------------------------------------------------------
+ */
+#if GFX_DISPLAY_DYNAMIC
+unsigned short
+gu3_get_hblank_start(void)
+#else
+unsigned short
+gfx_get_hblank_start(void)
+#endif
+{
+ return ((unsigned short)((READ_REG32(DC3_H_BLANK_TIMING) & 0x0FF8) + 8));
+}
+
+/*---------------------------------------------------------------------------
+ * gfx_get_hblank_end
+ *---------------------------------------------------------------------------
+ */
+#if GFX_DISPLAY_DYNAMIC
+unsigned short
+gu3_get_hblank_end(void)
+#else
+unsigned short
+gfx_get_hblank_end(void)
+#endif
+{
+ return ((unsigned short)(((READ_REG32(DC3_H_BLANK_TIMING) >> 16) & 0x0FF8)
+ + 8));
+}
+
+/*---------------------------------------------------------------------------
+ * gfx_get_vblank_start
+ *---------------------------------------------------------------------------
+ */
+#if GFX_DISPLAY_DYNAMIC
+unsigned short
+gu3_get_vblank_start(void)
+#else
+unsigned short
+gfx_get_vblank_start(void)
+#endif
+{
+ return ((unsigned short)((READ_REG32(DC3_V_BLANK_TIMING) & 0x07FF) + 1));
+}
+
+/*---------------------------------------------------------------------------
+ * gfx_get_vsync_start
+ *---------------------------------------------------------------------------
+ */
+#if GFX_DISPLAY_DYNAMIC
+unsigned short
+gu3_get_vsync_start(void)
+#else
+unsigned short
+gfx_get_vsync_start(void)
+#endif
+{
+ return ((unsigned short)((READ_REG32(DC3_V_SYNC_TIMING) & 0x07FF) + 1));
+}
+
+/*---------------------------------------------------------------------------
+ * gfx_get_vblank_end
+ *---------------------------------------------------------------------------
+ */
+#if GFX_DISPLAY_DYNAMIC
+unsigned short
+gu3_get_vblank_end(void)
+#else
+unsigned short
+gfx_get_vblank_end(void)
+#endif
+{
+ return ((unsigned short)(((READ_REG32(DC3_V_BLANK_TIMING) >> 16) & 0x07FF)
+ + 1));
+}
+
+/*----------------------------------------------------------------------------
+ * gfx_get_display_palette_entry
+ *----------------------------------------------------------------------------
+ */
+#if GFX_DISPLAY_DYNAMIC
+int
+gu3_get_display_palette_entry(unsigned long index, unsigned long *palette)
+#else
+int
+gfx_get_display_palette_entry(unsigned long index, unsigned long *palette)
+#endif
+{
+ if (index > 0xFF)
+ return GFX_STATUS_BAD_PARAMETER;
+
+ WRITE_REG32(DC3_PAL_ADDRESS, index);
+ *palette = READ_REG32(DC3_PAL_DATA);
+
+ return 0;
+}
+
+/*----------------------------------------------------------------------------
+ * gfx_get_display_palette
+ *----------------------------------------------------------------------------
+ */
+#if GFX_DISPLAY_DYNAMIC
+void
+gu3_get_display_palette(unsigned long *palette)
+#else
+void
+gfx_get_display_palette(unsigned long *palette)
+#endif
+{
+ unsigned long i;
+
+ WRITE_REG32(DC3_PAL_ADDRESS, 0);
+ for (i = 0; i < 256; i++) {
+ palette[i] = READ_REG32(DC3_PAL_DATA);
+ }
+}
+
+/*----------------------------------------------------------------------------
+ * gfx_get_cursor_enable
+ *----------------------------------------------------------------------------
+ */
+#if GFX_DISPLAY_DYNAMIC
+unsigned long
+gu3_get_cursor_enable(void)
+#else
+unsigned long
+gfx_get_cursor_enable(void)
+#endif
+{
+ return (READ_REG32(DC3_GENERAL_CFG) & DC3_GCFG_CURE);
+}
+
+/*----------------------------------------------------------------------------
+ * gfx_get_cursor_position
+ *----------------------------------------------------------------------------
+ */
+#if GFX_DISPLAY_DYNAMIC
+unsigned long
+gu3_get_cursor_position(void)
+#else
+unsigned long
+gfx_get_cursor_position(void)
+#endif
+{
+ return ((READ_REG32(DC3_CURSOR_X) & 0x07FF) |
+ ((READ_REG32(DC3_CURSOR_Y) << 16) & 0x07FF0000));
+}
+
+/*----------------------------------------------------------------------------
+ * gfx_get_cursor_offset
+ *----------------------------------------------------------------------------
+ */
+#if GFX_DISPLAY_DYNAMIC
+unsigned long
+gu3_get_cursor_clip(void)
+#else
+unsigned long
+gfx_get_cursor_clip(void)
+#endif
+{
+ return (((READ_REG32(DC3_CURSOR_X) >> 11) & 0x03F) |
+ ((READ_REG32(DC3_CURSOR_Y) << 5) & 0x3F0000));
+}
+
+/*----------------------------------------------------------------------------
+ * gfx_get_cursor_color
+ *---------------------------------------------------------------------------- */
+#if GFX_DISPLAY_DYNAMIC
+unsigned long
+gu3_get_cursor_color(int color)
+#else
+unsigned long
+gfx_get_cursor_color(int color)
+#endif
+{
+ if (color) {
+ WRITE_REG32(DC3_PAL_ADDRESS, 0x101);
+ } else {
+ WRITE_REG32(DC3_PAL_ADDRESS, 0x100);
+ }
+ return READ_REG32(DC3_PAL_DATA);
+}
+
+/*----------------------------------------------------------------------------
+ * gfx_get_compression_enable
+ *----------------------------------------------------------------------------
+ */
+#if GFX_DISPLAY_DYNAMIC
+int
+gu3_get_compression_enable(void)
+#else
+int
+gfx_get_compression_enable(void)
+#endif
+{
+ if (READ_REG32(DC3_GENERAL_CFG) & DC3_GCFG_CMPE)
+ return (1);
+
+ return (0);
+}
+
+/*----------------------------------------------------------------------------
+ * gfx_get_compression_offset
+ *----------------------------------------------------------------------------
+ */
+#if GFX_DISPLAY_DYNAMIC
+unsigned long
+gu3_get_compression_offset(void)
+#else
+unsigned long
+gfx_get_compression_offset(void)
+#endif
+{
+ return (READ_REG32(DC3_CB_ST_OFFSET) & 0x007FFFFF);
+}
+
+/*----------------------------------------------------------------------------
+ * gfx_get_compression_pitch
+ *----------------------------------------------------------------------------
+ */
+#if GFX_DISPLAY_DYNAMIC
+unsigned short
+gu3_get_compression_pitch(void)
+#else
+unsigned short
+gfx_get_compression_pitch(void)
+#endif
+{
+ unsigned short pitch;
+
+ pitch = (unsigned short)(READ_REG32(DC3_GFX_PITCH) >> 16);
+ return (pitch << 3);
+}
+
+/*----------------------------------------------------------------------------
+ * gfx_get_compression_size
+ *----------------------------------------------------------------------------
+ */
+#if GFX_DISPLAY_DYNAMIC
+unsigned short
+gu3_get_compression_size(void)
+#else
+unsigned short
+gfx_get_compression_size(void)
+#endif
+{
+ unsigned short size;
+
+ size =
+ (unsigned short)((READ_REG32(DC3_LINE_SIZE) >> DC3_LINE_SIZE_CB_SHIFT)
+ & 0x7F) - 1;
+ return ((size << 3) + 32);
+}
+
+/*----------------------------------------------------------------------------
+ * gfx_get_valid_bit
+ *----------------------------------------------------------------------------
+ */
+#if GFX_DISPLAY_DYNAMIC
+int
+gu3_get_valid_bit(int line)
+#else
+int
+gfx_get_valid_bit(int line)
+#endif
+{
+ unsigned long lock;
+ unsigned long offset;
+ int valid;
+
+ lock = READ_REG32(DC3_UNLOCK);
+ offset = READ_REG32(DC3_PHY_MEM_OFFSET) & 0xFF000000;
+ offset |= line;
+
+ WRITE_REG32(DC3_UNLOCK, DC3_UNLOCK_VALUE);
+ WRITE_REG32(DC3_PHY_MEM_OFFSET, offset);
+ WRITE_REG32(DC3_UNLOCK, lock);
+ valid = (int)READ_REG32(DC3_DV_ACC) & 2;
+
+ if (valid)
+ return 1;
+ return 0;
+}
+
+/*---------------------------------------------------------------------------
+ * gfx_get_display_video_offset (PRIVATE ROUTINE - NOT PART OF API)
+ *
+ * This routine is called by "gfx_get_video_offset". It abstracts the
+ * version of the display controller from the video overlay routines.
+ *---------------------------------------------------------------------------
+ */
+#if GFX_DISPLAY_DYNAMIC
+unsigned long
+gu3_get_display_video_offset(void)
+#else
+unsigned long
+gfx_get_display_video_offset(void)
+#endif
+{
+ return (READ_REG32(DC3_VID_Y_ST_OFFSET) & 0x0FFFFFFF);
+}
+
+/*---------------------------------------------------------------------------
+ * gfx_get_display_video_yuv_offsets (PRIVATE ROUTINE - NOT PART OF API)
+ *
+ * This routine is called by "gfx_get_video_yuv_offsets". It abstracts the
+ * version of the display controller from the video overlay routines.
+ *---------------------------------------------------------------------------
+ */
+#if GFX_DISPLAY_DYNAMIC
+void
+gu3_get_display_video_yuv_offsets(unsigned long *yoffset,
+ unsigned long *uoffset, unsigned long *voffset)
+#else
+void
+gfx_get_display_video_yuv_offsets(unsigned long *yoffset,
+ unsigned long *uoffset, unsigned long *voffset)
+#endif
+{
+ *yoffset = (READ_REG32(DC3_VID_Y_ST_OFFSET) & 0x0FFFFFFF);
+ *uoffset = (READ_REG32(DC3_VID_U_ST_OFFSET) & 0x0FFFFFFF);
+ *voffset = (READ_REG32(DC3_VID_V_ST_OFFSET) & 0x0FFFFFFF);
+}
+
+/*---------------------------------------------------------------------------
+ * gfx_get_display_video_yuv_pitch (PRIVATE ROUTINE - NOT PART OF API)
+ *
+ * This routine is called by "gfx_get_video_yuv_pitch". It abstracts the
+ * version of the display controller from the video overlay routines.
+ *---------------------------------------------------------------------------
+ */
+#if GFX_DISPLAY_DYNAMIC
+void
+gu3_get_display_video_yuv_pitch(unsigned long *ypitch, unsigned long *uvpitch)
+#else
+void
+gfx_get_display_video_yuv_pitch(unsigned long *ypitch, unsigned long *uvpitch)
+#endif
+{
+ unsigned long pitch = READ_REG32(DC3_VID_YUV_PITCH);
+
+ *ypitch = ((pitch & 0xFFFF) << 3);
+ *uvpitch = (pitch >> 13) & 0x7FFF8;
+}
+
+/*---------------------------------------------------------------------------
+ * gfx_get_display_video_size (PRIVATE ROUTINE - NOT PART OF API)
+ *
+ * This routine is called by "gfx_get_video_size". It abstracts the
+ * version of the display controller from the video overlay routines.
+ *---------------------------------------------------------------------------
+ */
+#if GFX_DISPLAY_DYNAMIC
+unsigned long
+gu3_get_display_video_size(void)
+#else
+unsigned long
+gfx_get_display_video_size(void)
+#endif
+{
+ /* RETURN THE LINE SIZE, AS THIS IS ALL THAT IS AVAILABLE */
+ /* Shift by three less to effect a multiply by 8. */
+
+ return ((READ_REG32(DC3_LINE_SIZE) & DC3_LINE_SIZE_VLS_MASK) >>
+ (DC3_LINE_SIZE_VB_SHIFT - 3));
+}
+
+/*---------------------------------------------------------------------------
+ * gfx_get_display_video_color_key (PRIVATE ROUTINE - NOT PART OF API)
+ *
+ * This routine is called by "gfx_get_video_color_key". It abstracts the
+ * version of the display controller from the video overlay routines.
+ *---------------------------------------------------------------------------
+ */
+#if GFX_DISPLAY_DYNAMIC
+unsigned long
+gu3_get_display_video_color_key(void)
+#else
+unsigned long
+gfx_get_display_video_color_key(void)
+#endif
+{
+ return (READ_REG32(DC3_COLOR_KEY) & 0xFFFFFF);
+}
+
+/*---------------------------------------------------------------------------
+ * gfx_get_display_video_color_key_mask (PRIVATE ROUTINE - NOT PART OF API)
+ *
+ * This routine is called by "gfx_get_video_color_key_mask". It abstracts the
+ * version of the display controller from the video overlay routines.
+ *---------------------------------------------------------------------------
+ */
+#if GFX_DISPLAY_DYNAMIC
+unsigned long
+gu3_get_display_video_color_key_mask(void)
+#else
+unsigned long
+gfx_get_display_video_color_key_mask(void)
+#endif
+{
+ return (READ_REG32(DC3_COLOR_MASK) & 0xFFFFFF);
+}
+
+#endif /* GFX_READ_ROUTINES */
+
+/* END OF FILE */