diff options
author | Jordan Crouse <jordan.crouse@amd.com> | 2006-07-06 14:56:42 -0600 |
---|---|---|
committer | Jordan Crouse <jordan.crouse@amd.com> | 2006-07-06 14:56:42 -0600 |
commit | c3ab9f1a60afe1f5e86db1cf2635acda14fae2f5 (patch) | |
tree | 00cfb19765f276220eb794553b545e9f67402688 /src/gfx |
Initial commit of the xf86-video-amd tree
Diffstat (limited to 'src/gfx')
40 files changed, 44906 insertions, 0 deletions
diff --git a/src/gfx/disp_gu1.c b/src/gfx/disp_gu1.c new file mode 100644 index 0000000..58e42ee --- /dev/null +++ b/src/gfx/disp_gu1.c @@ -0,0 +1,2532 @@ +/* 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. + */ + +void gu1_enable_compression(void); /* private routine definition */ +void gu1_disable_compression(void); /* private routine definition */ +void gfx_reset_video(void); /* private routine definition */ +int gfx_set_display_control(int sync_polarities); /* private routine + * definition */ +int gu1_set_specified_mode(DISPLAYMODE * pMode, int bpp); + +/* VIDEO BUFFER SIZE */ + +unsigned long vid_buf_size = 0; +int vid_enabled = 0; + +/*---------------------------------------------------------------------------- + * GU1_DELAY_APPROXIMATE (PRIVATE ROUTINE - NOT PART OF DURANGO API) + * + * Delay the requested number of milliseconds by reading a register. This + * function generally takes longer than the requested time. + *---------------------------------------------------------------------------- + */ + +#define READS_PER_MILLISECOND 60000L + +void +gu1_delay_approximate(unsigned long milliseconds) +{ + /* ASSUME 300 MHz, 5 CLOCKS PER READ */ + + unsigned long loop; + + loop = milliseconds * READS_PER_MILLISECOND; + while (loop-- > 0) { + READ_REG32(DC_UNLOCK); + } +} + +/*---------------------------------------------------------------------------- + * GU1_DELAY_PRECISE (PRIVATE ROUTINE - NOT PART OF DURANGO API) + * + * Delay the number of milliseconds on a more precise level, varying only by + * 1/10 of a ms. This function should only be called if an SC1200 is present. + *---------------------------------------------------------------------------- + */ +void +gu1_delay_precise(unsigned long milliseconds) +{ +#if GFX_VIDEO_SC1200 + +#define LOOP 1000 + unsigned long i, timer_start, timer_end, total_ticks, previous_ticks, + temp_ticks; + + /* Get current time */ + timer_start = IND(SC1200_CB_BASE_ADDR + SC1200_CB_TMVALUE); + + /* Calculate expected end time */ + if (INB(SC1200_CB_BASE_ADDR + SC1200_CB_TMCNFG) & SC1200_TMCLKSEL_27MHZ) + total_ticks = 27000 * milliseconds; /* timer resolution is 27 MHz */ + else + total_ticks = 1000 * milliseconds; /* timer resolution is 1 MHz */ + + if (total_ticks > ((unsigned long)0xffffffff - timer_start)) + /* wrap-around */ + timer_end = total_ticks - ((unsigned long)0xffffffff - timer_start); + else + timer_end = timer_start + total_ticks; + + /* in case of wrap around */ + if (timer_end < timer_start) { + previous_ticks = timer_start; + while (1) { + temp_ticks = IND(SC1200_CB_BASE_ADDR + SC1200_CB_TMVALUE); + if (temp_ticks < previous_ticks) + break; + else + previous_ticks = temp_ticks; + for (i = 0; i < LOOP; i++) + READ_REG32(DC_UNLOCK); + } + } + + /* now the non-wrap around part */ + while (1) { + for (i = 0; i < LOOP; i++) + READ_REG32(DC_UNLOCK); + if (IND(SC1200_CB_BASE_ADDR + SC1200_CB_TMVALUE) > timer_end) + break; + } +#endif /* GFX_VIDEO_SC1200 */ +} + +/*---------------------------------------------------------------------------- + * 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. + * + * For the SC1200, the high resolution timer can be used as an accurate + * mechanism for keeping time. However, in order to avoid a busy loop of IO + * reads, the timer is polled in-between busy loops, and therefore the actual + * delay might be longer than the requested delay by the time of one busy loop + * (which on a 200 MHz system took 95 us) + * + * There are thus two delay functions which are called from the main API + * routine. + * One is meant to be more precise and should only called if an SC1200 is + * present. + *---------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +void +gu1_delay_milliseconds(unsigned long milliseconds) +#else +void +gfx_delay_milliseconds(unsigned long milliseconds) +#endif +{ +#if GFX_VIDEO_SC1200 +#if GFX_VIDEO_DYNAMIC + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) { +#endif + gu1_delay_precise(milliseconds); + return; +#if GFX_VIDEO_DYNAMIC + } +#endif +#endif /* GFX_VIDEO_SC1200 */ + gu1_delay_approximate(milliseconds); +} + +#if GFX_DISPLAY_DYNAMIC +void +gu1_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 * 150; + + while (loop_count-- > 0) { + ; + } +} + +/*---------------------------------------------------------------------------- + * GFX_VIDEO_SHUTDOWN + * + * This routine disables the display controller output. + *---------------------------------------------------------------------------- + */ +void +gu1_video_shutdown(void) +{ + unsigned long unlock; + unsigned long gcfg, tcfg; + + /* DISABLE COMPRESSION */ + gu1_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(DC_UNLOCK); + WRITE_REG32(DC_UNLOCK, DC_UNLOCK_VALUE); + + /* READ THE CURRENT GX VALUES */ + gcfg = READ_REG32(DC_GENERAL_CFG); + tcfg = READ_REG32(DC_TIMING_CFG); + + /* BLANK THE GX DISPLAY AND DISABLE THE TIMING GENERATOR */ + tcfg &= ~((unsigned long)DC_TCFG_BLKE | (unsigned long)DC_TCFG_TGEN); + WRITE_REG32(DC_TIMING_CFG, tcfg); + + /* 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 AND DISABLE COMPRESSION */ + gcfg &= ~(unsigned long)(DC_GCFG_DFLE | DC_GCFG_CMPE | DC_GCFG_DECE); + WRITE_REG32(DC_GENERAL_CFG, gcfg); + WRITE_REG32(DC_UNLOCK, unlock); + return; +} + +/*---------------------------------------------------------------------------- + * GFX_SET_DISPLAY_BPP + * + * This routine programs the bpp in the display controller. + *---------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +int +gu1_set_display_bpp(unsigned short bpp) +#else +int +gfx_set_display_bpp(unsigned short bpp) +#endif +{ + unsigned long ocfg, lock; + + lock = READ_REG32(DC_UNLOCK); + ocfg = READ_REG32(DC_OUTPUT_CFG) & ~(DC_OCFG_8BPP | DC_OCFG_555); + + /* SET DC PIXEL FORMAT */ + if (bpp == 8) + ocfg |= DC_OCFG_8BPP; + else if (bpp == 15) + ocfg |= DC_OCFG_555; + else if (bpp != 16) + return GFX_STATUS_BAD_PARAMETER; + + WRITE_REG32(DC_UNLOCK, DC_UNLOCK_VALUE); + WRITE_REG32(DC_OUTPUT_CFG, ocfg); + WRITE_REG32(DC_UNLOCK, lock); + + /* SET BPP IN GRAPHICS PIPELINE */ + gfx_set_bpp(bpp); + + return 0; +} + +/*---------------------------------------------------------------------------- + * GFX_SET_SPECIFIED_MODE + * This routine uses the parameters in the specified display mode structure + * to program the display controller hardware. + *---------------------------------------------------------------------------- + */ +int +gu1_set_specified_mode(DISPLAYMODE * pMode, int bpp) +{ + unsigned long unlock, value; + unsigned long gcfg, tcfg, ocfg; + unsigned long size, pitch; + unsigned long hactive, vactive; + + gbpp = bpp; + + /* 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; + + /* SET GLOBAL FLAG */ + if (pMode->flags & GFX_MODE_LOCK_TIMING) + gfx_timing_lock = 1; + + /* DISABLE COMPRESSION */ + gu1_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(DC_UNLOCK); + WRITE_REG32(DC_UNLOCK, DC_UNLOCK_VALUE); + + /* READ THE CURRENT GX VALUES */ + gcfg = READ_REG32(DC_GENERAL_CFG); + tcfg = READ_REG32(DC_TIMING_CFG); + + /* BLANK THE GX DISPLAY AND DISABLE THE TIMING GENERATOR */ + tcfg &= ~((unsigned long)DC_TCFG_BLKE | (unsigned long)DC_TCFG_TGEN); + WRITE_REG32(DC_TIMING_CFG, tcfg); + + /* 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 AND DISABLE COMPRESSION */ + gcfg &= ~(unsigned long)(DC_GCFG_DFLE | DC_GCFG_CMPE | DC_GCFG_DECE); + WRITE_REG32(DC_GENERAL_CFG, gcfg); + + /* CLEAR THE "DCLK_MUL" FIELD */ + gcfg &= ~(unsigned long)(DC_GCFG_DDCK | DC_GCFG_DPCK | DC_GCFG_DFCK); + gcfg &= ~(unsigned long)DC_GCFG_DCLK_MASK; + WRITE_REG32(DC_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 "DCLK_MUL" FIELD OF DC_GENERAL_CFG */ + /* The GX hardware divides the dot clock, so 2x really means that the */ + /* internal dot clock equals the external dot clock. */ + if (pMode->frequency & 0x80000000) + gcfg |= 0x0040; + else + gcfg |= 0x0080; + + WRITE_REG32(DC_GENERAL_CFG, gcfg); + + /* DELAY: WAIT FOR THE ADL TO LOCK */ + /* This allows the clock generatation within GX to settle. This is */ + /* needed since some of the register writes that follow require that */ + /* clock to be present. */ + gfx_delay_milliseconds(1); + + /* SET THE GX DISPLAY CONTROLLER PARAMETERS */ + WRITE_REG32(DC_FB_ST_OFFSET, 0); + WRITE_REG32(DC_CB_ST_OFFSET, 0); + WRITE_REG32(DC_CURS_ST_OFFSET, 0); + + /* SET LINE SIZE AND PITCH */ + /* Flat panels use the current flat panel line size to */ + /* calculate the pitch, but load the true line size */ + /* for the mode into the "Frame Buffer Line Size" field */ + /* of DC_BUF_SIZE. */ + if (PanelEnable) + size = ModeWidth; + else + size = pMode->hactive; + + if (bpp > 8) + size <<= 1; + + /* ONLY PYRAMID SUPPORTS 4K LINE SIZE */ + if (size <= 1024) { + pitch = 1024; + /* SPECIAL CASE */ + /* Graphics acceleration in 16-bit pixel line double modes */ + /* requires a pitch of 2048. */ + if ((pMode->flags & GFX_MODE_LINE_DOUBLE) && bpp > 8) + pitch <<= 1; + } else { + if (gfx_cpu_version == GFX_CPU_PYRAMID) + pitch = (size <= 2048) ? 2048 : 4096; + else + pitch = 2048; + } + + WRITE_REG32(DC_LINE_DELTA, pitch >> 2); + + if (PanelEnable) { + size = pMode->hactive; + if (bpp > 8) + size <<= 1; + } + + /* ADD 2 TO SIZE FOR POSSIBLE START ADDRESS ALIGNMENTS */ + WRITE_REG32(DC_BUF_SIZE, (size >> 3) + 2); + + /* ALWAYS ENABLE "PANEL" DATA FROM MEDIAGX */ + /* That is really just the 18 BPP data bus to the companion chip */ + ocfg = DC_OCFG_PCKE | DC_OCFG_PDEL | DC_OCFG_PDEH; + + /* SET PIXEL FORMAT */ + if (bpp == 8) + ocfg |= DC_OCFG_8BPP; + else if (bpp == 15) + ocfg |= DC_OCFG_555; + + /* ENABLE TIMING GENERATOR, SYNCS, AND FP DATA */ + tcfg = DC_TCFG_FPPE | DC_TCFG_HSYE | DC_TCFG_VSYE | DC_TCFG_BLKE | + DC_TCFG_TGEN; + + /* SET FIFO PRIORITY, DCLK MULTIPLIER, AND FIFO ENABLE */ + /* Default 6/5 for FIFO, 2x for DCLK multiplier. */ + gcfg = + (6 << DC_GCFG_DFHPEL_POS) | (5 << DC_GCFG_DFHPSL_POS) | DC_GCFG_DFLE; + + /* INCREASE FIFO PRIORITY FOR LARGE MODES */ + if (pMode->hactive == 1280 && pMode->vactive == 1024) { + if ((bpp == 8) && (pMode->flags & GFX_MODE_85HZ)) + gcfg = + (8l << DC_GCFG_DFHPEL_POS) | (7l << DC_GCFG_DFHPSL_POS) | + DC_GCFG_DFLE; + + if ((bpp > 8) && (pMode->flags & GFX_MODE_75HZ)) + gcfg = + (7l << DC_GCFG_DFHPEL_POS) | (6l << DC_GCFG_DFHPSL_POS) | + DC_GCFG_DFLE; + + if ((bpp > 8) && (pMode->flags & GFX_MODE_85HZ)) + gcfg = + (9l << DC_GCFG_DFHPEL_POS) | (8l << DC_GCFG_DFHPSL_POS) | + DC_GCFG_DFLE; + } + + /* SET DOT CLOCK MULTIPLIER */ + /* Bit 31 of frequency indicates divide frequency by two */ + if (pMode->frequency & 0x80000000) + gcfg |= (1l << DC_GCFG_DCLK_POS); + else + gcfg |= (2l << DC_GCFG_DCLK_POS); + + /* DIVIDE VIDEO CLOCK */ + /* CPU core frequencies above 266 MHz will divide the video */ + /* clock by 4 to ensure that we are running below 150 MHz. */ + if (gfx_cpu_frequency > 266) + gcfg |= DC_GCFG_VCLK_DIV; + + /* ALWAYS ENABLE VIDEO IN THE DISPLAY CONTROLLER */ + /* Enabling video at an inopportune momemt can corrupt the DC fetch */ + /* engine and cause screen artifacts or system hang. */ + gcfg |= (DC_GCFG_VIDE | DC_GCFG_VRDY); + + /* SET THE PIXEL AND LINE DOUBLE BITS IF NECESSARY */ + hactive = pMode->hactive; + vactive = pMode->vactive; + gfx_line_double = 0; + gfx_pixel_double = 0; + + if (pMode->flags & GFX_MODE_LINE_DOUBLE) { + gcfg |= DC_GCFG_LDBL; + hactive <<= 1; + + /* SET GLOBAL FLAG */ + gfx_line_double = 1; + } + + if (pMode->flags & GFX_MODE_PIXEL_DOUBLE) { + tcfg |= DC_TCFG_PXDB; + vactive <<= 1; + + /* SET GLOBAL FLAG */ + gfx_pixel_double = 1; + } + + /* COMBINE AND SET TIMING VALUES */ + + value = (unsigned long)(hactive - 1) | + (((unsigned long)(pMode->htotal - 1)) << 16); + WRITE_REG32(DC_H_TIMING_1, value); + value = (unsigned long)(pMode->hblankstart - 1) | + (((unsigned long)(pMode->hblankend - 1)) << 16); + WRITE_REG32(DC_H_TIMING_2, value); + value = (unsigned long)(pMode->hsyncstart - 1) | + (((unsigned long)(pMode->hsyncend - 1)) << 16); + WRITE_REG32(DC_H_TIMING_3, value); + WRITE_REG32(DC_FP_H_TIMING, value); + value = (unsigned long)(vactive - 1) | + (((unsigned long)(pMode->vtotal - 1)) << 16); + WRITE_REG32(DC_V_TIMING_1, value); + value = (unsigned long)(pMode->vblankstart - 1) | + (((unsigned long)(pMode->vblankend - 1)) << 16); + WRITE_REG32(DC_V_TIMING_2, value); + value = (unsigned long)(pMode->vsyncstart - 1) | + (((unsigned long)(pMode->vsyncend - 1)) << 16); + WRITE_REG32(DC_V_TIMING_3, value); + value = (unsigned long)(pMode->vsyncstart - 2) | + (((unsigned long)(pMode->vsyncend - 2)) << 16); + WRITE_REG32(DC_FP_V_TIMING, value); + + WRITE_REG32(DC_OUTPUT_CFG, ocfg); + WRITE_REG32(DC_TIMING_CFG, tcfg); + gfx_delay_milliseconds(1); /* delay after TIMING_CFG */ + WRITE_REG32(DC_GENERAL_CFG, gcfg); + + /* ENABLE FLAT PANEL CENTERING */ + /* For 640x480 modes displayed with the 9211 within a 800x600 */ + /* flat panel display, turn on flat panel centering. */ + if (PanelEnable) { + if (ModeWidth < PanelWidth) { + tcfg = READ_REG32(DC_TIMING_CFG); + tcfg = tcfg | DC_TCFG_FCEN; + WRITE_REG32(DC_TIMING_CFG, tcfg); + gfx_delay_milliseconds(1); /* delay after TIMING_CFG */ + } + } + + /* 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 DC_UNLOCK */ + WRITE_REG32(DC_UNLOCK, unlock); + + /* ALSO WRITE GP_BLIT_STATUS FOR PITCH AND 8/18 BPP */ + /* Remember, only Pyramid supports 4K line pitch */ + value = 0; + if (bpp > 8) + value |= BC_16BPP; + if ((gfx_cpu_version == GFX_CPU_PYRAMID) && (pitch > 2048)) + value |= BC_FB_WIDTH_4096; + else if (pitch > 1024) + value |= BC_FB_WIDTH_2048; + + WRITE_REG16(GP_BLIT_STATUS, (unsigned short)value); + + return GFX_STATUS_OK; +} /* end gfx_set_specified_mode() */ + +/*---------------------------------------------------------------------------- + * GFX_IS_DISPLAY_MODE_SUPPORTED + * + * This routine sets the specified display mode. + * + * Returns the index of the mode if successful and mode returned, -1 if the + * mode could not be found. + *---------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +int +gu1_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 = 0; + unsigned long hz_flag = 0, bpp_flag = 0; + + /* SET FLAGS TO MATCH REFRESH RATE */ + if (hz == 56) + hz_flag = GFX_MODE_56HZ; + else if (hz == 60) + hz_flag = GFX_MODE_60HZ; + else if (hz == 70) + hz_flag = GFX_MODE_70HZ; + else if (hz == 72) + hz_flag = GFX_MODE_72HZ; + else if (hz == 75) + hz_flag = GFX_MODE_75HZ; + else if (hz == 85) + hz_flag = GFX_MODE_85HZ; + else + return -1; + + /* SET BPP FLAGS TO LIMIT MODE SELECTION */ + if (bpp == 8) + bpp_flag = GFX_MODE_8BPP; + else if (bpp == 15) + bpp_flag = GFX_MODE_15BPP; + else if (bpp == 16) + bpp_flag = GFX_MODE_16BPP; + else + return -1; + + /* ONLY PYRAMID SUPPORTS 4K PITCH */ + if (gfx_cpu_version != GFX_CPU_PYRAMID && xres > 1024) { + if (bpp > 8) + return (-1); /* return with mode not found */ + } + + /* LOOP THROUGH THE AVAILABLE MODES TO FIND A MATCH */ + for (mode = 0; mode < NUM_GX_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)) { + + /* 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 +gu1_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 (gu1_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 +gu1_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 (gu1_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 +gu1_set_vtotal(unsigned short vtotal) +#else +int +gfx_set_vtotal(unsigned short vtotal) +#endif +{ + unsigned long unlock, tcfg, timing1, timing2; + + /* UNLOCK THE DISPLAY CONTROLLER REGISTERS */ + unlock = READ_REG32(DC_UNLOCK); + WRITE_REG32(DC_UNLOCK, DC_UNLOCK_VALUE); + + /* READ THE CURRENT GX VALUES */ + tcfg = READ_REG32(DC_TIMING_CFG); + timing1 = READ_REG32(DC_V_TIMING_1); + timing2 = READ_REG32(DC_V_TIMING_2); + + /* DISABLE THE TIMING GENERATOR */ + WRITE_REG32(DC_TIMING_CFG, tcfg & ~(unsigned long)DC_TCFG_TGEN); + + /* WRITE NEW TIMING VALUES */ + WRITE_REG32(DC_V_TIMING_1, + (timing1 & 0xffff) | (unsigned long)(vtotal - 1) << 16); + WRITE_REG32(DC_V_TIMING_2, + (timing2 & 0xffff) | (unsigned long)(vtotal - 1) << 16); + + /* RESTORE GX VALUES */ + WRITE_REG32(DC_TIMING_CFG, tcfg); + WRITE_REG32(DC_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 +gu1_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(DC_UNLOCK); + + value = READ_REG32(DC_LINE_DELTA) & 0xFFFFF000; + value |= (pitch >> 2); + WRITE_REG32(DC_UNLOCK, DC_UNLOCK_VALUE); + WRITE_REG32(DC_LINE_DELTA, value); + WRITE_REG32(DC_UNLOCK, lock); + + /* ALSO UPDATE PITCH IN GRAPHICS ENGINE */ + /* Pyramid alone supports 4K line pitch */ + value = (unsigned long)READ_REG16(GP_BLIT_STATUS); + value &= ~(BC_FB_WIDTH_2048 | BC_FB_WIDTH_4096); + + if ((gfx_cpu_version == GFX_CPU_PYRAMID) && (pitch > 2048)) + value |= BC_FB_WIDTH_4096; + + else if (pitch > 1024) + value |= BC_FB_WIDTH_2048; + + WRITE_REG16(GP_BLIT_STATUS, (unsigned short)value); + return; +} + +/*--------------------------------------------------------------------------- + * 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 +gu1_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(DC_UNLOCK); + WRITE_REG32(DC_UNLOCK, DC_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(DC_FB_ST_OFFSET, offset); + if (gfx_compression_enabled) { + /* WAIT FOR THE OFFSET TO BE LATCHED */ + gfx_wait_vertical_blank(); + gu1_enable_compression(); + } + } else { + /* ONLY DISABLE COMPRESSION ONCE */ + if (gfx_compression_active) + gu1_disable_compression(); + + WRITE_REG32(DC_FB_ST_OFFSET, offset); + } + + WRITE_REG32(DC_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 +gu1_set_display_palette_entry(unsigned long index, unsigned long palette) +#else +int +gfx_set_display_palette_entry(unsigned long index, unsigned long palette) +#endif +{ + unsigned long data; + + if (index > 0xFF) + return GFX_STATUS_BAD_PARAMETER; + + WRITE_REG32(DC_PAL_ADDRESS, index); + data = ((palette >> 2) & 0x0003F) | + ((palette >> 4) & 0x00FC0) | ((palette >> 6) & 0x3F000); + WRITE_REG32(DC_PAL_DATA, data); + + 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. + * + * Restriction: + * Due to SC1200 Issue #748 (in Notes DB) this function should be called only + * when DCLK is active, i.e PLL is already powered up and genlock is not + * active. + *--------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +int +gu1_set_display_palette(unsigned long *palette) +#else +int +gfx_set_display_palette(unsigned long *palette) +#endif +{ + unsigned long data, i; + + WRITE_REG32(DC_PAL_ADDRESS, 0); + if (palette) { + for (i = 0; i < 256; i++) { + /* CONVERT 24 BPP COLOR DATA TO 18 BPP COLOR DATA */ + data = ((palette[i] >> 2) & 0x0003F) | + ((palette[i] >> 4) & 0x00FC0) | ((palette[i] >> 6) & 0x3F000); + WRITE_REG32(DC_PAL_DATA, data); + } + } + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_set_cursor_enable + * + * This routine enables or disables the hardware cursor. + * + * WARNING: The cusrsor 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 +gu1_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(DC_UNLOCK); + gcfg = READ_REG32(DC_GENERAL_CFG); + if (enable) + gcfg |= DC_GCFG_CURE; + else + gcfg &= ~(DC_GCFG_CURE); + + /* WRITE NEW REGISTER VALUE */ + WRITE_REG32(DC_UNLOCK, DC_UNLOCK_VALUE); + WRITE_REG32(DC_GENERAL_CFG, gcfg); + WRITE_REG32(DC_UNLOCK, unlock); +} + +/*--------------------------------------------------------------------------- + * gfx_set_cursor_colors + * + * This routine sets the colors of the hardware cursor. + * + * Restriction: + * Due to SC1200 Issue #748 (in Notes DB) this function should be called only + * when DCLK is active, i.e PLL is already powered up. + *--------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +void +gu1_set_cursor_colors(unsigned long bkcolor, unsigned long fgcolor) +#else +void +gfx_set_cursor_colors(unsigned long bkcolor, unsigned long fgcolor) +#endif +{ + unsigned long value; + + /* If genlock is enabled DCLK might be disabled in vertical blank. */ + /* Due to SC1200 Issue #748 in Notes DB this would fail the cursor color settings */ + /* So Wait for vertical blank to end */ + +#if GFX_VIDEO_SC1200 + if (gfx_test_timing_active()) + while ((gfx_get_vline()) > gfx_get_vactive()) ; +#endif + /* SET CURSOR COLORS */ + WRITE_REG32(DC_PAL_ADDRESS, 0x100); + value = ((bkcolor & 0x000000FC) >> 2) | + ((bkcolor & 0x0000FC00) >> (2 + 8 - 6)) | + ((bkcolor & 0x00FC0000) >> (2 + 16 - 12)); + WRITE_REG32(DC_PAL_DATA, value); + value = ((fgcolor & 0x000000FC) >> 2) | + ((fgcolor & 0x0000FC00) >> (2 + 8 - 6)) | + ((fgcolor & 0x00FC0000) >> (2 + 16 - 12)); + WRITE_REG32(DC_PAL_DATA, value); +} + +/*--------------------------------------------------------------------------- + * 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 +gu1_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, y; + short xoffset = 0; + short yoffset = 0; + + /* SUPPORT CURSOR IN EMULATED VGA MODES */ + /* Timings are for twice the resolution */ + if (gfx_pixel_double) + xpos <<= 1; + + if (gfx_line_double) + ypos <<= 1; + + x = (short)xpos - (short)xhotspot; + y = (short)ypos - (short)yhotspot; + if (x < -31) + return; + + if (y < -31) + return; + + if (x < 0) { + xoffset = -x; + x = 0; + } + + if (y < 0) { + yoffset = -y; + y = 0; + } + + memoffset += (unsigned long)yoffset << 3; + + if (PanelEnable) { + if ((ModeWidth > PanelWidth) || (ModeHeight > PanelHeight)) { + gfx_enable_panning(xpos, ypos); + x = x - (short)panelLeft; + y = y - (short)panelTop; + } + } + + /* SET CURSOR POSITION */ + unlock = READ_REG32(DC_UNLOCK); + WRITE_REG32(DC_UNLOCK, DC_UNLOCK_VALUE); + WRITE_REG32(DC_CURS_ST_OFFSET, memoffset); + WRITE_REG32(DC_CURSOR_X, (unsigned long)x | + (((unsigned long)xoffset) << 11)); + WRITE_REG32(DC_CURSOR_Y, (unsigned long)y | + (((unsigned long)yoffset) << 11)); + WRITE_REG32(DC_UNLOCK, unlock); +} + +/*--------------------------------------------------------------------------- + * gfx_set_cursor_shape32 + * + * This routine loads 32x32 cursor data into the specified location in + * graphics memory. + *--------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +void +gu1_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; + unsigned long value; + + for (i = 0; i < 32; i++) { + /* CONVERT TO 16 BITS AND MASK, 16 BITS XOR MASK PER DWORD */ + value = (andmask[i] & 0xFFFF0000) | (xormask[i] >> 16); + WRITE_FB32(memoffset, value); + memoffset += 4; + value = (andmask[i] << 16) | (xormask[i] & 0x0000FFFF); + WRITE_FB32(memoffset, value); + memoffset += 4; + } +} + +/*--------------------------------------------------------------------------- + * gu1_enable_compression + * + * This is a private routine to this module (not exposed in the Durango API). + * It enables display compression. + *--------------------------------------------------------------------------- + */ +void +gu1_enable_compression(void) +{ + int i; + unsigned long unlock, gcfg, offset; + + /* DO NOT ENABLE IF START ADDRESS IS NOT ZERO */ + offset = READ_REG32(DC_FB_ST_OFFSET) & 0x003FFFFF; + if (offset != 0) + return; + + /* DO NOT ENABLE IF WE ARE WITHIN AN EMULATED VGA MODE */ + if (gfx_line_double || gfx_pixel_double) + 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. */ + for (i = 0; i < 1024; i++) { + WRITE_REG32(MC_DR_ADD, i); + WRITE_REG32(MC_DR_ACC, 0); + } + + /* TURN ON COMPRESSION CONTROL BITS */ + unlock = READ_REG32(DC_UNLOCK); + gcfg = READ_REG32(DC_GENERAL_CFG); + gcfg |= DC_GCFG_CMPE | DC_GCFG_DECE; + WRITE_REG32(DC_UNLOCK, DC_UNLOCK_VALUE); + WRITE_REG32(DC_GENERAL_CFG, gcfg); + WRITE_REG32(DC_UNLOCK, unlock); +} + +/*--------------------------------------------------------------------------- + * gu1_disable_compression + * + * This is a private routine to this module (not exposed in the Durango API). + * It disables display compression. + *--------------------------------------------------------------------------- + */ +void +gu1_disable_compression(void) +{ + unsigned long unlock, gcfg; + + /* SET GLOBAL INDICATOR */ + gfx_compression_active = 0; + + /* TURN OFF COMPRESSION CONTROL BITS */ + unlock = READ_REG32(DC_UNLOCK); + gcfg = READ_REG32(DC_GENERAL_CFG); + gcfg &= ~(DC_GCFG_CMPE | DC_GCFG_DECE); + WRITE_REG32(DC_UNLOCK, DC_UNLOCK_VALUE); + WRITE_REG32(DC_GENERAL_CFG, gcfg); + WRITE_REG32(DC_UNLOCK, unlock); +} + +/*--------------------------------------------------------------------------- + * gfx_set_compression_enable + * + * This routine enables or disables display compression. + *--------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +int +gu1_set_compression_enable(int enable) +#else +int +gfx_set_compression_enable(int enable) +#endif +{ + /* SET GLOBAL VARIABLE FOR INTENDED 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) + gu1_enable_compression(); + else + gu1_disable_compression(); + + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_set_compression_offset + * + * This routine sets the base offset for the compression buffer. + *--------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +int +gu1_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 GXLV */ + if (offset & 0x0F) + return (1); + + /* SET REGISTER VALUE */ + lock = READ_REG32(DC_UNLOCK); + WRITE_REG32(DC_UNLOCK, DC_UNLOCK_VALUE); + WRITE_REG32(DC_CB_ST_OFFSET, offset); + WRITE_REG32(DC_UNLOCK, lock); + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_set_compression_pitch + * + * This routine sets the pitch, in bytes, of the compression buffer. + *--------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +int +gu1_set_compression_pitch(unsigned short pitch) +#else +int +gfx_set_compression_pitch(unsigned short pitch) +#endif +{ + unsigned long lock, line_delta; + + /* SET REGISTER VALUE */ + lock = READ_REG32(DC_UNLOCK); + line_delta = READ_REG32(DC_LINE_DELTA) & 0xFF800FFF; + line_delta |= ((unsigned long)pitch << 10l) & 0x007FF000; + WRITE_REG32(DC_UNLOCK, DC_UNLOCK_VALUE); + WRITE_REG32(DC_LINE_DELTA, line_delta); + WRITE_REG32(DC_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 +gu1_set_compression_size(unsigned short size) +#else +int +gfx_set_compression_size(unsigned short size) +#endif +{ + unsigned long lock, buf_size; + + /* SUBTRACT 16 FROM SIZE */ + /* The display controller will actually write */ + /* 2 extra QWords. So, if we assume that "size" */ + /* refers to the allocated size, we must subtract */ + /* 16 bytes. */ + size -= 16; + + /* SET REGISTER VALUE */ + lock = READ_REG32(DC_UNLOCK); + buf_size = READ_REG32(DC_BUF_SIZE) & 0xFFFF01FF; + buf_size |= (((size >> 2) + 1) & 0x7F) << 9; + WRITE_REG32(DC_UNLOCK, DC_UNLOCK_VALUE); + WRITE_REG32(DC_BUF_SIZE, buf_size); + WRITE_REG32(DC_UNLOCK, lock); + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_set_display_video_enable (PRIVATE ROUTINE - NOT PART OF API) + * + * This routine enables/disables video on GX. + *--------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +void +gu1_set_display_video_enable(int enable) +#else +void +gfx_set_display_video_enable(int enable) +#endif +{ + unsigned long lock, gcfg, buf_size; + + lock = READ_REG32(DC_UNLOCK); + gcfg = READ_REG32(DC_GENERAL_CFG); + buf_size = READ_REG32(DC_BUF_SIZE); + + WRITE_REG32(DC_UNLOCK, DC_UNLOCK_VALUE); + + vid_enabled = enable; + + /* SET THE BUFFER SIZE TO A NON-ZERO VALUE ONLY WHEN */ + /* ENABLING VIDEO */ + if (enable) { + gcfg |= (DC_GCFG_VIDE | DC_GCFG_VRDY); + WRITE_REG32(DC_GENERAL_CFG, gcfg); + + WRITE_REG32(DC_BUF_SIZE, (buf_size & 0x0000FFFFl) | vid_buf_size); + } + /* CLEAR THE VIDEO BUFFER SIZE WHEN DISABLING VIDEO */ + else { + gcfg &= ~(DC_GCFG_VIDE); + WRITE_REG32(DC_GENERAL_CFG, gcfg); + + vid_buf_size = buf_size & 0xFFFF0000l; + WRITE_REG32(DC_BUF_SIZE, buf_size & 0x0000FFFFl); + } + + WRITE_REG32(DC_UNLOCK, lock); + return; +} + +/*--------------------------------------------------------------------------- + * 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 +gu1_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, size, value; + + size = (unsigned long)(width << 1) * (unsigned long)height; + + /* STORE THE VIDEO BUFFER SIZE AS A GLOBAL */ + vid_buf_size = ((size + 63) >> 6) << 16; + + lock = READ_REG32(DC_UNLOCK); + WRITE_REG32(DC_UNLOCK, DC_UNLOCK_VALUE); + value = READ_REG32(DC_BUF_SIZE) & 0x0000FFFF; + value |= vid_buf_size; + WRITE_REG32(DC_BUF_SIZE, value); + WRITE_REG32(DC_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 +gu1_set_display_video_offset(unsigned long offset) +#else +void +gfx_set_display_video_offset(unsigned long offset) +#endif +{ + unsigned long lock; + + lock = READ_REG32(DC_UNLOCK); + WRITE_REG32(DC_UNLOCK, DC_UNLOCK_VALUE); + offset &= 0x003FFFFF; + WRITE_REG32(DC_VID_ST_OFFSET, offset); + WRITE_REG32(DC_UNLOCK, lock); +} + +/*--------------------------------------------------------------------------- + * gfx_set_display_priority_high + * + * This routine controls the x-bus round robin arbitration mechanism. + * When enable is TRUE, graphics pipeline requests and non-critical display + * controller requests are arbitrated at the same priority as processor + * requests. When FALSE processor requests are arbitrated at a higher priority + *--------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +void +gu1_set_display_priority_high(int enable) +#else +void +gfx_set_display_priority_high(int enable) +#endif +{ + unsigned long lock, control; + + lock = READ_REG32(DC_UNLOCK); + control = READ_REG32(MC_MEM_CNTRL1); + WRITE_REG32(DC_UNLOCK, DC_UNLOCK_VALUE); + if (enable) + control |= MC_XBUSARB; + else + control &= ~(MC_XBUSARB); + WRITE_REG32(MC_MEM_CNTRL1, control); + WRITE_REG32(DC_UNLOCK, lock); + return; +} + +/*--------------------------------------------------------------------------- + * gfx_test_timing_active + *--------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +int +gu1_test_timing_active(void) +#else +int +gfx_test_timing_active(void) +#endif +{ + if (READ_REG32(DC_TIMING_CFG) & DC_TCFG_TGEN) + return (1); + else + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_test_vertical_active + *--------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +int +gu1_test_vertical_active(void) +#else +int +gfx_test_vertical_active(void) +#endif +{ + if (READ_REG32(DC_TIMING_CFG) & DC_TCFG_VNA) + return (0); + else + return (1); +} + +/*--------------------------------------------------------------------------- + * gfx_wait_vertical_blank + *--------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +int +gu1_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 +gu1_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 = + (((ModeWidth + 1023) / 1024) * 1024) * modeBytesPerPixel; + + /* TEST FOR NO-WORK */ + if (x >= DeltaX && (unsigned short)x < (PanelWidth + DeltaX) && + y >= DeltaY && (unsigned short)y < (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 ((unsigned short)x >= (DeltaX + PanelWidth)) + DeltaX = x - PanelWidth + 1; + + if (y < DeltaY) + DeltaY = y; + else if ((unsigned short)y >= (DeltaY + PanelHeight)) + DeltaY = y - 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 +gu1_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 +gu1_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 != 15 && bpp != 16) + 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_hsync_end, gfx_get_htotal, gfx_get_vsync_end, gfx_get_vtotal * + * are used by the video overlay routines. * + * * + * gfx_get_vline and gfx_vactive are used to prevent an issue for the * + * SC1200. * + * * + * The others are part of the Durango API. * + *-----------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + * gfx_get_display_pitch + * + * This routine returns the current pitch of the frame buffer, in bytes. + *--------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +unsigned short +gu1_get_display_pitch(void) +#else +unsigned short +gfx_get_display_pitch(void) +#endif +{ + unsigned long value; + + if (gfx_cpu_version == GFX_CPU_PYRAMID) { + /* Pyramid update for 4KB line pitch */ + value = (READ_REG32(DC_LINE_DELTA) & 0x07FF) << 2; + } else { + value = (READ_REG32(DC_LINE_DELTA) & 0x03FF) << 2; + } + + return ((unsigned short)value); +} + +/*---------------------------------------------------------------------------- + * 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 +gu1_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_GX_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; + + *xres = DisplayParams[mode].hactive; + *yres = DisplayParams[mode].vactive; + + return (1); + } + return (0); +} + +/*---------------------------------------------------------------------------- + * GFX_GET_DISPLAY_MODE_COUNT + * + * Returns number of modes supported. + *---------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +int +gu1_get_display_mode_count(void) +#else +int +gfx_get_display_mode_count(void) +#endif +{ + return (NUM_GX_DISPLAY_MODES); +} + +/*---------------------------------------------------------------------------- + * gfx_get_frame_buffer_line_size + * + * Returns the current frame buffer line size, in bytes + *---------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +unsigned long +gu1_get_frame_buffer_line_size(void) +#else +unsigned long +gfx_get_frame_buffer_line_size(void) +#endif +{ + return ((READ_REG32(DC_BUF_SIZE) & 0x1FF) << 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 +gu1_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; + + bpp_flag = GFX_MODE_8BPP; + if (bpp > 8) + bpp_flag = GFX_MODE_16BPP; + + for (index = 0; index < NUM_GX_DISPLAY_MODES; index++) { + if ((DisplayParams[index].hactive == (unsigned short)xres) && + (DisplayParams[index].vactive == (unsigned short)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; + + return (hz); + } + } + return (-1); +} + +/*---------------------------------------------------------------------------- + * gfx_refreshrate_from_frequency + * + * This routine maps the frequency to close match refresh rate + *---------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +int +gu1_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; + + bpp_flag = GFX_MODE_8BPP; + if (bpp > 8) + bpp_flag = GFX_MODE_16BPP; + + /* 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_GX_DISPLAY_MODES; index++) { + if ((DisplayParams[index].htotal == (unsigned short)xres) && + (DisplayParams[index].vtotal == (unsigned short)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; + + 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 +gu1_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; + + bpp_flag = GFX_MODE_8BPP; + if (bpp > 8) + bpp_flag = GFX_MODE_16BPP; + + /* 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_GX_DISPLAY_MODES; index++) { + if ((DisplayParams[index].hactive == (unsigned short)xres) && + (DisplayParams[index].vactive == (unsigned short)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; + + return (1); +} + +/*---------------------------------------------------------------------------- + * gfx_get_frequency_from_refreshrate + * + * This routine maps the refresh rate to the closest matching PLL frequency. + *---------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +int +gu1_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; + + if (hz == 56) + hz_flag = GFX_MODE_56HZ; + else if (hz == 60) + hz_flag = GFX_MODE_60HZ; + else if (hz == 70) + hz_flag = GFX_MODE_70HZ; + else if (hz == 72) + hz_flag = GFX_MODE_72HZ; + else if (hz == 75) + hz_flag = GFX_MODE_75HZ; + else if (hz == 85) + hz_flag = GFX_MODE_85HZ; + + bpp_flag = GFX_MODE_8BPP; + if (bpp > 8) + bpp_flag = GFX_MODE_16BPP; + + /* FIND THE REGISTER VALUES FOR THE DESIRED FREQUENCY */ + + for (index = 0; index < NUM_GX_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 = 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 +gu1_get_max_supported_pixel_clock(void) +#else +unsigned long +gfx_get_max_supported_pixel_clock(void) +#endif +{ + /* ALL CHIPS CAN HANDLE 1280X1024@85HZ - 157.5 MHz */ + return 157500; +} + +/*---------------------------------------------------------------------------- + * 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 +gu1_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(); + + /* SUPPORT EMULATED VGA MODES */ + if (gfx_pixel_double) + *xres >>= 1; + + if (gfx_line_double) + *yres >>= 1; + + /* SET BPP FLAGS TO LIMIT MODE SELECTION */ + bpp_flag = GFX_MODE_8BPP; + if (*bpp > 8) + bpp_flag = GFX_MODE_16BPP; + + for (mode = 0; mode < NUM_GX_DISPLAY_MODES; mode++) { + if ((DisplayParams[mode].hactive == (unsigned short)*xres) && + (DisplayParams[mode].vactive == (unsigned short)*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; + + return (1); + } + } + return (-1); +} + +/*--------------------------------------------------------------------------- + * gfx_get_hactive + *--------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +unsigned short +gu1_get_hactive(void) +#else +unsigned short +gfx_get_hactive(void) +#endif +{ + return ((unsigned short)((READ_REG32(DC_H_TIMING_1) & 0x07F8) + 8)); +} + +/*--------------------------------------------------------------------------- + * gfx_get_hsync_start + *--------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +unsigned short +gu1_get_hsync_start(void) +#else +unsigned short +gfx_get_hsync_start(void) +#endif +{ + return ((unsigned short)((READ_REG32(DC_H_TIMING_3) & 0x07F8) + 8)); +} + +/*--------------------------------------------------------------------------- + * gfx_get_hsync_end + *--------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +unsigned short +gu1_get_hsync_end(void) +#else +unsigned short +gfx_get_hsync_end(void) +#endif +{ + return ((unsigned short)(((READ_REG32(DC_H_TIMING_3) >> 16) & 0x07F8) + + 8)); +} + +/*--------------------------------------------------------------------------- + * gfx_get_htotal + *--------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +unsigned short +gu1_get_htotal(void) +#else +unsigned short +gfx_get_htotal(void) +#endif +{ + return ((unsigned short)(((READ_REG32(DC_H_TIMING_1) >> 16) & 0x07F8) + + 8)); +} + +/*--------------------------------------------------------------------------- + * gfx_get_vactive + *--------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +unsigned short +gu1_get_vactive(void) +#else +unsigned short +gfx_get_vactive(void) +#endif +{ + return ((unsigned short)((READ_REG32(DC_V_TIMING_1) & 0x07FF) + 1)); +} + +/*--------------------------------------------------------------------------- + * gfx_get_vsync_end + *--------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +unsigned short +gu1_get_vsync_end(void) +#else +unsigned short +gfx_get_vsync_end(void) +#endif +{ + return ((unsigned short)(((READ_REG32(DC_V_TIMING_3) >> 16) & 0x07FF) + + 1)); +} + +/*--------------------------------------------------------------------------- + * gfx_get_vtotal + *--------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +unsigned short +gu1_get_vtotal(void) +#else +unsigned short +gfx_get_vtotal(void) +#endif +{ + return ((unsigned short)(((READ_REG32(DC_V_TIMING_1) >> 16) & 0x07FF) + + 1)); +} + +/*----------------------------------------------------------------------------- + * gfx_get_display_bpp + * + * This routine returns the current color depth of the active display. + *----------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +unsigned short +gu1_get_display_bpp(void) +#else +unsigned short +gfx_get_display_bpp(void) +#endif +{ + switch (READ_REG32(DC_OUTPUT_CFG) & 3) { + case 0: + return (16); + case 2: + return (15); + } + return (8); +} + +/*--------------------------------------------------------------------------- + * gfx_get_vline + *--------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +unsigned short +gu1_get_vline(void) +#else +unsigned short +gfx_get_vline(void) +#endif +{ + unsigned short current_scan_line; + + /* Read similar value twice to ensure that the value is not transitioning */ + do { + current_scan_line = + (unsigned short)READ_REG32(DC_V_LINE_CNT) & 0x07FF; + } while (current_scan_line != + (unsigned short)(READ_REG32(DC_V_LINE_CNT) & 0x07FF)); + + return (current_scan_line); +} + +/*----------------------------------------------------------------------------- + * gfx_get_display_offset + *----------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +unsigned long +gu1_get_display_offset(void) +#else +unsigned long +gfx_get_display_offset(void) +#endif +{ + return (READ_REG32(DC_FB_ST_OFFSET) & 0x003FFFFF); +} + +/*----------------------------------------------------------------------------- + * gfx_get_cursor_offset + *----------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +unsigned long +gu1_get_cursor_offset(void) +#else +unsigned long +gfx_get_cursor_offset(void) +#endif +{ + return (READ_REG32(DC_CURS_ST_OFFSET) & 0x003FFFFF); +} + +#if GFX_READ_ROUTINES + +/*************************************************************/ +/* READ ROUTINES | INCLUDED FOR DIAGNOSTIC PURPOSES ONLY */ +/*************************************************************/ + +/*--------------------------------------------------------------------------- + * gfx_get_hblank_start + *--------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +unsigned short +gu1_get_hblank_start(void) +#else +unsigned short +gfx_get_hblank_start(void) +#endif +{ + return ((unsigned short)((READ_REG32(DC_H_TIMING_2) & 0x07F8) + 8)); +} + +/*--------------------------------------------------------------------------- + * gfx_get_hblank_end + *--------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +unsigned short +gu1_get_hblank_end(void) +#else +unsigned short +gfx_get_hblank_end(void) +#endif +{ + return ((unsigned short)(((READ_REG32(DC_H_TIMING_2) >> 16) & 0x07F8) + + 8)); +} + +/*--------------------------------------------------------------------------- + * gfx_get_vblank_start + *--------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +unsigned short +gu1_get_vblank_start(void) +#else +unsigned short +gfx_get_vblank_start(void) +#endif +{ + return ((unsigned short)((READ_REG32(DC_V_TIMING_2) & 0x07FF) + 1)); +} + +/*--------------------------------------------------------------------------- + * gfx_get_vsync_start + *--------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +unsigned short +gu1_get_vsync_start(void) +#else +unsigned short +gfx_get_vsync_start(void) +#endif +{ + return ((unsigned short)((READ_REG32(DC_V_TIMING_3) & 0x07FF) + 1)); +} + +/*--------------------------------------------------------------------------- + * gfx_get_vblank_end + *--------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +unsigned short +gu1_get_vblank_end(void) +#else +unsigned short +gfx_get_vblank_end(void) +#endif +{ + return ((unsigned short)(((READ_REG32(DC_V_TIMING_2) >> 16) & 0x07FF) + + 1)); +} + +/*----------------------------------------------------------------------------- + * gfx_get_display_palette_entry + *----------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +int +gu1_get_display_palette_entry(unsigned long index, unsigned long *palette) +#else +int +gfx_get_display_palette_entry(unsigned long index, unsigned long *palette) +#endif +{ + unsigned long data; + + if (index > 0xFF) + return GFX_STATUS_BAD_PARAMETER; + + WRITE_REG32(DC_PAL_ADDRESS, index); + data = READ_REG32(DC_PAL_DATA); + data = ((data << 2) & 0x000000FC) | + ((data << 4) & 0x0000FC00) | ((data << 6) & 0x00FC0000); + + *palette = data; + return 0; +} + +/*----------------------------------------------------------------------------- + * gfx_get_display_palette + *----------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +void +gu1_get_display_palette(unsigned long *palette) +#else +void +gfx_get_display_palette(unsigned long *palette) +#endif +{ + unsigned long i, data; + + WRITE_REG32(DC_PAL_ADDRESS, 0); + for (i = 0; i < 256; i++) { + data = READ_REG32(DC_PAL_DATA); + data = ((data << 2) & 0x000000FC) | + ((data << 4) & 0x0000FC00) | ((data << 6) & 0x00FC0000); + palette[i] = data; + } +} + +/*----------------------------------------------------------------------------- + * gfx_get_cursor_enable + *----------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +unsigned long +gu1_get_cursor_enable(void) +#else +unsigned long +gfx_get_cursor_enable(void) +#endif +{ + return (READ_REG32(DC_GENERAL_CFG) & DC_GCFG_CURE); +} + +/*----------------------------------------------------------------------------- + * gfx_get_cursor_position + *----------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +unsigned long +gu1_get_cursor_position(void) +#else +unsigned long +gfx_get_cursor_position(void) +#endif +{ + return ((READ_REG32(DC_CURSOR_X) & 0x07FF) | + ((READ_REG32(DC_CURSOR_Y) << 16) & 0x03FF0000)); +} + +/*----------------------------------------------------------------------------- + * gfx_get_cursor_clip + *----------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +unsigned long +gu1_get_cursor_clip(void) +#else +unsigned long +gfx_get_cursor_clip(void) +#endif +{ + return (((READ_REG32(DC_CURSOR_X) >> 11) & 0x01F) | + ((READ_REG32(DC_CURSOR_Y) << 5) & 0x1F0000)); +} + +/*----------------------------------------------------------------------------- + * gfx_get_cursor_color + *----------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +unsigned long +gu1_get_cursor_color(int color) +#else +unsigned long +gfx_get_cursor_color(int color) +#endif +{ + unsigned long data; + + if (color) { + WRITE_REG32(DC_PAL_ADDRESS, 0x101); + } else { + WRITE_REG32(DC_PAL_ADDRESS, 0x100); + } + data = READ_REG32(DC_PAL_DATA); + data = ((data << 6) & 0x00FC0000) | + ((data << 4) & 0x0000FC00) | ((data << 2) & 0x000000FC); + return (data); +} + +/*----------------------------------------------------------------------------- + * gfx_get_compression_enable + *----------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +int +gu1_get_compression_enable(void) +#else +int +gfx_get_compression_enable(void) +#endif +{ + unsigned long gcfg; + + gcfg = READ_REG32(DC_GENERAL_CFG); + if (gcfg & DC_GCFG_CMPE) + return (1); + else + return (0); +} + +/*----------------------------------------------------------------------------- + * gfx_get_compression_offset + *----------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +unsigned long +gu1_get_compression_offset(void) +#else +unsigned long +gfx_get_compression_offset(void) +#endif +{ + unsigned long offset; + + offset = READ_REG32(DC_CB_ST_OFFSET) & 0x003FFFFF; + return (offset); +} + +/*----------------------------------------------------------------------------- + * gfx_get_compression_pitch + *----------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +unsigned short +gu1_get_compression_pitch(void) +#else +unsigned short +gfx_get_compression_pitch(void) +#endif +{ + unsigned short pitch; + + pitch = (unsigned short)(READ_REG32(DC_LINE_DELTA) >> 12) & 0x03FF; + return (pitch << 2); +} + +/*----------------------------------------------------------------------------- + * gfx_get_compression_size + *----------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +unsigned short +gu1_get_compression_size(void) +#else +unsigned short +gfx_get_compression_size(void) +#endif +{ + unsigned short size; + + size = (unsigned short)((READ_REG32(DC_BUF_SIZE) >> 9) & 0x7F) - 1; + return ((size << 2) + 16); +} + +/*----------------------------------------------------------------------------- + * gfx_get_valid_bit + *----------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +int +gu1_get_valid_bit(int line) +#else +int +gfx_get_valid_bit(int line) +#endif +{ + int valid; + + WRITE_REG32(MC_DR_ADD, line); + valid = (int)READ_REG32(MC_DR_ACC) & 1; + return (valid); +} + +/*--------------------------------------------------------------------------- + * 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 +gu1_get_display_video_offset(void) +#else +unsigned long +gfx_get_display_video_offset(void) +#endif +{ + return (READ_REG32(DC_VID_ST_OFFSET) & 0x003FFFFF); +} + +/*--------------------------------------------------------------------------- + * 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 +gu1_get_display_video_size(void) +#else +unsigned long +gfx_get_display_video_size(void) +#endif +{ + /* RETURN TOTAL SIZE, IN BYTES */ + return ((READ_REG32(DC_BUF_SIZE) >> 10) & 0x000FFFC0); +} + +/*----------------------------------------------------------------------------- + * gfx_get_display_priority_high + *----------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +int +gu1_get_display_priority_high(void) +#else +int +gfx_get_display_priority_high(void) +#endif +{ + if (READ_REG32(MC_MEM_CNTRL1) & MC_XBUSARB) + return (1); + else + return (0); +} + +#endif /* GFX_READ_ROUTINES */ + +/* END OF FILE */ diff --git a/src/gfx/disp_gu2.c b/src/gfx/disp_gu2.c new file mode 100644 index 0000000..403a72a --- /dev/null +++ b/src/gfx/disp_gu2.c @@ -0,0 +1,2788 @@ +/* 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 gu2_enable_compression(void); /* private routine definition */ +void gu2_disable_compression(void); /* private routine definition */ +int gfx_set_display_control(int sync_polarities); /* private routine + * definition */ +void gfx_reset_video(void); +int gu2_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 RC_READS_PER_MILLISECOND 15000L + +#if GFX_DISPLAY_DYNAMIC +void +gu2_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 * RC_READS_PER_MILLISECOND; + while (loop-- > 0) { + READ_REG32(MDC_UNLOCK); + } +} + +#if GFX_DISPLAY_DYNAMIC +void +gu2_delay_microseconds(unsigned long microseconds) +#else +void +gfx_delay_microseconds(unsigned long microseconds) +#endif +{ + /* ASSUME 400 MHz, 2 CLOCKS PER INCREMENT */ + unsigned long loop_count = microseconds * 15; + + while (loop_count-- > 0) { + READ_REG32(MDC_UNLOCK); + } +} + +/*---------------------------------------------------------------------------- + * GFX_SET_DISPLAY_BPP + * + * This routine programs the bpp in the display controller. + *---------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +int +gu2_set_display_bpp(unsigned short bpp) +#else +int +gfx_set_display_bpp(unsigned short bpp) +#endif +{ + unsigned long dcfg, lock; + + dcfg = + READ_REG32(MDC_DISPLAY_CFG) & ~(MDC_DCFG_DISP_MODE_MASK | + MDC_DCFG_16BPP_MODE_MASK); + lock = READ_REG32(MDC_UNLOCK); + + switch (bpp) { + case 12: + dcfg |= (MDC_DCFG_DISP_MODE_16BPP | MDC_DCFG_12BPP); + break; + case 15: + dcfg |= (MDC_DCFG_DISP_MODE_16BPP | MDC_DCFG_15BPP); + break; + case 16: + dcfg |= (MDC_DCFG_DISP_MODE_16BPP | MDC_DCFG_16BPP); + break; + case 32: + dcfg |= (MDC_DCFG_DISP_MODE_24BPP); + break; + case 8: + dcfg |= (MDC_DCFG_DISP_MODE_8BPP); + break; + default: + return GFX_STATUS_BAD_PARAMETER; + } + + WRITE_REG32(MDC_UNLOCK, MDC_UNLOCK_VALUE); + WRITE_REG32(MDC_DISPLAY_CFG, dcfg); + WRITE_REG32(MDC_UNLOCK, lock); + + /* SET BPP IN GRAPHICS PIPELINE */ + gfx_set_bpp(bpp); + + return 0; +} + +/*---------------------------------------------------------------------------- + * gu2_set_specified_mode (private routine) + * This routine uses the parameters in the specified display mode structure + * to program the display controller hardware. + *---------------------------------------------------------------------------- + */ +int +gu2_set_specified_mode(DISPLAYMODE * pMode, int bpp) +{ + unsigned long unlock, value; + unsigned long gcfg, dcfg; + unsigned long size, pitch; + unsigned long vid_buf_size; + 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 */ + gu2_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(MDC_UNLOCK); + WRITE_REG32(MDC_UNLOCK, MDC_UNLOCK_VALUE); + + /* READ THE CURRENT REGISTER VALUES */ + gcfg = READ_REG32(MDC_GENERAL_CFG); + dcfg = READ_REG32(MDC_DISPLAY_CFG); + + /* BLANK THE DISPLAY IN THE DISPLAY FILTER */ + gfx_set_crt_enable(0); + + /* DISABLE THE TIMING GENERATOR */ + dcfg &= ~(unsigned long)MDC_DCFG_TGEN; + WRITE_REG32(MDC_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(5); + + /* DISABLE DISPLAY FIFO LOAD */ + gcfg &= ~(unsigned long)MDC_GCFG_DFLE; + WRITE_REG32(MDC_GENERAL_CFG, gcfg); + + /* PRESERVE VIDEO INFORMATION */ + gcfg &= (unsigned long)(MDC_GCFG_YUVM | MDC_GCFG_VDSE); + dcfg = 0; + + /* SET THE DOT CLOCK FREQUENCY */ + /* Mask off the divide by two bit (bit 31) */ + if (!(pMode->flags & GFX_MODE_EXCLUDE_PLL)) + 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(10); + + /* SET THE GX DISPLAY CONTROLLER PARAMETERS */ + WRITE_REG32(MDC_FB_ST_OFFSET, 0); + WRITE_REG32(MDC_CB_ST_OFFSET, 0); + WRITE_REG32(MDC_CURS_ST_OFFSET, 0); + WRITE_REG32(MDC_ICON_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 = MDC_DV_LINE_SIZE_1024; + + if (size > 1024) { + pitch = 2048; + dv_size = MDC_DV_LINE_SIZE_2048; + } + + if (size > 2048) { + pitch = 4096; + dv_size = MDC_DV_LINE_SIZE_4096; + } + + if (size > 4096) { + pitch = 8192; + dv_size = MDC_DV_LINE_SIZE_8192; + } + + WRITE_REG32(MDC_GFX_PITCH, pitch >> 3); + + /* WRITE DIRTY/VALID CONTROL WITH LINE LENGTH */ + temp = READ_REG32(MDC_DV_CTL); + WRITE_REG32(MDC_DV_CTL, (temp & ~MDC_DV_LINE_SIZE_MASK) | dv_size); + + if (PanelEnable) { + size = pMode->hactive; + if (bpp > 8) + size <<= 1; + if (bpp > 16) + size <<= 1; + } + + /* SAVE PREVIOUSLY STORED VIDEO LINE SIZE */ + vid_buf_size = READ_REG32(MDC_LINE_SIZE) & 0xFF000000; + + /* ADD 2 TO SIZE FOR POSSIBLE START ADDRESS ALIGNMENTS */ + WRITE_REG32(MDC_LINE_SIZE, ((size >> 3) + 2) | vid_buf_size); + + /* ALWAYS ENABLE VIDEO AND GRAPHICS DATA */ + /* These bits are relics from a previous design and */ + /* should always be enabled. */ + dcfg |= (unsigned long)(MDC_DCFG_VDEN | MDC_DCFG_GDEN); + + /* SET PIXEL FORMAT */ + dcfg |= bpp_mask; + + /* ENABLE TIMING GENERATOR, TIM. REG. UPDATES, PALETTE BYPASS */ + /* AND VERT. INT. SELECT */ + dcfg |= + (unsigned long)(MDC_DCFG_TGEN | MDC_DCFG_TRUP | MDC_DCFG_PALB | + MDC_DCFG_VISL); + + /* DISABLE ADDRESS MASKS */ + dcfg |= MDC_DCFG_A20M; + dcfg |= MDC_DCFG_A18M; + + /* SET FIFO PRIORITIES AND DISPLAY FIFO LOAD ENABLE */ + /* Set the priorities higher for high resolution modes. */ + if (pMode->hactive > 1024 || bpp == 32) + gcfg |= 0x000A901; + else + gcfg |= 0x0006501; + + /* ENABLE FLAT PANEL CENTERING */ + /* For panel modes having a resolution smaller than the */ + /* panel resolution, turn on data centering. */ + if (PanelEnable && ModeWidth < PanelWidth) + dcfg |= MDC_DCFG_DCEN; + + /* COMBINE AND SET TIMING VALUES */ + value = (unsigned long)(pMode->hactive - 1) | + (((unsigned long)(pMode->htotal - 1)) << 16); + WRITE_REG32(MDC_H_ACTIVE_TIMING, value); + value = (unsigned long)(pMode->hblankstart - 1) | + (((unsigned long)(pMode->hblankend - 1)) << 16); + WRITE_REG32(MDC_H_BLANK_TIMING, value); + value = (unsigned long)(pMode->hsyncstart - 1) | + (((unsigned long)(pMode->hsyncend - 1)) << 16); + WRITE_REG32(MDC_H_SYNC_TIMING, value); + value = (unsigned long)(pMode->vactive - 1) | + (((unsigned long)(pMode->vtotal - 1)) << 16); + WRITE_REG32(MDC_V_ACTIVE_TIMING, value); + value = (unsigned long)(pMode->vblankstart - 1) | + (((unsigned long)(pMode->vblankend - 1)) << 16); + WRITE_REG32(MDC_V_BLANK_TIMING, value); + value = (unsigned long)(pMode->vsyncstart - 1) | + (((unsigned long)(pMode->vsyncend - 1)) << 16); + WRITE_REG32(MDC_V_SYNC_TIMING, value); + + WRITE_REG32(MDC_DISPLAY_CFG, dcfg); + WRITE_REG32(MDC_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 MDC_UNLOCK */ + WRITE_REG32(MDC_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 +gu2_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)) { + + /* REDCLOUD 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 +gu2_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 (gu2_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 +gu2_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 & 4) + gfx_display_mode.flags |= GFX_MODE_EXCLUDE_PLL; + 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 (gu2_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 +gu2_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(MDC_UNLOCK); + WRITE_REG32(MDC_UNLOCK, MDC_UNLOCK_VALUE); + + /* READ THE CURRENT RC VALUES */ + dcfg = READ_REG32(MDC_DISPLAY_CFG); + vactive = READ_REG32(MDC_V_ACTIVE_TIMING); + vblank = READ_REG32(MDC_V_BLANK_TIMING); + + /* DISABLE TIMING REGISTER UPDATES */ + WRITE_REG32(MDC_DISPLAY_CFG, dcfg & ~(unsigned long)MDC_DCFG_TRUP); + + /* WRITE NEW TIMING VALUES */ + WRITE_REG32(MDC_V_ACTIVE_TIMING, + (vactive & MDC_VAT_VA_MASK) | (unsigned long)(vtotal - 1) << 16); + WRITE_REG32(MDC_V_BLANK_TIMING, + (vblank & MDC_VBT_VBS_MASK) | (unsigned long)(vtotal - 1) << 16); + + /* RESTORE OLD RC VALUES */ + WRITE_REG32(MDC_DISPLAY_CFG, dcfg); + WRITE_REG32(MDC_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 +gu2_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(MDC_UNLOCK); + + value = READ_REG32(MDC_GFX_PITCH) & 0xFFFF0000; + value |= (pitch >> 3); + WRITE_REG32(MDC_UNLOCK, MDC_UNLOCK_VALUE); + WRITE_REG32(MDC_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(MDC_GENERAL_CFG); + + if (pitch == 1024 || pitch == 2048 || pitch == 4096 || pitch == 8192) + value &= ~(unsigned long)(MDC_GCFG_FDTY); + else + value |= (unsigned long)(MDC_GCFG_FDTY); + + WRITE_REG32(MDC_GENERAL_CFG, value); + WRITE_REG32(MDC_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 +gu2_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(MDC_UNLOCK); + WRITE_REG32(MDC_UNLOCK, MDC_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(MDC_FB_ST_OFFSET, offset); + if (gfx_compression_enabled) { + /* WAIT FOR THE OFFSET TO BE LATCHED */ + gfx_wait_vertical_blank(); + gu2_enable_compression(); + } + } else { + /* ONLY DISABLE COMPRESSION ONCE */ + if (gfx_compression_active) + gu2_disable_compression(); + + WRITE_REG32(MDC_FB_ST_OFFSET, offset); + } + + WRITE_REG32(MDC_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 +gu2_set_display_palette_entry(unsigned long index, unsigned long palette) +#else +int +gfx_set_display_palette_entry(unsigned long index, unsigned long palette) +#endif +{ + unsigned long dcfg, unlock; + + if (index > 0xFF) + return GFX_STATUS_BAD_PARAMETER; + + unlock = READ_REG32(MDC_UNLOCK); + dcfg = READ_REG32(MDC_DISPLAY_CFG); + + WRITE_REG32(MDC_UNLOCK, MDC_UNLOCK_VALUE); + WRITE_REG32(MDC_DISPLAY_CFG, dcfg & ~MDC_DCFG_PALB); + WRITE_REG32(MDC_UNLOCK, unlock); + + WRITE_REG32(MDC_PAL_ADDRESS, index); + WRITE_REG32(MDC_PAL_DATA, palette); + + return GFX_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * 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 +gu2_set_display_palette(unsigned long *palette) +#else +int +gfx_set_display_palette(unsigned long *palette) +#endif +{ + unsigned long unlock, dcfg, i; + + WRITE_REG32(MDC_PAL_ADDRESS, 0); + + if (palette) { + unlock = READ_REG32(MDC_UNLOCK); + dcfg = READ_REG32(MDC_DISPLAY_CFG); + + WRITE_REG32(MDC_UNLOCK, MDC_UNLOCK_VALUE); + WRITE_REG32(MDC_DISPLAY_CFG, dcfg & ~MDC_DCFG_PALB); + WRITE_REG32(MDC_UNLOCK, unlock); + + for (i = 0; i < 256; i++) + WRITE_REG32(MDC_PAL_DATA, palette[i]); + + return GFX_STATUS_OK; + } + return GFX_STATUS_BAD_PARAMETER; +} + +/*--------------------------------------------------------------------------- + * 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 +gu2_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(MDC_UNLOCK); + gcfg = READ_REG32(MDC_GENERAL_CFG); + if (enable) + gcfg |= MDC_GCFG_CURE; + else + gcfg &= ~(MDC_GCFG_CURE); + + /* WRITE NEW REGISTER VALUE */ + WRITE_REG32(MDC_UNLOCK, MDC_UNLOCK_VALUE); + WRITE_REG32(MDC_GENERAL_CFG, gcfg); + WRITE_REG32(MDC_UNLOCK, unlock); +} + +/*--------------------------------------------------------------------------- + * gfx_set_cursor_colors + * + * This routine sets the colors of the hardware cursor. + *--------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +void +gu2_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(MDC_PAL_ADDRESS, 0x100); + WRITE_REG32(MDC_PAL_DATA, bkcolor); + WRITE_REG32(MDC_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 +gu2_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(MDC_UNLOCK); + WRITE_REG32(MDC_UNLOCK, MDC_UNLOCK_VALUE); + WRITE_REG32(MDC_CURS_ST_OFFSET, memoffset); + WRITE_REG32(MDC_CURSOR_X, (unsigned long)x | + (((unsigned long)xoffset) << 11)); + WRITE_REG32(MDC_CURSOR_Y, (unsigned long)y | + (((unsigned long)yoffset) << 11)); + WRITE_REG32(MDC_UNLOCK, unlock); +} + +/*--------------------------------------------------------------------------- + * gfx_set_cursor_shape32 + * + * This routine loads 32x32 cursor data into the cursor buffer in graphics + * memory. + * As the Redcloud cursor is actually 64x64, we must pad the outside of the + * cursor data with transparent pixels. + *--------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +void +gu2_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 +gu2_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; + } +} + +/*--------------------------------------------------------------------------- + * gfx_set_icon_enable + * + * This routine enables or disables the hardware icon. The icon position + * and colors should be programmed prior to calling this routine for the + * first time. + *--------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +void +gu2_set_icon_enable(int enable) +#else +void +gfx_set_icon_enable(int enable) +#endif +{ + unsigned long unlock, gcfg; + + /* SET OR CLEAR ICON ENABLE BIT */ + unlock = READ_REG32(MDC_UNLOCK); + gcfg = READ_REG32(MDC_GENERAL_CFG); + if (enable) + gcfg |= MDC_GCFG_ICNE; + else + gcfg &= ~(MDC_GCFG_ICNE); + + /* WRITE NEW REGISTER VALUE */ + WRITE_REG32(MDC_UNLOCK, MDC_UNLOCK_VALUE); + WRITE_REG32(MDC_GENERAL_CFG, gcfg); + WRITE_REG32(MDC_UNLOCK, unlock); +} + +/*--------------------------------------------------------------------------- + * gfx_set_icon_colors + * + * This routine sets the three icon colors. + *--------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +void +gu2_set_icon_colors(unsigned long color0, unsigned long color1, + unsigned long color2) +#else +void +gfx_set_icon_colors(unsigned long color0, unsigned long color1, + unsigned long color2) +#endif +{ + /* ICON COLORS LOCATED AT PALETTE INDEXES 102-104h */ + WRITE_REG32(MDC_PAL_ADDRESS, 0x102); + + WRITE_REG32(MDC_PAL_DATA, color0); + WRITE_REG32(MDC_PAL_DATA, color1); + WRITE_REG32(MDC_PAL_DATA, color2); +} + +/*--------------------------------------------------------------------------- + * gfx_set_icon_position + * + * This routine sets the starting X coordinate for the hardware icon and the + * memory offset for the icon buffer. + *--------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +void +gu2_set_icon_position(unsigned long memoffset, unsigned short xpos) +#else +void +gfx_set_icon_position(unsigned long memoffset, unsigned short xpos) +#endif +{ + unsigned long lock = READ_REG32(MDC_UNLOCK); + + WRITE_REG32(MDC_UNLOCK, MDC_UNLOCK_VALUE); + + /* PROGRAM THE MEMORY OFFSET */ + WRITE_REG32(MDC_ICON_ST_OFFSET, memoffset & 0x0FFFFFFF); + + /* PROGRAM THE XCOORDINATE */ + WRITE_REG32(MDC_ICON_X, (unsigned long)(xpos & 0x07FF)); + + WRITE_REG32(MDC_UNLOCK, lock); +} + +/*--------------------------------------------------------------------------- + * gfx_set_icon_shape64 + * + * This routine initializes the icon buffer according to the current mode. + *--------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +void +gu2_set_icon_shape64(unsigned long memoffset, unsigned long *andmask, + unsigned long *xormask, unsigned int lines) +#else +void +gfx_set_icon_shape64(unsigned long memoffset, unsigned long *andmask, + unsigned long *xormask, unsigned int lines) +#endif +{ + unsigned short i, height; + + height = lines << 1; + + for (i = 0; i < height; i += 2) { + /* EVEN QWORDS CONTAIN THE AND MASK */ + /* Swap dwords to hide qword constraint */ + 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; + } +} + +/*--------------------------------------------------------------------------- + * gu2_enable_compression + * + * This is a private routine to this module (not exposed in the Durango API). + * It enables display compression. + *--------------------------------------------------------------------------- + */ +void +gu2_enable_compression(void) +{ + unsigned long unlock, gcfg, temp; + + /* DO NOT ENABLE IF START ADDRESS IS NOT ZERO */ + if (READ_REG32(MDC_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. */ + temp = READ_REG32(MDC_DV_CTL); + WRITE_REG32(MDC_DV_CTL, temp | 0x00000001); + + /* TURN ON COMPRESSION CONTROL BITS */ + unlock = READ_REG32(MDC_UNLOCK); + gcfg = READ_REG32(MDC_GENERAL_CFG); + gcfg |= MDC_GCFG_CMPE | MDC_GCFG_DECE; + WRITE_REG32(MDC_UNLOCK, MDC_UNLOCK_VALUE); + WRITE_REG32(MDC_GENERAL_CFG, gcfg); + WRITE_REG32(MDC_UNLOCK, unlock); +} + +/*--------------------------------------------------------------------------- + * gu2_disable_compression + * + * This is a private routine to this module (not exposed in the Durango API). + * It disables display compression. + *--------------------------------------------------------------------------- + */ +void +gu2_disable_compression(void) +{ + unsigned long unlock, gcfg; + + /* SET GLOBAL INDICATOR */ + + gfx_compression_active = 0; + + /* TURN OFF COMPRESSION CONTROL BITS */ + + unlock = READ_REG32(MDC_UNLOCK); + gcfg = READ_REG32(MDC_GENERAL_CFG); + gcfg &= ~(MDC_GCFG_CMPE | MDC_GCFG_DECE); + WRITE_REG32(MDC_UNLOCK, MDC_UNLOCK_VALUE); + WRITE_REG32(MDC_GENERAL_CFG, gcfg); + WRITE_REG32(MDC_UNLOCK, unlock); +} + +/*--------------------------------------------------------------------------- + * gfx_set_compression_enable + * + * This routine enables or disables display compression. + *--------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +int +gu2_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) + gu2_enable_compression(); + else + gu2_disable_compression(); + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_set_compression_offset + * + * This routine sets the base offset for the compression buffer. + *--------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +int +gu2_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 REDCLOUD */ + + if (offset & 0x0F) + return (1); + + /* SET REGISTER VALUE */ + + lock = READ_REG32(MDC_UNLOCK); + WRITE_REG32(MDC_UNLOCK, MDC_UNLOCK_VALUE); + WRITE_REG32(MDC_CB_ST_OFFSET, offset & 0x0FFFFFFF); + WRITE_REG32(MDC_UNLOCK, lock); + + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_set_compression_pitch + * + * This routine sets the pitch, in bytes, of the compression buffer. + *--------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +int +gu2_set_compression_pitch(unsigned short pitch) +#else +int +gfx_set_compression_pitch(unsigned short pitch) +#endif +{ + unsigned long lock, line_delta; + + lock = READ_REG32(MDC_UNLOCK); + + /* SET REGISTER VALUE */ + + line_delta = READ_REG32(MDC_GFX_PITCH) & 0x0000FFFF; + line_delta |= (((unsigned long)pitch << 13) & 0xFFFF0000); + WRITE_REG32(MDC_UNLOCK, MDC_UNLOCK_VALUE); + WRITE_REG32(MDC_GFX_PITCH, line_delta); + WRITE_REG32(MDC_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 +gu2_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(MDC_UNLOCK); + buf_size = READ_REG32(MDC_LINE_SIZE) & 0xFF80FFFF; + buf_size |= ((((unsigned long)size >> 3) + 1) & 0x7F) << 16; + WRITE_REG32(MDC_UNLOCK, MDC_UNLOCK_VALUE); + WRITE_REG32(MDC_LINE_SIZE, buf_size); + WRITE_REG32(MDC_UNLOCK, lock); + return (0); +} + +/*--------------------------------------------------------------------------- + * 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 +gu2_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(MDC_UNLOCK); + gcfg = READ_REG32(MDC_GENERAL_CFG); + + switch (format) { + case VIDEO_FORMAT_Y0Y1Y2Y3: + case VIDEO_FORMAT_Y3Y2Y1Y0: + case VIDEO_FORMAT_Y1Y0Y3Y2: + case VIDEO_FORMAT_Y1Y2Y3Y0: + gcfg |= MDC_GCFG_YUVM; + break; + + default: + gcfg &= ~MDC_GCFG_YUVM; + break; + } + + WRITE_REG32(MDC_UNLOCK, MDC_UNLOCK_VALUE); + WRITE_REG32(MDC_GENERAL_CFG, gcfg); + WRITE_REG32(MDC_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 +gu2_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(MDC_UNLOCK); + gcfg = READ_REG32(MDC_GENERAL_CFG); + dcfg = READ_REG32(MDC_DISPLAY_CFG); + + /* SET OR CLEAR VIDEO ENABLE IN GENERAL_CFG */ + + if (enable) + gcfg |= MDC_GCFG_VIDE; + else + gcfg &= ~MDC_GCFG_VIDE; + + /* WRITE REGISTER */ + + WRITE_REG32(MDC_UNLOCK, MDC_UNLOCK_VALUE); + WRITE_REG32(MDC_GENERAL_CFG, gcfg); + WRITE_REG32(MDC_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 +gu2_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(MDC_UNLOCK); + value = READ_REG32(MDC_LINE_SIZE) & 0x00FFFFFF; + yuv_420 = READ_REG32(MDC_GENERAL_CFG) & MDC_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 */ + + value |= ((unsigned long)width << 21); + + /* WRITE THE REGISTER */ + + WRITE_REG32(MDC_UNLOCK, MDC_UNLOCK_VALUE); + WRITE_REG32(MDC_LINE_SIZE, value); + WRITE_REG32(MDC_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 +gu2_set_display_video_offset(unsigned long offset) +#else +void +gfx_set_display_video_offset(unsigned long offset) +#endif +{ + unsigned long lock; + + lock = READ_REG32(MDC_UNLOCK); + WRITE_REG32(MDC_UNLOCK, MDC_UNLOCK_VALUE); + offset &= 0x0FFFFFF0; + WRITE_REG32(MDC_VID_Y_ST_OFFSET, offset); + WRITE_REG32(MDC_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 +gu2_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(MDC_UNLOCK); + + yoffset &= 0x0FFFFFF0; + uoffset &= 0x0FFFFFF8; + voffset &= 0x0FFFFFF8; + + WRITE_REG32(MDC_UNLOCK, MDC_UNLOCK_VALUE); + WRITE_REG32(MDC_VID_Y_ST_OFFSET, yoffset); + WRITE_REG32(MDC_VID_U_ST_OFFSET, uoffset); + WRITE_REG32(MDC_VID_V_ST_OFFSET, voffset); + WRITE_REG32(MDC_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 +gu2_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(MDC_UNLOCK); + + pitch = ((uvpitch << 13) & 0xFFFF0000) | ((ypitch >> 3) & 0xFFFF); + + WRITE_REG32(MDC_UNLOCK, MDC_UNLOCK_VALUE); + WRITE_REG32(MDC_VID_YUV_PITCH, pitch); + WRITE_REG32(MDC_UNLOCK, lock); +} + +/*--------------------------------------------------------------------------- + * gfx_set_display_video_downscale (PRIVATE ROUTINE - NOT PART OF API) + * + * This routine is called by gfx_set_video_vertical_downscale. It abstracts + * the version of the display controller from the video overlay routines. + *--------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +void +gu2_set_display_video_downscale(unsigned short srch, unsigned short dsth) +#else +void +gfx_set_display_video_downscale(unsigned short srch, unsigned short dsth) +#endif +{ + unsigned long lock, delta; + + lock = READ_REG32(MDC_UNLOCK); + + /* CLIP SCALING LIMITS */ + /* Upscaling is performed in a separate function. */ + /* Maximum scale ratio is 1/2. */ + + if (dsth > srch || dsth <= (srch >> 1)) + delta = 0; + else + delta = (((unsigned long)srch << 14) / (unsigned long)dsth) << 18; + + WRITE_REG32(MDC_UNLOCK, MDC_UNLOCK_VALUE); + WRITE_REG32(MDC_VID_DS_DELTA, delta); + WRITE_REG32(MDC_UNLOCK, lock); +} + +/*--------------------------------------------------------------------------- + * gfx_set_display_video_downscale_enable (PRIVATE ROUTINE - NOT PART OF API) + * + * This routine is called by "gfx_set_video_vertical_downscale_enable". + * It abstracts the version of the display controller from the video overlay + * routines. + *--------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +void +gu2_set_display_video_vertical_downscale_enable(int enable) +#else +void +gfx_set_display_video_vertical_downscale_enable(int enable) +#endif +{ + unsigned long gcfg, unlock; + + unlock = READ_REG32(MDC_UNLOCK); + gcfg = READ_REG32(MDC_GENERAL_CFG); + + if (enable) + gcfg |= MDC_GCFG_VDSE; + else + gcfg &= ~MDC_GCFG_VDSE; + + WRITE_REG32(MDC_UNLOCK, MDC_UNLOCK_VALUE); + WRITE_REG32(MDC_GENERAL_CFG, gcfg); + WRITE_REG32(MDC_UNLOCK, unlock); +} + +/*--------------------------------------------------------------------------- + * gfx_test_timing_active + *--------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +int +gu2_test_timing_active(void) +#else +int +gfx_test_timing_active(void) +#endif +{ + if (READ_REG32(MDC_DISPLAY_CFG) & MDC_DCFG_TGEN) + return (1); + else + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_test_vertical_active + *--------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +int +gu2_test_vertical_active(void) +#else +int +gfx_test_vertical_active(void) +#endif +{ + if (READ_REG32(MDC_LINE_CNT_STATUS) & MDC_LNCNT_VNA) + return (0); + + return (1); +} + +/*--------------------------------------------------------------------------- + * gfx_wait_vertical_blank + *--------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +int +gu2_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 +gu2_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(MDC_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_is_panel_mode_supported + *--------------------------------------------------------------------------- + */ + +#if GFX_DISPLAY_DYNAMIC +int +gu2_is_panel_mode_supported(int panelResX, int panelResY, + unsigned short width, unsigned short height, unsigned short bpp) +#else +int +gfx_is_panel_mode_supported(int panelResX, int panelResY, + unsigned short width, unsigned short height, unsigned short bpp) +#endif +{ + unsigned int mode; + + /* 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)) { + return ((int)mode); + } + } + + return -1; +} + +/*--------------------------------------------------------------------------- + * gfx_set_fixed_timings + *--------------------------------------------------------------------------- + */ + +#if GFX_DISPLAY_DYNAMIC +int +gu2_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 +gu2_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 +gu2_get_display_pitch(void) +#else +unsigned short +gfx_get_display_pitch(void) +#endif +{ + return ((unsigned short)(READ_REG32(MDC_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 +gu2_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 +gu2_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 +gu2_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 +gu2_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 = 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 +gu2_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 +gu2_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 +gu2_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 +gu2_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 +gu2_get_frame_buffer_line_size(void) +#else +unsigned long +gfx_get_frame_buffer_line_size(void) +#endif +{ + return ((READ_REG32(MDC_LINE_SIZE) & 0x7FF) << 3); +} + +/*--------------------------------------------------------------------------- + * gfx_get_hactive + *--------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +unsigned short +gu2_get_hactive(void) +#else +unsigned short +gfx_get_hactive(void) +#endif +{ + return ((unsigned short)((READ_REG32(MDC_H_ACTIVE_TIMING) & 0x0FF8) + 8)); +} + +/*--------------------------------------------------------------------------- + * gfx_get_hsync_start + *--------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +unsigned short +gu2_get_hsync_start(void) +#else +unsigned short +gfx_get_hsync_start(void) +#endif +{ + return ((unsigned short)((READ_REG32(MDC_H_SYNC_TIMING) & 0x0FF8) + 8)); +} + +/*--------------------------------------------------------------------------- + * gfx_get_hsync_end + *--------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +unsigned short +gu2_get_hsync_end(void) +#else +unsigned short +gfx_get_hsync_end(void) +#endif +{ + return ((unsigned short)(((READ_REG32(MDC_H_SYNC_TIMING) >> 16) & 0x0FF8) + + 8)); +} + +/*--------------------------------------------------------------------------- + * gfx_get_htotal + *--------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +unsigned short +gu2_get_htotal(void) +#else +unsigned short +gfx_get_htotal(void) +#endif +{ + return ((unsigned short)(((READ_REG32(MDC_H_ACTIVE_TIMING) >> 16) & + 0x0FF8) + 8)); +} + +/*--------------------------------------------------------------------------- + * gfx_get_vactive + *--------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +unsigned short +gu2_get_vactive(void) +#else +unsigned short +gfx_get_vactive(void) +#endif +{ + return ((unsigned short)((READ_REG32(MDC_V_ACTIVE_TIMING) & 0x07FF) + 1)); +} + +/*--------------------------------------------------------------------------- + * gfx_get_vsync_end + *--------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +unsigned short +gu2_get_vsync_end(void) +#else +unsigned short +gfx_get_vsync_end(void) +#endif +{ + return ((unsigned short)(((READ_REG32(MDC_V_SYNC_TIMING) >> 16) & 0x07FF) + + 1)); +} + +/*--------------------------------------------------------------------------- + * gfx_get_vtotal + *--------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +unsigned short +gu2_get_vtotal(void) +#else +unsigned short +gfx_get_vtotal(void) +#endif +{ + return ((unsigned short)(((READ_REG32(MDC_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 +gu2_get_display_bpp(void) +#else +unsigned short +gfx_get_display_bpp(void) +#endif +{ + unsigned long dcfg = READ_REG32(MDC_DISPLAY_CFG); + + switch ((dcfg & MDC_DCFG_DISP_MODE_MASK) >> 8) { + case 0: + return (8); + case 2: + return (32); + case 1: + switch ((dcfg & MDC_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 +gu2_get_vline(void) +#else +unsigned short +gfx_get_vline(void) +#endif +{ + unsigned short current_scan_line; + + /* Read similar value twice to ensure that the value is not + * transitioning */ + do + current_scan_line = + (unsigned short)(READ_REG32(MDC_LINE_CNT_STATUS) & + MDC_LNCNT_V_LINE_CNT); + while (current_scan_line != + (unsigned short)(READ_REG32(MDC_LINE_CNT_STATUS) & + MDC_LNCNT_V_LINE_CNT)); + + return (current_scan_line >> 16); +} + +/*----------------------------------------------------------------------------- + * gfx_get_display_offset + *----------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +unsigned long +gu2_get_display_offset(void) +#else +unsigned long +gfx_get_display_offset(void) +#endif +{ + return (READ_REG32(MDC_FB_ST_OFFSET) & 0x0FFFFFFF); +} + +/*----------------------------------------------------------------------------- + * gfx_get_cursor_offset + *----------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +unsigned long +gu2_get_cursor_offset(void) +#else +unsigned long +gfx_get_cursor_offset(void) +#endif +{ + return (READ_REG32(MDC_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 +gu2_get_hblank_start(void) +#else +unsigned short +gfx_get_hblank_start(void) +#endif +{ + return ((unsigned short)((READ_REG32(MDC_H_BLANK_TIMING) & 0x0FF8) + 8)); +} + +/*--------------------------------------------------------------------------- + * gfx_get_hblank_end + *--------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +unsigned short +gu2_get_hblank_end(void) +#else +unsigned short +gfx_get_hblank_end(void) +#endif +{ + return ((unsigned short)(((READ_REG32(MDC_H_BLANK_TIMING) >> 16) & 0x0FF8) + + 8)); +} + +/*--------------------------------------------------------------------------- + * gfx_get_vblank_start + *--------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +unsigned short +gu2_get_vblank_start(void) +#else +unsigned short +gfx_get_vblank_start(void) +#endif +{ + return ((unsigned short)((READ_REG32(MDC_V_BLANK_TIMING) & 0x07FF) + 1)); +} + +/*--------------------------------------------------------------------------- + * gfx_get_vsync_start + *--------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +unsigned short +gu2_get_vsync_start(void) +#else +unsigned short +gfx_get_vsync_start(void) +#endif +{ + return ((unsigned short)((READ_REG32(MDC_V_SYNC_TIMING) & 0x07FF) + 1)); +} + +/*--------------------------------------------------------------------------- + * gfx_get_vblank_end + *--------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +unsigned short +gu2_get_vblank_end(void) +#else +unsigned short +gfx_get_vblank_end(void) +#endif +{ + return ((unsigned short)(((READ_REG32(MDC_V_BLANK_TIMING) >> 16) & 0x07FF) + + 1)); +} + +/*---------------------------------------------------------------------------- + * gfx_get_display_palette_entry + *---------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +int +gu2_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(MDC_PAL_ADDRESS, index); + *palette = READ_REG32(MDC_PAL_DATA); + + return 0; +} + +/*---------------------------------------------------------------------------- + * gfx_get_display_palette + *---------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +void +gu2_get_display_palette(unsigned long *palette) +#else +void +gfx_get_display_palette(unsigned long *palette) +#endif +{ + unsigned long i; + + WRITE_REG32(MDC_PAL_ADDRESS, 0); + for (i = 0; i < 256; i++) { + palette[i] = READ_REG32(MDC_PAL_DATA); + } +} + +/*---------------------------------------------------------------------------- + * gfx_get_cursor_enable + *---------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +unsigned long +gu2_get_cursor_enable(void) +#else +unsigned long +gfx_get_cursor_enable(void) +#endif +{ + return (READ_REG32(MDC_GENERAL_CFG) & MDC_GCFG_CURE); +} + +/*---------------------------------------------------------------------------- + * gfx_get_cursor_position + *---------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +unsigned long +gu2_get_cursor_position(void) +#else +unsigned long +gfx_get_cursor_position(void) +#endif +{ + return ((READ_REG32(MDC_CURSOR_X) & 0x07FF) | + ((READ_REG32(MDC_CURSOR_Y) << 16) & 0x07FF0000)); +} + +/*---------------------------------------------------------------------------- + * gfx_get_cursor_offset + *---------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +unsigned long +gu2_get_cursor_clip(void) +#else +unsigned long +gfx_get_cursor_clip(void) +#endif +{ + return (((READ_REG32(MDC_CURSOR_X) >> 11) & 0x03F) | + ((READ_REG32(MDC_CURSOR_Y) << 5) & 0x3F0000)); +} + +/*---------------------------------------------------------------------------- + * gfx_get_cursor_color + *---------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +unsigned long +gu2_get_cursor_color(int color) +#else +unsigned long +gfx_get_cursor_color(int color) +#endif +{ + if (color) { + WRITE_REG32(MDC_PAL_ADDRESS, 0x101); + } else { + WRITE_REG32(MDC_PAL_ADDRESS, 0x100); + } + return READ_REG32(MDC_PAL_DATA); +} + +/*---------------------------------------------------------------------------- + * gfx_get_icon_enable + *---------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +unsigned long +gu2_get_icon_enable(void) +#else +unsigned long +gfx_get_icon_enable(void) +#endif +{ + return (READ_REG32(MDC_GENERAL_CFG) & MDC_GCFG_ICNE); +} + +/*---------------------------------------------------------------------------- + * gfx_get_icon_offset + *---------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +unsigned long +gu2_get_icon_offset(void) +#else +unsigned long +gfx_get_icon_offset(void) +#endif +{ + return (READ_REG32(MDC_ICON_ST_OFFSET) & 0x0FFFFFFF); +} + +/*---------------------------------------------------------------------------- + * gfx_get_icon_position + *---------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +unsigned long +gu2_get_icon_position(void) +#else +unsigned long +gfx_get_icon_position(void) +#endif +{ + return (READ_REG32(MDC_ICON_X) & 0x07FF); +} + +/*---------------------------------------------------------------------------- + * gfx_get_icon_color + *---------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +unsigned long +gu2_get_icon_color(int color) +#else +unsigned long +gfx_get_icon_color(int color) +#endif +{ + if (color >= 3) + return 0; + + WRITE_REG32(MDC_PAL_ADDRESS, 0x102 + color); + + return READ_REG32(MDC_PAL_DATA); +} + +/*---------------------------------------------------------------------------- + * gfx_get_compression_enable + *---------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +int +gu2_get_compression_enable(void) +#else +int +gfx_get_compression_enable(void) +#endif +{ + if (READ_REG32(MDC_GENERAL_CFG) & MDC_GCFG_CMPE) + return (1); + + return (0); +} + +/*---------------------------------------------------------------------------- + * gfx_get_compression_offset + *---------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +unsigned long +gu2_get_compression_offset(void) +#else +unsigned long +gfx_get_compression_offset(void) +#endif +{ + return (READ_REG32(MDC_CB_ST_OFFSET) & 0x007FFFFF); +} + +/*---------------------------------------------------------------------------- + * gfx_get_compression_pitch + *---------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +unsigned short +gu2_get_compression_pitch(void) +#else +unsigned short +gfx_get_compression_pitch(void) +#endif +{ + unsigned short pitch; + + pitch = (unsigned short)(READ_REG32(MDC_GFX_PITCH) >> 16); + return (pitch << 3); +} + +/*---------------------------------------------------------------------------- + * gfx_get_compression_size + *---------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +unsigned short +gu2_get_compression_size(void) +#else +unsigned short +gfx_get_compression_size(void) +#endif +{ + unsigned short size; + + size = (unsigned short)((READ_REG32(MDC_LINE_SIZE) >> 16) & 0x7F) - 1; + return ((size << 3) + 32); +} + +/*---------------------------------------------------------------------------- + * gfx_get_valid_bit + *---------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +int +gu2_get_valid_bit(int line) +#else +int +gfx_get_valid_bit(int line) +#endif +{ + unsigned long offset; + int valid; + + offset = READ_REG32(MDC_PHY_MEM_OFFSET) & 0xFF000000; + offset |= line; + + WRITE_REG32(MDC_PHY_MEM_OFFSET, offset); + valid = (int)READ_REG32(MDC_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 +gu2_get_display_video_offset(void) +#else +unsigned long +gfx_get_display_video_offset(void) +#endif +{ + return (READ_REG32(MDC_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 +gu2_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(MDC_VID_Y_ST_OFFSET) & 0x0FFFFFFF); + *uoffset = (READ_REG32(MDC_VID_U_ST_OFFSET) & 0x0FFFFFFF); + *voffset = (READ_REG32(MDC_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 +gu2_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(MDC_VID_YUV_PITCH); + + *ypitch = ((pitch & 0xFFFF) << 3); + *uvpitch = (pitch >> 13) & 0x7FFF8; +} + +/*--------------------------------------------------------------------------- + * gfx_get_display_video_downscale_delta (PRIVATE ROUTINE - NOT PART OF API) + * + * This routine is called by "gfx_get_video_downscale_delta". It abstracts the + * version of the display controller from the video overlay routines. + *--------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +unsigned long +gu2_get_display_video_downscale_delta(void) +#else +unsigned long +gfx_get_display_video_downscale_delta(void) +#endif +{ + return (READ_REG32(MDC_VID_DS_DELTA) >> 18); +} + +/*--------------------------------------------------------------------------- + * gfx_get_display_video_downscale_enable (PRIVATE ROUTINE - NOT PART OF API) + * + * This routine is called by "gfx_get_video_vertical_downscale_enable". + * It abstracts the version of the display controller from the video overlay + * routines. + *--------------------------------------------------------------------------- + */ +#if GFX_DISPLAY_DYNAMIC +int +gu2_get_display_video_downscale_enable(void) +#else +int +gfx_get_display_video_downscale_enable(void) +#endif +{ + return ((int)((READ_REG32(MDC_GENERAL_CFG) >> 19) & 1)); +} + +/*--------------------------------------------------------------------------- + * 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 +gu2_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 */ + + return ((READ_REG32(MDC_LINE_SIZE) >> 21) & 0x000007FF); +} + +#endif /* GFX_READ_ROUTINES */ + +/* END OF FILE */ 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 */ diff --git a/src/gfx/durango.c b/src/gfx/durango.c new file mode 100644 index 0000000..47c72d8 --- /dev/null +++ b/src/gfx/durango.c @@ -0,0 +1,488 @@ +/* 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 is the main file used to add Durango graphics support to a software + * project. The main reason to have a single file include the other files + * is that it centralizes the location of the compiler options. This file + * should be tuned for a specific implementation, and then modified as needed + * for new Durango releases. The releases.txt file indicates any updates to + * this main file, such as a new definition for a new hardware platform. + * + * In other words, this file should be copied from the Durango source files + * once when a software project starts, and then maintained as necessary. + * It should not be recopied with new versions of Durango unless the + * developer is willing to tune the file again for the specific project. + * */ + +/* COMPILER OPTIONS + * These compiler options specify how the Durango routines are compiled + * for the different hardware platforms. For best performance, a driver + * would build for a specific platform. The "dynamic" switches are set + * by diagnostic applications such as Darwin that will run on a variety + * of platforms and use the appropriate code at runtime. Each component + * may be separately dynamic, so that a driver has the option of being + * tuned for a specific 2D accelerator, but will still run with a variety + * of chipsets. + */ + +#define GFX_DISPLAY_DYNAMIC 1 /* runtime selection */ +#define GFX_DISPLAY_GU1 1 /* 1st generation display controller */ +#define GFX_DISPLAY_GU2 1 /* 2nd generation display controller */ +#define GFX_DISPLAY_GU3 1 /* 3rd generation display controller */ + +#define GFX_INIT_DYNAMIC 1 /* runtime selection */ +#define GFX_INIT_GU1 1 /* Geode family */ +#define GFX_INIT_GU2 1 /* Redcloud */ +#define GFX_INIT_GU3 1 /* Castle */ + +#define GFX_MSR_DYNAMIC 1 /* runtime selection */ +#define GFX_MSR_REDCLOUD 1 /* Redcloud */ + +#define GFX_2DACCEL_DYNAMIC 1 /* runtime selection */ +#define GFX_2DACCEL_GU1 1 /* 1st generation 2D accelerator */ +#define GFX_2DACCEL_GU2 1 /* 2nd generation 2D accelerator */ + +#define GFX_VIDEO_DYNAMIC 1 /* runtime selection */ +#define GFX_VIDEO_CS5530 1 /* support for CS5530 */ +#define GFX_VIDEO_SC1200 1 /* support for SC1200 */ +#define GFX_VIDEO_REDCLOUD 1 /* support for Redcloud */ +#define GFX_VIDEO_CASTLE 1 /* support for Castle */ + +#define GFX_VIP_DYNAMIC 1 /* runtime selection */ +#define GFX_VIP_SC1200 1 /* support for SC1200 */ + +#define GFX_DECODER_DYNAMIC 1 /* runtime selection */ +#define GFX_DECODER_SAA7114 1 /* Philips SAA7114 decoder */ + +#define GFX_TV_DYNAMIC 1 /* runtime selection */ +#define GFX_TV_FS451 1 /* Focus Enhancements FS450 */ +#define GFX_TV_SC1200 1 /* SC1200 integrated TV encoder */ + +#define GFX_I2C_DYNAMIC 1 /* runtime selection */ +#define GFX_I2C_ACCESS 1 /* support for ACCESS.BUS */ +#define GFX_I2C_GPIO 1 /* support for CS5530 GPIOs */ + +#define GFX_VGA_DYNAMIC 1 /* runtime selection */ +#define GFX_VGA_GU1 1 /* 1st generation graphics unit */ + +#define FB4MB 1 /* Set to use 4Mb video ram for Pyramid */ + +#define GFX_NO_IO_IN_WAIT_MACROS 0 /* Set to remove I/O accesses in GP + * bit testing */ + +/* ROUTINES TO READ VALUES + * These are routines used by Darwin or other diagnostics to read the + * current state of the hardware. Display drivers or embedded applications + * can reduce the size of the Durango code by not including these routines. + */ +#define GFX_READ_ROUTINES 1 /* add routines to read values */ + +/* VARIABLES USED FOR RUNTIME SELECTION + * If part of the graphics subsystem is declared as dynamic, then the + * following variables are used to specify which platform has been detected. + * The variables are set in the "gfx_detect_cpu" routine. The values should + * be bit flags to allow masks to be used to check for multiple platforms. + */ + +#if GFX_DISPLAY_DYNAMIC +int gfx_display_type = 0; +#endif + +#if GFX_INIT_DYNAMIC +int gfx_init_type = 0; +#endif + +#if GFX_MSR_DYNAMIC +int gfx_msr_type = 0; +#endif + +#if GFX_2DACCEL_DYNAMIC +int gfx_2daccel_type = 0; +#endif + +#if GFX_VIDEO_DYNAMIC +int gfx_video_type = 0; +#endif + +#if GFX_VIP_DYNAMIC +int gfx_vip_type = 0; +#endif + +#if GFX_DECODER_DYNAMIC +int gfx_decoder_type = 0; +#endif + +#if GFX_TV_DYNAMIC +int gfx_tv_type = 0; +#endif + +#if GFX_I2C_DYNAMIC +int gfx_i2c_type = 0; +#endif + +#if GFX_VGA_DYNAMIC +int gfx_vga_type = 0; +#endif + +/* HEADER FILE FOR DURANGO ROUTINE DEFINITIONS + * Needed since some of the Durango routines call other Durango routines. + * Also defines the size of chipset array (GFX_CSPTR_SIZE). + */ +#include "gfx_rtns.h" /* routine definitions */ + +/* INCLUDE PROTOTYPES FOR PRIVATE ROUTINES */ + +#include "gfx_priv.h" + +/* DEFINE POINTERS TO MEMORY MAPPED REGIONS + * These pointers are used by the Durango routines to access the hardware. + * The variables must be set by the project's initialization code after + * mapping the regions in the appropriate manner. + */ + +/* DEFINE VIRTUAL ADDRESSES */ +/* Note: These addresses define the starting base expected by all */ +/* Durango offsets. Under an OS that requires these pointers */ +/* to be mapped to linear addresses (i.e Windows), it may not */ +/* be possible to keep these base offsets. In these cases, */ +/* the addresses are modified to point to the beginning of the */ +/* relevant memory region and the access macros are adjusted */ +/* to subtract the offset from the default base. For example, */ +/* the register pointer could be moved to be 0x40008000, while */ +/* the WRITE_REG* macros are modified to subtract 0x8000 from */ +/* the offset. */ + +unsigned char *gfx_virt_regptr = (unsigned char *)0x40000000; +unsigned char *gfx_virt_fbptr = (unsigned char *)0x40800000; +unsigned char *gfx_virt_vidptr = (unsigned char *)0x40010000; +unsigned char *gfx_virt_vipptr = (unsigned char *)0x40015000; +unsigned char *gfx_virt_spptr = (unsigned char *)0x40000000; +unsigned char *gfx_virt_gpptr = (unsigned char *)0x40000000; + +/* DEFINE PHYSICAL ADDRESSES */ + +unsigned char *gfx_phys_regptr = (unsigned char *)0x40000000; +unsigned char *gfx_phys_fbptr = (unsigned char *)0x40800000; +unsigned char *gfx_phys_vidptr = (unsigned char *)0x40010000; +unsigned char *gfx_phys_vipptr = (unsigned char *)0x40015000; + +/* HEADER FILE FOR GRAPHICS REGISTER DEFINITIONS + * This contains only constant definitions, so it should be able to be + * included in any software project as is. + */ +#include "gfx_regs.h" /* graphics register definitions */ + +/* HEADER FILE FOR REGISTER ACCESS MACROS + * This file contains the definitions of the WRITE_REG32 and similar macros + * used by the Durango routines to access the hardware. The file assumes + * that the environment can handle 32-bit pointer access. If this is not + * the case, or if there are special requirements, then this header file + * should not be included and the project must define the macros itself. + * (A project may define WRITE_REG32 to call a routine, for example). + */ +#include "gfx_defs.h" /* register access macros */ + +/* IO MACROS AND ROUTINES + * These macros must be defined before the initialization or I2C + * routines will work properly. + */ + +#if defined(OS_WIN32) /* For Windows */ + +/* VSA II CALL */ + +void +gfx_msr_asm_read(unsigned short msrReg, unsigned long msrAddr, + unsigned long *ptrHigh, unsigned long *ptrLow) +{ + unsigned long temp1, temp2; + + _asm { + mov dx, 0x0AC1C + mov eax, 0x0FC530007 + out dx, eax add dl, 2 mov ecx, msrAddr mov cx, msrReg in ax, dx; + EDX:EAX will contain MSR contents.mov temp1, edx mov temp2, eax} + + *ptrHigh = temp1; + *ptrLow = temp2; +} + +void +gfx_msr_asm_write(unsigned short msrReg, unsigned long msrAddr, + unsigned long *ptrHigh, unsigned long *ptrLow) +{ + unsigned long temp1 = *ptrHigh; + unsigned long temp2 = *ptrLow; + + _asm { + + mov dx, 0x0AC1C + mov eax, 0x0FC530007 out dx, eax add dl, 2 mov ecx, msrAddr; + ECX contains msrAddr | msrReg mov cx, msrReg; + mov ebx, temp1; + + <OR_mask_hi > mov eax, temp2; + <OR_mask_hi > mov esi, 0; + <AND_mask_hi > mov edi, 0; + <AND_mask_lo > out dx, ax; + MSR is written at this point} +} + +unsigned char +gfx_inb(unsigned short port) +{ + unsigned char data; + + _asm { + pushf mov dx, port in al, dx mov data, al popf} + return (data); +} + +unsigned short +gfx_inw(unsigned short port) +{ + unsigned short data; + + _asm { + pushf mov dx, port in ax, dx mov data, ax popf} + return (data); +} + +unsigned long +gfx_ind(unsigned short port) +{ + unsigned long data; + + _asm { + pushf mov dx, port in eax, dx mov data, eax popf} + return (data); +} + +void +gfx_outb(unsigned short port, unsigned char data) +{ + _asm { + pushf mov al, data mov dx, port out dx, al popf} +} + +void +gfx_outw(unsigned short port, unsigned short data) +{ + _asm { + pushf mov ax, data mov dx, port out dx, ax popf} +} + +void +gfx_outd(unsigned short port, unsigned long data) +{ + _asm { + pushf mov eax, data mov dx, port out dx, eax popf} +} + +#elif defined(OS_VXWORKS) || defined (OS_LINUX) /* VxWorks and Linux */ + +#if defined(OS_LINUX) +#include "asm/msr.h" +#endif + +void +gfx_msr_asm_read(unsigned short msrReg, unsigned long msrAddr, + unsigned long *ptrHigh, unsigned long *ptrLow) +{ + unsigned long addr, val1, val2; + + addr = msrAddr | (unsigned long)msrReg; + rdmsr(addr, val1, val2); + + *ptrHigh = val2; + *ptrLow = val1; +} + +void +gfx_msr_asm_write(unsigned short msrReg, unsigned long msrAddr, + unsigned long *ptrHigh, unsigned long *ptrLow) +{ + unsigned long addr, val1, val2; + + val2 = *ptrHigh; + val1 = *ptrLow; + + addr = (msrAddr & 0xFFFF0000) | (unsigned long)msrReg; + wrmsr(addr, val1, val2); +} + +unsigned char +gfx_inb(unsigned short port) +{ + unsigned char value; + __asm__ volatile ("inb %1,%0":"=a" (value):"d"(port)); + + return value; +} + +unsigned short +gfx_inw(unsigned short port) +{ + unsigned short value; + __asm__ volatile ("in %1,%0":"=a" (value):"d"(port)); + + return value; +} + +unsigned long +gfx_ind(unsigned short port) +{ + unsigned long value; + __asm__ volatile ("inl %1,%0":"=a" (value):"d"(port)); + + return value; +} + +void +gfx_outb(unsigned short port, unsigned char data) +{ + __asm__ volatile ("outb %0,%1"::"a" (data), "d"(port)); +} + +void +gfx_outw(unsigned short port, unsigned short data) +{ + __asm__ volatile ("out %0,%1"::"a" (data), "d"(port)); +} + +void +gfx_outd(unsigned short port, unsigned long data) +{ + __asm__ volatile ("outl %0,%1"::"a" (data), "d"(port)); +} + +#else /* else nothing */ + +unsigned char +gfx_inb(unsigned short port) +{ + /* ADD OS SPECIFIC IMPLEMENTATION */ + return (0); +} + +unsigned short +gfx_inw(unsigned short port) +{ + /* ADD OS SPECIFIC IMPLEMENTATION */ + return (0); +} + +unsigned long +gfx_ind(unsigned short port) +{ + /* ADD OS SPECIFIC IMPLEMENTATION */ + return (0); +} + +void +gfx_outb(unsigned short port, unsigned char data) +{ + /* ADD OS SPECIFIC IMPLEMENTATION */ +} + +void +gfx_outw(unsigned short port, unsigned short data) +{ + /* ADD OS SPECIFIC IMPLEMENTATION */ +} + +void +gfx_outd(unsigned short port, unsigned long data) +{ + /* ADD OS SPECIFIC IMPLEMENTATION */ +} +#endif + +#define INB(port) gfx_inb(port) +#define INW(port) gfx_inw(port) +#define IND(port) gfx_ind(port) +#define OUTB(port, data) gfx_outb(port, data) +#define OUTW(port, data) gfx_outw(port, data) +#define OUTD(port, data) gfx_outd(port, data) + +/* INITIALIZATION ROUTINES + * These routines are used during the initialization of the driver to + * perform such tasks as detecting the type of CPU and video hardware. + * The routines require the use of IO, so the above IO routines need + * to be implemented before the initialization routines will work + * properly. + */ + +#include "gfx_init.c" + +/* INCLUDE MSR ACCESS ROUTINES */ + +#include "gfx_msr.c" + +/* INCLUDE GRAPHICS ENGINE ROUTINES + * These routines are used to program the 2D graphics accelerator. If + * the project does not use graphics acceleration (direct frame buffer + * access only), then this file does not need to be included. + */ +#include "gfx_rndr.c" /* graphics engine routines */ + +/* INCLUDE DISPLAY CONTROLLER ROUTINES + * These routines are used if the display mode is set directly. If the + * project uses VGA registers to set a display mode, then these files + * do not need to be included. + */ +#include "gfx_mode.h" /* display mode tables */ +#include "gfx_disp.c" /* display controller routines */ + +/* INCLUDE VIDEO OVERLAY ROUTINES + * These routines control the video overlay hardware. + */ +#include "gfx_vid.c" /* video overlay routines */ + +/* VIDEO PORT AND VIDEO DECODER ROUTINES + * These routines rely on the I2C routines. + */ +#include "gfx_vip.c" /* video port routines */ +#include "gfx_dcdr.c" /* video decoder routines */ + +/* I2C BUS ACCESS ROUTINES + * These routines are used by the video decoder and possibly an + * external TV encoer. + */ +#include "gfx_i2c.c" /* I2C bus access routines */ + +/* TV ENCODER ROUTINES + * This file does not need to be included if the system does not + * support TV output. + */ +#include "gfx_tv.c" /* TV encoder routines */ + +/* VGA ROUTINES + * This file is used if setting display modes using VGA registers. + */ +#include "gfx_vga.c" /* VGA routines */ + +/* END OF FILE */ diff --git a/src/gfx/gfx_dcdr.c b/src/gfx/gfx_dcdr.c new file mode 100644 index 0000000..57abe37 --- /dev/null +++ b/src/gfx/gfx_dcdr.c @@ -0,0 +1,499 @@ +/* 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 to control the video decoder. + * + * gfx_set_decoder_defaults + * gfx_set_decoder_analog_input + * gfx_set_decoder_brightness + * gfx_set_decoder_contrast + * gfx_set_decoder_luminance_filter + * gfx_set_decoder_hue + * gfx_set_decoder_saturation + * gfx_set_decoder_input_offset + * gfx_set_decoder_input_size + * gfx_set_decoder_output_size + * gfx_set_decoder_scale + * gfx_set_decoder_TV_standard + * gfx_set_decoder_vbi_enable + * gfx_set_decoder_vbi_format + * gfx_set_decoder_vbi_upscale + * gfx_decoder_software_reset + * gfx_decoder_detect_macrovision + * gfx_decoder_detect_video + * + * And the following routines if GFX_READ_ROUTINES is set: + * + * gfx_get_decoder_brightness + * gfx_get_decoder_contrast + * gfx_get_decoder_hue + * gfx_get_decoder_saturation + * gfx_get_decoder_input_offset + * gfx_get_decoder_input_size + * gfx_get_decoder_output_size + * gfx_get_decoder_vbi_format + */ + +/* INCLUDE SUPPORT FOR PHILIPS SAA7114 DECODER, IF SPECIFIED */ + +#if GFX_DECODER_SAA7114 +#include "saa7114.c" +#endif + +/* WRAPPERS IF DYNAMIC SELECTION */ +/* Extra layer to call various decoders. Currently only the Pillips */ +/* decoder is supported, but still organized to easily expand later. */ + +#if GFX_DECODER_DYNAMIC + +/*---------------------------------------------------------------------------- + * gfx_set_decoder_defaults + *---------------------------------------------------------------------------- + */ +int +gfx_set_decoder_defaults(void) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_DECODER_SAA7114 + if (gfx_decoder_type == GFX_DECODER_SAA7114) + status = saa7114_set_decoder_defaults(); +#endif + return (status); +} + +/*---------------------------------------------------------------------------- + * gfx_set_decoder_analog_input + *---------------------------------------------------------------------------- + */ +int +gfx_set_decoder_analog_input(unsigned char input) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_DECODER_SAA7114 + if (gfx_decoder_type == GFX_DECODER_SAA7114) + status = saa7114_set_decoder_analog_input(input); +#endif + return (status); +} + +/*---------------------------------------------------------------------------- + * gfx_set_decoder_brightness + *---------------------------------------------------------------------------- + */ +int +gfx_set_decoder_brightness(unsigned char brightness) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_DECODER_SAA7114 + if (gfx_decoder_type == GFX_DECODER_SAA7114) + status = saa7114_set_decoder_brightness(brightness); +#endif + return (status); +} + +/*---------------------------------------------------------------------------- + * gfx_set_decoder_contrast + *---------------------------------------------------------------------------- + */ +int +gfx_set_decoder_contrast(unsigned char contrast) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_DECODER_SAA7114 + if (gfx_decoder_type == GFX_DECODER_SAA7114) + status = saa7114_set_decoder_contrast(contrast); +#endif + return (status); +} + +/*---------------------------------------------------------------------------- + * gfx_set_decoder_hue + *---------------------------------------------------------------------------- + */ +int +gfx_set_decoder_hue(char hue) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_DECODER_SAA7114 + if (gfx_decoder_type == GFX_DECODER_SAA7114) + status = saa7114_set_decoder_hue(hue); +#endif + return (status); +} + +/*---------------------------------------------------------------------------- + * gfx_set_decoder_saturation + *---------------------------------------------------------------------------- + */ +int +gfx_set_decoder_saturation(unsigned char saturation) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_DECODER_SAA7114 + if (gfx_decoder_type == GFX_DECODER_SAA7114) + status = saa7114_set_decoder_saturation(saturation); +#endif + return (status); +} + +/*---------------------------------------------------------------------------- + * gfx_set_decoder_input_offset + *---------------------------------------------------------------------------- + */ +int +gfx_set_decoder_input_offset(unsigned short x, unsigned short y) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_DECODER_SAA7114 + if (gfx_decoder_type == GFX_DECODER_SAA7114) + status = saa7114_set_decoder_input_offset(x, y); +#endif + return (status); +} + +/*---------------------------------------------------------------------------- + * gfx_set_decoder_input_size + *---------------------------------------------------------------------------- + */ +int +gfx_set_decoder_input_size(unsigned short width, unsigned short height) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_DECODER_SAA7114 + if (gfx_decoder_type == GFX_DECODER_SAA7114) + status = saa7114_set_decoder_input_size(width, height); +#endif + return (status); +} + +/*---------------------------------------------------------------------------- + * gfx_set_decoder_output_size + *---------------------------------------------------------------------------- + */ +int +gfx_set_decoder_output_size(unsigned short width, unsigned short height) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_DECODER_SAA7114 + if (gfx_decoder_type == GFX_DECODER_SAA7114) + status = saa7114_set_decoder_output_size(width, height); +#endif + return (status); +} + +/*---------------------------------------------------------------------------- + * gfx_set_decoder_scale + *---------------------------------------------------------------------------- + */ +int +gfx_set_decoder_scale(unsigned short srcw, unsigned short srch, + unsigned short dstw, unsigned short dsth) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_DECODER_SAA7114 + if (gfx_decoder_type == GFX_DECODER_SAA7114) + status = saa7114_set_decoder_scale(srcw, srch, dstw, dsth); +#endif + return (status); +} + +/*---------------------------------------------------------------------------- + * gfx_set_decoder_vbi_format + *---------------------------------------------------------------------------- + */ +int +gfx_set_decoder_vbi_format(int start, int end, int format) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_DECODER_SAA7114 + if (gfx_decoder_type == GFX_DECODER_SAA7114) + status = saa7114_set_decoder_vbi_format(start, end, format); +#endif + return (status); +} + +/*---------------------------------------------------------------------------- + * gfx_set_decoder_vbi_enable + *---------------------------------------------------------------------------- + */ +int +gfx_set_decoder_vbi_enable(int enable) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_DECODER_SAA7114 + if (gfx_decoder_type == GFX_DECODER_SAA7114) + status = saa7114_set_decoder_vbi_enable(enable); +#endif + return (status); +} + +/*---------------------------------------------------------------------------- + * gfx_set_decoder_vbi_upscale + *---------------------------------------------------------------------------- + */ +int +gfx_set_decoder_vbi_upscale(void) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_DECODER_SAA7114 + if (gfx_decoder_type == GFX_DECODER_SAA7114) + status = saa7114_set_decoder_vbi_upscale(); +#endif + return (status); +} + +/*---------------------------------------------------------------------------- + * gfx_set_decoder_TV_standard + *---------------------------------------------------------------------------- + */ +int +gfx_set_decoder_TV_standard(TVStandardType TVStandard) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_DECODER_SAA7114 + if (gfx_decoder_type == GFX_DECODER_SAA7114) + status = saa7114_set_decoder_TV_standard(TVStandard); +#endif + return (status); +} + +/*---------------------------------------------------------------------------- + * gfx_set_decoder_luminance_filter + *---------------------------------------------------------------------------- + */ +int +gfx_set_decoder_luminance_filter(unsigned char lufi) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_DECODER_SAA7114 + if (gfx_decoder_type == GFX_DECODER_SAA7114) + status = saa7114_set_decoder_luminance_filter(lufi); +#endif + return (status); +} + +/*---------------------------------------------------------------------------- + * gfx_decoder_software_reset + *---------------------------------------------------------------------------- + */ +int +gfx_decoder_software_reset(void) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_DECODER_SAA7114 + if (gfx_decoder_type == GFX_DECODER_SAA7114) + status = saa7114_decoder_software_reset(); +#endif + return (status); +} + +/*---------------------------------------------------------------------------- + * gfx_decoder_detect_macrovision + *---------------------------------------------------------------------------- + */ +int +gfx_decoder_detect_macrovision(void) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_DECODER_SAA7114 + if (gfx_decoder_type == GFX_DECODER_SAA7114) + status = saa7114_decoder_detect_macrovision(); +#endif + return (status); +} + +/*---------------------------------------------------------------------------- + * gfx_decoder_detect_video + *---------------------------------------------------------------------------- + */ +int +gfx_decoder_detect_video(void) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_DECODER_SAA7114 + if (gfx_decoder_type == GFX_DECODER_SAA7114) + status = saa7114_decoder_detect_video(); +#endif + return (status); +} + +/*************************************************************/ +/* READ ROUTINES | INCLUDED FOR DIAGNOSTIC PURPOSES ONLY */ +/*************************************************************/ + +#if GFX_READ_ROUTINES + +/*---------------------------------------------------------------------------- + * gfx_get_decoder_brightness + *---------------------------------------------------------------------------- + */ +unsigned char +gfx_get_decoder_brightness(void) +{ + unsigned char brightness = 0; + +#if GFX_DECODER_SAA7114 + if (gfx_decoder_type == GFX_DECODER_SAA7114) + brightness = saa7114_get_decoder_brightness(); +#endif + return (brightness); +} + +/*---------------------------------------------------------------------------- + * gfx_get_decoder_contrast + *---------------------------------------------------------------------------- + */ +unsigned char +gfx_get_decoder_contrast(void) +{ + unsigned char contrast = 0; + +#if GFX_DECODER_SAA7114 + if (gfx_decoder_type == GFX_DECODER_SAA7114) + contrast = saa7114_get_decoder_contrast(); +#endif + return (contrast); +} + +/*---------------------------------------------------------------------------- + * gfx_get_decoder_hue + *---------------------------------------------------------------------------- + */ +char +gfx_get_decoder_hue(void) +{ + unsigned char hue = 0; + +#if GFX_DECODER_SAA7114 + if (gfx_decoder_type == GFX_DECODER_SAA7114) + hue = saa7114_get_decoder_hue(); +#endif + return ((char)hue); +} + +/*---------------------------------------------------------------------------- + * gfx_get_decoder_saturation + *---------------------------------------------------------------------------- + */ +unsigned char +gfx_get_decoder_saturation(void) +{ + unsigned char saturation = 0; + +#if GFX_DECODER_SAA7114 + if (gfx_decoder_type == GFX_DECODER_SAA7114) + saturation = saa7114_get_decoder_saturation(); +#endif + return (saturation); +} + +/*---------------------------------------------------------------------------- + * gfx_get_decoder_input_offset + *---------------------------------------------------------------------------- + */ +unsigned long +gfx_get_decoder_input_offset() +{ + unsigned long offset = 0; + +#if GFX_DECODER_SAA7114 + if (gfx_decoder_type == GFX_DECODER_SAA7114) + offset = saa7114_get_decoder_input_offset(); +#endif + return (offset); +} + +/*---------------------------------------------------------------------------- + * gfx_get_decoder_input_size + *---------------------------------------------------------------------------- + */ +unsigned long +gfx_get_decoder_input_size() +{ + unsigned long size = 0; + +#if GFX_DECODER_SAA7114 + if (gfx_decoder_type == GFX_DECODER_SAA7114) + size = saa7114_get_decoder_input_size(); +#endif + return (size); +} + +/*---------------------------------------------------------------------------- + * gfx_get_decoder_output_size + *---------------------------------------------------------------------------- + */ +unsigned long +gfx_get_decoder_output_size() +{ + unsigned long size = 0; + +#if GFX_DECODER_SAA7114 + if (gfx_decoder_type == GFX_DECODER_SAA7114) + size = saa7114_get_decoder_output_size(); +#endif + return (size); +} + +/*---------------------------------------------------------------------------- + * gfx_get_decoder_vbi_format + *---------------------------------------------------------------------------- + */ +int +gfx_get_decoder_vbi_format(int line) +{ + int format = 0; + +#if GFX_DECODER_SAA7114 + if (gfx_decoder_type == GFX_DECODER_SAA7114) + format = saa7114_get_decoder_vbi_format(line); +#endif + return (format); +} + +#endif /* GFX_READ_ROUTINES */ + +#endif /* GFX_DECODER_DYNAMIC */ + +/* END OF FILE */ diff --git a/src/gfx/gfx_defs.h b/src/gfx/gfx_defs.h new file mode 100644 index 0000000..dde8385 --- /dev/null +++ b/src/gfx/gfx_defs.h @@ -0,0 +1,348 @@ +/* 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 header file contains the macros used to access the hardware. These + * macros assume that 32-bit access is possible, which is true for most + * applications. Projects using 16-bit compilers (the Windows98 display + * driver) and special purpose applications (such as Darwin) need to define + * their own versions of these macros, which typically call a subroutine. + * */ + +/* ACCESS TO THE CPU REGISTERS */ + +#define WRITE_REG8(offset, value) \ + (*(volatile unsigned char *)(gfx_virt_regptr + (offset))) = (value) + +#define WRITE_REG16(offset, value) \ + (*(volatile unsigned short *)(gfx_virt_regptr + (offset))) = (value) + +#define WRITE_REG32(offset, value) \ + (*(volatile unsigned long *)(gfx_virt_regptr + (offset))) = (value) + +#define READ_REG16(offset) \ + (*(volatile unsigned short *)(gfx_virt_regptr + (offset))) + +#define READ_REG32(offset) \ + (*(volatile unsigned long *)(gfx_virt_regptr + (offset))) + +/* ACCESS TO THE ACCELERATOR REGISTERS (REDCLOUD ONLY) */ + +#define WRITE_GP8(offset, value) \ + (*(volatile unsigned char *)(gfx_virt_gpptr + (offset))) = (value) + +#define WRITE_GP16(offset, value) \ + (*(volatile unsigned short *)(gfx_virt_gpptr + (offset))) = (value) + +#define WRITE_GP32(offset, value) \ + (*(volatile unsigned long *)(gfx_virt_gpptr + (offset))) = (value) + +#define READ_GP16(offset) \ + (*(volatile unsigned short *)(gfx_virt_gpptr + (offset))) + +#define READ_GP32(offset) \ + (*(volatile unsigned long *)(gfx_virt_gpptr + (offset))) + +/* ACCESS TO THE FRAME BUFFER */ + +#define WRITE_FB32(offset, value) \ + (*(volatile unsigned long *)(gfx_virt_fbptr + (offset))) = (value) + +#define WRITE_FB16(offset, value) \ + (*(volatile unsigned short *)(gfx_virt_fbptr + (offset))) = (value) + +#define WRITE_FB8(offset, value) \ + (*(volatile unsigned char *)(gfx_virt_fbptr + (offset))) = (value) + +/* ACCESS TO THE VIDEO HARDWARE */ + +#define READ_VID32(offset) \ + (*(volatile unsigned long *)(gfx_virt_vidptr + (offset))) + +#define WRITE_VID32(offset, value) \ + (*(volatile unsigned long *)(gfx_virt_vidptr + (offset))) = (value) + +/* ACCESS TO THE VIP HARDWARE */ + +#define READ_VIP32(offset) \ + (*(volatile unsigned long *)(gfx_virt_vipptr + (offset))) + +#define WRITE_VIP32(offset, value) \ + (*(volatile unsigned long *)(gfx_virt_vipptr + (offset))) = (value) + +/* ACCESS TO THE SCRATCHPAD RAM */ + +#define WRITE_SCRATCH32(offset, value) \ + (*(volatile unsigned long *)(gfx_virt_spptr + (offset))) = (value) + +#define WRITE_SCRATCH16(offset, value) \ + (*(volatile unsigned short *)(gfx_virt_spptr + (offset))) = (value) + +#define WRITE_SCRATCH8(offset, value) \ + (*(volatile unsigned char *)(gfx_virt_spptr + (offset))) = (value) + +#define READ_SCRATCH16(offset) \ + (*(volatile unsigned short *)(gfx_virt_spptr + (offset))) + +#define READ_SCRATCH32(offset) \ + (*(volatile unsigned long *)(gfx_virt_spptr + (offset))) + +/* ACCESS TO MSRS */ + +void gfx_msr_asm_write(unsigned short msrReg, unsigned long msrAddr, + unsigned long *ptrHigh, unsigned long *ptrLow); +void gfx_msr_asm_read(unsigned short msrReg, unsigned long msrAddr, + unsigned long *ptrHigh, unsigned long *ptrLow); + +#define MSR_READ( MBD_MSR_CAP, address, valueHigh_ptr, valueLow_ptr ) \ + gfx_msr_asm_read( ((unsigned short)(MBD_MSR_CAP)), address, \ + valueHigh_ptr, valueLow_ptr ) + +#define MSR_WRITE( MBD_MSR_CAP, address, valueHigh_ptr, valueLow_ptr ) \ + gfx_msr_asm_write( ((unsigned short)(MBD_MSR_CAP)), address, \ + valueHigh_ptr, valueLow_ptr ) + +/* OPTIMIZATION MACROS */ +/* The following macros have been added to allow more complete optimization of + * the bitmap-to-screen routines in Durango. These routines also allow + * Durango to run properly within a 16-bit environment. + * */ + +/***************************************************************************** + * Macro: SET_SCRATCH_BASE + * Purpose: Record the base address of the BLT buffers. The + * WRITE_SCRATCH_STRINGxx macros assume that this address is used + * as the base for all writes. + * + * Arguments: + * scratch_base - offset into the GX base for the first BLT buffer byte. + ****************************************************************************/ + +#define SET_SCRATCH_BASE(scratch_base) \ + { gfx_gx1_scratch_base = (unsigned long)gfx_virt_spptr + scratch_base; } + +#ifdef GFX_OPTIMIZE_ASSEMBLY + +/***************************************************************************** + * Macro: WRITE_SCRATCH_STRING + * Purpose: Write multiple bytes to the scratchpad buffer + * + * Arguments: + * dword_bytes - number of bytes to transfer. This number will always. + * be a multiple of 4. It cannot be modified within the + * macro (ex. bytes -= 4) + * bytes_extra - number of non-DWORD aligned bytes + * array - pointer to an array of unsigned characters. + * array_offset - offset into the array from which to pull the first + * character. + ****************************************************************************/ + +#define WRITE_SCRATCH_STRING(dwords, bytes, array, array_offset) \ +{ \ + _asm { mov edi, gfx_gx1_scratch_base } \ + _asm { mov esi, array } \ + _asm { add esi, array_offset } \ + _asm { mov ecx, dwords } \ + _asm { shr ecx, 2 } \ + _asm { rep movsd } \ + _asm { mov ecx, bytes } \ + _asm { rep movsb } \ +} + +/***************************************************************************** + * Macro: WRITE_FRAME_BUFFER_STRING32 + * Purpose: Write multiple dwords to the Frame buffer + * + * Arguments: + * fboffset - offset to the beginning frame buffer location. + * bytes - number of bytes to transfer. This number will always. + * be a multiple of 4. It cannot be modified within the + * macro (ex. bytes -= 4) + * array - pointer to an array of unsigned characters. + * array_offset - offset into the array from which to pull the first + * character. + ****************************************************************************/ + +#define WRITE_FRAME_BUFFER_STRING32(fboffset, bytes, array, array_offset) \ +{ \ + _asm { mov ecx, bytes } \ + _asm { shr ecx, 2 } \ + _asm { cld } \ + _asm { mov edi, gfx_virt_fbptr } \ + _asm { add edi, fboffset } \ + _asm { mov esi, array } \ + _asm { add esi, array_offset } \ + _asm { rep movsd } \ +} + +#else + +/***************************************************************************** + * Macro: WRITE_SCRATCH_STRING + * Purpose: Write multiple bytes to the scratchpad buffer + * + * Arguments: + * dword_bytes - number of bytes to transfer. This number will always. + * be a multiple of 4. It cannot be modified within the + * macro (ex. bytes -= 4) + * bytes_extra - number of non-DWORD aligned bytes + * array - pointer to an array of unsigned characters. + * array_offset - offset into the array from which to pull the first + * character. + ****************************************************************************/ + +#define WRITE_SCRATCH_STRING(dword_bytes, bytes_extra, array, array_offset) \ +{ \ + unsigned long i, j; \ + unsigned long aroffset = (unsigned long)array + (array_offset); \ + \ + /* WRITE DWORDS */ \ + \ + for (i = 0; i < dword_bytes; i += 4) \ + *((volatile unsigned long *)(gfx_gx1_scratch_base + i)) = \ + *((unsigned long *)(aroffset + i)); \ + \ + /* WRITE BYTES */ \ + \ + j = i + bytes_extra; \ + while (i < j) { \ + *((volatile unsigned char *)(gfx_gx1_scratch_base + i)) = \ + *((unsigned char *)(aroffset + i)); \ + i++; \ + } \ +} + +/***************************************************************************** + * Macro: WRITE_FRAME_BUFFER_STRING32 + * Purpose: Write multiple dwords to the Frame buffer + * + * Arguments: + * fboffset - offset to the beginning frame buffer location. + * bytes - number of bytes to transfer. This number will always. + * be a multiple of 4. It cannot be modified within the + * macro (ex. bytes -= 4) + * array - pointer to an array of unsigned characters. + * array_offset - offset into the array from which to pull the first + * character. + ****************************************************************************/ + +#define WRITE_FRAME_BUFFER_STRING32(fboffset, bytes, array, array_offset) \ +{ \ + unsigned long i; \ + unsigned long aroffset = (unsigned long)array + (array_offset); \ + for (i = 0; i < bytes; i += 4) \ + WRITE_FB32 ((fboffset) + i, *((unsigned long *)(aroffset + i))); \ +} + +#endif + +/***************************************************************************** + * Macro: WRITE_FRAME_BUFFER_STRING8 + * Purpose: Write multiple bytes to the frame buffer + * + * Arguments: + * spoffset - offset to the beginning frame buffer location. + * bytes - number of bytes to transfer. This number cannot be + * modified within the macro (ex. bytes -= 4) + * array - pointer to an array of unsigned characters. + * array_offset - offset into the array from which to pull the first + * character. + ****************************************************************************/ + +#define WRITE_FRAME_BUFFER_STRING8(fboffset, bytes, array, array_offset) \ +{ \ + unsigned long i; \ + unsigned long aroffset = (unsigned long)array + (array_offset); \ + for (i = 0; i < bytes; i++) \ + WRITE_FB8 ((fboffset) + i, *((unsigned char *)(aroffset + i))); \ +} + +/***************************************************************************** + * Macro: WRITE_GPREG_STRING32 + * Purpose: Write multiple dwords to one GP register. + * + * Arguments: + * regoffset - Offset of the GP register to be written. + * dwords - number of dwords to transfer. It cannot be modified + * within the macro (ex. dwords--) + * counter - name of a counter variable that can be used in a loop. + * This is used to optimize macros written in C. + * array - pointer to an array of unsigned characters. + * array_offset - offset into the array from which to pull the first + * character. + * temp - name of a temporary variable that can be used for + * calculations. + * This argument is also used for C-only macros. + ****************************************************************************/ + +#define WRITE_GPREG_STRING32(regoffset, dwords, counter, array, \ + array_offset, temp) \ +{ \ + temp = (unsigned long)array + (array_offset); \ + for (counter = 0; counter < dwords; counter++) \ + WRITE_GP32 (regoffset, *((unsigned long *)temp + counter)); \ +} + +/***************************************************************************** + * Macro: WRITE_GPREG_STRING8 + * Purpose: Write 4 or less bytes to one GP register. + * + * Arguments: + * regoffset - Offset of the GP register to be written. + * bytes - number of bytes to transfer. This number will always. + * be less than 4. It cannot be modified within the + * macro (ex. bytes--) + * shift - name of a shift variable that can be used as a shift + * count. + * This variable holds the initial shift value into the + * GP register. + * counter - name of a counter variable that can be used in a loop. + * This is used to optimize macros written in C. + * array - pointer to an array of unsigned characters. + * array_offset - offset into the array from which to pull the first + * character. + * temp1 - name of a temporary variable that can be used for + * calculations. + * This argument is also used for C-only macros. + * temp2 - name of a temporary variable that can be used for + * calculations. + * This argument is also used for C-only macros. + ****************************************************************************/ +#define WRITE_GPREG_STRING8(regoffset, bytes, shift, counter, array, \ + array_offset, temp1, temp2) \ +{ \ + if (bytes) { \ + temp1 = (unsigned long)array + (array_offset); \ + temp2 = 0; \ + for (counter = 0; counter < bytes; counter++) { \ + temp2 |= ((unsigned long)(*((unsigned char *)(temp1 + \ + counter)))) << shift; \ + shift += 8; \ + } \ + WRITE_GP32 (regoffset, temp2); \ + } \ +} + +/* END OF FILE */ diff --git a/src/gfx/gfx_disp.c b/src/gfx/gfx_disp.c new file mode 100644 index 0000000..035cbab --- /dev/null +++ b/src/gfx/gfx_disp.c @@ -0,0 +1,2925 @@ +/* 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 to program the display controller. + * + * The "disp_gu1.c" and "disp_gu2.c" files implement the following routines: + * + * gfx_get_display_mode_count + * gfx_get_display_mode + * gfx_is_display_mode_supported + * gfx_get_display_details + * gfx_set_display_mode + * gfx_set_display_bpp + * gfx_set_display_timings + * gfx_set_vtotal + * gfx_get_display_pitch + * gfx_set_display_pitch + * gfx_set_display_offset + * gfx_set_display_palette + * gfx_set_display_palette_entry + * gfx_set_cursor_enable + * gfx_set_cursor_colors + * gfx_set_cursor_position + * gfx_set_cursor_shape32 + * gfx_set_cursor_shape64 + * gfx_set_compression_enable + * gfx_set_compression_offset + * gfx_set_compression_pitch + * gfx_set_compression_size + * gfx_set_display_priority_high + * gfx_test_timing_active + * gfx_test_vertical_active + * gfx_wait_vertical_blank + * gfx_reset_timing_lock + * + * And the following routines if GFX_READ_ROUTINES is set: + * + * gfx_get_hactive + * gfx_get_hblank_start + * gfx_get_hsync_start + * gfx_get_hsync_end + * gfx_get_hblank_end + * gfx_get_htotal + * gfx_get_vactive + * gfx_get_vblank_start + * gfx_get_vsync_start + * gfx_get_vsync_end + * gfx_get_vblank_end + * gfx_get_vtotal + * gfx_get_vline + * gfx_get_display_bpp + * gfx_get_display_offset + * gfx_get_display_palette + * gfx_get_cursor_enable + * gfx_get_cursor_base + * gfx_get_cursor_position + * gfx_get_cursor_offset + * gfx_get_cursor_color + * gfx_get_compression_enable + * gfx_get_compression_offset + * gfx_get_compression_pitch + * gfx_get_compression_size + * gfx_get_display_priority_high + * gfx_get_valid_bit + * */ + +unsigned short PanelWidth = 0; +unsigned short PanelHeight = 0; +unsigned short PanelEnable = 0; +unsigned short ModeWidth; +unsigned short ModeHeight; + +int DeltaX = 0; +int DeltaY = 0; +unsigned long prevstartAddr = 0; +unsigned long panelTop = 0; +unsigned long panelLeft = 0; + +int gbpp = 8; + +int gfx_compression_enabled = 0; +int gfx_compression_active = 0; +int gfx_line_double = 0; +int gfx_pixel_double = 0; +int gfx_timing_lock = 0; +DISPLAYMODE gfx_display_mode; + +/* DISPLAY MODE TIMINGS */ + +DISPLAYMODE DisplayParams[] = { + +/* 320 x 200 */ + + { + GFX_MODE_70HZ | /* refresh rate = 60 */ + GFX_MODE_8BPP | GFX_MODE_16BPP | /* 8 and 16 BPP valid */ + GFX_MODE_NEG_HSYNC | /* negative HSYNC */ + GFX_MODE_PIXEL_DOUBLE | /* Double width */ + GFX_MODE_LINE_DOUBLE, /* Double height */ + 0x140, 0x288, 0x290, 0x2F0, 0x318, 0x320, /* horizontal timings */ + 0x0C8, 0x197, 0x19C, 0x19E, 0x1BA, 0x1C1, /* vertical timings */ + 0x00192CCC, /* freq = 25.175 MHz */ + }, + +/* 320 x 240 */ + + { + GFX_MODE_75HZ | /* refresh rate = 75 */ + GFX_MODE_8BPP | GFX_MODE_16BPP | /* 8 and 16 BPP valid */ + GFX_MODE_NEG_HSYNC | GFX_MODE_NEG_VSYNC | /* negative syncs */ + GFX_MODE_PIXEL_DOUBLE | /* Double width */ + GFX_MODE_LINE_DOUBLE, /* Double height */ + 0x0140, 0x0280, 0x0290, 0x02D0, 0x0348, 0x0348, + /* horizontal timings */ + 0x00F0, 0x01E0, 0x01E1, 0x01E4, 0x01F4, 0x01F4, + /* vertical timings */ + 0x001F8000, /* freq = 31.5 MHz */ + }, + +/* 400 x 300 */ + + { + GFX_MODE_75HZ | /* refresh rate = 75 */ + GFX_MODE_8BPP | GFX_MODE_16BPP | /* 8 and 16 BPP valid */ + GFX_MODE_PIXEL_DOUBLE | /* Double width */ + GFX_MODE_LINE_DOUBLE, /* Double height */ + 0x0190, 0x0320, 0x0330, 0x0380, 0x0420, 0x0420, + /* horizontal timings */ + 0x012C, 0x0258, 0x0259, 0x025C, 0x0271, 0x0271, + /* vertical timings */ + 0x00318000, /* freq = 49.5 MHz */ + }, + +/* 512 x 384 */ + + { + GFX_MODE_75HZ | /* refresh rate = 75 */ + GFX_MODE_8BPP | GFX_MODE_16BPP | /* 8 and 16 BPP valid */ + GFX_MODE_PIXEL_DOUBLE | /* Double width */ + GFX_MODE_LINE_DOUBLE, /* Double height */ + 0x0200, 0x0400, 0x0410, 0x0470, 0x0520, 0x0520, + /* horizontal timings */ + 0x0180, 0x0300, 0x0301, 0x0304, 0x0320, 0x0320, + /* vertical timings */ + 0x004EC000, /* freq = 78.75 MHz */ + }, + +/* 640 x 400 */ + + { + GFX_MODE_70HZ | /* refresh rate = 60 */ + GFX_MODE_8BPP | GFX_MODE_12BPP | GFX_MODE_15BPP | + /* all BPP valid */ + GFX_MODE_16BPP | GFX_MODE_24BPP | GFX_MODE_NEG_HSYNC, + /* negative HSYNC */ + 0x280, 0x288, 0x290, 0x2F0, 0x318, 0x320, /* horizontal timings */ + 0x190, 0x197, 0x19C, 0x19E, 0x1BA, 0x1C1, /* vertical timings */ + 0x00192CCC, /* freq = 25.175 MHz */ + }, + +/* 640x480 */ + + { + GFX_MODE_60HZ | /* refresh rate = 60 */ + GFX_MODE_8BPP | GFX_MODE_12BPP | GFX_MODE_15BPP | + /* all BPP valid */ + GFX_MODE_16BPP | GFX_MODE_24BPP | GFX_MODE_NEG_HSYNC | GFX_MODE_NEG_VSYNC, /* negative syncs */ + 0x0280, 0x0288, 0x0290, 0x02E8, 0x0318, 0x0320, + /* horizontal timings */ + 0x01E0, 0x01E8, 0x01EA, 0x01EC, 0x0205, 0x020D, + /* vertical timings */ + 0x00192CCC, /* freq = 25.175 MHz */ + }, + + { + GFX_MODE_70HZ | /* refresh rate = 60 */ + GFX_MODE_8BPP | GFX_MODE_12BPP | GFX_MODE_15BPP | + /* all BPP valid */ + GFX_MODE_16BPP | GFX_MODE_24BPP, + 0x0280, 0x0280, 0x0298, 0x02D8, 0x0330, 0x0330, + /* horizontal timings */ + 0x01E0, 0x01E0, 0x01E2, 0x01E5, 0x01F4, 0x01F4, + /* vertical timings */ + 0x001C8F5C, /* freq = 28.560 MHz */ + }, + + { + GFX_MODE_72HZ | /* refresh rate = 72 */ + GFX_MODE_8BPP | GFX_MODE_12BPP | GFX_MODE_15BPP | + /* all BPP valid */ + GFX_MODE_16BPP | GFX_MODE_24BPP | GFX_MODE_NEG_HSYNC | GFX_MODE_NEG_VSYNC, /* negative syncs */ + 0x0280, 0x0288, 0x0298, 0x02c0, 0x0338, 0x0340, + /* horizontal timings */ + 0x01e0, 0x01e8, 0x01e9, 0x01ec, 0x0200, 0x0208, + /* vertical timings */ + 0x001F8000, /* freq = 31.5 MHz */ + }, + + { + GFX_MODE_75HZ | /* refresh rate = 75 */ + GFX_MODE_8BPP | GFX_MODE_12BPP | GFX_MODE_15BPP | + /* all BPP valid */ + GFX_MODE_16BPP | GFX_MODE_24BPP | GFX_MODE_NEG_HSYNC | GFX_MODE_NEG_VSYNC, /* negative syncs */ + 0x0280, 0x0280, 0x0290, 0x02D0, 0x0348, 0x0348, + /* horizontal timings */ + 0x01E0, 0x01E0, 0x01E1, 0x01E4, 0x01F4, 0x01F4, + /* vertical timings */ + 0x001F8000, /* freq = 31.5 MHz */ + }, + + { + GFX_MODE_85HZ | /* refresh rate = 85 */ + GFX_MODE_8BPP | GFX_MODE_12BPP | GFX_MODE_15BPP | + /* all BPP valid */ + GFX_MODE_16BPP | GFX_MODE_24BPP | GFX_MODE_NEG_HSYNC | GFX_MODE_NEG_VSYNC, /* negative syncs */ + 0x0280, 0x0280, 0x02B8, 0x02F0, 0x0340, 0x0340, + /* horizontal timings */ + 0x01E0, 0x01E0, 0x01E1, 0x01E4, 0x01FD, 0x01FD, + /* vertical timings */ + 0x00240000, /* freq = 36.0 MHz */ + }, + + { + GFX_MODE_90HZ | /* refresh rate = 90 */ + GFX_MODE_8BPP | GFX_MODE_12BPP | GFX_MODE_15BPP | + /* all BPP valid */ + GFX_MODE_16BPP | GFX_MODE_24BPP, + 0x0280, 0x0280, 0x02A0, 0x02E0, 0x0340, 0x0340, + /* horizontal timings */ + 0x01E0, 0x01E0, 0x01E1, 0x01E4, 0x01FA, 0x01FA, + /* vertical timings */ + 0x0025E395, /* freq = 37.889 MHz */ + }, + + { + GFX_MODE_100HZ | /* refresh rate = 100 */ + GFX_MODE_8BPP | GFX_MODE_12BPP | GFX_MODE_15BPP | + /* all BPP valid */ + GFX_MODE_16BPP | GFX_MODE_24BPP, + 0x0280, 0x0280, 0x02A8, 0x02E8, 0x0350, 0x0350, + /* horizontal timings */ + 0x01E0, 0x01E0, 0x01E1, 0x01E4, 0x01FD, 0x01FD, + /* vertical timings */ + 0x002B29BA, /* freq = 43.163 MHz */ + }, + +/* 800x600 */ + + { + GFX_MODE_56HZ | /* refresh rate = 56 */ + GFX_MODE_8BPP | GFX_MODE_12BPP | GFX_MODE_15BPP | + /* all BPP valid */ + GFX_MODE_16BPP | GFX_MODE_24BPP, + 0x0320, 0x0320, 0x0338, 0x0380, 0x0400, 0x0400, + /* horizontal timings */ + 0x0258, 0x0258, 0x0259, 0x025B, 0x0271, 0x0271, + /* vertical timings */ + 0x00240000, /* freq = 36.00 MHz */ + }, + + { + GFX_MODE_60HZ | /* refresh rate = 60 */ + GFX_MODE_8BPP | GFX_MODE_12BPP | GFX_MODE_15BPP | + /* all BPP valid */ + GFX_MODE_16BPP | GFX_MODE_24BPP, + 0x0320, 0x0328, 0x0348, 0x03D0, 0x0418, 0x0420, + /* horizontal timings */ + 0x0258, 0x0258, 0x0259, 0x025D, 0x0274, 0x0274, + /* vertical timings */ + 0x00280000, /* freq = 40.00 MHz */ + }, + + { + GFX_MODE_70HZ | /* refresh rate = 70 */ + GFX_MODE_8BPP | GFX_MODE_12BPP | GFX_MODE_15BPP | + /* all BPP valid */ + GFX_MODE_16BPP | GFX_MODE_24BPP, + 0x0320, 0x0320, 0x0348, 0x0398, 0x0410, 0x0410, + /* horizontal timings */ + 0x0258, 0x0258, 0x025c, 0x025F, 0x0274, 0x0274, + /* vertical timings */ + 0x002DB851, /* freq = 45.72 MHz */ + }, + + { + GFX_MODE_72HZ | /* refresh rate = 72 */ + GFX_MODE_8BPP | GFX_MODE_12BPP | GFX_MODE_15BPP | + /* all BPP valid */ + GFX_MODE_16BPP | GFX_MODE_24BPP, + 0x0320, 0x0320, 0x0358, 0x03D0, 0x0410, 0x0410, + /* horizontal timings */ + 0x0258, 0x0258, 0x027D, 0x0283, 0x029A, 0x029A, + /* vertical timings */ + 0x00320000, /* freq = 49.5 MHz */ + }, + + { + GFX_MODE_75HZ | /* refresh rate = 75 */ + GFX_MODE_8BPP | GFX_MODE_12BPP | GFX_MODE_15BPP | + /* all BPP valid */ + GFX_MODE_16BPP | GFX_MODE_24BPP, + 0x0320, 0x0320, 0x0330, 0x0380, 0x0420, 0x0420, + /* horizontal timings */ + 0x0258, 0x0258, 0x0259, 0x025C, 0x0271, 0x0271, + /* vertical timings */ + 0x00318000, /* freq = 49.5 MHz */ + }, + + { + GFX_MODE_85HZ | /* refresh rate = 85 */ + GFX_MODE_8BPP | GFX_MODE_12BPP | GFX_MODE_15BPP | + /* all BPP valid */ + GFX_MODE_16BPP | GFX_MODE_24BPP, + 0x0320, 0x0320, 0x0340, 0x0380, 0x0418, 0x0418, + /* horizontal timings */ + 0x0258, 0x0258, 0x0259, 0x025C, 0x0277, 0x0277, + /* vertical timings */ + 0x00384000, /* freq = 56.25 MHz */ + }, + + { + GFX_MODE_90HZ | /* refresh rate = 90 */ + GFX_MODE_8BPP | GFX_MODE_12BPP | GFX_MODE_15BPP | + /* all BPP valid */ + GFX_MODE_16BPP | GFX_MODE_24BPP, + 0x0320, 0x0320, 0x0348, 0x03A0, 0x0420, 0x0420, + /* horizontal timings */ + 0x0258, 0x0258, 0x0259, 0x025C, 0x0278, 0x0278, + /* vertical timings */ + 0x003C10A3, /* freq = 60.065 MHz */ + }, + + { + GFX_MODE_100HZ | /* refresh rate = 100 */ + GFX_MODE_8BPP | GFX_MODE_12BPP | GFX_MODE_15BPP | + /* all BPP valid */ + GFX_MODE_16BPP | GFX_MODE_24BPP, + 0x0320, 0x0320, 0x0350, 0x03A8, 0x0430, 0x0430, + /* horizontal timings */ + 0x0258, 0x0258, 0x0259, 0x025C, 0x0277, 0x027C, + /* vertical timings */ + 0x00442DD2, /* freq = 68.179 MHz */ + }, + +/* 1024x768 */ + + { + GFX_MODE_60HZ | /* refresh rate = 60 */ + GFX_MODE_8BPP | GFX_MODE_12BPP | GFX_MODE_15BPP | + /* all BPP valid */ + GFX_MODE_16BPP | GFX_MODE_24BPP | GFX_MODE_NEG_HSYNC | GFX_MODE_NEG_VSYNC, /* negative syncs */ + 0x0400, 0x0400, 0x0418, 0x04A0, 0x0540, 0x0540, + /* horizontal timings */ + 0x0300, 0x0300, 0x0303, 0x0309, 0x0326, 0x0326, + /* vertical timings */ + 0x00410000, /* freq = 65.00 MHz */ + }, + + { + GFX_MODE_70HZ | /* refresh rate = 70 */ + GFX_MODE_8BPP | GFX_MODE_12BPP | GFX_MODE_15BPP | + /* all BPP valid */ + GFX_MODE_16BPP | GFX_MODE_24BPP | GFX_MODE_NEG_HSYNC | GFX_MODE_NEG_VSYNC, /* negative syncs */ + 0x0400, 0x0400, 0x0418, 0x04A0, 0x0530, 0x0530, + /* horizontal timings */ + 0x0300, 0x0300, 0x0303, 0x0309, 0x0326, 0x0326, + /* vertical timings */ + 0x004B0000, /* freq = 75.00 MHz */ + }, + + { + GFX_MODE_72HZ | /* refresh rate = 72 */ + GFX_MODE_8BPP | GFX_MODE_12BPP | GFX_MODE_15BPP | + /* all BPP valid */ + GFX_MODE_16BPP | GFX_MODE_24BPP, + 0x0400, 0x0400, 0x0438, 0x04A8, 0x0550, 0x0550, + /* horizontal timings */ + 0x0300, 0x0300, 0x0304, 0x0307, 0x0324, 0x0324, + /* vertical timings */ + 0x004EC000, /* freq = 78.75 MHz */ + }, + + { + GFX_MODE_75HZ | /* refresh rate = 75 */ + GFX_MODE_8BPP | GFX_MODE_12BPP | GFX_MODE_15BPP | + /* all BPP valid */ + GFX_MODE_16BPP | GFX_MODE_24BPP, + 0x0400, 0x0400, 0x0410, 0x0470, 0x0520, 0x0520, + /* horizontal timings */ + 0x0300, 0x0300, 0x0301, 0x0304, 0x0320, 0x0320, + /* vertical timings */ + 0x004EC000, /* freq = 78.75 MHz */ + }, + + { + GFX_MODE_85HZ | /* refresh rate = 85 */ + GFX_MODE_8BPP | GFX_MODE_12BPP | GFX_MODE_15BPP | + /* all BPP valid */ + GFX_MODE_16BPP | GFX_MODE_24BPP, + 0x0400, 0x0400, 0x0430, 0x0490, 0x0560, 0x0560, + /* horizontal timings */ + 0x0300, 0x0300, 0x0301, 0x0304, 0x0328, 0x0328, + /* vertical timings */ + 0x005E8000, /* freq = 94.50 MHz */ + }, + + { + GFX_MODE_90HZ | /* refresh rate = 90 */ + GFX_MODE_8BPP | GFX_MODE_12BPP | GFX_MODE_15BPP | + /* all BPP valid */ + GFX_MODE_16BPP | GFX_MODE_24BPP, + 0x0400, 0x0400, 0x0440, 0x04B0, 0x0560, 0x0560, + /* horizontal timings */ + 0x0300, 0x0300, 0x0301, 0x0304, 0x0329, 0x0329, + /* vertical timings */ + 0x00642FDF, /* freq = 100.187 MHz */ + }, + + { + GFX_MODE_100HZ | /* refresh rate = 100 */ + GFX_MODE_8BPP | GFX_MODE_12BPP | GFX_MODE_15BPP | + /* all BPP valid */ + GFX_MODE_16BPP | GFX_MODE_24BPP, + 0x0400, 0x0400, 0x0448, 0x04B8, 0x0570, 0x0570, + /* horizontal timings */ + 0x0300, 0x0300, 0x0301, 0x0304, 0x032E, 0x032E, + /* vertical timings */ + 0x00714F1A, /* freq = 113.309 MHz */ + }, + +/* 1152x864 */ + + { + GFX_MODE_60HZ | /* refresh rate = 60 */ + GFX_MODE_8BPP | GFX_MODE_12BPP | GFX_MODE_15BPP | + /* all BPP valid */ + GFX_MODE_16BPP | GFX_MODE_24BPP, + 0x0480, 0x0480, 0x04C0, 0x0538, 0x05F0, 0x05F0, + /* horizontal timings */ + 0x0360, 0x0360, 0x0361, 0x0364, 0x037F, 0x037F, + /* vertical timings */ + 0x00519999, /* freq = 81.60 MHz */ + }, + + { + GFX_MODE_70HZ | /* refresh rate = 70 */ + GFX_MODE_8BPP | GFX_MODE_12BPP | GFX_MODE_15BPP | + /* all BPP valid */ + GFX_MODE_16BPP | GFX_MODE_24BPP, + 0x0480, 0x0480, 0x04C8, 0x0540, 0x0600, 0x0600, + /* horizontal timings */ + 0x0360, 0x0360, 0x0368, 0x036B, 0x038B, 0x038B, + /* vertical timings */ + 0x00618560, /* freq = 97.521 MHz */ + }, + + { + GFX_MODE_72HZ | /* refresh rate = 70 */ + GFX_MODE_8BPP | GFX_MODE_12BPP | GFX_MODE_15BPP | + /* all BPP valid */ + GFX_MODE_16BPP | GFX_MODE_24BPP, + 0x0480, 0x0480, 0x04C8, 0x0548, 0x0610, 0x0610, + /* horizontal timings */ + 0x0360, 0x0360, 0x0367, 0x036A, 0x038B, 0x038B, + /* vertical timings */ + 0x00656B85, /* freq = 101.42 MHz */ + }, + + { + GFX_MODE_75HZ | /* refresh rate = 75 */ + GFX_MODE_8BPP | GFX_MODE_12BPP | GFX_MODE_15BPP | + /* all BPP valid */ + GFX_MODE_16BPP | GFX_MODE_24BPP, + 0x0480, 0x0480, 0x04C0, 0x0540, 0x0640, 0x0640, + /* horizontal timings */ + 0x0360, 0x0360, 0x0361, 0x0364, 0x0384, 0x0384, + /* vertical timings */ + 0x006C0000, /* freq = 108.00 MHz */ + }, + + { + GFX_MODE_85HZ | /* refresh rate = 85 */ + GFX_MODE_8BPP | GFX_MODE_12BPP | GFX_MODE_15BPP | + /* all BPP valid */ + GFX_MODE_16BPP | GFX_MODE_24BPP, + 0x0480, 0x0480, 0x04C8, 0x0548, 0x0610, 0x0610, + /* horizontal timings */ + 0x0360, 0x0360, 0x0363, 0x0366, 0x038B, 0x038B, + /* vertical timings */ + 0x0077A666, /* freq = 119.65 MHz */ + }, + + { + GFX_MODE_90HZ | /* refresh rate = 90 */ + GFX_MODE_8BPP | GFX_MODE_12BPP | GFX_MODE_15BPP | + /* all BPP valid */ + GFX_MODE_16BPP | GFX_MODE_24BPP, + 0x0480, 0x0480, 0x04D0, 0x0550, 0x0620, 0x0620, + /* horizontal timings */ + 0x0360, 0x0360, 0x0363, 0x0366, 0x038E, 0x038E, + /* vertical timings */ + 0x00806666, /* freq = 128.40 MHz */ + }, + + { + GFX_MODE_100HZ | /* refresh rate = 100 */ + GFX_MODE_8BPP | GFX_MODE_12BPP | GFX_MODE_15BPP | + /* all BPP valid */ + GFX_MODE_16BPP | GFX_MODE_24BPP, + 0x0480, 0x0480, 0x04D0, 0x0550, 0x0620, 0x0620, + /* horizontal timings */ + 0x0360, 0x0360, 0x0365, 0x0368, 0x0398, 0x0398, + /* vertical timings */ + 0x00906147, /* freq = 144.38 MHz */ + }, + +/* 1280x1024 */ + + { + GFX_MODE_60HZ | /* refresh rate = 60 */ + GFX_MODE_8BPP | GFX_MODE_12BPP | GFX_MODE_15BPP | + /* all BPP valid */ + GFX_MODE_16BPP | GFX_MODE_24BPP, + 0x0500, 0x0500, 0x0530, 0x05A0, 0x0698, 0x0698, + /* horizontal timings */ + 0x0400, 0x0400, 0x0401, 0x0404, 0x042A, 0x042A, + /* vertical timings */ + 0x006C0000, /* freq = 108.0 MHz */ + }, + + { + GFX_MODE_70HZ | /* refresh rate = 70 */ + GFX_MODE_8BPP | GFX_MODE_12BPP | GFX_MODE_15BPP | + /* all BPP valid */ + GFX_MODE_16BPP | GFX_MODE_24BPP, + 0x0500, 0x0500, 0x0558, 0x05E0, 0x06C0, 0x06C0, + /* horizontal timings */ + 0x0400, 0x0400, 0x040A, 0x040D, 0x0433, 0x0433, + /* vertical timings */ + 0x00821999, /* freq = 130.1 MHz */ + }, + + { + GFX_MODE_72HZ | /* refresh rate = 72 */ + GFX_MODE_8BPP | GFX_MODE_12BPP | GFX_MODE_15BPP | + /* all BPP valid */ + GFX_MODE_16BPP | GFX_MODE_24BPP, + 0x0500, 0x0500, 0x0558, 0x05E0, 0x06C0, 0x06C0, + /* horizontal timings */ + 0x0400, 0x0400, 0x0407, 0x040A, 0x0431, 0x0431, + /* vertical timings */ + 0x00858000, /* freq = 133.5 MHz */ + }, + + { + GFX_MODE_75HZ | /* refresh rate = 75 */ + GFX_MODE_8BPP | GFX_MODE_12BPP | GFX_MODE_15BPP | + /* all BPP valid */ + GFX_MODE_16BPP | GFX_MODE_24BPP, + 0x0500, 0x0500, 0x0510, 0x05A0, 0x0698, 0x0698, + /* horizontal timings */ + 0x0400, 0x0400, 0x0401, 0x0404, 0x042A, 0x042A, + /* vertical timings */ + 0x00870000, /* freq = 135.0 MHz */ + }, + + { + GFX_MODE_85HZ | /* refresh rate = 85 */ + GFX_MODE_8BPP | GFX_MODE_12BPP | GFX_MODE_15BPP | + /* all BPP valid */ + GFX_MODE_16BPP | GFX_MODE_24BPP, + 0x0500, 0x0500, 0x0540, 0x05E0, 0x06C0, 0x06C0, + /* horizontal timings */ + 0x0400, 0x0400, 0x0401, 0x0404, 0x0430, 0x0430, + /* vertical timings */ + 0x009D8000, /* freq = 157.5 MHz */ + }, + + { + GFX_MODE_90HZ | /* refresh rate = 90 */ + GFX_MODE_8BPP | GFX_MODE_12BPP | GFX_MODE_15BPP | + /* all BPP valid */ + GFX_MODE_16BPP | GFX_MODE_24BPP, + 0x0500, 0x0500, 0x0560, 0x05E8, 0x06D0, 0x06D0, + /* horizontal timings */ + 0x0400, 0x0400, 0x0401, 0x0404, 0x0436, 0x0436, + /* vertical timings */ + 0x00A933F7, /* freq = 169.203 MHz */ + }, + + { + GFX_MODE_100HZ | /* refresh rate = 100 */ + GFX_MODE_8BPP | GFX_MODE_12BPP | GFX_MODE_15BPP | + /* all BPP valid */ + GFX_MODE_16BPP | GFX_MODE_24BPP, + 0x0500, 0x0500, 0x0560, 0x05F0, 0x06E0, 0x06E0, + /* horizontal timings */ + 0x0400, 0x0400, 0x0401, 0x0404, 0x043D, 0x043D, + /* vertical timings */ + 0x00BEF5C2, /* freq = 190.96 MHz */ + }, + +/*********************************/ +/* BEGIN REDCLOUD-SPECIFIC MODES */ +/*-------------------------------*/ + +/* 1600 x 1200 */ + + { + GFX_MODE_60HZ | /* refresh rate = 60 */ + GFX_MODE_8BPP | GFX_MODE_12BPP | GFX_MODE_15BPP | + /* all BPP valid */ + GFX_MODE_16BPP | GFX_MODE_24BPP, + 0x0640, 0x0640, 0x0680, 0x0740, 0x0870, 0x0870, + /* horizontal timings */ + 0x04B0, 0x04B0, 0x04B1, 0x04B4, 0x04E2, 0x04E2, + /* vertical timings */ + 0x00A20000, /* freq = 162.0 MHz */ + }, + + { + GFX_MODE_70HZ | /* refresh rate = 70 */ + GFX_MODE_8BPP | GFX_MODE_12BPP | GFX_MODE_15BPP | + /* all BPP valid */ + GFX_MODE_16BPP | GFX_MODE_24BPP, + 0x0640, 0x0640, 0x0680, 0x0740, 0x0870, 0x0870, + /* horizontal timings */ + 0x04B0, 0x04B0, 0x04B1, 0x04B4, 0x04E2, 0x04E2, + /* vertical timings */ + 0x00BD0000, /* freq = 189.0 MHz */ + }, + + { + GFX_MODE_72HZ | /* refresh rate = 72 */ + GFX_MODE_8BPP | GFX_MODE_12BPP | GFX_MODE_15BPP | + /* all BPP valid */ + GFX_MODE_16BPP | GFX_MODE_24BPP, + 0x0640, 0x0640, 0x06B0, 0x0760, 0x0880, 0x0880, + /* horizontal timings */ + 0x04B0, 0x04B0, 0x04BD, 0x04C0, 0x04EF, 0x04EF, + /* vertical timings */ + 0x00C60000, /* freq = 198.0 MHz */ + }, + + { + GFX_MODE_75HZ | /* refresh rate = 75 */ + GFX_MODE_8BPP | GFX_MODE_12BPP | GFX_MODE_15BPP | + /* all BPP valid */ + GFX_MODE_16BPP | GFX_MODE_24BPP, + 0x0640, 0x0640, 0x0680, 0x0740, 0x0870, 0x0870, + /* horizontal timings */ + 0x04B0, 0x04B0, 0x04B1, 0x04B4, 0x04E2, 0x04E2, + /* vertical timings */ + 0x00CA8000, /* freq = 202.5 MHz */ + }, + + { + GFX_MODE_85HZ | /* refresh rate = 85 */ + GFX_MODE_8BPP | GFX_MODE_12BPP | GFX_MODE_15BPP | + /* all BPP valid */ + GFX_MODE_16BPP | GFX_MODE_24BPP, + 0x0640, 0x0640, 0x0680, 0x0740, 0x0870, 0x0870, + /* horizontal timings */ + 0x04B0, 0x04B0, 0x04B1, 0x04B4, 0x04E2, 0x04E2, + /* vertical timings */ + 0x00E58000, /* freq = 229.5 MHz */ + }, +}; + +/* UPDATE THIS VARIABLE WHENEVER NEW REDCLOUD-SPECIFIC MODES ARE ADDED */ + +#define REDCLOUD_SPECIFIC_MODES 4 + +#define NUM_RC_DISPLAY_MODES sizeof(DisplayParams) / sizeof(DISPLAYMODE) +#define NUM_GX_DISPLAY_MODES (NUM_RC_DISPLAY_MODES - REDCLOUD_SPECIFIC_MODES) + +FIXEDTIMINGS FixedParams[] = { +/* 640x480 Panel */ + {640, 480, 640, 480, + 0x0280, 0x0280, 0x0290, 0x02E8, 0x0318, 0x0320, + 0x01E0, 0x01E0, 0x01EA, 0x01EC, 0x0205, 0x020D, + 0x00192CCC, + }, + + {640, 480, 800, 600, + 0x0280, 0x0280, 0x0290, 0x02E8, 0x0318, 0x0320, + 0x01E0, 0x01E0, 0x01EA, 0x01EC, 0x0205, 0x020D, + 0x00192CCC, + }, + + {640, 480, 1024, 768, + 0x0280, 0x0280, 0x0290, 0x02E8, 0x0318, 0x0320, + 0x01E0, 0x01E0, 0x01EA, 0x01EC, 0x0205, 0x020D, + 0x00192CCC, + }, + + {640, 480, 1152, 864, + 0x0280, 0x0280, 0x0290, 0x02E8, 0x0318, 0x0320, + 0x01E0, 0x01E0, 0x01EA, 0x01EC, 0x0205, 0x020D, + 0x00192CCC, + }, + + {640, 480, 1280, 1024, + 0x0280, 0x0280, 0x0290, 0x02E8, 0x0318, 0x0320, + 0x01E0, 0x01E0, 0x01EA, 0x01EC, 0x0205, 0x020D, + 0x00192CCC, + }, + + {640, 480, 1600, 1200, + 0x0280, 0x0280, 0x0290, 0x02E8, 0x0318, 0x0320, + 0x01E0, 0x01E0, 0x01EA, 0x01EC, 0x0205, 0x020D, + 0x00192CCC, + }, + +/* 800x600 Panel */ + {800, 600, 640, 480, + 0x0280, 0x2d0, 0x2f8, 0x378, 0x3d0, 0x420, + 0x1e0, 0x21c, 0x21d, 0x221, 0x238, 0x274, + 0x00280000, + }, + + {800, 600, 800, 600, + 0x320, 0x320, 0x348, 0x3c8, 0x420, 0x420, + 0x258, 0x258, 0x259, 0x25d, 0x274, 0x274, + 0x00280000, + }, + + {800, 600, 1024, 768, + 0x320, 0x320, 0x348, 0x3c8, 0x420, 0x420, + 0x258, 0x258, 0x259, 0x25d, 0x274, 0x274, + 0x00280000, + }, + + {800, 600, 1152, 864, + 0x320, 0x320, 0x348, 0x3c8, 0x420, 0x420, + 0x258, 0x258, 0x259, 0x25d, 0x274, 0x274, + 0x00280000, + }, + + {800, 600, 1280, 1024, + 0x320, 0x320, 0x348, 0x3c8, 0x420, 0x420, + 0x258, 0x258, 0x259, 0x25d, 0x274, 0x274, + 0x00280000, + }, + + {800, 600, 1600, 1200, + 0x320, 0x320, 0x348, 0x3c8, 0x420, 0x420, + 0x258, 0x258, 0x259, 0x25d, 0x274, 0x274, + 0x00280000, + }, + +/* 1024x768 panel */ + {1024, 768, 640, 480, + 0x0280, 0x340, 0x368, 0x3e8, 0x480, 0x540, + 0x1e0, 0x270, 0x271, 0x275, 0x296, 0x326, + 0x00410000, + }, + + {1024, 768, 800, 600, + 0x0320, 0x390, 0x3b8, 0x438, 0x4D0, 0x540, + 0x258, 0x2ac, 0x2ad, 0x2b1, 0x2D2, 0x326, + 0x00410000, + }, + + {1024, 768, 1024, 768, + 0x0400, 0x0400, 0x0418, 0x04A0, 0x0540, 0x0540, + 0x0300, 0x0300, 0x0303, 0x0309, 0x0326, 0x0326, + 0x00410000, + }, + + {1024, 768, 1152, 864, + 0x0400, 0x0400, 0x0418, 0x04A0, 0x0540, 0x0540, + 0x0300, 0x0300, 0x0303, 0x0309, 0x0326, 0x0326, + 0x00410000, + }, + + {1024, 768, 1280, 1024, + 0x0400, 0x0400, 0x0418, 0x04A0, 0x0540, 0x0540, + 0x0300, 0x0300, 0x0303, 0x0309, 0x0326, 0x0326, + 0x00410000, + }, + + {1024, 768, 1600, 1200, + 0x0400, 0x0400, 0x0418, 0x04A0, 0x0540, 0x0540, + 0x0300, 0x0300, 0x0303, 0x0309, 0x0326, 0x0326, + 0x00410000, + }, + +/* 1280x1024 panel */ + {1280, 1024, 640, 480, + 640, 960, 1008, 1120, 1368, 1688, + 480, 752, 753, 756, 794, 1066, + 0x006C0000, + }, + + {1280, 1024, 800, 600, + 800, 1040, 1088, 1200, 1448, 1688, + 600, 812, 813, 816, 854, 1066, + 0x006C0000, + }, + + {1280, 1024, 1024, 768, + 1024, 1152, 1200, 1312, 1560, 1688, + 768, 896, 897, 900, 938, 1066, + 0x006C0000, + }, + + {1280, 1024, 1152, 864, + 1152, 1216, 1264, 1376, 1624, 1688, + 864, 944, 945, 948, 986, 1066, + 0x006C0000, + }, + + {1280, 1024, 1280, 1024, + 1280, 1280, 1328, 1440, 1688, 1688, + 1024, 1024, 1025, 1028, 1066, 1066, + 0x006C0000, + }, + +}; + +#define NUM_FIXED_TIMINGS_MODES sizeof(FixedParams)/sizeof(FIXEDTIMINGS) + +/* INCLUDE SUPPORT FOR FIRST GENERATION, IF SPECIFIED. */ + +#if GFX_DISPLAY_GU1 +#include "disp_gu1.c" +#endif + +/* INCLUDE SUPPORT FOR SECOND GENERATION, IF SPECIFIED. */ + +#if GFX_DISPLAY_GU2 +#include "disp_gu2.c" +#endif + +#if GFX_DISPLAY_GU3 +#include "disp_gu3.c" +#endif + +/*--------------------------------------------------------------------------- + * gfx_reset_timing_lock + * + * This routine resets the timing change lock. The lock can only be set by + * setting a flag when calling mode set. + *--------------------------------------------------------------------------- + */ +void +gfx_reset_timing_lock(void) +{ + gfx_timing_lock = 0; +} + +/* WRAPPERS IF DYNAMIC SELECTION */ +/* Extra layer to call either first or second generation routines. */ + +#if GFX_DISPLAY_DYNAMIC + +/*--------------------------------------------------------------------------- + * gfx_set_display_bpp + *--------------------------------------------------------------------------- + */ +int +gfx_set_display_bpp(unsigned short bpp) +{ + int retval = 0; + +#if GFX_DISPLAY_GU1 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU1) + retval = gu1_set_display_bpp(bpp); +#endif +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + retval = gu2_set_display_bpp(bpp); +#endif +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + retval = gu3_set_display_bpp(bpp); +#endif + return (retval); +} + +/*--------------------------------------------------------------------------- + * gfx_is_display_mode_supported + * check if given mode supported, + * return the supported mode on success, -1 on fail + *--------------------------------------------------------------------------- + */ +int +gfx_is_display_mode_supported(int xres, int yres, int bpp, int hz) +{ + int retval = -1; + +#if GFX_DISPLAY_GU1 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU1) + retval = gu1_is_display_mode_supported(xres, yres, bpp, hz); +#endif +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + retval = gu2_is_display_mode_supported(xres, yres, bpp, hz); +#endif +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + retval = gu3_is_display_mode_supported(xres, yres, bpp, hz); +#endif + return (retval); +} + +/*--------------------------------------------------------------------------- + * gfx_set_display_mode + *--------------------------------------------------------------------------- + */ +int +gfx_set_display_mode(int xres, int yres, int bpp, int hz) +{ + int retval = 0; + +#if GFX_DISPLAY_GU1 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU1) + retval = gu1_set_display_mode(xres, yres, bpp, hz); +#endif +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + retval = gu2_set_display_mode(xres, yres, bpp, hz); +#endif +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + retval = gu3_set_display_mode(xres, yres, bpp, hz); +#endif + return (retval); +} + +/*--------------------------------------------------------------------------- + * gfx_set_display_timings + *--------------------------------------------------------------------------- + */ +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) +{ + int retval = 0; + +#if GFX_DISPLAY_GU1 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU1) + retval = gu1_set_display_timings(bpp, flags, + hactive, hblankstart, hsyncstart, hsyncend, hblankend, htotal, + vactive, vblankstart, vsyncstart, vsyncend, vblankend, vtotal, + frequency); +#endif +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + retval = gu2_set_display_timings(bpp, flags, + hactive, hblankstart, hsyncstart, hsyncend, hblankend, htotal, + vactive, vblankstart, vsyncstart, vsyncend, vblankend, vtotal, + frequency); +#endif +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + retval = gu3_set_display_timings(bpp, flags, + hactive, hblankstart, hsyncstart, hsyncend, hblankend, htotal, + vactive, vblankstart, vsyncstart, vsyncend, vblankend, vtotal, + frequency); +#endif + return (retval); +} + +/*--------------------------------------------------------------------------- + * gfx_set_display_pitch + *--------------------------------------------------------------------------- + */ +void +gfx_set_display_pitch(unsigned short pitch) +{ +#if GFX_DISPLAY_GU1 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU1) + gu1_set_display_pitch(pitch); +#endif +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + gu2_set_display_pitch(pitch); +#endif +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + gu3_set_display_pitch(pitch); +#endif +} + +/*--------------------------------------------------------------------------- + * gfx_set_display_offset + *--------------------------------------------------------------------------- + */ +void +gfx_set_display_offset(unsigned long offset) +{ +#if GFX_DISPLAY_GU1 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU1) + gu1_set_display_offset(offset); +#endif +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + gu2_set_display_offset(offset); +#endif +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + gu3_set_display_offset(offset); +#endif +} + +/*--------------------------------------------------------------------------- + * gfx_set_display_palette_entry + *--------------------------------------------------------------------------- + */ +int +gfx_set_display_palette_entry(unsigned long index, unsigned long palette) +{ + int status = 0; + +#if GFX_DISPLAY_GU1 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU1) + status = gu1_set_display_palette_entry(index, palette); +#endif +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + status = gu2_set_display_palette_entry(index, palette); +#endif +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + status = gu3_set_display_palette_entry(index, palette); +#endif + return (status); +} + +/*--------------------------------------------------------------------------- + * gfx_set_display_palette + *--------------------------------------------------------------------------- + */ +int +gfx_set_display_palette(unsigned long *palette) +{ + int status = 0; + +#if GFX_DISPLAY_GU1 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU1) + status = gu1_set_display_palette(palette); +#endif +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + status = gu2_set_display_palette(palette); +#endif +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + status = gu3_set_display_palette(palette); +#endif + return (status); +} + +/*--------------------------------------------------------------------------- + * gfx_set_cursor_enable + *--------------------------------------------------------------------------- + */ +void +gfx_set_cursor_enable(int enable) +{ +#if GFX_DISPLAY_GU1 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU1) + gu1_set_cursor_enable(enable); +#endif +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + gu2_set_cursor_enable(enable); +#endif +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + gu3_set_cursor_enable(enable); +#endif +} + +/*--------------------------------------------------------------------------- + * gfx_set_cursor_colors + *--------------------------------------------------------------------------- + */ +void +gfx_set_cursor_colors(unsigned long bkcolor, unsigned long fgcolor) +{ +#if GFX_DISPLAY_GU1 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU1) + gu1_set_cursor_colors(bkcolor, fgcolor); +#endif +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + gu2_set_cursor_colors(bkcolor, fgcolor); +#endif +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + gu3_set_cursor_colors(bkcolor, fgcolor); +#endif +} + +/*--------------------------------------------------------------------------- + * gfx_set_cursor_position + *--------------------------------------------------------------------------- + */ +void +gfx_set_cursor_position(unsigned long memoffset, + unsigned short xpos, unsigned short ypos, + unsigned short xhotspot, unsigned short yhotspot) +{ +#if GFX_DISPLAY_GU1 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU1) + gu1_set_cursor_position(memoffset, xpos, ypos, xhotspot, yhotspot); +#endif +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + gu2_set_cursor_position(memoffset, xpos, ypos, xhotspot, yhotspot); +#endif +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + gu3_set_cursor_position(memoffset, xpos, ypos, xhotspot, yhotspot); +#endif +} + +/*--------------------------------------------------------------------------- + * gfx_set_cursor_shape32 + *--------------------------------------------------------------------------- + */ +void +gfx_set_cursor_shape32(unsigned long memoffset, + unsigned long *andmask, unsigned long *xormask) +{ +#if GFX_DISPLAY_GU1 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU1) + gu1_set_cursor_shape32(memoffset, andmask, xormask); +#endif +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + gu2_set_cursor_shape32(memoffset, andmask, xormask); +#endif +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + gu3_set_cursor_shape32(memoffset, andmask, xormask); +#endif +} + +/*--------------------------------------------------------------------------- + * gfx_set_cursor_shape64 + *--------------------------------------------------------------------------- + */ +void +gfx_set_cursor_shape64(unsigned long memoffset, + unsigned long *andmask, unsigned long *xormask) +{ +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + gu2_set_cursor_shape64(memoffset, andmask, xormask); +#endif +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + gu3_set_cursor_shape64(memoffset, andmask, xormask); +#endif +} + +/*--------------------------------------------------------------------------- + * gfx_set_icon_enable + *--------------------------------------------------------------------------- + */ +void +gfx_set_icon_enable(int enable) +{ +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + gu2_set_icon_enable(enable); +#endif +} + +/*--------------------------------------------------------------------------- + * gfx_set_icon_colors + *--------------------------------------------------------------------------- + */ +void +gfx_set_icon_colors(unsigned long color0, unsigned long color1, + unsigned long color2) +{ +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + gu2_set_icon_colors(color0, color1, color2); +#endif +} + +/*--------------------------------------------------------------------------- + * gfx_set_icon_position + *--------------------------------------------------------------------------- + */ +void +gfx_set_icon_position(unsigned long memoffset, unsigned short xpos) +{ +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + gu2_set_icon_position(memoffset, xpos); +#endif +} + +/*--------------------------------------------------------------------------- + * gfx_set_icon_shape64 + *--------------------------------------------------------------------------- + */ +void +gfx_set_icon_shape64(unsigned long memoffset, + unsigned long *andmask, unsigned long *xormask, unsigned int lines) +{ +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + gu2_set_icon_shape64(memoffset, andmask, xormask, lines); +#endif +} + +/*--------------------------------------------------------------------------- + * gfx_set_compression_enable + *--------------------------------------------------------------------------- + */ +int +gfx_set_compression_enable(int enable) +{ + int status = 0; + +#if GFX_DISPLAY_GU1 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU1) + status = gu1_set_compression_enable(enable); +#endif +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + status = gu2_set_compression_enable(enable); +#endif +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + status = gu3_set_compression_enable(enable); +#endif + return (status); +} + +/*--------------------------------------------------------------------------- + * gfx_set_compression_offset + *--------------------------------------------------------------------------- + */ +int +gfx_set_compression_offset(unsigned long offset) +{ + int status = 0; + +#if GFX_DISPLAY_GU1 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU1) + status = gu1_set_compression_offset(offset); +#endif +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + status = gu2_set_compression_offset(offset); +#endif +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + status = gu3_set_compression_offset(offset); +#endif + return (status); +} + +/*--------------------------------------------------------------------------- + * gfx_set_compression_pitch + *--------------------------------------------------------------------------- + */ +int +gfx_set_compression_pitch(unsigned short pitch) +{ + int status = 0; + +#if GFX_DISPLAY_GU1 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU1) + status = gu1_set_compression_pitch(pitch); +#endif +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + status = gu2_set_compression_pitch(pitch); +#endif +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + status = gu3_set_compression_pitch(pitch); +#endif + return (status); +} + +/*--------------------------------------------------------------------------- + * gfx_set_compression_size + *--------------------------------------------------------------------------- + */ +int +gfx_set_compression_size(unsigned short size) +{ + int status = 0; + +#if GFX_DISPLAY_GU1 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU1) + status = gu1_set_compression_size(size); +#endif +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + status = gu2_set_compression_size(size); +#endif +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + status = gu3_set_compression_size(size); +#endif + return (status); +} + +/*--------------------------------------------------------------------------- + * gfx_set_display_priority_high + *--------------------------------------------------------------------------- + */ +void +gfx_set_display_priority_high(int enable) +{ +#if GFX_DISPLAY_GU1 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU1) + gu1_set_display_priority_high(enable); +#endif +} + +/*--------------------------------------------------------------------------- + * 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. + *--------------------------------------------------------------------------- + */ +void +gfx_set_display_video_format(unsigned long format) +{ +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + gu2_set_display_video_format(format); +#endif +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + gu3_set_display_video_format(format); +#endif +} + +/*--------------------------------------------------------------------------- + * 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. + *--------------------------------------------------------------------------- + */ +void +gfx_set_display_video_color_key(unsigned long key, unsigned long mask, + int enable) +{ +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + gu3_set_display_video_color_key(key, mask, enable); +#endif +} + +/*--------------------------------------------------------------------------- + * 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. + *--------------------------------------------------------------------------- + */ +void +gfx_set_display_video_enable(int enable) +{ +#if GFX_DISPLAY_GU1 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU1) + gu1_set_display_video_enable(enable); +#endif +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + gu2_set_display_video_enable(enable); +#endif +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + gu3_set_display_video_enable(enable); +#endif + return; +} + +/*--------------------------------------------------------------------------- + * 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. + *--------------------------------------------------------------------------- + */ +void +gfx_set_display_video_size(unsigned short width, unsigned short height) +{ +#if GFX_DISPLAY_GU1 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU1) + gu1_set_display_video_size(width, height); +#endif +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + gu2_set_display_video_size(width, height); +#endif +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + gu3_set_display_video_size(width, height); +#endif +} + +/*--------------------------------------------------------------------------- + * 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. + *--------------------------------------------------------------------------- + */ +void +gfx_set_display_video_offset(unsigned long offset) +{ +#if GFX_DISPLAY_GU1 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU1) + gu1_set_display_video_offset(offset); +#endif +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + gu2_set_display_video_offset(offset); +#endif +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + gu3_set_display_video_offset(offset); +#endif +} + +/*--------------------------------------------------------------------------- + * 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. + *--------------------------------------------------------------------------- + */ +void +gfx_set_display_video_yuv_offsets(unsigned long yoffset, + unsigned long uoffset, unsigned long voffset) +{ +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + gu2_set_display_video_yuv_offsets(yoffset, uoffset, voffset); +#endif +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + gu3_set_display_video_yuv_offsets(yoffset, uoffset, voffset); +#endif +} + +/*--------------------------------------------------------------------------- + * 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. + *--------------------------------------------------------------------------- + */ +void +gfx_set_display_video_yuv_pitch(unsigned long ypitch, unsigned long uvpitch) +{ +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + gu2_set_display_video_yuv_pitch(ypitch, uvpitch); +#endif +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + gu3_set_display_video_yuv_pitch(ypitch, uvpitch); +#endif +} + +/*--------------------------------------------------------------------------- + * gfx_set_display_video_downscale (PRIVATE ROUTINE - NOT PART OF API) + * + * This routine is called by "gfx_set_video_vertical_downscale". It abstracts the + * version of the display controller from the video overlay routines. + *--------------------------------------------------------------------------- + */ +void +gfx_set_display_video_downscale(unsigned short srch, unsigned short dsth) +{ +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + gu2_set_display_video_downscale(srch, dsth); +#endif +} + +/*--------------------------------------------------------------------------- + * gfx_set_display_video_vertical_downscale_enable (PRIVATE ROUTINE - NOT PART OF API) + * + * This routine is called by "gfx_set_video_vertical_downscale_enable". It abstracts the + * version of the display controller from the video overlay routines. + *--------------------------------------------------------------------------- + */ +void +gfx_set_display_video_vertical_downscale_enable(int enable) +{ +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + gu2_set_display_video_vertical_downscale_enable(enable); +#endif +} + +/*--------------------------------------------------------------------------- + * gfx_test_timing_active + *--------------------------------------------------------------------------- + */ +int +gfx_test_timing_active(void) +{ + int status = 0; + +#if GFX_DISPLAY_GU1 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU1) + status = gu1_test_timing_active(); +#endif +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + status = gu2_test_timing_active(); +#endif +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + status = gu3_test_timing_active(); +#endif + return (status); +} + +/*--------------------------------------------------------------------------- + * gfx_test_vertical_active + *--------------------------------------------------------------------------- + */ +int +gfx_test_vertical_active(void) +{ + int status = 0; + +#if GFX_DISPLAY_GU1 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU1) + status = gu1_test_vertical_active(); +#endif +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + status = gu2_test_vertical_active(); +#endif +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + status = gu3_test_vertical_active(); +#endif + return (status); +} + +/*--------------------------------------------------------------------------- + * gfx_wait_vertical_blank + *--------------------------------------------------------------------------- + */ +int +gfx_wait_vertical_blank(void) +{ + int status = 0; + +#if GFX_DISPLAY_GU1 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU1) + status = gu1_wait_vertical_blank(); +#endif +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + status = gu2_wait_vertical_blank(); +#endif +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + status = gu3_wait_vertical_blank(); +#endif + return (status); +} + +/*--------------------------------------------------------------------------- + * gfx_delay_milliseconds + *--------------------------------------------------------------------------- + */ +void +gfx_delay_milliseconds(unsigned long milliseconds) +{ +#if GFX_DISPLAY_GU1 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU1) + gu1_delay_milliseconds(milliseconds); +#endif +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + gu2_delay_milliseconds(milliseconds); +#endif +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + gu3_delay_milliseconds(milliseconds); +#endif +} + +/*--------------------------------------------------------------------------- + * gfx_delay_microseconds + *--------------------------------------------------------------------------- + */ +void +gfx_delay_microseconds(unsigned long microseconds) +{ +#if GFX_DISPLAY_GU1 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU1) + gu1_delay_microseconds(microseconds); +#endif +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + gu2_delay_microseconds(microseconds); +#endif +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + gu3_delay_microseconds(microseconds); +#endif +} + +/*--------------------------------------------------------------------------- + * gfx_enable_panning + * + * This routine enables the panning when the Mode is bigger than the panel + * size. + *--------------------------------------------------------------------------- + */ +void +gfx_enable_panning(int x, int y) +{ +#if GFX_DISPLAY_GU1 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU1) + gu1_enable_panning(x, y); +#endif +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + gu2_enable_panning(x, y); +#endif +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + gu3_enable_panning(x, y); +#endif +} + +/*--------------------------------------------------------------------------- + * gfx_is_panel_mode_supported + *--------------------------------------------------------------------------- + */ +int +gfx_is_panel_mode_supported(int panelResX, int panelResY, + unsigned short width, unsigned short height, unsigned short bpp) +{ + int status = -1; + +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + status = + gu2_is_panel_mode_supported(panelResX, panelResY, width, height, + bpp); +#endif + + return (status); +} + +/*--------------------------------------------------------------------------- + * gfx_set_fixed_timings + *--------------------------------------------------------------------------- + */ +int +gfx_set_fixed_timings(int panelResX, int panelResY, unsigned short width, + unsigned short height, unsigned short bpp) +{ + int status = 0; + +#if GFX_DISPLAY_GU1 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU1) + status = + gu1_set_fixed_timings(panelResX, panelResY, width, height, bpp); +#endif +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + status = + gu2_set_fixed_timings(panelResX, panelResY, width, height, bpp); +#endif +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + status = + gu3_set_fixed_timings(panelResX, panelResY, width, height, bpp); +#endif + return (status); +} + +/*--------------------------------------------------------------------------- + * gfx_set_panel_present + *--------------------------------------------------------------------------- + */ +int +gfx_set_panel_present(int panelResX, int panelResY, unsigned short width, + unsigned short height, unsigned short bpp) +{ + int status = 0; + +#if GFX_DISPLAY_GU1 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU1) + status = + gu1_set_panel_present(panelResX, panelResY, width, height, bpp); +#endif +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + status = + gu2_set_panel_present(panelResX, panelResY, width, height, bpp); +#endif +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + status = + gu3_set_panel_present(panelResX, panelResY, width, height, bpp); +#endif + return (status); +} + +/*--------------------------------------------------------------------------- + * gfx_set_vtotal + *--------------------------------------------------------------------------- + */ +int +gfx_set_vtotal(unsigned short vtotal) +{ + int retval = 0; + +#if GFX_DISPLAY_GU1 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU1) + retval = gu1_set_vtotal(vtotal); +#endif +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + retval = gu2_set_vtotal(vtotal); +#endif +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + retval = gu3_set_vtotal(vtotal); +#endif + return (retval); +} + +/*-----------------------------------------------------------------------* + * THE FOLLOWING READ ROUTINES ARE ALWAYS INCLUDED: * + * gfx_get_hsync_end, gfx_get_htotal, gfx_get_vsync_end, gfx_get_vtotal * + * are used by the video overlay routines. * + * * + * gfx_get_vline and gfx_vactive are used to prevent an issue for the * + * SC1200. * + * * + * The others are part of the Durango API. * + *-----------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- + * gfx_mode_frequency_supported + *---------------------------------------------------------------------------- + */ +int +gfx_mode_frequency_supported(int xres, int yres, int bpp, + unsigned long frequency) +{ + int freq = 0; + +#if GFX_DISPLAY_GU1 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU1) + freq = gu1_mode_frequency_supported(xres, yres, bpp, frequency); +#endif +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + freq = gu2_mode_frequency_supported(xres, yres, bpp, frequency); +#endif +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + freq = gu3_mode_frequency_supported(xres, yres, bpp, frequency); +#endif + return (freq); +} + +/*---------------------------------------------------------------------------- + * gfx_refreshrate_from_frequency + *---------------------------------------------------------------------------- + */ +int +gfx_get_refreshrate_from_frequency(int xres, int yres, int bpp, int *hz, + unsigned long frequency) +{ +#if GFX_DISPLAY_GU1 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU1) + gu1_get_refreshrate_from_frequency(xres, yres, bpp, hz, frequency); +#endif +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + gu2_get_refreshrate_from_frequency(xres, yres, bpp, hz, frequency); +#endif +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + gu3_get_refreshrate_from_frequency(xres, yres, bpp, hz, frequency); +#endif + + return (1); +} + +/*---------------------------------------------------------------------------- + * gfx_refreshrate_from_mode + *---------------------------------------------------------------------------- + */ +int +gfx_get_refreshrate_from_mode(int xres, int yres, int bpp, int *hz, + unsigned long frequency) +{ +#if GFX_DISPLAY_GU1 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU1) + gu1_get_refreshrate_from_mode(xres, yres, bpp, hz, frequency); +#endif +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + gu2_get_refreshrate_from_mode(xres, yres, bpp, hz, frequency); +#endif +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + gu3_get_refreshrate_from_mode(xres, yres, bpp, hz, frequency); +#endif + + return (1); +} + +/*---------------------------------------------------------------------------- + * gfx_get_frequency_from_refreshrate + *---------------------------------------------------------------------------- + */ +int +gfx_get_frequency_from_refreshrate(int xres, int yres, int bpp, int hz, + int *frequency) +{ + int retval = -1; + +#if GFX_DISPLAY_GU1 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU1) + retval = + gu1_get_frequency_from_refreshrate(xres, yres, bpp, hz, + frequency); +#endif +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + retval = + gu2_get_frequency_from_refreshrate(xres, yres, bpp, hz, + frequency); +#endif +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + retval = + gu3_get_frequency_from_refreshrate(xres, yres, bpp, hz, + frequency); +#endif + + return retval; +} + +/*--------------------------------------------------------------------------- + * gfx_get_max_supported_pixel_clock + *--------------------------------------------------------------------------- + */ +unsigned long +gfx_get_max_supported_pixel_clock(void) +{ + unsigned long status = 0; + +#if GFX_DISPLAY_GU1 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU1) + status = gu1_get_max_supported_pixel_clock(); +#endif +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + status = gu2_get_max_supported_pixel_clock(); +#endif +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + status = gu3_get_max_supported_pixel_clock(); +#endif + return (status); +} + +/*--------------------------------------------------------------------------- + * gfx_get_display_pitch + *--------------------------------------------------------------------------- + */ +unsigned short +gfx_get_display_pitch(void) +{ + unsigned short pitch = 0; + +#if GFX_DISPLAY_GU1 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU1) + pitch = gu1_get_display_pitch(); +#endif +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + pitch = gu2_get_display_pitch(); +#endif +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + pitch = gu3_get_display_pitch(); +#endif + return (pitch); +} + +/*--------------------------------------------------------------------------- + * gfx_get_display_mode_count + * return # of modes supported. + *--------------------------------------------------------------------------- + */ +int +gfx_get_display_mode_count(void) +{ + int retval = 0; + +#if GFX_DISPLAY_GU1 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU1) + retval = gu1_get_display_mode_count(); +#endif +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + retval = gu2_get_display_mode_count(); +#endif +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + retval = gu3_get_display_mode_count(); +#endif + return (retval); +} + +/*--------------------------------------------------------------------------- + * gfx_get_frame_buffer_line_size + *--------------------------------------------------------------------------- + */ +unsigned long +gfx_get_frame_buffer_line_size(void) +{ + unsigned long retval = 0; + +#if GFX_DISPLAY_GU1 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU1) + retval = gu1_get_frame_buffer_line_size(); +#endif +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + retval = gu2_get_frame_buffer_line_size(); +#endif +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + retval = gu3_get_frame_buffer_line_size(); +#endif + return (retval); +} + +/*--------------------------------------------------------------------------- + * gfx_get_display_mode + * get the curent mode set, + * return the supported mode on success, -1 on fail + *--------------------------------------------------------------------------- + */ +int +gfx_get_display_mode(int *xres, int *yres, int *bpp, int *hz) +{ + int retval = -1; + +#if GFX_DISPLAY_GU1 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU1) + retval = gu1_get_display_mode(xres, yres, bpp, hz); +#endif +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + retval = gu2_get_display_mode(xres, yres, bpp, hz); +#endif +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + retval = gu3_get_display_mode(xres, yres, bpp, hz); +#endif + return (retval); +} + +/*--------------------------------------------------------------------------- + * gfx_get_display_details + * given the mode get's the resoultion details, width, height, freq + *--------------------------------------------------------------------------- + */ +int +gfx_get_display_details(unsigned int mode, int *xres, int *yres, int *hz) +{ + int retval = -1; + +#if GFX_DISPLAY_GU1 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU1) + retval = gu1_get_display_details(mode, xres, yres, hz); +#endif +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + retval = gu2_get_display_details(mode, xres, yres, hz); +#endif +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + retval = gu3_get_display_details(mode, xres, yres, hz); +#endif + return (retval); +} + +/*--------------------------------------------------------------------------- + * gfx_get_hactive + *--------------------------------------------------------------------------- + */ +unsigned short +gfx_get_hactive(void) +{ + unsigned short hactive = 0; + +#if GFX_DISPLAY_GU1 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU1) + hactive = gu1_get_hactive(); +#endif +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + hactive = gu2_get_hactive(); +#endif +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + hactive = gu3_get_hactive(); +#endif + return (hactive); +} + +/*--------------------------------------------------------------------------- + * gfx_get_hsync_start + *--------------------------------------------------------------------------- + */ +unsigned short +gfx_get_hsync_start(void) +{ + unsigned short hsync_start = 0; + +#if GFX_DISPLAY_GU1 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU1) + hsync_start = gu1_get_hsync_start(); +#endif +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + hsync_start = gu2_get_hsync_start(); +#endif +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + hsync_start = gu3_get_hsync_start(); +#endif + return (hsync_start); +} + +/*--------------------------------------------------------------------------- + * gfx_get_hsync_end + *--------------------------------------------------------------------------- + */ +unsigned short +gfx_get_hsync_end(void) +{ + unsigned short hsync_end = 0; + +#if GFX_DISPLAY_GU1 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU1) + hsync_end = gu1_get_hsync_end(); +#endif +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + hsync_end = gu2_get_hsync_end(); +#endif +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + hsync_end = gu3_get_hsync_end(); +#endif + return (hsync_end); +} + +/*--------------------------------------------------------------------------- + * gfx_get_htotal + *--------------------------------------------------------------------------- + */ +unsigned short +gfx_get_htotal(void) +{ + unsigned short htotal = 0; + +#if GFX_DISPLAY_GU1 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU1) + htotal = gu1_get_htotal(); +#endif +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + htotal = gu2_get_htotal(); +#endif +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + htotal = gu3_get_htotal(); +#endif + return (htotal); +} + +/*--------------------------------------------------------------------------- + * gfx_get_vactive + *--------------------------------------------------------------------------- + */ +unsigned short +gfx_get_vactive(void) +{ + unsigned short vactive = 0; + +#if GFX_DISPLAY_GU1 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU1) + vactive = gu1_get_vactive(); +#endif +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + vactive = gu2_get_vactive(); +#endif +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + vactive = gu3_get_vactive(); +#endif + return (vactive); +} + +/*--------------------------------------------------------------------------- + * gfx_get_vsync_end + *--------------------------------------------------------------------------- + */ +unsigned short +gfx_get_vsync_end(void) +{ + unsigned short vsync_end = 0; + +#if GFX_DISPLAY_GU1 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU1) + vsync_end = gu1_get_vsync_end(); +#endif +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + vsync_end = gu2_get_vsync_end(); +#endif +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + vsync_end = gu3_get_vsync_end(); +#endif + return (vsync_end); +} + +/*--------------------------------------------------------------------------- + * gfx_get_vtotal + *--------------------------------------------------------------------------- + */ +unsigned short +gfx_get_vtotal(void) +{ + unsigned short vtotal = 0; + +#if GFX_DISPLAY_GU1 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU1) + vtotal = gu1_get_vtotal(); +#endif +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + vtotal = gu2_get_vtotal(); +#endif +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + vtotal = gu3_get_vtotal(); +#endif + return (vtotal); +} + +/*--------------------------------------------------------------------------- + * gfx_get_display_bpp + *--------------------------------------------------------------------------- + */ +unsigned short +gfx_get_display_bpp(void) +{ + unsigned short bpp = 0; + +#if GFX_DISPLAY_GU1 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU1) + bpp = gu1_get_display_bpp(); +#endif +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + bpp = gu2_get_display_bpp(); +#endif +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + bpp = gu3_get_display_bpp(); +#endif + return (bpp); +} + +/*--------------------------------------------------------------------------- + * gfx_get_vline + *--------------------------------------------------------------------------- + */ +unsigned short +gfx_get_vline(void) +{ + unsigned short vline = 0; + +#if GFX_DISPLAY_GU1 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU1) + vline = gu1_get_vline(); +#endif +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + vline = gu2_get_vline(); +#endif +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + vline = gu3_get_vline(); +#endif + return (vline); +} + +/*--------------------------------------------------------------------------- + * gfx_get_display_offset + *--------------------------------------------------------------------------- + */ +unsigned long +gfx_get_display_offset(void) +{ + unsigned long offset = 0; + +#if GFX_DISPLAY_GU1 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU1) + offset = gu1_get_display_offset(); +#endif +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + offset = gu2_get_display_offset(); +#endif +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + offset = gu3_get_display_offset(); +#endif + return (offset); +} + +/*--------------------------------------------------------------------------- + * gfx_get_cursor_offset + *--------------------------------------------------------------------------- + */ +unsigned long +gfx_get_cursor_offset(void) +{ + unsigned long base = 0; + +#if GFX_DISPLAY_GU1 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU1) + base = gu1_get_cursor_offset(); +#endif +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + base = gu2_get_cursor_offset(); +#endif +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + base = gu3_get_cursor_offset(); +#endif + return (base); +} + +/*************************************************************/ +/* READ ROUTINES | INCLUDED FOR DIAGNOSTIC PURPOSES ONLY */ +/*************************************************************/ + +#if GFX_READ_ROUTINES + +/*--------------------------------------------------------------------------- + * gfx_get_hblank_start + *--------------------------------------------------------------------------- + */ +unsigned short +gfx_get_hblank_start(void) +{ + unsigned short hblank_start = 0; + +#if GFX_DISPLAY_GU1 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU1) + hblank_start = gu1_get_hblank_start(); +#endif +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + hblank_start = gu2_get_hblank_start(); +#endif +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + hblank_start = gu3_get_hblank_start(); +#endif + return (hblank_start); +} + +/*--------------------------------------------------------------------------- + * gfx_get_hblank_end + *--------------------------------------------------------------------------- + */ +unsigned short +gfx_get_hblank_end(void) +{ + unsigned short hblank_end = 0; + +#if GFX_DISPLAY_GU1 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU1) + hblank_end = gu1_get_hblank_end(); +#endif +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + hblank_end = gu2_get_hblank_end(); +#endif +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + hblank_end = gu3_get_hblank_end(); +#endif + return (hblank_end); +} + +/*--------------------------------------------------------------------------- + * gfx_get_vblank_start + *--------------------------------------------------------------------------- + */ +unsigned short +gfx_get_vblank_start(void) +{ + unsigned short vblank_start = 0; + +#if GFX_DISPLAY_GU1 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU1) + vblank_start = gu1_get_vblank_start(); +#endif +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + vblank_start = gu2_get_vblank_start(); +#endif +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + vblank_start = gu3_get_vblank_start(); +#endif + return (vblank_start); +} + +/*--------------------------------------------------------------------------- + * gfx_get_vsync_start + *--------------------------------------------------------------------------- + */ +unsigned short +gfx_get_vsync_start(void) +{ + unsigned short vsync_start = 0; + +#if GFX_DISPLAY_GU1 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU1) + vsync_start = gu1_get_vsync_start(); +#endif +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + vsync_start = gu2_get_vsync_start(); +#endif +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + vsync_start = gu3_get_vsync_start(); +#endif + return (vsync_start); +} + +/*--------------------------------------------------------------------------- + * gfx_get_vblank_end + *--------------------------------------------------------------------------- + */ +unsigned short +gfx_get_vblank_end(void) +{ + unsigned short vblank_end = 0; + +#if GFX_DISPLAY_GU1 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU1) + vblank_end = gu1_get_vblank_end(); +#endif +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + vblank_end = gu2_get_vblank_end(); +#endif +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + vblank_end = gu3_get_vblank_end(); +#endif + return (vblank_end); +} + +/*--------------------------------------------------------------------------- + * gfx_get_display_palette_entry + *--------------------------------------------------------------------------- + */ +int +gfx_get_display_palette_entry(unsigned long index, unsigned long *palette) +{ + int status = 0; + +#if GFX_DISPLAY_GU1 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU1) + status = gu1_get_display_palette_entry(index, palette); +#endif +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + status = gu2_get_display_palette_entry(index, palette); +#endif +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + status = gu3_get_display_palette_entry(index, palette); +#endif + + return status; +} + +/*--------------------------------------------------------------------------- + * gfx_get_display_palette + *--------------------------------------------------------------------------- + */ +void +gfx_get_display_palette(unsigned long *palette) +{ +#if GFX_DISPLAY_GU1 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU1) + gu1_get_display_palette(palette); +#endif +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + gu2_get_display_palette(palette); +#endif +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + gu3_get_display_palette(palette); +#endif +} + +/*--------------------------------------------------------------------------- + * gfx_get_cursor_enable + *--------------------------------------------------------------------------- + */ +unsigned long +gfx_get_cursor_enable(void) +{ + unsigned long enable = 0; + +#if GFX_DISPLAY_GU1 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU1) + enable = gu1_get_cursor_enable(); +#endif +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + enable = gu2_get_cursor_enable(); +#endif +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + enable = gu3_get_cursor_enable(); +#endif + return (enable); +} + +/*--------------------------------------------------------------------------- + * gfx_get_cursor_position + *--------------------------------------------------------------------------- + */ +unsigned long +gfx_get_cursor_position(void) +{ + unsigned long position = 0; + +#if GFX_DISPLAY_GU1 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU1) + position = gu1_get_cursor_position(); +#endif +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + position = gu2_get_cursor_position(); +#endif +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + position = gu3_get_cursor_position(); +#endif + return (position); +} + +/*--------------------------------------------------------------------------- + * gfx_get_cursor_clip + *--------------------------------------------------------------------------- + */ +unsigned long +gfx_get_cursor_clip(void) +{ + unsigned long offset = 0; + +#if GFX_DISPLAY_GU1 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU1) + offset = gu1_get_cursor_clip(); +#endif +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + offset = gu2_get_cursor_clip(); +#endif +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + offset = gu3_get_cursor_clip(); +#endif + return (offset); +} + +/*--------------------------------------------------------------------------- + * gfx_get_cursor_color + *--------------------------------------------------------------------------- + */ +unsigned long +gfx_get_cursor_color(int index) +{ + unsigned long color = 0; + +#if GFX_DISPLAY_GU1 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU1) + color = gu1_get_cursor_color(index); +#endif +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + color = gu2_get_cursor_color(index); +#endif +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + color = gu3_get_cursor_color(index); +#endif + return (color); +} + +/*--------------------------------------------------------------------------- + * gfx_get_icon_enable + *--------------------------------------------------------------------------- + */ +unsigned long +gfx_get_icon_enable(void) +{ + unsigned long enable = 0; + +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + enable = gu2_get_icon_enable(); +#endif + return (enable); +} + +/*--------------------------------------------------------------------------- + * gfx_get_icon_offset + *--------------------------------------------------------------------------- + */ +unsigned long +gfx_get_icon_offset(void) +{ + unsigned long base = 0; + +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + base = gu2_get_icon_offset(); +#endif + + return (base); +} + +/*--------------------------------------------------------------------------- + * gfx_get_icon_position + *--------------------------------------------------------------------------- + */ +unsigned long +gfx_get_icon_position(void) +{ + unsigned long position = 0; + +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + position = gu2_get_icon_position(); +#endif + + return (position); +} + +/*--------------------------------------------------------------------------- + * gfx_get_icon_color + *--------------------------------------------------------------------------- + */ +unsigned long +gfx_get_icon_color(int index) +{ + unsigned long color = 0; + +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + color = gu2_get_icon_color(index); +#endif + + return (color); +} + +/*--------------------------------------------------------------------------- + * gfx_get_compression_enable + *--------------------------------------------------------------------------- + */ +int +gfx_get_compression_enable(void) +{ + int enable = 0; + +#if GFX_DISPLAY_GU1 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU1) + enable = gu1_get_compression_enable(); +#endif +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + enable = gu2_get_compression_enable(); +#endif +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + enable = gu3_get_compression_enable(); +#endif + return (enable); +} + +/*--------------------------------------------------------------------------- + * gfx_get_compression_offset + *--------------------------------------------------------------------------- + */ +unsigned long +gfx_get_compression_offset(void) +{ + unsigned long offset = 0; + +#if GFX_DISPLAY_GU1 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU1) + offset = gu1_get_compression_offset(); +#endif +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + offset = gu2_get_compression_offset(); +#endif +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + offset = gu3_get_compression_offset(); +#endif + return (offset); +} + +/*--------------------------------------------------------------------------- + * gfx_get_compression_pitch + *--------------------------------------------------------------------------- + */ +unsigned short +gfx_get_compression_pitch(void) +{ + unsigned short pitch = 0; + +#if GFX_DISPLAY_GU1 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU1) + pitch = gu1_get_compression_pitch(); +#endif +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + pitch = gu2_get_compression_pitch(); +#endif +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + pitch = gu3_get_compression_pitch(); +#endif + return (pitch); +} + +/*--------------------------------------------------------------------------- + * gfx_get_compression_size + *--------------------------------------------------------------------------- + */ +unsigned short +gfx_get_compression_size(void) +{ + unsigned short size = 0; + +#if GFX_DISPLAY_GU1 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU1) + size = gu1_get_compression_size(); +#endif +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + size = gu2_get_compression_size(); +#endif +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + size = gu3_get_compression_size(); +#endif + return (size); +} + +/*--------------------------------------------------------------------------- + * gfx_get_display_priority_high + *--------------------------------------------------------------------------- + */ +int +gfx_get_display_priority_high(void) +{ + int high = GFX_STATUS_UNSUPPORTED; + +#if GFX_DISPLAY_GU1 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU1) + high = gu1_get_display_priority_high(); +#endif + return (high); +} + +/*--------------------------------------------------------------------------- + * gfx_get_valid_bit + *--------------------------------------------------------------------------- + */ +int +gfx_get_valid_bit(int line) +{ + int valid = 0; + +#if GFX_DISPLAY_GU1 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU1) + valid = gu1_get_valid_bit(line); +#endif +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + valid = gu2_get_valid_bit(line); +#endif +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + valid = gu3_get_valid_bit(line); +#endif + return (valid); +} + +/*--------------------------------------------------------------------------- + * gfx_get_display_video_color_key + *--------------------------------------------------------------------------- + */ +unsigned long +gfx_get_display_video_color_key(void) +{ + unsigned long value = 0; + +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + value = gu3_get_display_video_color_key(); +#endif + return (value); +} + +/*--------------------------------------------------------------------------- + * gfx_get_display_video_offset + *--------------------------------------------------------------------------- + */ +unsigned long +gfx_get_display_video_offset(void) +{ + unsigned long offset = 0; + +#if GFX_DISPLAY_GU1 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU1) + offset = gu1_get_display_video_offset(); +#endif +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + offset = gu2_get_display_video_offset(); +#endif +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + offset = gu3_get_display_video_offset(); +#endif + return (offset); +} + +/*--------------------------------------------------------------------------- + * gfx_get_display_video_yuv_offsets + *--------------------------------------------------------------------------- + */ +void +gfx_get_display_video_yuv_offsets(unsigned long *yoffset, + unsigned long *uoffset, unsigned long *voffset) +{ +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + gu2_get_display_video_yuv_offsets(yoffset, uoffset, voffset); +#endif +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + gu3_get_display_video_yuv_offsets(yoffset, uoffset, voffset); +#endif +} + +/*--------------------------------------------------------------------------- + * gfx_get_display_video_yuv_offsets + *--------------------------------------------------------------------------- + */ +void +gfx_get_display_video_yuv_pitch(unsigned long *ypitch, unsigned long *uvpitch) +{ +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + gu2_get_display_video_yuv_pitch(ypitch, uvpitch); +#endif +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + gu3_get_display_video_yuv_pitch(ypitch, uvpitch); +#endif +} + +/*--------------------------------------------------------------------------- + * gfx_get_display_video_downscale_delta + *--------------------------------------------------------------------------- + */ +unsigned long +gfx_get_display_video_downscale_delta(void) +{ + unsigned long ret_value = 0; + +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + ret_value = gu2_get_display_video_downscale_delta(); +#endif + + return ret_value; +} + +/*--------------------------------------------------------------------------- + * gfx_get_display_video_downscale_delta + *--------------------------------------------------------------------------- + */ +int +gfx_get_display_video_downscale_enable(void) +{ + int ret_value = 0; + +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + ret_value = gu2_get_display_video_downscale_enable(); +#endif + + return ret_value; +} + +/*--------------------------------------------------------------------------- + * gfx_get_display_video_size + *--------------------------------------------------------------------------- + */ +unsigned long +gfx_get_display_video_size(void) +{ + unsigned long size = 0; + +#if GFX_DISPLAY_GU1 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU1) + size = gu1_get_display_video_size(); +#endif +#if GFX_DISPLAY_GU2 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU2) + size = gu2_get_display_video_size(); +#endif +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + size = gu3_get_display_video_size(); +#endif + return (size); +} + +/*--------------------------------------------------------------------------- + * gfx_get_display_video_color_key_mask + *--------------------------------------------------------------------------- + */ +unsigned long +gfx_get_display_video_color_key_mask(void) +{ + unsigned long mask = 0; + +#if GFX_DISPLAY_GU3 + if (gfx_display_type & GFX_DISPLAY_TYPE_GU3) + mask = gu3_get_display_video_color_key_mask(); +#endif + return (mask); +} + +#endif /* GFX_READ_ROUTINES */ + +#endif /* GFX_DISPLAY_DYNAMIC */ + +/* END OF FILE */ diff --git a/src/gfx/gfx_i2c.c b/src/gfx/gfx_i2c.c new file mode 100644 index 0000000..7a3ad42 --- /dev/null +++ b/src/gfx/gfx_i2c.c @@ -0,0 +1,168 @@ +/* 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 to write to and read from the I2C bus. + * */ + +/* INCLUDE ROUTINES FOR ACCESS.BUS, IF SPECIFIED */ +/* This is for SC1200 systems. */ + +#if GFX_I2C_ACCESS +#include "i2c_acc.c" +#endif + +/* INCLUDE ROUTINES FOR CS5530 GPIOs, IF SPECIFIED */ +/* This is for GXLV systems that use GPIOs on the CS5530 for I2C. */ + +#if GFX_I2C_GPIO +#include "i2c_gpio.c" +#endif + +/* WRAPPERS IF DYNAMIC SELECTION */ +/* Extra layer to call either ACCESS.bus or GPIO routines. */ + +#if GFX_I2C_DYNAMIC + +/*--------------------------------------------------------------------------- + * gfx_i2c_reset + *--------------------------------------------------------------------------- + */ +int +gfx_i2c_reset(unsigned char busnum, short adr, char freq) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_I2C_ACCESS + if (gfx_i2c_type & GFX_I2C_TYPE_ACCESS) + status = acc_i2c_reset(busnum, adr, freq); +#endif +#if GFX_I2C_GPIO + if (gfx_i2c_type & GFX_I2C_TYPE_GPIO) + status = gpio_i2c_reset(busnum, adr, freq); +#endif + return (status); +} + +/*--------------------------------------------------------------------------- + * gfx_i2c_select_gpio + *--------------------------------------------------------------------------- + */ +int +gfx_i2c_select_gpio(int clock, int data) +{ +#if GFX_I2C_ACCESS + if (gfx_i2c_type & GFX_I2C_TYPE_ACCESS) + acc_i2c_select_gpio(clock, data); +#endif +#if GFX_I2C_GPIO + if (gfx_i2c_type & GFX_I2C_TYPE_GPIO) + gpio_i2c_select_gpio(clock, data); +#endif + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_i2c_write + *--------------------------------------------------------------------------- + */ +int +gfx_i2c_write(unsigned char busnum, unsigned char chipadr, + unsigned char subadr, unsigned char bytes, unsigned char *data) +{ + int status = -1; + +#if GFX_I2C_ACCESS + if (gfx_i2c_type & GFX_I2C_TYPE_ACCESS) + status = acc_i2c_write(busnum, chipadr, subadr, bytes, data); +#endif +#if GFX_I2C_GPIO + if (gfx_i2c_type & GFX_I2C_TYPE_GPIO) + status = gpio_i2c_write(busnum, chipadr, subadr, bytes, data); +#endif + return (status); +} + +/*--------------------------------------------------------------------------- + * gfx_i2c_read + *--------------------------------------------------------------------------- + */ +int +gfx_i2c_read(unsigned char busnum, unsigned char chipadr, + unsigned char subadr, unsigned char bytes, unsigned char *data) +{ + int status = -1; + +#if GFX_I2C_ACCESS + if (gfx_i2c_type & GFX_I2C_TYPE_ACCESS) + status = acc_i2c_read(busnum, chipadr, subadr, bytes, data); +#endif +#if GFX_I2C_GPIO + if (gfx_i2c_type & GFX_I2C_TYPE_GPIO) + status = gpio_i2c_read(busnum, chipadr, subadr, bytes, data); +#endif + return (status); +} + +/*--------------------------------------------------------------------------- + * gfx_i2c_init + *--------------------------------------------------------------------------- + */ +int +gfx_i2c_init(void) +{ + int status = -1; + +#if GFX_I2C_ACCESS + if (gfx_i2c_type & GFX_I2C_TYPE_ACCESS) + status = acc_i2c_init(); +#endif +#if GFX_I2C_GPIO + if (gfx_i2c_type & GFX_I2C_TYPE_GPIO) + status = gpio_i2c_init(); +#endif + return (status); +} + +/*--------------------------------------------------------------------------- + * gfx_i2c_cleanup + *--------------------------------------------------------------------------- + */ +void +gfx_i2c_cleanup(void) +{ +#if GFX_I2C_ACCESS + if (gfx_i2c_type & GFX_I2C_TYPE_ACCESS) + acc_i2c_cleanup(); +#endif +#if GFX_I2C_GPIO + if (gfx_i2c_type & GFX_I2C_TYPE_GPIO) + gpio_i2c_cleanup(); +#endif +} + +#endif /* GFX_I2C_DYNAMIC */ + +/* END OF FILE */ diff --git a/src/gfx/gfx_init.c b/src/gfx/gfx_init.c new file mode 100644 index 0000000..73a8c80 --- /dev/null +++ b/src/gfx/gfx_init.c @@ -0,0 +1,731 @@ +/* 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 typically used in driver initialization. + * + * Routines: + * + * gfx_pci_config_read + * gfx_cpu_config_read + * gfx_detect_cpu + * gfx_detect_video + * gfx_get_cpu_register_base + * gfx_get_frame_buffer_base + * gfx_get_frame_buffer_size + * gfx_get_vid_register_base + * gfx_get_vip_register_base + * */ + +/* CONSTANTS USED BY THE INITIALIZATION CODE */ + +#define PCI_CONFIG_ADDR 0x0CF8 +#define PCI_CONFIG_DATA 0x0CFC +#define PCI_VENDOR_DEVICE_GXM 0x00011078 +#define PCI_VENDOR_DEVICE_REDCLOUD 0x0028100B +#define REDCLOUD_VIDEO_PCI_VENDOR_DEVICE 0x0030100B +#define PCI_VENDOR_DEVICE_CASTLE 0x20801022 +#define CASTLE_VIDEO_PCI_VENDOR_DEVICE 0x20811022 + +#define GXM_CONFIG_GCR 0xB8 +#define GXM_CONFIG_CCR3 0xC3 +#define GXM_CONFIG_DIR0 0xFE +#define GXM_CONFIG_DIR1 0xFF + +/* STATIC VARIABLES FOR THIS FILE */ + +unsigned long gfx_cpu_version = 0; +unsigned long gfx_cpu_frequency = 0; +unsigned long gfx_vid_version = 0; +unsigned long gfx_gx1_scratch_base = 0; +unsigned long gfx_gx2_scratch_base = 0x7FC000; +unsigned long gfx_pci_speed_khz = 33300; +ChipType gfx_chip_revision = CHIP_NOT_DETECTED; + +ChipType gfx_detect_chip(void); + +/* INCLUDE SUPPORT FOR FIRST GENERATION, IF SPECIFIED. */ + +#if GFX_INIT_GU1 +#include "init_gu1.c" +#endif + +/* INCLUDE SUPPORT FOR SECOND GENERATION, IF SPECIFIED. */ + +#if GFX_INIT_GU2 +#include "init_gu2.c" +#endif + +/* INCLUDE SUPPORT FOR THIRD GENERATION, IF SPECIFIED. */ + +#if GFX_INIT_GU3 +#include "init_gu3.c" +#endif + +/* THE FOLLOWING ROUTINES ARE NEVER DYNAMIC */ +/* They are used to set the variables for future dynamic */ +/* function calls. */ + +/*---------------------------------------------------------------------------- + * gfx_detect_chip + * + * This routine returns the name and revision of the chip. This function is + * only relevant to the SC1200. + *---------------------------------------------------------------------------- + */ +ChipType +gfx_detect_chip(void) +{ + unsigned char pid = INB(SC1200_CB_BASE_ADDR + SC1200_CB_PID); + unsigned char rev = INB(SC1200_CB_BASE_ADDR + SC1200_CB_REV); + unsigned short clk = INW(SC1200_CB_BASE_ADDR + SC1200_CB_CCFC); + + gfx_chip_revision = CHIP_NOT_DETECTED; + + if (pid == 0x4) { + switch (rev) { + case 0: + gfx_chip_revision = SC1200_REV_A; + break; + case 1: + gfx_chip_revision = SC1200_REV_B1_B2; + break; + case 2: + gfx_chip_revision = SC1200_REV_B3; + break; + case 3: + gfx_chip_revision = SC1200_REV_C1; + break; + case 4: + gfx_chip_revision = SC1200_REV_D1; + break; + case 5: + gfx_chip_revision = SC1200_REV_D1_1; + break; + case 6: + gfx_chip_revision = SC1200_REV_D2_MVD; + break; + } + if (rev > 0x6) + gfx_chip_revision = SC1200_FUTURE_REV; + } else if (pid == 0x5) { + if (rev == 0x6) + gfx_chip_revision = SC1200_REV_D2_MVE; + else if (rev > 0x6) + gfx_chip_revision = SC1200_FUTURE_REV; + } + + switch ((clk >> 8) & 3) { + case 0: + default: + gfx_pci_speed_khz = 33300; + break; + case 1: + gfx_pci_speed_khz = 48000; + break; + case 2: + gfx_pci_speed_khz = 66600; + break; + } + + return (gfx_chip_revision); +} + +/*---------------------------------------------------------------------------- + * gfx_detect_cpu + * + * This routine returns the type and revison of the CPU. If a Geode + * processor is not present, the routine returns zero. + * + * The return value is as follows: + * bits[24:16] = minor version + * bits[15:8] = major version + * bits[7:0] = type (1 = GXm, 2 = SC1200, 3 = Redcloud) + * + * A return value of 0x00020501, for example, indicates GXm version 5.2. + *---------------------------------------------------------------------------- + */ +unsigned long +gfx_detect_cpu(void) +{ + + unsigned long value = 0; + unsigned long version = 0; + + /* initialize core freq. to 0 */ + gfx_cpu_frequency = 0; + +#if GFX_INIT_GU1 + + value = gfx_pci_config_read(0x80000000); + + if (value == PCI_VENDOR_DEVICE_GXM) { + unsigned char dir0 = gfx_gxm_config_read(GXM_CONFIG_DIR0) & 0xF0; + unsigned char dir1 = gfx_gxm_config_read(GXM_CONFIG_DIR1); + + if (dir0 == 0x40) { + /* CHECK FOR GXLV (and GXm) (DIR1 = 0x30 THROUGH 0x82) */ + + if ((dir1 >= 0x30) && (dir1 <= 0x82)) { + /* Major version is one less than what appears in DIR1 */ + if ((dir1 & 0xF0) < 0x70) { + + version = GFX_CPU_GXLV | (((((unsigned long)dir1 >> 4) - 1) << 8)) | /* major - 1 */ + ((((unsigned long)dir1 & 0x0F)) << 16); /* minor */ + } else { + version = GFX_CPU_GXLV | ((((unsigned long)dir1 >> 4)) + << 8) | /* major */ + ((((unsigned long)dir1 & 0x0F)) << 16); /* minor */ + } + /* Currently always CS5530 for video overlay. */ + +#if GFX_VIDEO_DYNAMIC + gfx_video_type = GFX_VIDEO_TYPE_CS5530; +#endif + + /* Currently always CS5530 GPIOs for I2C access. */ + +#if GFX_I2C_DYNAMIC + gfx_i2c_type = GFX_I2C_TYPE_GPIO; +#endif + +#if GFX_TV_DYNAMIC + gfx_tv_type = GFX_TV_TYPE_FS451; +#endif + } + } else if (dir0 == 0xB0) { + /* CHECK FOR SC1200 */ + + if ((dir1 == 0x70) || (dir1 == 0x81)) { + version = GFX_CPU_SC1200 | ((((unsigned long)dir1 >> 4)) + << 8) | /* major */ + ((((unsigned long)dir1 & 0x0F)) << 16); /* minor */ + + /* Detect SC1200 revision */ + + gfx_detect_chip(); + + /* SC1200 for video overlay and VIP. */ + +#if GFX_VIDEO_DYNAMIC + gfx_video_type = GFX_VIDEO_TYPE_SC1200; +#endif + +#if GFX_VIP_DYNAMIC + gfx_vip_type = GFX_VIP_TYPE_SC1200; +#endif + + /* Currently always SAA7114 decoder. */ + +#if GFX_DECODER_DYNAMIC + gfx_decoder_type = GFX_DECODER_TYPE_SAA7114; +#endif + + /* SC1200 for TV encoder */ + +#if GFX_TV_DYNAMIC + gfx_tv_type = GFX_TV_TYPE_SC1200; +#endif + + /* Currently always ACCESS.bus for I2C access. */ + +#if GFX_I2C_DYNAMIC + gfx_i2c_type = GFX_I2C_TYPE_ACCESS; +#endif + } + } + + if (version) { + /* ALWAYS FIRST GENERATION GRAPHICS UNIT */ + +#if GFX_DISPLAY_DYNAMIC + gfx_display_type = GFX_DISPLAY_TYPE_GU1; +#endif +#if GFX_2DACCEL_DYNAMIC + gfx_2daccel_type = GFX_2DACCEL_TYPE_GU1; +#endif +#if GFX_INIT_DYNAMIC + gfx_init_type = GFX_INIT_TYPE_GU1; +#endif + + /* READ THE CORE FREQUENCY */ + + gfx_cpu_frequency = gfx_get_core_freq(); + } + } +#endif + +#if GFX_INIT_GU2 + + value = gfx_pci_config_read(0x80000800); + + if (value == PCI_VENDOR_DEVICE_REDCLOUD) { + Q_WORD msr_value; + int valid, i; + + /* CHECK FOR SOFT VG */ + /* If SoftVG is not present, the base addresses for all devices */ + /* will not be allocated. Essentially, it is as if no Redcloud */ + /* video hardware is present. */ + + value = gfx_pci_config_read(0x80000900); + + if (value == REDCLOUD_VIDEO_PCI_VENDOR_DEVICE) { + valid = 1; + + /* BAR0 - BAR3 HOLD THE PERIPHERAL BASE ADDRESSES */ + + for (i = 0; i < 4; i++) { + value = gfx_pci_config_read(0x80000910 + (i << 2)); + if (value == 0x00000000 || value == 0xFFFFFFFF) { + valid = 0; + break; + } + } + + if (valid) { + /* REDCLOUD INTEGRATED VIDEO */ + +#if GFX_VIDEO_DYNAMIC + gfx_video_type = GFX_VIDEO_TYPE_REDCLOUD; +#endif + + /* CURRENTLY, ALWAYS GPIO FOR I2C ACCESS */ + +#if GFX_I2C_DYNAMIC + gfx_i2c_type = GFX_I2C_TYPE_GPIO; +#endif + + /* SECOND-GENERATION DISPLAY CONTROLLER */ + +#if GFX_DISPLAY_DYNAMIC + gfx_display_type = GFX_DISPLAY_TYPE_GU2; +#endif + + /* SECOND-GENERATION GRAPHICS UNIT */ + +#if GFX_2DACCEL_DYNAMIC + gfx_2daccel_type = GFX_2DACCEL_TYPE_GU2; +#endif + + /* SECOND-GENERATION INITIALIZATION */ + +#if GFX_INIT_DYNAMIC + gfx_init_type = GFX_INIT_TYPE_GU2; +#endif + + /* MBUS MSR ACCESSES */ + +#if GFX_MSR_DYNAMIC + gfx_msr_type = GFX_MSR_TYPE_REDCLOUD; +#endif + + /* CS5530 GPIO I2C */ + +#if GFX_I2C_DYNAMIC + gfx_i2c_type = GFX_I2C_TYPE_GPIO; +#endif + + /* READ VERSION */ + + gfx_msr_init(); + + gfx_msr_read(RC_ID_MCP, MCP_RC_REVID, &msr_value); + + /* SUBTRACT 1 FROM REV ID */ + /* REDCLOUD 1.X rev id is 1 less than the reported value */ + + if ((msr_value.low & 0xF0) == 0x10) + msr_value.low--; + + version = GFX_CPU_REDCLOUD | ((msr_value.low & 0xF0) << 4) | /* MAJOR */ + ((msr_value.low & 0x0F) << 16); /* MINOR */ + + /* READ THE CORE FREQUENCY */ + + gfx_cpu_frequency = gfx_get_core_freq(); + + /* SET THE GP SCRATCH AREA */ + /* Color bitmap BLTs use the last 16K of frame buffer space */ + + gfx_gx2_scratch_base = gfx_get_frame_buffer_size() - 0x4000; + } + } + } +#endif + +#if GFX_INIT_GU3 + + value = gfx_pci_config_read(0x80000800); + + if (value == PCI_VENDOR_DEVICE_CASTLE) { + Q_WORD msr_value; + int valid, i; + + /* CHECK FOR SOFT VG */ + /* If SoftVG is not present, the base addresses for all devices */ + + /* will not be allocated. Essentially, it is as if no Redcloud */ + /* video hardware is present. */ + + value = gfx_pci_config_read(0x80000900); + + if (value == CASTLE_VIDEO_PCI_VENDOR_DEVICE) { + valid = 1; + + /* BAR0 - BAR3 HOLD THE PERIPHERAL BASE ADDRESSES */ + + for (i = 0; i < 4; i++) { + value = gfx_pci_config_read(0x80000910 + (i << 2)); + if (value == 0x00000000 || value == 0xFFFFFFFF) { + valid = 0; + break; + } + } + + if (valid) { + /* REDCLOUD INTEGRATED VIDEO */ + +#if GFX_VIDEO_DYNAMIC + gfx_video_type = GFX_VIDEO_TYPE_CASTLE; +#endif + + /* CURRENTLY, ALWAYS GPIO FOR I2C ACCESS */ + +#if GFX_I2C_DYNAMIC + gfx_i2c_type = GFX_I2C_TYPE_GPIO; +#endif + + /* THIRD-GENERATION DISPLAY CONTROLLER */ + +#if GFX_DISPLAY_DYNAMIC + gfx_display_type = GFX_DISPLAY_TYPE_GU3; +#endif + + /* SECOND-GENERATION GRAPHICS UNIT */ + +#if GFX_2DACCEL_DYNAMIC + gfx_2daccel_type = GFX_2DACCEL_TYPE_GU2; +#endif + + /* THIRD-GENERATION INITIALIZATION */ + +#if GFX_INIT_DYNAMIC + gfx_init_type = GFX_INIT_TYPE_GU3; +#endif + + /* MBUS MSR ACCESSES */ + +#if GFX_MSR_DYNAMIC + gfx_msr_type = GFX_MSR_TYPE_REDCLOUD; +#endif + + /* READ VERSION */ + + gfx_msr_init(); + + gfx_msr_read(RC_ID_MCP, MCP_RC_REVID, &msr_value); + + version = GFX_CPU_CASTLE | ((msr_value.low & 0xF0) << 4) | /* MAJOR */ + ((msr_value.low & 0x0F) << 16); /* MINOR */ + + /* READ THE CORE FREQUENCY */ + + gfx_cpu_frequency = gfx_get_core_freq(); + + /* SET THE GP SCRATCH AREA */ + /* Color bitmap BLTs use the last 16K of frame buffer space */ + + gfx_gx2_scratch_base = gfx_get_frame_buffer_size() - 0x4000; + + /* CAP AT 16MB */ + + if (gfx_gx2_scratch_base > 0xFFC000) + gfx_gx2_scratch_base = 0xFFC000; + } + + } + } +#endif + + if (!version) { + /* ALWAYS SECOND GENERATION IF SIMULATING */ + /* For now, that is. This could change. */ + +#if GFX_DISPLAY_DYNAMIC + gfx_display_type = GFX_DISPLAY_TYPE_GU2; +#endif +#if GFX_2DACCEL_DYNAMIC + gfx_2daccel_type = GFX_2DACCEL_TYPE_GU2; +#endif +#if GFX_INIT_DYNAMIC + gfx_init_type = GFX_INIT_TYPE_GU2; +#endif +#if GFX_MSR_DYNAMIC + gfx_msr_type = GFX_MSR_TYPE_REDCLOUD; +#endif +#if GFX_VIDEO_DYNAMIC + gfx_video_type = GFX_VIDEO_TYPE_REDCLOUD; +#endif +#if GFX_I2C_DYNAMIC + gfx_i2c_type = GFX_I2C_TYPE_GPIO; +#endif + } + gfx_cpu_version = version; + + return (version); +} + +/*---------------------------------------------------------------------------- + * gfx_detect_video + * + * This routine returns the type of the video hardware. + * + * The return value is as follows: + * bits[7:0] = type (1 = CS5530, 2 = SC1200, 3 = Redcloud) + * + * Currently this routine does not actually detect any hardware, and bases + * the video hardware entirely on the detected CPU. + *---------------------------------------------------------------------------- + */ +unsigned long +gfx_detect_video(void) +{ + unsigned long version = 0; + + if ((gfx_cpu_version & 0xFF) == GFX_CPU_GXLV) + version = GFX_VID_CS5530; + else if ((gfx_cpu_version & 0xFF) == GFX_CPU_SC1200) + version = GFX_VID_SC1200; + else if ((gfx_cpu_version & 0xFF) == GFX_CPU_REDCLOUD) + version = GFX_VID_REDCLOUD; + else if ((gfx_cpu_version & 0xFF) == GFX_CPU_CASTLE) + version = GFX_VID_CASTLE; + gfx_vid_version = version; + return (version); +} + +/*---------------------------------------------------------------------------- + * gfx_pci_config_read + * + * This routine reads a 32-bit value from the specified location in PCI + * configuration space. + *---------------------------------------------------------------------------- + */ +unsigned long +gfx_pci_config_read(unsigned long address) +{ + unsigned long value = 0xFFFFFFFF; + + OUTD(PCI_CONFIG_ADDR, address); + value = IND(PCI_CONFIG_DATA); + return (value); +} + +/*---------------------------------------------------------------------------- + * gfx_pci_config_write + * + * This routine writes a 32-bit value to the specified location in PCI + * configuration space. + *---------------------------------------------------------------------------- + */ +void +gfx_pci_config_write(unsigned long address, unsigned long data) +{ + OUTD(PCI_CONFIG_ADDR, address); + OUTD(PCI_CONFIG_DATA, data); + return; +} + +/* WRAPPERS IF DYNAMIC SELECTION */ +/* Extra layer to call either first or second generation routines. */ + +#if GFX_INIT_DYNAMIC + +/*---------------------------------------------------------------------------- + * gfx_get_core_freq + *---------------------------------------------------------------------------- + */ +unsigned long +gfx_get_core_freq(void) +{ + unsigned long freq = 0; + +#if GFX_INIT_GU1 + if (gfx_init_type & GFX_INIT_TYPE_GU1) + freq = gu1_get_core_freq(); +#endif +#if GFX_INIT_GU2 + if (gfx_init_type & GFX_INIT_TYPE_GU2) + freq = gu2_get_core_freq(); +#endif +#if GFX_INIT_GU3 + if (gfx_init_type & GFX_INIT_TYPE_GU3) + freq = gu3_get_core_freq(); +#endif + return freq; +} + +/*---------------------------------------------------------------------------- + * gfx_get_cpu_register_base + *---------------------------------------------------------------------------- + */ +unsigned long +gfx_get_cpu_register_base(void) +{ + unsigned long base = 0; + +#if GFX_INIT_GU1 + if (gfx_init_type & GFX_INIT_TYPE_GU1) + base = gu1_get_cpu_register_base(); +#endif +#if GFX_INIT_GU2 + if (gfx_init_type & GFX_INIT_TYPE_GU2) + base = gu2_get_cpu_register_base(); +#endif +#if GFX_INIT_GU3 + if (gfx_init_type & GFX_INIT_TYPE_GU3) + base = gu3_get_cpu_register_base(); +#endif + + return (base); +} + +/*---------------------------------------------------------------------------- + * gfx_get_graphics_register_base + *---------------------------------------------------------------------------- + */ +unsigned long +gfx_get_graphics_register_base(void) +{ + unsigned long base = 0; + +#if GFX_INIT_GU2 + if (gfx_init_type & GFX_INIT_TYPE_GU2) + base = gu2_get_graphics_register_base(); +#endif +#if GFX_INIT_GU3 + if (gfx_init_type & GFX_INIT_TYPE_GU3) + base = gu3_get_graphics_register_base(); +#endif + + return (base); +} + +/*---------------------------------------------------------------------------- + * gfx_get_frame_buffer_base + *---------------------------------------------------------------------------- + */ +unsigned long +gfx_get_frame_buffer_base(void) +{ + unsigned long base = 0; + +#if GFX_INIT_GU1 + if (gfx_init_type & GFX_INIT_TYPE_GU1) + base = gu1_get_frame_buffer_base(); +#endif +#if GFX_INIT_GU2 + if (gfx_init_type & GFX_INIT_TYPE_GU2) + base = gu2_get_frame_buffer_base(); +#endif +#if GFX_INIT_GU3 + if (gfx_init_type & GFX_INIT_TYPE_GU3) + base = gu3_get_frame_buffer_base(); +#endif + + return (base); +} + +/*---------------------------------------------------------------------------- + * gfx_get_frame_buffer_size + *---------------------------------------------------------------------------- + */ +unsigned long +gfx_get_frame_buffer_size(void) +{ + unsigned long size = 0; + +#if GFX_INIT_GU1 + if (gfx_init_type & GFX_INIT_TYPE_GU1) + size = gu1_get_frame_buffer_size(); +#endif +#if GFX_INIT_GU2 + if (gfx_init_type & GFX_INIT_TYPE_GU2) + size = gu2_get_frame_buffer_size(); +#endif +#if GFX_INIT_GU3 + if (gfx_init_type & GFX_INIT_TYPE_GU3) + size = gu3_get_frame_buffer_size(); +#endif + + return size; +} + +/*---------------------------------------------------------------------------- + * gfx_get_vid_register_base + *---------------------------------------------------------------------------- + */ +unsigned long +gfx_get_vid_register_base(void) +{ + unsigned long base = 0; + +#if GFX_INIT_GU1 + if (gfx_init_type & GFX_INIT_TYPE_GU1) + base = gu1_get_vid_register_base(); +#endif +#if GFX_INIT_GU2 + if (gfx_init_type & GFX_INIT_TYPE_GU2) + base = gu2_get_vid_register_base(); +#endif +#if GFX_INIT_GU3 + if (gfx_init_type & GFX_INIT_TYPE_GU3) + base = gu3_get_vid_register_base(); +#endif + + return (base); +} + +/*---------------------------------------------------------------------------- + * gfx_get_vip_register_base + *---------------------------------------------------------------------------- + */ +unsigned long +gfx_get_vip_register_base(void) +{ + unsigned long base = 0; + +#if GFX_INIT_GU1 + if (gfx_init_type & GFX_INIT_TYPE_GU1) + base = gu1_get_vip_register_base(); +#endif + + return (base); +} + +#endif + +/* END OF FILE */ diff --git a/src/gfx/gfx_mode.h b/src/gfx/gfx_mode.h new file mode 100644 index 0000000..f9b42b0 --- /dev/null +++ b/src/gfx/gfx_mode.h @@ -0,0 +1,194 @@ +/* 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 header file contains the mode tables. It is used by the "gfx_disp.c" + * file to set a display mode. + * */ + +#ifndef _gfx_mode_h +#define _gfx_mode_h + +/* MODE FLAGS (BITWISE-OR) */ + +#define GFX_MODE_8BPP 0x00000001 +#define GFX_MODE_12BPP 0x00000002 +#define GFX_MODE_15BPP 0x00000004 +#define GFX_MODE_16BPP 0x00000008 +#define GFX_MODE_24BPP 0x00000010 +#define GFX_MODE_56HZ 0x00000020 +#define GFX_MODE_60HZ 0x00000040 +#define GFX_MODE_70HZ 0x00000080 +#define GFX_MODE_72HZ 0x00000100 +#define GFX_MODE_75HZ 0x00000200 +#define GFX_MODE_85HZ 0x00000400 +#define GFX_MODE_90HZ 0x00000800 +#define GFX_MODE_100HZ 0x00001000 +#define GFX_MODE_NEG_HSYNC 0x00002000 +#define GFX_MODE_NEG_VSYNC 0x00004000 +#define GFX_MODE_PIXEL_DOUBLE 0x00008000 +#define GFX_MODE_LINE_DOUBLE 0x00010000 +#define GFX_MODE_TV_NTSC 0x00020000 +#define GFX_MODE_TV_PAL 0x00040000 +#define GFX_MODE_EXCLUDE_PLL 0x00080000 +#define GFX_MODE_LOCK_TIMING 0x10000000 + +#define gfx_mode_hz_conversion \ + switch (hz) { \ + case 56: \ + hz_flag = GFX_MODE_56HZ; \ + break; \ + case 60: \ + hz_flag = GFX_MODE_60HZ; \ + break; \ + case 70: \ + hz_flag = GFX_MODE_70HZ; \ + break; \ + case 72: \ + hz_flag = GFX_MODE_72HZ; \ + break; \ + case 75: \ + hz_flag = GFX_MODE_75HZ; \ + break; \ + case 85: \ + hz_flag = GFX_MODE_85HZ; \ + break; \ + case 90: \ + hz_flag = GFX_MODE_90HZ; \ + break; \ + case 100: \ + hz_flag = GFX_MODE_100HZ; \ + break; \ + } + +#define gfx_mode_bpp_conversion \ + switch (bpp) { \ + case 8: \ + bpp_flag = GFX_MODE_8BPP; \ + break; \ + case 12: \ + bpp_flag = GFX_MODE_12BPP; \ + break; \ + case 15: \ + bpp_flag = GFX_MODE_15BPP; \ + break; \ + case 16: \ + bpp_flag = GFX_MODE_16BPP; \ + break; \ + case 32: \ + bpp_flag = GFX_MODE_24BPP; \ + break; \ + default: \ + return -1; \ + } + +#define gfx_mode_bpp_conversion_def(bpp) \ + switch (bpp) { \ + case 8: \ + bpp_flag = GFX_MODE_8BPP; \ + break; \ + case 12: \ + bpp_flag = GFX_MODE_12BPP; \ + break; \ + case 15: \ + bpp_flag = GFX_MODE_15BPP; \ + break; \ + case 16: \ + bpp_flag = GFX_MODE_16BPP; \ + break; \ + case 32: \ + bpp_flag = GFX_MODE_24BPP; \ + break; \ + default: \ + bpp_flag = GFX_MODE_8BPP; \ + } + +/* STRUCTURE DEFINITION */ + +typedef struct tagDISPLAYMODE +{ + /* DISPLAY MODE FLAGS */ + /* Specify valid color depths and the refresh rate. */ + + unsigned long flags; + + /* TIMINGS */ + + 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; + + /* CLOCK FREQUENCY */ + + unsigned long frequency; + +} DISPLAYMODE; + +/* For Fixed timings */ +typedef struct tagFIXEDTIMINGS +{ + /* DISPLAY MODE FLAGS */ + /* Specify valid color depths and the refresh rate. */ + + int panelresx; + int panelresy; + unsigned short xres; + unsigned short yres; + + /* TIMINGS */ + + 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; + + /* CLOCK FREQUENCY */ + + unsigned long frequency; + +} FIXEDTIMINGS; + +#endif /* !_gfx_mode_h */ + +/* END OF FILE */ diff --git a/src/gfx/gfx_msr.c b/src/gfx/gfx_msr.c new file mode 100644 index 0000000..3d48d3d --- /dev/null +++ b/src/gfx/gfx_msr.c @@ -0,0 +1,152 @@ +/* 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 to read machine-specific registers (MSRs) + * + * Routines: + * + * gfx_msr_init + * gfx_id_msr_device + * gfx_get_msr_dev_address + * gfx_get_glink_id_at_address + * gfx_msr_read + * gfx_msr_write + * */ + +/* INCLUDE SUPPORT FOR REDCLOUD, IF SPECIFIED */ + +#if GFX_MSR_REDCLOUD +#include "msr_rdcl.c" +#endif + +/* EXTRA WRAPPERS FOR DYNAMIC SELECTION */ + +#if GFX_MSR_DYNAMIC + +/*---------------------------------------------------------------------------- + * gfx_msr_init + *---------------------------------------------------------------------------- + */ +int +gfx_msr_init() +{ + int ret_value = 0; + +#if GFX_MSR_REDCLOUD + if (gfx_msr_type & GFX_MSR_TYPE_REDCLOUD) + ret_value = redcloud_msr_init(); +#endif + + return ret_value; +} + +/*---------------------------------------------------------------------------- + * gfx_id_msr_device + *---------------------------------------------------------------------------- + */ +DEV_STATUS +gfx_id_msr_device(MSR * pDev, unsigned long address) +{ + DEV_STATUS ret_value = NOT_KNOWN; + +#if GFX_MSR_REDCLOUD + if (gfx_msr_type & GFX_MSR_TYPE_REDCLOUD) + ret_value = redcloud_id_msr_device(pDev, address); +#endif + + return ret_value; +} + +/*---------------------------------------------------------------------------- + * gfx_get_msr_dev_address + *---------------------------------------------------------------------------- + */ +DEV_STATUS +gfx_get_msr_dev_address(unsigned int device, unsigned long *address) +{ + DEV_STATUS ret_value = NOT_KNOWN; + +#if GFX_MSR_REDCLOUD + if (gfx_msr_type & GFX_MSR_TYPE_REDCLOUD) + ret_value = redcloud_get_msr_dev_address(device, address); +#endif + + return ret_value; +} + +/*---------------------------------------------------------------------------- + * gfx_get_glink_id_at_address + *---------------------------------------------------------------------------- + */ +DEV_STATUS +gfx_get_glink_id_at_address(unsigned int *device, unsigned long address) +{ + DEV_STATUS ret_value = NOT_KNOWN; + +#if GFX_MSR_REDCLOUD + if (gfx_msr_type & GFX_MSR_TYPE_REDCLOUD) + ret_value = redcloud_get_glink_id_at_address(device, address); +#endif + + return ret_value; +} + +/*---------------------------------------------------------------------------- + * gfx_msr_read + *---------------------------------------------------------------------------- + */ +DEV_STATUS +gfx_msr_read(unsigned int device, unsigned int msrRegister, Q_WORD * msrValue) +{ + DEV_STATUS ret_value = NOT_KNOWN; + +#if GFX_MSR_REDCLOUD + if (gfx_msr_type & GFX_MSR_TYPE_REDCLOUD) + ret_value = redcloud_msr_read(device, msrRegister, msrValue); +#endif + + return ret_value; +} + +/*---------------------------------------------------------------------------- + * gfx_msr_write + *---------------------------------------------------------------------------- + */ +DEV_STATUS +gfx_msr_write(unsigned int device, unsigned int msrRegister, + Q_WORD * msrValue) +{ + DEV_STATUS ret_value = NOT_KNOWN; + +#if GFX_MSR_REDCLOUD + if (gfx_msr_type & GFX_MSR_TYPE_REDCLOUD) + ret_value = redcloud_msr_write(device, msrRegister, msrValue); +#endif + + return ret_value; +} + +#endif diff --git a/src/gfx/gfx_priv.h b/src/gfx/gfx_priv.h new file mode 100644 index 0000000..5647af8 --- /dev/null +++ b/src/gfx/gfx_priv.h @@ -0,0 +1,981 @@ +/* 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 header file contains the prototypes for local and private routines. + * */ + +/*---------------------------------*/ +/* FIRST GENERATION INITIALIZATION */ +/*---------------------------------*/ + +#if GFX_INIT_GU1 + +/* PRIVATE ROUTINES */ + +unsigned char gfx_gxm_config_read(unsigned char index); + +/* DYNAMIC ROUTINES */ + +#if GFX_INIT_DYNAMIC +unsigned long gu1_get_core_freq(void); +unsigned long gu1_get_cpu_register_base(void); +unsigned long gu1_get_graphics_register_base(void); +unsigned long gu1_get_frame_buffer_base(void); +unsigned long gu1_get_frame_buffer_size(void); +unsigned long gu1_get_vid_register_base(void); +unsigned long gu1_get_vip_register_base(void); +#endif + +#endif + +/*----------------------------------*/ +/* SECOND GENERATION INITIALIZATION */ +/*----------------------------------*/ + +#if GFX_INIT_GU2 + +/* DYNAMIC ROUTINES */ + +#if GFX_INIT_DYNAMIC +unsigned long gu2_get_core_freq(void); +unsigned long gu2_get_cpu_register_base(void); +unsigned long gu2_get_graphics_register_base(void); +unsigned long gu2_get_frame_buffer_base(void); +unsigned long gu2_get_frame_buffer_size(void); +unsigned long gu2_get_vid_register_base(void); +unsigned long gu2_get_vip_register_base(void); +#endif + +#endif + +/*----------------------------------*/ +/* MSR ROUTINES */ +/*----------------------------------*/ + +#if GFX_MSR_REDCLOUD + +/* PRIVATE ROUTINES */ + +void redcloud_build_mbus_tree(void); +int redcloud_init_msr_devices(MSR aDev[], unsigned int array_size); +DEV_STATUS redcloud_find_msr_device(MSR * pDev); + +/* DYNAMIC ROUTINES */ + +#if GFX_MSR_DYNAMIC +int redcloud_msr_init(void); +DEV_STATUS redcloud_id_msr_device(MSR * pDev, unsigned long address); +DEV_STATUS redcloud_get_msr_dev_address(unsigned int device, + unsigned long *address); +DEV_STATUS redcloud_get_glink_id_at_address(unsigned int *device, + unsigned long address); +DEV_STATUS redcloud_msr_read(unsigned int device, unsigned int msrRegister, + Q_WORD * msrValue); +DEV_STATUS redcloud_msr_write(unsigned int device, unsigned int msrRegister, + Q_WORD * msrValue); +#endif + +#endif + +void gfx_set_display_video_enable(int enable); +void gfx_set_display_video_size(unsigned short width, unsigned short height); +void gfx_set_display_video_offset(unsigned long offset); +unsigned long gfx_get_display_video_offset(void); +unsigned long gfx_get_display_video_size(void); + +/*----------------------------------*/ +/* FIRST GENERATION DISPLAY */ +/*----------------------------------*/ + +#if GFX_DISPLAY_GU1 + +/* PRIVATE ROUTINES */ + +void gu1_enable_compression(void); +void gu1_disable_compression(void); +void gu1_delay_approximate(unsigned long milliseconds); +void gu1_delay_precise(unsigned long milliseconds); + +/* DYNAMIC ROUTINES */ + +#if GFX_DISPLAY_DYNAMIC +void gu1_set_display_video_enable(int enable); +void gu1_set_display_video_size(unsigned short width, unsigned short height); +void gu1_set_display_video_offset(unsigned long offset); +unsigned long gu1_get_display_video_offset(void); +unsigned long gu1_get_display_video_size(void); +int gu1_set_display_bpp(unsigned short bpp); +int gu1_is_display_mode_supported(int xres, int yres, int bpp, int hz); +int gu1_set_display_mode(int xres, int yres, int bpp, int hz); +int gu1_set_display_timings(unsigned short bpp, unsigned short flags, + unsigned short hactive, unsigned short hblank_start, + unsigned short hsync_start, unsigned short hsync_end, + unsigned short hblank_end, unsigned short htotal, + unsigned short vactive, unsigned short vblank_start, + unsigned short vsync_start, unsigned short vsync_end, + unsigned short vblank_end, unsigned short vtotal, + unsigned long frequency); +int gu1_set_vtotal(unsigned short vtotal); +void gu1_set_display_pitch(unsigned short pitch); +void gu1_set_display_offset(unsigned long offset); +int gu1_set_display_palette_entry(unsigned long index, unsigned long palette); +int gu1_set_display_palette(unsigned long *palette); +void gu1_video_shutdown(void); +void gu1_set_cursor_enable(int enable); +void gu1_set_cursor_colors(unsigned long bkcolor, unsigned long fgcolor); +void gu1_set_cursor_position(unsigned long memoffset, + unsigned short xpos, unsigned short ypos, + unsigned short xhotspot, unsigned short yhotspot); +void gu1_set_cursor_shape32(unsigned long memoffset, + unsigned long *andmask, unsigned long *xormask); +int gu1_set_compression_enable(int enable); +int gu1_set_compression_offset(unsigned long offset); +int gu1_set_compression_pitch(unsigned short pitch); +int gu1_set_compression_size(unsigned short size); +void gu1_set_display_priority_high(int enable); +int gu1_test_timing_active(void); +int gu1_test_vertical_active(void); +int gu1_wait_vertical_blank(void); +void gu1_delay_milliseconds(unsigned long milliseconds); +void gu1_delay_microseconds(unsigned long microseconds); +void gu1_enable_panning(int x, int y); +int gu1_set_fixed_timings(int panelResX, int panelResY, unsigned short width, + unsigned short height, unsigned short bpp); +int gu1_set_panel_present(int panelResX, int panelResY, unsigned short width, + unsigned short height, unsigned short bpp); +void gu1_reset_timing_lock(void); +int gu1_get_display_details(unsigned int mode, int *xres, int *yres, int *hz); +unsigned short gu1_get_display_pitch(void); +unsigned long gu1_get_max_supported_pixel_clock(void); +int gu1_mode_frequency_supported(int xres, int yres, int bpp, + unsigned long frequency); +int gu1_get_refreshrate_from_frequency(int xres, int yres, int bpp, int *hz, + unsigned long frequency); +int gu1_get_refreshrate_from_mode(int xres, int yres, int bpp, int *hz, + unsigned long frequency); +int gu1_get_frequency_from_refreshrate(int xres, int yres, int bpp, int hz, + int *frequency); +int gu1_get_display_mode_count(void); +int gu1_get_display_mode(int *xres, int *yres, int *bpp, int *hz); +unsigned long gu1_get_frame_buffer_line_size(void); +unsigned short gu1_get_hactive(void); +unsigned short gu1_get_hblank_start(void); +unsigned short gu1_get_hsync_start(void); +unsigned short gu1_get_hsync_end(void); +unsigned short gu1_get_hblank_end(void); +unsigned short gu1_get_htotal(void); +unsigned short gu1_get_vactive(void); +unsigned short gu1_get_vline(void); +unsigned short gu1_get_vblank_start(void); +unsigned short gu1_get_vsync_start(void); +unsigned short gu1_get_vsync_end(void); +unsigned short gu1_get_vblank_end(void); +unsigned short gu1_get_vtotal(void); +unsigned short gu1_get_display_bpp(void); +unsigned long gu1_get_display_offset(void); +int gu1_get_display_palette_entry(unsigned long index, + unsigned long *palette); +void gu1_get_display_palette(unsigned long *palette); +unsigned long gu1_get_cursor_enable(void); +unsigned long gu1_get_cursor_offset(void); +unsigned long gu1_get_cursor_position(void); +unsigned long gu1_get_cursor_clip(void); +unsigned long gu1_get_cursor_color(int color); +unsigned long gu1_get_icon_enable(void); +unsigned long gu1_get_icon_offset(void); +unsigned long gu1_get_icon_position(void); +unsigned long gu1_get_icon_color(int color); +int gu1_get_compression_enable(void); +unsigned long gu1_get_compression_offset(void); +unsigned short gu1_get_compression_pitch(void); +unsigned short gu1_get_compression_size(void); +int gu1_get_display_priority_high(void); +int gu1_get_valid_bit(int line); +#endif + +#endif + +void gfx_set_display_video_format(unsigned long format); +void gfx_set_display_video_yuv_offsets(unsigned long yoffset, + unsigned long uoffset, unsigned long voffset); +void gfx_set_display_video_yuv_pitch(unsigned long ypitch, + unsigned long uvpitch); +void gfx_set_display_video_downscale(unsigned short srch, + unsigned short dsth); +void gfx_set_display_video_vertical_downscale_enable(int enable); +void gfx_get_display_video_yuv_offsets(unsigned long *yoffset, + unsigned long *uoffset, unsigned long *voffset); +void gfx_get_display_video_yuv_pitch(unsigned long *ypitch, + unsigned long *uvpitch); +unsigned long gfx_get_display_video_downscale_delta(void); +int gfx_get_display_video_downscale_enable(void); + +/*----------------------------------*/ +/* SECOND GENERATION DISPLAY */ +/*----------------------------------*/ + +#if GFX_DISPLAY_GU2 + +/* PRIVATE ROUTINES */ + +void gu2_enable_compression(void); +void gu2_disable_compression(void); + +/* DYNAMIC ROUTINES */ + +#if GFX_DISPLAY_DYNAMIC +void gu2_get_display_video_yuv_offsets(unsigned long *yoffset, + unsigned long *uoffset, unsigned long *voffset); +void gu2_get_display_video_yuv_pitch(unsigned long *ypitch, + unsigned long *uvpitch); +unsigned long gu2_get_display_video_downscale_delta(void); +int gu2_get_display_video_downscale_enable(void); +void gu2_set_display_video_yuv_offsets(unsigned long yoffset, + unsigned long uoffset, unsigned long voffset); +void gu2_set_display_video_format(unsigned long format); +void gu2_set_display_video_yuv_pitch(unsigned long ypitch, + unsigned long uvpitch); +void gu2_set_display_video_downscale(unsigned short srch, + unsigned short dsth); +void gu2_set_display_video_vertical_downscale_enable(int enable); +void gu2_set_display_video_enable(int enable); +void gu2_set_display_video_size(unsigned short width, unsigned short height); +void gu2_set_display_video_offset(unsigned long offset); +unsigned long gu2_get_display_video_offset(void); +unsigned long gu2_get_display_video_size(void); +int gu2_set_display_bpp(unsigned short bpp); +int gu2_is_display_mode_supported(int xres, int yres, int bpp, int hz); +int gu2_set_display_mode(int xres, int yres, int bpp, int hz); +int gu2_set_display_timings(unsigned short bpp, unsigned short flags, + unsigned short hactive, unsigned short hblank_start, + unsigned short hsync_start, unsigned short hsync_end, + unsigned short hblank_end, unsigned short htotal, + unsigned short vactive, unsigned short vblank_start, + unsigned short vsync_start, unsigned short vsync_end, + unsigned short vblank_end, unsigned short vtotal, + unsigned long frequency); +int gu2_set_vtotal(unsigned short vtotal); +void gu2_set_display_pitch(unsigned short pitch); +void gu2_set_display_offset(unsigned long offset); +int gu2_set_display_palette_entry(unsigned long index, unsigned long palette); +int gu2_set_display_palette(unsigned long *palette); +void gu2_set_cursor_enable(int enable); +void gu2_set_cursor_colors(unsigned long bkcolor, unsigned long fgcolor); +void gu2_set_cursor_position(unsigned long memoffset, + unsigned short xpos, unsigned short ypos, + unsigned short xhotspot, unsigned short yhotspot); +void gu2_set_cursor_shape32(unsigned long memoffset, + unsigned long *andmask, unsigned long *xormask); +void gu2_set_cursor_shape64(unsigned long memoffset, + unsigned long *andmask, unsigned long *xormask); +void gu2_set_icon_enable(int enable); +void gu2_set_icon_colors(unsigned long color0, unsigned long color1, + unsigned long color2); +void gu2_set_icon_position(unsigned long memoffset, unsigned short xpos); +void gu2_set_icon_shape64(unsigned long memoffset, unsigned long *andmask, + unsigned long *xormask, unsigned int lines); +int gu2_set_compression_enable(int enable); +int gu2_set_compression_offset(unsigned long offset); +int gu2_set_compression_pitch(unsigned short pitch); +int gu2_set_compression_size(unsigned short size); +void gu2_set_display_priority_high(int enable); +int gu2_test_timing_active(void); +int gu2_test_vertical_active(void); +int gu2_wait_vertical_blank(void); +void gu2_delay_milliseconds(unsigned long milliseconds); +void gu2_delay_microseconds(unsigned long microseconds); +void gu2_enable_panning(int x, int y); +int gu2_is_panel_mode_supported(int panelResX, int panelResY, + unsigned short width, unsigned short height, unsigned short bpp); +int gu2_set_fixed_timings(int panelResX, int panelResY, unsigned short width, + unsigned short height, unsigned short bpp); +int gu2_set_panel_present(int panelResX, int panelResY, unsigned short width, + unsigned short height, unsigned short bpp); +void gu2_reset_timing_lock(void); +int gu2_get_display_details(unsigned int mode, int *xres, int *yres, int *hz); +unsigned short gu2_get_display_pitch(void); +unsigned long gu2_get_max_supported_pixel_clock(void); +int gu2_mode_frequency_supported(int xres, int yres, int bpp, + unsigned long frequency); +int gu2_get_refreshrate_from_frequency(int xres, int yres, int bpp, int *hz, + unsigned long frequency); +int gu2_get_refreshrate_from_mode(int xres, int yres, int bpp, int *hz, + unsigned long frequency); +int gu2_get_frequency_from_refreshrate(int xres, int yres, int bpp, int hz, + int *frequency); +int gu2_get_display_mode_count(void); +int gu2_get_display_mode(int *xres, int *yres, int *bpp, int *hz); +unsigned long gu2_get_frame_buffer_line_size(void); +unsigned short gu2_get_hactive(void); +unsigned short gu2_get_hblank_start(void); +unsigned short gu2_get_hsync_start(void); +unsigned short gu2_get_hsync_end(void); +unsigned short gu2_get_hblank_end(void); +unsigned short gu2_get_htotal(void); +unsigned short gu2_get_vactive(void); +unsigned short gu2_get_vline(void); +unsigned short gu2_get_vblank_start(void); +unsigned short gu2_get_vsync_start(void); +unsigned short gu2_get_vsync_end(void); +unsigned short gu2_get_vblank_end(void); +unsigned short gu2_get_vtotal(void); +unsigned short gu2_get_display_bpp(void); +unsigned long gu2_get_display_offset(void); +int gu2_get_display_palette_entry(unsigned long index, + unsigned long *palette); +void gu2_get_display_palette(unsigned long *palette); +unsigned long gu2_get_cursor_enable(void); +unsigned long gu2_get_cursor_offset(void); +unsigned long gu2_get_cursor_position(void); +unsigned long gu2_get_cursor_clip(void); +unsigned long gu2_get_cursor_color(int color); +unsigned long gu2_get_icon_enable(void); +unsigned long gu2_get_icon_offset(void); +unsigned long gu2_get_icon_position(void); +unsigned long gu2_get_icon_color(int color); +int gu2_get_compression_enable(void); +unsigned long gu2_get_compression_offset(void); +unsigned short gu2_get_compression_pitch(void); +unsigned short gu2_get_compression_size(void); +int gu2_get_valid_bit(int line); +#endif + +#endif + +/*----------------------------------*/ +/* FIRST GENERATION 2D ACCELERATION */ +/*----------------------------------*/ + +#if GFX_2DACCEL_GU1 + +/* PRIVATE ROUTINES */ + +void gu1_solid_fill(unsigned short x, unsigned short y, + unsigned short width, unsigned short height, unsigned long color); +void gu1_detect_blt_buffer_base(void); + +/* DYNAMIC ROUTINES */ + +#if GFX_2DACCEL_DYNAMIC +void gu1_set_bpp(unsigned short bpp); +void gu1_set_solid_pattern(unsigned long color); +void gu1_set_mono_pattern(unsigned long bgcolor, unsigned long fgcolor, + unsigned long data0, unsigned long data1, unsigned char transparency); +void gu1_set_color_pattern(unsigned long bgcolor, unsigned long fgcolor, + unsigned long data0, unsigned long data1, unsigned long data2, + unsigned long data3, unsigned char transparency); +void gu1_load_color_pattern_line(short y, unsigned long *pattern_8x8); +void gu1_set_solid_source(unsigned long color); +void gu1_set_mono_source(unsigned long bgcolor, unsigned long fgcolor, + unsigned short transparent); +void gu1_set_pattern_flags(unsigned short flags); +void gu1_set_raster_operation(unsigned char rop); +void gu1_pattern_fill(unsigned short x, unsigned short y, + unsigned short width, unsigned short height); +void gu1_color_pattern_fill(unsigned short x, unsigned short y, + unsigned short width, unsigned short height, unsigned long *pattern); +void gu1_screen_to_screen_blt(unsigned short srcx, unsigned short srcy, + unsigned short dstx, unsigned short dsty, unsigned short width, + unsigned short height); +void gu1_screen_to_screen_xblt(unsigned short srcx, unsigned short srcy, + unsigned short dstx, unsigned short dsty, unsigned short width, + unsigned short height, unsigned long color); +void gu1_color_bitmap_to_screen_blt(unsigned short srcx, unsigned short srcy, + unsigned short dstx, unsigned short dsty, unsigned short width, + unsigned short height, unsigned char *data, long pitch); +void gu1_color_bitmap_to_screen_xblt(unsigned short srcx, unsigned short srcy, + unsigned short dstx, unsigned short dsty, unsigned short width, + unsigned short height, unsigned char *data, long pitch, + unsigned long color); +void gu1_mono_bitmap_to_screen_blt(unsigned short srcx, unsigned short srcy, + unsigned short dstx, unsigned short dsty, unsigned short width, + unsigned short height, unsigned char *data, short pitch); +void gu1_text_blt(unsigned short dstx, unsigned short dsty, + unsigned short width, unsigned short height, unsigned char *data); +void gu1_bresenham_line(unsigned short x, unsigned short y, + unsigned short length, unsigned short initerr, unsigned short axialerr, + unsigned short diagerr, unsigned short flags); +void gu1_wait_until_idle(void); +int gu1_test_blt_pending(void); +#endif + +#endif + +/*-----------------------------------*/ +/* SECOND GENERATION 2D ACCELERATION */ +/*-----------------------------------*/ + +#if GFX_2DACCEL_GU2 + +/* DYNAMIC ROUTINES */ + +#if GFX_2DACCEL_DYNAMIC +void gfx_reset_pitch(unsigned short pitch); +void gu2_reset_pitch(unsigned short pitch); +void gu2_set_bpp(unsigned short bpp); +void gu2_set_solid_pattern(unsigned long color); +void gu2_set_mono_pattern(unsigned long bgcolor, unsigned long fgcolor, + unsigned long data0, unsigned long data1, unsigned char transparency); +void gu2_set_color_pattern(unsigned long bgcolor, unsigned long fgcolor, + unsigned long data0, unsigned long data1, unsigned long data2, + unsigned long data3, unsigned char transparency); +void gu2_load_color_pattern_line(short y, unsigned long *pattern_8x8); +void gu2_set_solid_source(unsigned long color); +void gu2_set_mono_source(unsigned long bgcolor, unsigned long fgcolor, + unsigned short transparent); +void gu2_set_pattern_flags(unsigned short flags); +void gu2_set_raster_operation(unsigned char rop); +void gu2_pattern_fill(unsigned short x, unsigned short y, + unsigned short width, unsigned short height); +void gu2_color_pattern_fill(unsigned short x, unsigned short y, + unsigned short width, unsigned short height, unsigned long *pattern); +void gu2_screen_to_screen_blt(unsigned short srcx, unsigned short srcy, + unsigned short dstx, unsigned short dsty, unsigned short width, + unsigned short height); +void gu2_screen_to_screen_xblt(unsigned short srcx, unsigned short srcy, + unsigned short dstx, unsigned short dsty, unsigned short width, + unsigned short height, unsigned long color); +void gu2_color_bitmap_to_screen_blt(unsigned short srcx, unsigned short srcy, + unsigned short dstx, unsigned short dsty, unsigned short width, + unsigned short height, unsigned char *data, long pitch); +void gu2_color_bitmap_to_screen_xblt(unsigned short srcx, unsigned short srcy, + unsigned short dstx, unsigned short dsty, unsigned short width, + unsigned short height, unsigned char *data, long pitch, + unsigned long color); +void gu2_mono_bitmap_to_screen_blt(unsigned short srcx, unsigned short srcy, + unsigned short dstx, unsigned short dsty, unsigned short width, + unsigned short height, unsigned char *data, short pitch); +void gu2_text_blt(unsigned short dstx, unsigned short dsty, + unsigned short width, unsigned short height, unsigned char *data); +void gu2_bresenham_line(unsigned short x, unsigned short y, + unsigned short length, unsigned short initerr, unsigned short axialerr, + unsigned short diagerr, unsigned short flags); +void gu2_wait_until_idle(void); +int gu2_test_blt_pending(void); + +void gu22_set_source_stride(unsigned short stride); +void gu22_set_destination_stride(unsigned short stride); +void gu22_set_pattern_origin(int x, int y); +void gu22_set_source_transparency(unsigned long color, unsigned long mask); +void gu22_set_alpha_mode(int mode); +void gu22_set_alpha_value(unsigned char value); +void gu22_pattern_fill(unsigned long dstoffset, unsigned short width, + unsigned short height); +void gu22_color_pattern_fill(unsigned long dstoffset, unsigned short width, + unsigned short height, unsigned long *pattern); +void gu22_screen_to_screen_blt(unsigned long srcoffset, + unsigned long dstoffset, unsigned short width, unsigned short height, + int flags); +void gu22_mono_expand_blt(unsigned long srcbase, unsigned short srcx, + unsigned short srcy, unsigned long dstoffset, unsigned short width, + unsigned short height, int byte_packed); +void gu22_color_bitmap_to_screen_blt(unsigned short srcx, unsigned short srcy, + unsigned long dstoffset, unsigned short width, unsigned short height, + unsigned char *data, short pitch); +void gu22_mono_bitmap_to_screen_blt(unsigned short srcx, unsigned short srcy, + unsigned long dstoffset, unsigned short width, unsigned short height, + unsigned char *data, short pitch); +void gu22_text_blt(unsigned long dstoffset, unsigned short width, + unsigned short height, unsigned char *data); +void gu22_bresenham_line(unsigned long dstoffset, unsigned short length, + unsigned short initerr, unsigned short axialerr, unsigned short diagerr, + unsigned short flags); +void gu22_sync_to_vblank(void); +#endif + +#endif + +void gfx_reset_video(void); +int gfx_set_display_control(int sync_polarities); +int gfx_set_screen_enable(int enable); + +/*-----------------------*/ +/* CS5530 VIDEO ROUTINES */ +/*-----------------------*/ + +#if GFX_VIDEO_CS5530 + +/* PRIVATE ROUTINES */ + +/* DYNAMIC ROUTINES */ + +#if GFX_VIDEO_DYNAMIC +void cs5530_reset_video(void); +int cs5530_set_display_control(int sync_polarities); +void cs5530_set_clock_frequency(unsigned long frequency); +unsigned long cs5530_get_clock_frequency(void); +int cs5530_set_crt_enable(int enable); +int cs5530_get_sync_polarities(void); +int cs5530_get_vsa2_softvga_enable(void); +int cs5530_set_video_enable(int enable); +int cs5530_set_video_format(unsigned long format); +int cs5530_set_video_size(unsigned short width, unsigned short height); +int cs5530_set_video_offset(unsigned long offset); +int cs5530_set_video_window(short x, short y, unsigned short w, + unsigned short h); +int cs5530_set_video_left_crop(unsigned short x); +int cs5530_set_video_scale(unsigned short srcw, unsigned short srch, + unsigned short dstw, unsigned short dsth); +int cs5530_set_video_color_key(unsigned long key, unsigned long mask, + int bluescreen); +int cs5530_set_video_filter(int xfilter, int yfilter); +int cs5530_set_video_palette(unsigned long *palette); +int cs5530_set_video_palette_entry(unsigned long index, unsigned long color); +int cs5530_disable_softvga(void); +int cs5530_enable_softvga(void); +unsigned long cs5530_get_max_video_width(void); + +/* READ ROUTINES IN GFX_VID.C */ + +int cs5530_get_video_enable(void); +int cs5530_get_video_format(void); +unsigned long cs5530_get_video_src_size(void); +unsigned long cs5530_get_video_line_size(void); +unsigned long cs5530_get_video_xclip(void); +unsigned long cs5530_get_video_offset(void); +unsigned long cs5530_get_video_upscale(void); +unsigned long cs5530_get_video_scale(void); +unsigned long cs5530_get_video_dst_size(void); +unsigned long cs5530_get_video_position(void); +unsigned long cs5530_get_video_color_key(void); +unsigned long cs5530_get_video_color_key_mask(void); +int cs5530_get_video_palette_entry(unsigned long index, + unsigned long *palette); +int cs5530_get_video_color_key_src(void); +int cs5530_get_video_filter(void); +unsigned long cs5530_read_crc(void); +#endif +#endif + +/*-----------------------*/ +/* SC1200 VIDEO ROUTINES */ +/*-----------------------*/ + +#if GFX_VIDEO_SC1200 + +/* PRIVATE ROUTINES */ + +/* DYNAMIC ROUTINES */ + +#if GFX_VIDEO_DYNAMIC +void sc1200_reset_video(void); +int sc1200_set_display_control(int sync_polarities); +int sc1200_set_screen_enable(int enable); +void sc1200_set_clock_frequency(unsigned long frequency); +unsigned long sc1200_get_clock_frequency(void); +int sc1200_set_crt_enable(int enable); +int sc1200_get_sync_polarities(void); +int sc1200_get_vsa2_softvga_enable(void); +int sc1200_set_video_enable(int enable); +int sc1200_set_video_format(unsigned long format); +int sc1200_set_video_size(unsigned short width, unsigned short height); +int sc1200_set_video_offset(unsigned long offset); +int sc1200_set_video_window(short x, short y, unsigned short w, + unsigned short h); +int sc1200_set_video_left_crop(unsigned short x); +int sc1200_set_video_upscale(unsigned short srcw, unsigned short srch, + unsigned short dstw, unsigned short dsth); +int sc1200_set_video_scale(unsigned short srcw, unsigned short srch, + unsigned short dstw, unsigned short dsth); +int sc1200_set_video_downscale_config(unsigned short type, unsigned short m); +int sc1200_set_video_color_key(unsigned long key, unsigned long mask, + int bluescreen); +int sc1200_set_video_filter(int xfilter, int yfilter); +int sc1200_set_video_palette(unsigned long *palette); +int sc1200_set_video_palette_bypass(int enable); +int sc1200_set_video_palette_entry(unsigned long index, unsigned long color); +int sc1200_set_video_downscale_coefficients(unsigned short coef1, + unsigned short coef2, unsigned short coef3, unsigned short coef4); +int sc1200_set_video_downscale_enable(int enable); +int sc1200_set_video_source(VideoSourceType source); +int sc1200_set_vbi_source(VbiSourceType source); +int sc1200_set_vbi_lines(unsigned long even, unsigned long odd); +int sc1200_set_vbi_total(unsigned long even, unsigned long odd); +int sc1200_set_video_interlaced(int enable); +int sc1200_set_color_space_YUV(int enable); +int sc1200_set_vertical_scaler_offset(char offset); +int sc1200_set_top_line_in_odd(int enable); +int sc1200_set_genlock_delay(unsigned long delay); +int sc1200_set_genlock_enable(int flags); +int sc1200_set_video_cursor(unsigned long key, unsigned long mask, + unsigned short select_color2, unsigned long color1, unsigned long color2); +int sc1200_set_video_request(short x, short y); + +int sc1200_select_alpha_region(int region); +int sc1200_set_alpha_enable(int enable); +int sc1200_set_alpha_window(short x, short y, + unsigned short width, unsigned short height); +int sc1200_set_alpha_value(unsigned char alpha, char delta); +int sc1200_set_alpha_priority(int priority); +int sc1200_set_alpha_color(unsigned long color); +int sc1200_set_alpha_color_enable(int enable); +int sc1200_set_no_ck_outside_alpha(int enable); +int sc1200_disable_softvga(void); +int sc1200_enable_softvga(void); +int sc1200_set_macrovision_enable(int enable); +unsigned long sc1200_get_max_video_width(void); + +/* READ ROUTINES IN GFX_VID.C */ + +int sc1200_get_video_enable(void); +int sc1200_get_video_format(void); +unsigned long sc1200_get_video_src_size(void); +unsigned long sc1200_get_video_line_size(void); +unsigned long sc1200_get_video_xclip(void); +unsigned long sc1200_get_video_offset(void); +unsigned long sc1200_get_video_upscale(void); +unsigned long sc1200_get_video_scale(void); +int sc1200_get_video_downscale_config(unsigned short *type, + unsigned short *m); +void sc1200_get_video_downscale_coefficients(unsigned short *coef1, + unsigned short *coef2, unsigned short *coef3, unsigned short *coef4); +void sc1200_get_video_downscale_enable(int *enable); +unsigned long sc1200_get_video_dst_size(void); +unsigned long sc1200_get_video_position(void); +unsigned long sc1200_get_video_color_key(void); +unsigned long sc1200_get_video_color_key_mask(void); +int sc1200_get_video_palette_entry(unsigned long index, + unsigned long *palette); +int sc1200_get_video_color_key_src(void); +int sc1200_get_video_filter(void); +int sc1200_get_video_request(short *x, short *y); +int sc1200_get_video_source(VideoSourceType * source); +int sc1200_get_vbi_source(VbiSourceType * source); +unsigned long sc1200_get_vbi_lines(int odd); +unsigned long sc1200_get_vbi_total(int odd); +int sc1200_get_video_interlaced(void); +int sc1200_get_color_space_YUV(void); +int sc1200_get_vertical_scaler_offset(char *offset); +unsigned long sc1200_get_genlock_delay(void); +int sc1200_get_genlock_enable(void); +int sc1200_get_video_cursor(unsigned long *key, unsigned long *mask, + unsigned short *select_color2, unsigned long *color1, + unsigned short *color2); +unsigned long sc1200_read_crc(void); +int sc1200_get_macrovision_enable(void); + +void sc1200_get_alpha_enable(int *enable); +void sc1200_get_alpha_size(unsigned short *x, unsigned short *y, + unsigned short *width, unsigned short *height); +void sc1200_get_alpha_value(unsigned char *alpha, char *delta); +void sc1200_get_alpha_priority(int *priority); +void sc1200_get_alpha_color(unsigned long *color); +#endif +#endif + +/*-------------------------*/ +/* REDCLOUD VIDEO ROUTINES */ +/*-------------------------*/ + +#if GFX_VIDEO_REDCLOUD + +/* PRIVATE ROUTINES */ + +/* DYNAMIC ROUTINES */ + +#if GFX_VIDEO_DYNAMIC +void redcloud_reset_video(void); +int redcloud_set_display_control(int sync_polarities); +void redcloud_set_clock_frequency(unsigned long frequency); +unsigned long redcloud_get_clock_frequency(void); +int redcloud_set_crt_enable(int enable); +int redcloud_get_sync_polarities(void); +int redcloud_set_video_enable(int enable); +int redcloud_set_video_format(unsigned long format); +int redcloud_set_video_size(unsigned short width, unsigned short height); +int redcloud_set_video_yuv_pitch(unsigned long ypitch, unsigned long uvpitch); +int redcloud_set_video_offset(unsigned long offset); +int redcloud_set_video_yuv_offsets(unsigned long yoffset, + unsigned long uoffset, unsigned long voffset); +int redcloud_set_video_window(short x, short y, unsigned short w, + unsigned short h); +int redcloud_set_video_left_crop(unsigned short x); +int redcloud_set_video_scale(unsigned short srcw, unsigned short srch, + unsigned short dstw, unsigned short dsth); +int redcloud_set_video_vertical_downscale(unsigned short srch, + unsigned short dsth); +void redcloud_set_video_vertical_downscale_enable(int enable); +int redcloud_set_video_downscale_config(unsigned short type, + unsigned short m); +int redcloud_set_video_color_key(unsigned long key, unsigned long mask, + int bluescreen); +int redcloud_set_video_filter(int xfilter, int yfilter); +int redcloud_set_video_palette(unsigned long *palette); +int redcloud_set_graphics_palette(unsigned long *palette); +int redcloud_set_video_palette_bypass(int enable); +int redcloud_set_video_palette_entry(unsigned long index, + unsigned long color); +int redcloud_set_graphics_palette_entry(unsigned long index, + unsigned long color); +int redcloud_set_video_downscale_coefficients(unsigned short coef1, + unsigned short coef2, unsigned short coef3, unsigned short coef4); +int redcloud_set_video_downscale_enable(int enable); +int redcloud_set_video_cursor(unsigned long key, unsigned long mask, + unsigned short select_color2, unsigned long color1, unsigned long color2); +int redcloud_set_video_cursor_enable(int enable); + +int redcloud_select_alpha_region(int region); +int redcloud_set_alpha_enable(int enable); +int redcloud_set_alpha_window(short x, short y, + unsigned short width, unsigned short height); +int redcloud_set_alpha_value(unsigned char alpha, char delta); +int redcloud_set_alpha_priority(int priority); +int redcloud_set_alpha_color(unsigned long color); +int redcloud_set_alpha_color_enable(int enable); +int redcloud_set_no_ck_outside_alpha(int enable); +int redcloud_set_video_request(short x, short y); + +/* READ ROUTINES IN GFX_VID.C */ + +int redcloud_get_video_enable(void); +int redcloud_get_video_format(void); +unsigned long redcloud_get_video_src_size(void); +unsigned long redcloud_get_video_line_size(void); +unsigned long redcloud_get_video_xclip(void); +unsigned long redcloud_get_video_offset(void); +void redcloud_get_video_yuv_offsets(unsigned long *yoffset, + unsigned long *uoffset, unsigned long *voffset); +void redcloud_get_video_yuv_pitch(unsigned long *ypitch, + unsigned long *uvpitch); +unsigned long redcloud_get_video_scale(void); +unsigned long redcloud_get_video_downscale_delta(void); +int redcloud_get_video_vertical_downscale_enable(void); +int redcloud_get_video_downscale_config(unsigned short *type, + unsigned short *m); +void redcloud_get_video_downscale_coefficients(unsigned short *coef1, + unsigned short *coef2, unsigned short *coef3, unsigned short *coef4); +void redcloud_get_video_downscale_enable(int *enable); +unsigned long redcloud_get_video_dst_size(void); +unsigned long redcloud_get_video_position(void); +unsigned long redcloud_get_video_color_key(void); +unsigned long redcloud_get_video_color_key_mask(void); +int redcloud_get_video_palette_entry(unsigned long index, + unsigned long *palette); +int redcloud_get_video_color_key_src(void); +int redcloud_get_video_filter(void); +int redcloud_get_video_cursor(unsigned long *key, unsigned long *mask, + unsigned short *select_color2, unsigned long *color1, + unsigned short *color2); +unsigned long redcloud_read_crc(void); +unsigned long redcloud_read_crc32(void); +unsigned long redcloud_read_window_crc(int source, unsigned short x, + unsigned short y, unsigned short width, unsigned short height, int crc32); + +void redcloud_get_alpha_enable(int *enable); +void redcloud_get_alpha_size(unsigned short *x, unsigned short *y, + unsigned short *width, unsigned short *height); +void redcloud_get_alpha_value(unsigned char *alpha, char *delta); +void redcloud_get_alpha_priority(int *priority); +void redcloud_get_alpha_color(unsigned long *color); +int redcloud_get_video_request(short *x, short *y); +#endif +#endif + +/*--------------*/ +/* VIP ROUTINES */ +/*--------------*/ + +#if GFX_VIP_SC1200 + +/* DYNAMIC ROUTINES */ + +#if GFX_VIP_DYNAMIC +int sc1200_set_vip_enable(int enable); +int sc1200_set_vip_capture_run_mode(int mode); +int sc1200_set_vip_base(unsigned long even, unsigned long odd); +int sc1200_set_vip_pitch(unsigned long pitch); +int sc1200_set_vip_mode(int mode); +int sc1200_set_vbi_enable(int enable); +int sc1200_set_vbi_mode(int mode); +int sc1200_set_vbi_base(unsigned long even, unsigned long odd); +int sc1200_set_vbi_pitch(unsigned long pitch); +int sc1200_set_vbi_direct(unsigned long even_lines, unsigned long odd_lines); +int sc1200_set_vbi_interrupt(int enable); +int sc1200_set_vip_bus_request_threshold_high(int enable); +int sc1200_set_vip_last_line(int last_line); +int sc1200_test_vip_odd_field(void); +int sc1200_test_vip_bases_updated(void); +int sc1200_test_vip_fifo_overflow(void); +int sc1200_get_vip_line(void); +int sc1200_get_vip_enable(void); +unsigned long sc1200_get_vip_base(int odd); +unsigned long sc1200_get_vip_pitch(void); +int sc1200_get_vip_mode(void); +int sc1200_get_vbi_enable(void); +int sc1200_get_vbi_mode(void); +unsigned long sc1200_get_vbi_base(int odd); +unsigned long sc1200_get_vbi_pitch(void); +unsigned long sc1200_get_vbi_direct(int odd); +int sc1200_get_vbi_interrupt(void); +int sc1200_get_vip_bus_request_threshold_high(void); +#endif +#endif + +/* DECODER ROUTINES */ + +#if GFX_DECODER_SAA7114 + +/* PRIVATE ROUTINES */ + +int saa7114_write_reg(unsigned char reg, unsigned char val); +int saa7114_read_reg(unsigned char reg, unsigned char *val); + +/* DYNAMIC ROUTINES */ + +#if GFX_DECODER_DYNAMIC +int saa7114_set_decoder_defaults(void); +int saa7114_set_decoder_analog_input(unsigned char input); +int saa7114_set_decoder_brightness(unsigned char brightness); +int saa7114_set_decoder_contrast(unsigned char contrast); +int saa7114_set_decoder_hue(char hue); +int saa7114_set_decoder_saturation(unsigned char saturation); +int saa7114_set_decoder_input_offset(unsigned short x, unsigned short y); +int saa7114_set_decoder_input_size(unsigned short width, + unsigned short height); +int saa7114_set_decoder_output_size(unsigned short width, + unsigned short height); +int saa7114_set_decoder_scale(unsigned short srcw, unsigned short srch, + unsigned short dstw, unsigned short dsth); +int saa7114_set_decoder_vbi_format(int start, int end, int format); +int saa7114_set_decoder_vbi_enable(int enable); +int saa7114_set_decoder_vbi_upscale(void); +int saa7114_set_decoder_TV_standard(TVStandardType TVStandard); +int saa7114_set_decoder_luminance_filter(unsigned char lufi); +int saa7114_decoder_software_reset(void); +int saa7114_decoder_detect_macrovision(void); +int saa7114_decoder_detect_video(void); +unsigned char saa7114_get_decoder_brightness(void); +unsigned char saa7114_get_decoder_contrast(void); +char saa7114_get_decoder_hue(void); +unsigned char saa7114_get_decoder_saturation(void); +unsigned long saa7114_get_decoder_input_offset(void); +unsigned long saa7114_get_decoder_input_size(void); +unsigned long saa7114_get_decoder_output_size(void); +int saa7114_get_decoder_vbi_format(int line); +#endif +#endif + +/* ACCESS I2C ROUTINES */ + +#if GFX_I2C_ACCESS + +#if GFX_I2C_DYNAMIC +int acc_i2c_reset(unsigned char busnum, short adr, char freq); +int acc_i2c_write(unsigned char busnum, unsigned char chipadr, + unsigned char subadr, unsigned char bytes, unsigned char *data); +int acc_i2c_read(unsigned char busnum, unsigned char chipadr, + unsigned char subadr, unsigned char bytes, unsigned char *data); +int acc_i2c_select_gpio(int clock, int data); +int acc_i2c_init(void); +void acc_i2c_cleanup(void); +#endif +#endif + +/* GPIO I2C ROUTINES */ + +#if GFX_I2C_GPIO + +#if GFX_I2C_DYNAMIC +int gpio_i2c_reset(unsigned char busnum, short adr, char freq); +int gpio_i2c_write(unsigned char busnum, unsigned char chipadr, + unsigned char subadr, unsigned char bytes, unsigned char *data); +int gpio_i2c_read(unsigned char busnum, unsigned char chipadr, + unsigned char subadr, unsigned char bytes, unsigned char *data); +int gpio_i2c_select_gpio(int clock, int data); +int gpio_i2c_init(void); +void gpio_i2c_cleanup(void); +#endif +#endif + +/* TV ROUTINES */ + +#if GFX_TV_SC1200 + +#if GFX_TV_DYNAMIC +int sc1200_set_tv_format(TVStandardType format, GfxOnTVType resolution); +int sc1200_set_tv_output(int output); +int sc1200_set_tv_enable(int enable); +int sc1200_set_tv_flicker_filter(int ff); +int sc1200_set_tv_sub_carrier_reset(int screset); +int sc1200_set_tv_vphase(int vphase); +int sc1200_set_tv_YC_delay(int delay); +int sc1200_set_tvenc_reset_interval(int interval); +int sc1200_set_tv_cc_enable(int enable); +int sc1200_set_tv_cc_data(unsigned char data1, unsigned char data2); +int sc1200_set_tv_display(int width, int height); +int sc1200_test_tvout_odd_field(void); +int sc1200_test_tvenc_odd_field(void); +int sc1200_set_tv_field_status_invert(int enable); +int sc1200_get_tv_vphase(void); +int sc1200_get_tv_enable(unsigned int *p_on); +int sc1200_get_tv_output(void); +int sc1200_get_tv_mode_count(TVStandardType format); +int sc1200_get_tv_display_mode(int *width, int *height, int *bpp, int *hz); +int sc1200_get_tv_display_mode_frequency(unsigned short width, + unsigned short height, TVStandardType format, int *frequency); +int sc1200_is_tv_display_mode_supported(unsigned short width, + unsigned short height, TVStandardType format); +unsigned char cc_add_parity_bit(unsigned char data); + +#endif +#endif + +/* FS450 ROUTINES */ + +#if GFX_TV_FS451 + +#if GFX_TV_DYNAMIC +int fs450_set_tv_format(TVStandardType format, GfxOnTVType resolution); +int fs450_set_tv_output(int output); +int fs450_set_tv_enable(int enable); +int fs450_get_tv_standard(unsigned long *p_standard); +int fs450_get_available_tv_standards(unsigned long *p_standards); +int fs450_set_tv_standard(unsigned long standard); +int fs450_get_tv_vga_mode(unsigned long *p_vga_mode); +int fs450_get_available_tv_vga_modes(unsigned long *p_vga_modes); +int fs450_set_tv_vga_mode(unsigned long vga_mode); +int fs450_get_tvout_mode(unsigned long *p_tvout_mode); +int fs450_set_tvout_mode(unsigned long tvout_mode); +int fs450_get_sharpness(int *p_sharpness); +int fs450_set_sharpness(int sharpness); +int fs450_get_flicker_filter(int *p_flicker); +int fs450_set_flicker_filter(int flicker); +int fs450_get_overscan(int *p_x, int *p_y); +int fs450_set_overscan(int x, int y); +int fs450_get_position(int *p_x, int *p_y); +int fs450_set_position(int x, int y); +int fs450_get_color(int *p_color); +int fs450_set_color(int color); +int fs450_get_brightness(int *p_brightness); +int fs450_set_brightness(int brightness); +int fs450_get_contrast(int *p_contrast); +int fs450_set_contrast(int constrast); +int fs450_get_yc_filter(unsigned int *p_yc_filter); +int fs450_set_yc_filter(unsigned int yc_filter); +int fs450_get_aps_trigger_bits(unsigned int *p_trigger_bits); +int fs450_set_aps_trigger_bits(unsigned int trigger_bits); +#endif +#endif diff --git a/src/gfx/gfx_regs.h b/src/gfx/gfx_regs.h new file mode 100644 index 0000000..8d062f7 --- /dev/null +++ b/src/gfx/gfx_regs.h @@ -0,0 +1,1654 @@ +/* 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 header file contains the graphics register definitions. + * */ + +/*----------------------------------*/ +/* FIRST GENERATION GRAPHICS UNIT */ +/*----------------------------------*/ + +#define GP_DST_XCOOR 0x8100 /* x destination origin */ +#define GP_DST_YCOOR 0x8102 /* y destination origin */ +#define GP_WIDTH 0x8104 /* pixel width */ +#define GP_HEIGHT 0x8106 /* pixel height */ +#define GP_SRC_XCOOR 0x8108 /* x source origin */ +#define GP_SRC_YCOOR 0x810A /* y source origin */ + +#define GP_VECTOR_LENGTH 0x8104 /* vector length */ +#define GP_INIT_ERROR 0x8106 /* vector initial error */ +#define GP_AXIAL_ERROR 0x8108 /* axial error increment */ +#define GP_DIAG_ERROR 0x810A /* diagonal error increment */ + +#define GP_SRC_COLOR_0 0x810C /* source color 0 */ +#define GP_SRC_COLOR_1 0x810E /* source color 1 */ +#define GP_PAT_COLOR_0 0x8110 /* pattern color 0 */ +#define GP_PAT_COLOR_1 0x8112 /* pattern color 1 */ +#define GP_PAT_COLOR_2 0x8114 /* pattern color 2 */ +#define GP_PAT_COLOR_3 0x8116 /* pattern color 3 */ +#define GP_PAT_DATA_0 0x8120 /* bits 31:0 of pattern */ +#define GP_PAT_DATA_1 0x8124 /* bits 63:32 of pattern */ +#define GP_PAT_DATA_2 0x8128 /* bits 95:64 of pattern */ +#define GP_PAT_DATA_3 0x812C /* bits 127:96 of pattern */ + +#define GP_VGA_WRITE 0x8140 /* VGA write path control */ +#define GP_VGA_READ 0x8144 /* VGA read path control */ + +#define GP_RASTER_MODE 0x8200 /* raster operation */ +#define GP_VECTOR_MODE 0x8204 /* vector mode register */ +#define GP_BLIT_MODE 0x8208 /* blit mode register */ +#define GP_BLIT_STATUS 0x820C /* blit status register */ + +#define GP_VGA_BASE 0x8210 /* VGA memory offset (x64K) */ +#define GP_VGA_LATCH 0x8214 /* VGA display latch */ + +/* "GP_VECTOR_MODE" BIT DEFINITIONS */ + +#define VM_X_MAJOR 0x0000 /* X major vector */ +#define VM_Y_MAJOR 0x0001 /* Y major vector */ +#define VM_MAJOR_INC 0x0002 /* positive major axis step */ +#define VM_MINOR_INC 0x0004 /* positive minor axis step */ +#define VM_READ_DST_FB 0x0008 /* read destination data */ + +/* "GP_RASTER_MODE" BIT DEFINITIONS */ + +#define RM_PAT_DISABLE 0x0000 /* pattern is disabled */ +#define RM_PAT_MONO 0x0100 /* 1BPP pattern expansion */ +#define RM_PAT_DITHER 0x0200 /* 2BPP pattern expansion */ +#define RM_PAT_COLOR 0x0300 /* 8BPP or 16BPP pattern */ +#define RM_PAT_MASK 0x0300 /* mask for pattern mode */ +#define RM_PAT_TRANSPARENT 0x0400 /* transparent 1BPP pattern */ +#define RM_SRC_TRANSPARENT 0x0800 /* transparent 1BPP source */ + +/* "GP_BLIT_STATUS" BIT DEFINITIONS */ + +#define BS_BLIT_BUSY 0x0001 /* blit engine is busy */ +#define BS_PIPELINE_BUSY 0x0002 /* graphics pipeline is busy */ +#define BS_BLIT_PENDING 0x0004 /* blit pending */ +#define BC_FLUSH 0x0080 /* flush pipeline requests */ +#define BC_8BPP 0x0000 /* 8BPP mode */ +#define BC_16BPP 0x0100 /* 16BPP mode */ +#define BC_FB_WIDTH_1024 0x0000 /* framebuffer width = 1024 */ +#define BC_FB_WIDTH_2048 0x0200 /* framebuffer width = 2048 */ +#define BC_FB_WIDTH_4096 0x0400 /* framebuffer width = 4096 */ + +/* "GP_BLIT_MODE" BIT DEFINITIONS */ + +#define BM_READ_SRC_NONE 0x0000 /* source foreground color */ +#define BM_READ_SRC_FB 0x0001 /* read source from FB */ +#define BM_READ_SRC_BB0 0x0002 /* read source from BB0 */ +#define BM_READ_SRC_BB1 0x0003 /* read source from BB1 */ +#define BM_READ_SRC_MASK 0x0003 /* read source mask */ + +#define BM_READ_DST_NONE 0x0000 /* no destination data */ +#define BM_READ_DST_BB0 0x0008 /* destination from BB0 */ +#define BM_READ_DST_BB1 0x000C /* destination from BB1 */ +#define BM_READ_DST_FB0 0x0010 /* dest from FB (store BB0) */ +#define BM_READ_DST_FB1 0x0014 /* dest from FB (store BB1) */ +#define BM_READ_DST_MASK 0x001C /* read destination mask */ + +#define BM_WRITE_FB 0x0000 /* write to framebuffer */ +#define BM_WRITE_MEM 0x0020 /* write to memory */ +#define BM_WRITE_MASK 0x0020 /* write mask */ + +#define BM_SOURCE_COLOR 0x0000 /* source is 8BPP or 16BPP */ +#define BM_SOURCE_EXPAND 0x0040 /* source is 1BPP */ +#define BM_SOURCE_TEXT 0x00C0 /* source is 1BPP text */ +#define BM_SOURCE_MASK 0x00C0 /* source mask */ + +#define BM_REVERSE_Y 0x0100 /* reverse Y direction */ + +/*---------------------------------------*/ +/* FIRST GENERATION DISPLAY CONTROLLER */ +/*---------------------------------------*/ + +#define DC_UNLOCK 0x8300 /* lock register */ +#define DC_GENERAL_CFG 0x8304 /* config registers... */ +#define DC_TIMING_CFG 0x8308 +#define DC_OUTPUT_CFG 0x830C + +#define DC_FB_ST_OFFSET 0x8310 /* framebuffer start offset */ +#define DC_CB_ST_OFFSET 0x8314 /* compression start offset */ +#define DC_CURS_ST_OFFSET 0x8318 /* cursor start offset */ +#define DC_ICON_ST_OFFSET 0x831C /* icon start offset */ +#define DC_VID_ST_OFFSET 0x8320 /* video start offset */ +#define DC_LINE_DELTA 0x8324 /* fb and cb skip counts */ +#define DC_BUF_SIZE 0x8328 /* fb and cb line size */ + +#define DC_H_TIMING_1 0x8330 /* horizontal timing... */ +#define DC_H_TIMING_2 0x8334 +#define DC_H_TIMING_3 0x8338 +#define DC_FP_H_TIMING 0x833C + +#define DC_V_TIMING_1 0x8340 /* vertical timing... */ +#define DC_V_TIMING_2 0x8344 +#define DC_V_TIMING_3 0x8348 +#define DC_FP_V_TIMING 0x834C + +#define DC_CURSOR_X 0x8350 /* cursor x position */ +#define DC_ICON_X 0x8354 /* HACK - 1.3 definition */ +#define DC_V_LINE_CNT 0x8354 /* vertical line counter */ +#define DC_CURSOR_Y 0x8358 /* cursor y position */ +#define DC_ICON_Y 0x835C /* HACK - 1.3 definition */ +#define DC_SS_LINE_CMP 0x835C /* line compare value */ +#define DC_CURSOR_COLOR 0x8360 /* cursor colors */ +#define DC_ICON_COLOR 0x8364 /* icon colors */ +#define DC_BORDER_COLOR 0x8368 /* border color */ +#define DC_PAL_ADDRESS 0x8370 /* palette address */ +#define DC_PAL_DATA 0x8374 /* palette data */ +#define DC_DFIFO_DIAG 0x8378 /* display FIFO diagnostic */ +#define DC_CFIFO_DIAG 0x837C /* compression FIF0 diagnostic */ + +/* PALETTE LOCATIONS */ + +#define PAL_CURSOR_COLOR_0 0x100 +#define PAL_CURSOR_COLOR_1 0x101 +#define PAL_ICON_COLOR_0 0x102 +#define PAL_ICON_COLOR_1 0x103 +#define PAL_OVERSCAN_COLOR 0x104 + +/* UNLOCK VALUE */ + +#define DC_UNLOCK_VALUE 0x00004758 /* used to unlock DC regs */ + +/* "DC_GENERAL_CFG" BIT DEFINITIONS */ + +#define DC_GCFG_DFLE 0x00000001 /* display FIFO load enable */ +#define DC_GCFG_CURE 0x00000002 /* cursor enable */ +#define DC_GCFG_VCLK_DIV 0x00000004 /* vid clock divisor */ +#define DC_GCFG_PLNO 0x00000004 /* planar offset LSB */ +#define DC_GCFG_PPC 0x00000008 /* pixel pan compatibility */ +#define DC_GCFG_CMPE 0x00000010 /* compression enable */ +#define DC_GCFG_DECE 0x00000020 /* decompression enable */ +#define DC_GCFG_DCLK_MASK 0x000000C0 /* dotclock multiplier */ +#define DC_GCFG_DCLK_POS 6 /* dotclock multiplier */ +#define DC_GCFG_DFHPSL_MASK 0x00000F00 /* FIFO high-priority start */ +#define DC_GCFG_DFHPSL_POS 8 /* FIFO high-priority start */ +#define DC_GCFG_DFHPEL_MASK 0x0000F000 /* FIFO high-priority end */ +#define DC_GCFG_DFHPEL_POS 12 /* FIFO high-priority end */ +#define DC_GCFG_CIM_MASK 0x00030000 /* compressor insert mode */ +#define DC_GCFG_CIM_POS 16 /* compressor insert mode */ +#define DC_GCFG_FDTY 0x00040000 /* frame dirty mode */ +#define DC_GCFG_RTPM 0x00080000 /* real-time perf. monitor */ +#define DC_GCFG_DAC_RS_MASK 0x00700000 /* DAC register selects */ +#define DC_GCFG_DAC_RS_POS 20 /* DAC register selects */ +#define DC_GCFG_CKWR 0x00800000 /* clock write */ +#define DC_GCFG_LDBL 0x01000000 /* line double */ +#define DC_GCFG_DIAG 0x02000000 /* FIFO diagnostic mode */ +#define DC_GCFG_CH4S 0x04000000 /* sparse refresh mode */ +#define DC_GCFG_SSLC 0x08000000 /* enable line compare */ +#define DC_GCFG_VIDE 0x10000000 /* video enable */ +#define DC_GCFG_DFCK 0x20000000 /* divide flat-panel clock */ + /* - rev 2.3 down */ +#define DC_GCFG_VRDY 0x20000000 /* video port speed */ + /* - rev 2.4 up */ +#define DC_GCFG_DPCK 0x40000000 /* divide pixel clock */ +#define DC_GCFG_DDCK 0x80000000 /* divide dot clock */ + +/* "DC_TIMING_CFG" BIT DEFINITIONS */ + +#define DC_TCFG_FPPE 0x00000001 /* flat-panel power enable */ +#define DC_TCFG_HSYE 0x00000002 /* horizontal sync enable */ +#define DC_TCFG_VSYE 0x00000004 /* vertical sync enable */ +#define DC_TCFG_BLKE 0x00000008 /* blank enable */ +#define DC_TCFG_DDCK 0x00000010 /* DDC clock */ +#define DC_TCFG_TGEN 0x00000020 /* timing generator enable */ +#define DC_TCFG_VIEN 0x00000040 /* vertical interrupt enable */ +#define DC_TCFG_BLNK 0x00000080 /* blink enable */ +#define DC_TCFG_CHSP 0x00000100 /* horizontal sync polarity */ +#define DC_TCFG_CVSP 0x00000200 /* vertical sync polarity */ +#define DC_TCFG_FHSP 0x00000400 /* panel horz sync polarity */ +#define DC_TCFG_FVSP 0x00000800 /* panel vert sync polarity */ +#define DC_TCFG_FCEN 0x00001000 /* flat-panel centering */ +#define DC_TCFG_CDCE 0x00002000 /* HACK - 1.3 definition */ +#define DC_TCFG_PLNR 0x00002000 /* planar mode enable */ +#define DC_TCFG_INTL 0x00004000 /* interlace scan */ +#define DC_TCFG_PXDB 0x00008000 /* pixel double */ +#define DC_TCFG_BKRT 0x00010000 /* blink rate */ +#define DC_TCFG_PSD_MASK 0x000E0000 /* power sequence delay */ +#define DC_TCFG_PSD_POS 17 /* power sequence delay */ +#define DC_TCFG_DDCI 0x08000000 /* DDC input (RO) */ +#define DC_TCFG_SENS 0x10000000 /* monitor sense (RO) */ +#define DC_TCFG_DNA 0x20000000 /* display not active (RO) */ +#define DC_TCFG_VNA 0x40000000 /* vertical not active (RO) */ +#define DC_TCFG_VINT 0x80000000 /* vertical interrupt (RO) */ + +/* "DC_OUTPUT_CFG" BIT DEFINITIONS */ + +#define DC_OCFG_8BPP 0x00000001 /* 8/16 bpp select */ +#define DC_OCFG_555 0x00000002 /* 16 bpp format */ +#define DC_OCFG_PCKE 0x00000004 /* PCLK enable */ +#define DC_OCFG_FRME 0x00000008 /* frame rate mod enable */ +#define DC_OCFG_DITE 0x00000010 /* dither enable */ +#define DC_OCFG_2PXE 0x00000020 /* 2 pixel enable */ +#define DC_OCFG_2XCK 0x00000040 /* 2 x pixel clock */ +#define DC_OCFG_2IND 0x00000080 /* 2 index enable */ +#define DC_OCFG_34ADD 0x00000100 /* 3- or 4-bit add */ +#define DC_OCFG_FRMS 0x00000200 /* frame rate mod select */ +#define DC_OCFG_CKSL 0x00000400 /* clock select */ +#define DC_OCFG_PRMP 0x00000800 /* palette re-map */ +#define DC_OCFG_PDEL 0x00001000 /* panel data enable low */ +#define DC_OCFG_PDEH 0x00002000 /* panel data enable high */ +#define DC_OCFG_CFRW 0x00004000 /* comp line buffer r/w sel */ +#define DC_OCFG_DIAG 0x00008000 /* comp line buffer diag */ + +#define MC_MEM_CNTRL1 0x00008400 +#define MC_DR_ADD 0x00008418 +#define MC_DR_ACC 0x0000841C + +/* MC_MEM_CNTRL1 BIT DEFINITIONS */ + +#define MC_XBUSARB 0x00000008 /* 0 = GP priority < CPU priority */ + /* 1 = GP priority = CPU priority */ + /* GXm databook V2.0 is wrong ! */ +/*----------*/ +/* CS5530 */ +/*----------*/ + +/* CS5530 REGISTER DEFINITIONS */ + +#define CS5530_VIDEO_CONFIG 0x0000 +#define CS5530_DISPLAY_CONFIG 0x0004 +#define CS5530_VIDEO_X_POS 0x0008 +#define CS5530_VIDEO_Y_POS 0x000C +#define CS5530_VIDEO_SCALE 0x0010 +#define CS5530_VIDEO_COLOR_KEY 0x0014 +#define CS5530_VIDEO_COLOR_MASK 0x0018 +#define CS5530_PALETTE_ADDRESS 0x001C +#define CS5530_PALETTE_DATA 0x0020 +#define CS5530_DOT_CLK_CONFIG 0x0024 +#define CS5530_CRCSIG_TFT_TV 0x0028 + +/* "CS5530_VIDEO_CONFIG" BIT DEFINITIONS */ + +#define CS5530_VCFG_VID_EN 0x00000001 +#define CS5530_VCFG_VID_REG_UPDATE 0x00000002 +#define CS5530_VCFG_VID_INP_FORMAT 0x0000000C +#define CS5530_VCFG_8_BIT_4_2_0 0x00000004 +#define CS5530_VCFG_16_BIT_4_2_0 0x00000008 +#define CS5530_VCFG_GV_SEL 0x00000010 +#define CS5530_VCFG_CSC_BYPASS 0x00000020 +#define CS5530_VCFG_X_FILTER_EN 0x00000040 +#define CS5530_VCFG_Y_FILTER_EN 0x00000080 +#define CS5530_VCFG_LINE_SIZE_LOWER_MASK 0x0000FF00 +#define CS5530_VCFG_INIT_READ_MASK 0x01FF0000 +#define CS5530_VCFG_EARLY_VID_RDY 0x02000000 +#define CS5530_VCFG_LINE_SIZE_UPPER 0x08000000 +#define CS5530_VCFG_4_2_0_MODE 0x10000000 +#define CS5530_VCFG_16_BIT_EN 0x20000000 +#define CS5530_VCFG_HIGH_SPD_INT 0x40000000 + +/* "CS5530_DISPLAY_CONFIG" BIT DEFINITIONS */ + +#define CS5530_DCFG_DIS_EN 0x00000001 +#define CS5530_DCFG_HSYNC_EN 0x00000002 +#define CS5530_DCFG_VSYNC_EN 0x00000004 +#define CS5530_DCFG_DAC_BL_EN 0x00000008 +#define CS5530_DCFG_DAC_PWDNX 0x00000020 +#define CS5530_DCFG_FP_PWR_EN 0x00000040 +#define CS5530_DCFG_FP_DATA_EN 0x00000080 +#define CS5530_DCFG_CRT_HSYNC_POL 0x00000100 +#define CS5530_DCFG_CRT_VSYNC_POL 0x00000200 +#define CS5530_DCFG_FP_HSYNC_POL 0x00000400 +#define CS5530_DCFG_FP_VSYNC_POL 0x00000800 +#define CS5530_DCFG_XGA_FP 0x00001000 +#define CS5530_DCFG_FP_DITH_EN 0x00002000 +#define CS5530_DCFG_CRT_SYNC_SKW_MASK 0x0001C000 +#define CS5530_DCFG_CRT_SYNC_SKW_INIT 0x00010000 +#define CS5530_DCFG_PWR_SEQ_DLY_MASK 0x000E0000 +#define CS5530_DCFG_PWR_SEQ_DLY_INIT 0x00080000 +#define CS5530_DCFG_VG_CK 0x00100000 +#define CS5530_DCFG_GV_PAL_BYP 0x00200000 +#define CS5530_DCFG_DDC_SCL 0x00400000 +#define CS5530_DCFG_DDC_SDA 0x00800000 +#define CS5530_DCFG_DDC_OE 0x01000000 +#define CS5530_DCFG_16_BIT_EN 0x02000000 + +/*----------*/ +/* SC1200 */ +/*----------*/ + +/* SC1200 VIDEO REGISTER DEFINITIONS */ + +#define SC1200_VIDEO_CONFIG 0x000 +#define SC1200_DISPLAY_CONFIG 0x004 +#define SC1200_VIDEO_X_POS 0x008 +#define SC1200_VIDEO_Y_POS 0x00C +#define SC1200_VIDEO_UPSCALE 0x010 +#define SC1200_VIDEO_COLOR_KEY 0x014 +#define SC1200_VIDEO_COLOR_MASK 0x018 +#define SC1200_PALETTE_ADDRESS 0x01C +#define SC1200_PALETTE_DATA 0x020 +#define SC1200_VID_MISC 0x028 +#define SC1200_VID_CLOCK_SELECT 0x02C +#define SC1200_VIDEO_DOWNSCALER_CONTROL 0x03C +#define SC1200_VIDEO_DOWNSCALER_COEFFICIENTS 0x40 +#define SC1200_VID_CRC 0x044 +#define SC1200_DEVICE_ID 0x048 +#define SC1200_VID_ALPHA_CONTROL 0x04C +#define SC1200_CURSOR_COLOR_KEY 0x050 +#define SC1200_CURSOR_COLOR_MASK 0x054 +#define SC1200_CURSOR_COLOR_1 0x058 +#define SC1200_CURSOR_COLOR_2 0x05C +#define SC1200_ALPHA_XPOS_1 0x060 +#define SC1200_ALPHA_YPOS_1 0x064 +#define SC1200_ALPHA_COLOR_1 0x068 +#define SC1200_ALPHA_CONTROL_1 0x06C +#define SC1200_ALPHA_XPOS_2 0x070 +#define SC1200_ALPHA_YPOS_2 0x074 +#define SC1200_ALPHA_COLOR_2 0x078 +#define SC1200_ALPHA_CONTROL_2 0x07C +#define SC1200_ALPHA_XPOS_3 0x080 +#define SC1200_ALPHA_YPOS_3 0x084 +#define SC1200_ALPHA_COLOR_3 0x088 +#define SC1200_ALPHA_CONTROL_3 0x08C +#define SC1200_VIDEO_REQUEST 0x090 +#define SC1200_ALPHA_WATCH 0x094 +#define SC1200_VIDEO_DISPLAY_MODE 0x400 +#define SC1200_VIDEO_ODD_VBI_LINE_ENABLE 0x40C +#define SC1200_VIDEO_EVEN_VBI_LINE_ENABLE 0x410 +#define SC1200_VIDEO_VBI_HORIZ_CONTROL 0x414 +#define SC1200_VIDEO_ODD_VBI_TOTAL_COUNT 0x418 +#define SC1200_VIDEO_EVEN_VBI_TOTAL_COUNT 0x41C +#define SC1200_GENLOCK 0x420 +#define SC1200_GENLOCK_DELAY 0x424 +#define SC1200_TVOUT_HORZ_TIM 0x800 +#define SC1200_TVOUT_HORZ_SYNC 0x804 +#define SC1200_TVOUT_VERT_SYNC 0x808 +#define SC1200_TVOUT_LINE_END 0x80C +#define SC1200_TVOUT_VERT_DOWNSCALE 0x810 /* REV. A & B */ +#define SC1200_TVOUT_HORZ_PRE_ENCODER_SCALE 0x810 /* REV. C */ +#define SC1200_TVOUT_HORZ_SCALING 0x814 +#define SC1200_TVOUT_DEBUG 0x818 +#define SC1200_TVENC_TIM_CTRL_1 0xC00 +#define SC1200_TVENC_TIM_CTRL_2 0xC04 +#define SC1200_TVENC_TIM_CTRL_3 0xC08 +#define SC1200_TVENC_SUB_FREQ 0xC0C +#define SC1200_TVENC_DISP_POS 0xC10 +#define SC1200_TVENC_DISP_SIZE 0xC14 +#define SC1200_TVENC_CC_DATA 0xC18 +#define SC1200_TVENC_EDS_DATA 0xC1C +#define SC1200_TVENC_CGMS_DATA 0xC20 +#define SC1200_TVENC_WSS_DATA 0xC24 +#define SC1200_TVENC_CC_CONTROL 0xC28 +#define SC1200_TVENC_DAC_CONTROL 0xC2C +#define SC1200_TVENC_MV_CONTROL 0xC30 + +/* "SC1200_VIDEO_CONFIG" BIT DEFINITIONS */ + +#define SC1200_VCFG_VID_EN 0x00000001 +#define SC1200_VCFG_VID_INP_FORMAT 0x0000000C +#define SC1200_VCFG_UYVY_FORMAT 0x00000000 +#define SC1200_VCFG_Y2YU_FORMAT 0x00000004 +#define SC1200_VCFG_YUYV_FORMAT 0x00000008 +#define SC1200_VCFG_YVYU_FORMAT 0x0000000C +#define SC1200_VCFG_X_FILTER_EN 0x00000040 +#define SC1200_VCFG_Y_FILTER_EN 0x00000080 +#define SC1200_VCFG_LINE_SIZE_LOWER_MASK 0x0000FF00 +#define SC1200_VCFG_INIT_READ_MASK 0x01FF0000 +#define SC1200_VCFG_LINE_SIZE_UPPER 0x08000000 +#define SC1200_VCFG_4_2_0_MODE 0x10000000 + +/* "SC1200_DISPLAY_CONFIG" BIT DEFINITIONS */ + +#define SC1200_DCFG_DIS_EN 0x00000001 +#define SC1200_DCFG_HSYNC_EN 0x00000002 +#define SC1200_DCFG_VSYNC_EN 0x00000004 +#define SC1200_DCFG_DAC_BL_EN 0x00000008 +#define SC1200_DCFG_FP_PWR_EN 0x00000040 +#define SC1200_DCFG_FP_DATA_EN 0x00000080 +#define SC1200_DCFG_CRT_HSYNC_POL 0x00000100 +#define SC1200_DCFG_CRT_VSYNC_POL 0x00000200 +#define SC1200_DCFG_CRT_SYNC_SKW_MASK 0x0001C000 +#define SC1200_DCFG_CRT_SYNC_SKW_INIT 0x00010000 +#define SC1200_DCFG_PWR_SEQ_DLY_MASK 0x000E0000 +#define SC1200_DCFG_PWR_SEQ_DLY_INIT 0x00080000 +#define SC1200_DCFG_VG_CK 0x00100000 +#define SC1200_DCFG_GV_PAL_BYP 0x00200000 +#define SC1200_DCFG_DDC_SCL 0x00400000 +#define SC1200_DCFG_DDC_SDA 0x00800000 +#define SC1200_DCFG_DDC_OE 0x01000000 + +/* "SC1200_VID_MISC" BIT DEFINITIONS */ + +#define SC1200_GAMMA_BYPASS_BOTH 0x00000001 +#define SC1200_DAC_POWER_DOWN 0x00000400 +#define SC1200_ANALOG_POWER_DOWN 0x00000800 +#define SC1200_PLL_POWER_NORMAL 0x00001000 + +/* "SC1200_VIDEO_DOWNSCALER_CONTROL" BIT DEFINITIONS */ + +#define SC1200_VIDEO_DOWNSCALE_ENABLE 0x00000001 +#define SC1200_VIDEO_DOWNSCALE_FACTOR_POS 1 +#define SC1200_VIDEO_DOWNSCALE_FACTOR_MASK 0x0000001E +#define SC1200_VIDEO_DOWNSCALE_TYPE_A 0x00000000 +#define SC1200_VIDEO_DOWNSCALE_TYPE_B 0x00000040 +#define SC1200_VIDEO_DOWNSCALE_TYPE_MASK 0x00000040 + +/* "SC1200_VIDEO_DOWNSCALER_COEFFICIENTS" BIT DEFINITIONS */ + +#define SC1200_VIDEO_DOWNSCALER_COEF1_POS 0 +#define SC1200_VIDEO_DOWNSCALER_COEF2_POS 8 +#define SC1200_VIDEO_DOWNSCALER_COEF3_POS 16 +#define SC1200_VIDEO_DOWNSCALER_COEF4_POS 24 +#define SC1200_VIDEO_DOWNSCALER_COEF_MASK 0xF + +/* VIDEO DE-INTERLACING AND ALPHA CONTROL (REGISTER 0x4C) */ + +#define SC1200_VERTICAL_SCALER_SHIFT_MASK 0x00000007 +#define SC1200_VERTICAL_SCALER_SHIFT_INIT 0x00000004 +#define SC1200_VERTICAL_SCALER_SHIFT_EN 0x00000010 +#define SC1200_TOP_LINE_IN_ODD 0x00000040 +#define SC1200_NO_CK_OUTSIDE_ALPHA 0x00000100 +#define SC1200_VIDEO_IS_INTERLACED 0x00000200 +#define SC1200_CSC_VIDEO_YUV_TO_RGB 0x00000400 +#define SC1200_CSC_GFX_RGB_TO_YUV 0x00000800 +#define SC1200_VIDEO_INPUT_IS_RGB 0x00002000 +#define SC1200_VIDEO_LINE_OFFSET_ODD 0x00001000 +#define SC1200_ALPHA1_PRIORITY_POS 16 +#define SC1200_ALPHA1_PRIORITY_MASK 0x00030000 +#define SC1200_ALPHA2_PRIORITY_POS 18 +#define SC1200_ALPHA2_PRIORITY_MASK 0x000C0000 +#define SC1200_ALPHA3_PRIORITY_POS 20 +#define SC1200_ALPHA3_PRIORITY_MASK 0x00300000 + +/* VIDEO CURSOR COLOR KEY DEFINITIONS (REGISTER 0x50) */ + +#define SC1200_CURSOR_COLOR_KEY_OFFSET_POS 24 +#define SC1200_CURSOR_COLOR_BITS 23 +#define SC1200_COLOR_MASK 0x00FFFFFF /* 24 significant + * bits */ + +/* ALPHA COLOR BIT DEFINITION (REGISTERS 0x68, 0x78, AND 0x88) */ + +#define SC1200_ALPHA_COLOR_ENABLE 0x01000000 + +/* ALPHA CONTROL BIT DEFINITIONS (REGISTERS 0x6C, 0x7C, AND 0x8C) */ + +#define SC1200_ACTRL_WIN_ENABLE 0x00010000 +#define SC1200_ACTRL_LOAD_ALPHA 0x00020000 + +/* VIDEO REQUEST DEFINITIONS (REGISTER 0x90) */ + +#define SC1200_VIDEO_Y_REQUEST_POS 0 +#define SC1200_VIDEO_X_REQUEST_POS 16 +#define SC1200_VIDEO_REQUEST_MASK 0x00000FFF + +/* VIDEO DISPLAY MODE (REGISTER 0x400) */ + +#define SC1200_VIDEO_SOURCE_MASK 0x00000003 +#define SC1200_VIDEO_SOURCE_GX1 0x00000000 +#define SC1200_VIDEO_SOURCE_DVIP 0x00000002 +#define SC1200_VBI_SOURCE_MASK 0x00000004 +#define SC1200_VBI_SOURCE_DVIP 0x00000000 +#define SC1200_VBI_SOURCE_GX1 0x00000004 + +/* ODD/EVEN VBI LINE ENABLE (REGISTERS 0x40C, 0x410) */ + +#define SC1200_VIDEO_VBI_LINE_ENABLE_MASK 0x00FFFFFC +#define SC1200_VIDEO_ALL_ACTIVE_IS_VBI 0x01000000 +#define SC1200_VIDEO_VBI_LINE_OFFSET_POS 25 +#define SC1200_VIDEO_VBI_LINE_OFFSET_MASK 0x3E000000 + +/* ODD/EVEN VBI TOTAL COUNT (REGISTERS 0x418, 0x41C) */ + +#define SC1200_VIDEO_VBI_TOTAL_COUNT_MASK 0x000FFFFF + +/* GENLOCK BIT DEFINITIONS */ + +#define SC1200_GENLOCK_SINGLE_ENABLE 0x00000001 +#define SC1200_GENLOCK_FIELD_SYNC_ENABLE 0x00000001 +#define SC1200_GENLOCK_CONTINUOUS_ENABLE 0x00000002 +#define SC1200_GENLOCK_GX_VSYNC_FALLING_EDGE 0x00000004 +#define SC1200_GENLOCK_VIP_VSYNC_FALLING_EDGE 0x00000008 +#define SC1200_GENLOCK_TIMEOUT_ENABLE 0x00000010 +#define SC1200_GENLOCK_TVENC_RESET_EVEN_FIELD 0x00000020 +#define SC1200_GENLOCK_TVENC_RESET_BEFORE_DELAY 0x00000040 +#define SC1200_GENLOCK_TVENC_RESET_ENABLE 0x00000080 +#define SC1200_GENLOCK_SYNC_TO_TVENC 0x00000100 +#define SC1200_GENLOCK_DELAY_MASK 0x001FFFFF + +/* TVOUT HORIZONTAL PRE ENCODER SCALE BIT DEFINITIONS */ + +#define SC1200_TVOUT_YC_DELAY_MASK 0x00C00000 +#define SC1200_TVOUT_YC_DELAY_NONE 0x00000000 +#define SC1200_TVOUT_Y_DELAY_ONE_PIXEL 0x00400000 +#define SC1200_TVOUT_C_DELAY_ONE_PIXEL 0x00800000 +#define SC1200_TVOUT_C_DELAY_TWO_PIXELS 0x00C00000 + +/* TVOUT HORIZONTAL SCALING/CONTROL BIT DEFINITIONS */ + +#define SC1200_TVOUT_FLICKER_FILTER_MASK 0x60000000 +#define SC1200_TVOUT_FLICKER_FILTER_FOURTH_HALF_FOURTH 0x00000000 +#define SC1200_TVOUT_FLICKER_FILTER_HALF_ONE_HALF 0x20000000 +#define SC1200_TVOUT_FLICKER_FILTER_DISABLED 0x40000000 +#define SC1200_TVENC_EXTERNAL_RESET_INTERVAL_MASK 0x0F000000 +#define SC1200_TVENC_EXTERNAL_RESET_EVERY_ODD_FIELD 0x00000000 +#define SC1200_TVENC_EXTERNAL_RESET_EVERY_EVEN_FIELD 0x02000000 +#define SC1200_TVENC_EXTERNAL_RESET_NEXT_ODD_FIELD 0x05000000 +#define SC1200_TVENC_EXTERNAL_RESET_NEXT_EVEN_FIELD 0x07000000 +#define SC1200_TVENC_EXTERNAL_RESET_EVERY_FIELD 0x0E000000 +#define SC1200_TVENC_EXTERNAL_RESET_EVERY_X_ODD_FIELDS 0x08000000 +#define SC1200_TVENC_EXTERNAL_RESET_EVERY_X_EVEN_FIELDS 0x0A000000 + +/* TVOUT DEBUG BIT DEFINITIONS */ + +#define SC1200_TVOUT_FIELD_STATUS_EVEN 0x00000040 +#define SC1200_TVOUT_FIELD_STATUS_TV 0x00000080 +#define SC1200_TVOUT_CRT_VSYNC_STATUS_TRAILING 0x00000100 +#define SC1200_TVOUT_FIELD_STATUS_INVERT 0x00000200 +#define SC1200_TVOUT_CONVERTER_INTERPOLATION 0x00000400 + +/* TVENC TIMING/CONTROL 1 BIT DEFINITIONS (REGISTER 0xC00) */ + +#define SC1200_TVENC_VPHASE_MASK 0x001FF800 +#define SC1200_TVENC_VPHASE_POS 11 +#define SC1200_TVENC_SUB_CARRIER_RESET_MASK 0x30000000 +#define SC1200_TVENC_SUB_CARRIER_RESET_NEVER 0x00000000 +#define SC1200_TVENC_SUB_CARRIER_RESET_EVERY_TWO_LINES 0x10000000 +#define SC1200_TVENC_SUB_CARRIER_RESET_EVERY_TWO_FRAMES 0x20000000 +#define SC1200_TVENC_SUB_CARRIER_RESET_EVERY_FOUR_FRAMES 0x30000000 +#define SC1200_TVENC_VIDEO_TIMING_ENABLE 0x80000000 + +/* TVENC TIMING/CONTROL 2 BIT DEFINITIONS (REGISTER 0xC04) */ + +#define SC1200_TVENC_OUTPUT_YCBCR 0x40000000 +#define SC1200_TVENC_CFS_MASK 0x00030000 +#define SC1200_TVENC_CFS_BYPASS 0x00000000 +#define SC1200_TVENC_CFS_CVBS 0x00020000 +#define SC1200_TVENC_CFS_SVIDEO 0x00030000 + +/* TVENC TIMING/CONTROL 3 BIT DEFINITIONS (REGISTER 0xC08) */ + +#define SC1200_TVENC_CS 0x00000001 +#define SC1200_TVENC_SYNCMODE_MASK 0x00000006 +#define SC1200_TVENC_SYNC_ON_GREEN 0x00000002 +#define SC1200_TVENC_SYNC_ON_CVBS 0x00000004 +#define SC1200_TVENC_CM 0x00000008 + +/* TVENC DAC CONTROL BIT DEFINITIONS (REGISTER 0xC2C) */ +#define SC1200_TVENC_TRIM_MASK 0x00000007 +#define SC1200_TVENC_POWER_DOWN 0x00000020 + +/* TVENC MV CONTROL BIT DEFINITIONS (REGISTER 0xC30) */ +#define SC1200_TVENC_MV_ENABLE 0xBE + +/* SC1200 VIP REGISTER DEFINITIONS */ + +#define SC1200_VIP_CONFIG 0x00000000 +#define SC1200_VIP_CONTROL 0x00000004 +#define SC1200_VIP_STATUS 0x00000008 +#define SC1200_VIP_CURRENT_LINE 0x00000010 +#define SC1200_VIP_LINE_TARGET 0x00000014 +#define SC1200_ODD_DIRECT_VBI_LINE_ENABLE 0x00000018 +#define SC1200_EVEN_DIRECT_VBI_LINE_ENABLE 0x0000001C +#define SC1200_VIP_ODD_BASE 0x00000020 +#define SC1200_VIP_EVEN_BASE 0x00000024 +#define SC1200_VIP_PITCH 0x00000028 +#define SC1200_VBI_ODD_BASE 0x00000040 +#define SC1200_VBI_EVEN_BASE 0x00000044 +#define SC1200_VBI_PITCH 0x00000048 + +/* "SC1200_VIP_CONFIG" BIT DEFINITIONS */ + +#define SC1200_VIP_MODE_MASK 0x00000003 +#define SC1200_VIP_MODE_C 0x00000002 +#define SC1200_VBI_ANCILLARY_TO_MEMORY 0x000C0000 +#define SC1200_VBI_TASK_A_TO_MEMORY 0x00140000 +#define SC1200_VBI_TASK_B_TO_MEMORY 0x00240000 +#define SC1200_VIP_BUS_REQUEST_THRESHOLD 0x00400000 + +/* "SC1200_VIP_CONTROL" BIT DEFINITIONS */ + +#define SC1200_CAPTURE_RUN_MODE_MASK 0x00000003 +#define SC1200_CAPTURE_RUN_MODE_STOP_LINE 0x00000000 +#define SC1200_CAPTURE_RUN_MODE_STOP_FIELD 0x00000001 +#define SC1200_CAPTURE_RUN_MODE_START 0x00000003 +#define SC1200_VIP_DATA_CAPTURE_EN 0x00000100 +#define SC1200_VIP_VBI_CAPTURE_EN 0x00000200 +#define SC1200_VIP_VBI_FIELD_INTERRUPT_EN 0x00010000 + +/* "SC1200_VIP_STATUS" BIT DEFINITIONS */ + +#define SC1200_VIP_CURRENT_FIELD_ODD 0x01000000 +#define SC1200_VIP_BASE_NOT_UPDATED 0x00200000 +#define SC1200_VIP_FIFO_OVERFLOW 0x00100000 +#define SC1200_VIP_CLEAR_LINE_INT 0x00020000 +#define SC1200_VIP_CLEAR_FIELD_INT 0x00010000 +#define SC1200_VBI_DATA_CAPTURE_ACTIVE 0x00000200 +#define SC1200_VIDEO_DATA_CAPTURE_ACTIVE 0x00000100 + +/* "SC1200_VIP_CURRENT_LINE" BIT DEFINITIONS */ + +#define SC1200_VIP_CURRENT_LINE_MASK 0x000003FF + +/* "SC1200_VIP_LINE_TARGET" BIT DEFINITIONS */ + +#define SC1200_VIP_LAST_LINE_MASK 0x03FF0000 + +/* "SC1200_VIP_PITCH" BIT DEFINITION */ + +#define SC1200_VIP_PITCH_MASK 0x0000FFFC + +/* "SC1200_VBI_PITCH" BIT DEFINITION */ + +#define SC1200_VBI_PITCH_MASK 0x0000FFFC + +/* SC1200 DIRECT VBI LINE ENABLE BIT DEFINITION */ + +#define SC1200_DIRECT_VBI_LINE_ENABLE_MASK 0x00FFFFFF + +/* SC1200 CONFIGURATION BLOCK */ + +#define SC1200_CB_BASE_ADDR 0x9000 +#define SC1200_CB_WDTO 0x0000 +#define SC1200_CB_WDCNFG 0x0002 +#define SC1200_CB_WDSTS 0x0004 +#define SC1200_CB_TMVALUE 0x0008 +#define SC1200_CB_TMCNFG 0x000D +#define SC1200_CB_CCFC 0x001E +#define SC1200_CB_PMR 0x0030 +#define SC1200_CB_MCR 0x0034 +#define SC1200_CB_INTSEL 0x0038 +#define SC1200_CB_PID 0x003C +#define SC1200_CB_REV 0x003D + +/* SC1200 HIGH RESOLUTION TIMER CONFIGURATION REGISTER BITS */ + +#define SC1200_TMCLKSEL_27MHZ 0x2 + +/*---------------------------------*/ +/* PHILIPS SAA7114 VIDEO DECODER */ +/*---------------------------------*/ + +#define SAA7114_CHIPADDR 0x42 + +/* VIDEO DECODER REGISTER DEFINITIONS */ + +#define SAA7114_ANALOG_INPUT_CTRL1 0x02 +#define SAA7114_LUMINANCE_CONTROL 0x09 +#define SAA7114_BRIGHTNESS 0x0A +#define SAA7114_CONTRAST 0x0B +#define SAA7114_SATURATION 0x0C +#define SAA7114_HUE 0x0D +#define SAA7114_STATUS 0x1F +#define SAA7114_IPORT_CONTROL 0x86 + +/* TASK A REGISTER DEFINITIONS */ + +#define SAA7114_TASK_A_HORZ_OUTPUT_LO 0x9C +#define SAA7114_TASK_A_HORZ_OUTPUT_HI 0x9D +#define SAA7114_TASK_A_HSCALE_LUMA_LO 0xA8 +#define SAA7114_TASK_A_HSCALE_LUMA_HI 0xA9 +#define SAA7114_TASK_A_HSCALE_CHROMA_LO 0xAC +#define SAA7114_TASK_A_HSCALE_CHROMA_HI 0xAD + +/* TASK B REGISTER DEFINITIONS */ + +#define SAA7114_HORZ_OFFSET_LO 0xC4 +#define SAA7114_HORZ_OFFSET_HI 0xC5 +#define SAA7114_HORZ_INPUT_LO 0xC6 +#define SAA7114_HORZ_INPUT_HI 0xC7 +#define SAA7114_VERT_OFFSET_LO 0xC8 +#define SAA7114_VERT_OFFSET_HI 0xC9 +#define SAA7114_VERT_INPUT_LO 0xCA +#define SAA7114_VERT_INPUT_HI 0xCB +#define SAA7114_HORZ_OUTPUT_LO 0xCC +#define SAA7114_HORZ_OUTPUT_HI 0xCD +#define SAA7114_VERT_OUTPUT_LO 0xCE +#define SAA7114_VERT_OUTPUT_HI 0xCF +#define SAA7114_HORZ_PRESCALER 0xD0 +#define SAA7114_HORZ_ACL 0xD1 +#define SAA7114_HORZ_FIR_PREFILTER 0xD2 +#define SAA7114_FILTER_CONTRAST 0xD5 +#define SAA7114_FILTER_SATURATION 0xD6 +#define SAA7114_HSCALE_LUMA_LO 0xD8 +#define SAA7114_HSCALE_LUMA_HI 0xD9 +#define SAA7114_HSCALE_CHROMA_LO 0xDC +#define SAA7114_HSCALE_CHROMA_HI 0xDD +#define SAA7114_VSCALE_LUMA_LO 0xE0 +#define SAA7114_VSCALE_LUMA_HI 0xE1 +#define SAA7114_VSCALE_CHROMA_LO 0xE2 +#define SAA7114_VSCALE_CHROMA_HI 0xE3 +#define SAA7114_VSCALE_CONTROL 0xE4 +#define SAA7114_VSCALE_CHROMA_OFFS0 0xE8 +#define SAA7114_VSCALE_CHROMA_OFFS1 0xE9 +#define SAA7114_VSCALE_CHROMA_OFFS2 0xEA +#define SAA7114_VSCALE_CHROMA_OFFS3 0xEB +#define SAA7114_VSCALE_LUMINA_OFFS0 0xEC +#define SAA7114_VSCALE_LUMINA_OFFS1 0xED +#define SAA7114_VSCALE_LUMINA_OFFS2 0xEE +#define SAA7114_VSCALE_LUMINA_OFFS3 0xEF + +/* Still need to determine PHO value (common phase offset) */ +#define SAA7114_VSCALE_PHO 0x00 + +/*----------------------------------------------*/ +/* SECOND GENERATION GRAPHICS UNIT (REDCLOUD) */ +/*----------------------------------------------*/ + +#define MGP_DST_OFFSET 0x0000 /* dst address */ +#define MGP_SRC_OFFSET 0x0004 /* src address */ +#define MGP_VEC_ERR 0x0004 /* vector diag/axial errors */ +#define MGP_STRIDE 0x0008 /* src and dst strides */ +#define MGP_WID_HEIGHT 0x000C /* width and height of BLT */ +#define MGP_VEC_LEN 0x000C /* vector length/init error */ +#define MGP_SRC_COLOR_FG 0x0010 /* src mono data fgcolor */ +#define MGP_SRC_COLOR_BG 0x0014 /* src mono data bkcolor */ +#define MGP_PAT_COLOR_0 0x0018 /* pattern color 0 */ +#define MGP_PAT_COLOR_1 0x001C /* pattern color 1 */ +#define MGP_PAT_COLOR_2 0x0020 /* pattern color 2 */ +#define MGP_PAT_COLOR_3 0x0024 /* pattern color 3 */ +#define MGP_PAT_COLOR_4 0x0028 /* pattern color 4 */ +#define MGP_PAT_COLOR_5 0x002C /* pattern color 5 */ +#define MGP_PAT_DATA_0 0x0030 /* pattern data 0 */ +#define MGP_PAT_DATA_1 0x0034 /* pattern data 1 */ +#define MGP_RASTER_MODE 0x0038 /* raster operation */ +#define MGP_VECTOR_MODE 0x003C /* render vector */ +#define MGP_BLT_MODE 0x0040 /* render BLT */ +#define MGP_BLT_STATUS 0x0044 /* BLT status register */ +#define MGP_RESET 0x0044 /* reset register (write) */ +#define MGP_HST_SOURCE 0x0048 /* host src data (bitmap) */ +#define MGP_BASE_OFFSET 0x004C /* base render offset */ + +/* MGP_RASTER_MODE DEFINITIONS */ + +#define MGP_RM_BPPFMT_332 0x00000000 /* 8 BPP, 3:3:2 */ +#define MGP_RM_BPPFMT_4444 0x40000000 /* 16 BPP, 4:4:4:4 */ +#define MGP_RM_BPPFMT_1555 0x50000000 /* 16 BPP, 1:5:5:5 */ +#define MGP_RM_BPPFMT_565 0x60000000 /* 16 BPP, 5:6:5 */ +#define MGP_RM_BPPFMT_8888 0x80000000 /* 32 BPP, 8:8:8:8 */ +#define MGP_RM_ALPHA_EN_MASK 0x00C00000 /* Alpha enable */ +#define MGP_RM_ALPHA_TO_RGB 0x00400000 /* Alpha applies to RGB */ +#define MGP_RM_ALPHA_TO_ALPHA 0x00800000 /* Alpha applies to alpha */ +#define MGP_RM_ALPHA_OP_MASK 0x00300000 /* Alpha operation */ +#define MGP_RM_ALPHA_TIMES_A 0x00000000 /* Alpha * A */ +#define MGP_RM_BETA_TIMES_B 0x00100000 /* (1-alpha) * B */ +#define MGP_RM_A_PLUS_BETA_B 0x00200000 /* A + (1-alpha) * B */ +#define MGP_RM_ALPHA_A_PLUS_BETA_B 0x00300000 /* alpha * A + (1 - alpha)B */ +#define MGP_RM_ALPHA_SELECT 0x000E0000 /* Alpha Select */ +#define MGP_RM_SELECT_ALPHA_A 0x00000000 /* Alpha from channel A */ +#define MGP_RM_SELECT_ALPHA_B 0x00020000 /* Alpha from channel B */ +#define MGP_RM_SELECT_ALPHA_R 0x00040000 /* Registered alpha */ +#define MGP_RM_SELECT_ALPHA_1 0x00060000 /* Constant 1 */ +#define MGP_RM_SELECT_ALPHA_CHAN_A 0x00080000 /* RGB Values from A */ +#define MGP_RM_SELECT_ALPHA_CHAN_B 0x000A0000 /* RGB Values from B */ +#define MGP_RM_DEST_FROM_CHAN_A 0x00010000 /* Alpha channel select */ +#define MGP_RM_PAT_FLAGS 0x00000700 /* pattern related bits */ +#define MGP_RM_PAT_MONO 0x00000100 /* monochrome pattern */ +#define MGP_RM_PAT_COLOR 0x00000200 /* color pattern */ +#define MGP_RM_PAT_TRANS 0x00000400 /* pattern transparency */ +#define MGP_RM_SRC_TRANS 0x00000800 /* source transparency */ + +/* MGP_VECTOR_MODE DEFINITIONS */ + +#define MGP_VM_DST_REQ 0x00000008 /* dst data required */ +#define MGP_VM_THROTTLE 0x00000010 /* sync to VBLANK */ + +/* MGP_BLT_MODE DEFINITIONS */ + +#define MGP_BM_SRC_FB 0x00000001 /* src = frame buffer */ +#define MGP_BM_SRC_HOST 0x00000002 /* src = host register */ +#define MGP_BM_DST_REQ 0x00000004 /* dst data required */ +#define MGP_BM_SRC_MONO 0x00000040 /* monochrome source data */ +#define MGP_BM_SRC_BP_MONO 0x00000080 /* Byte-packed monochrome */ +#define MGP_BM_SRC_TYPE_MASK 0x000000C0 /* Mask for all source fmts */ +#define MGP_BM_NEG_YDIR 0x00000100 /* negative Y direction */ +#define MGP_BM_NEG_XDIR 0x00000200 /* negative X direction */ +#define MGP_BM_THROTTLE 0x00000400 /* sync to VBLANK */ + +/* MGP_BLT_STATUS DEFINITIONS */ + +#define MGP_BS_BLT_BUSY 0x00000001 /* GP is not idle */ +#define MGP_BS_BLT_PENDING 0x00000004 /* second BLT is pending */ +#define MGP_BS_HALF_EMPTY 0x00000008 /* src FIFO half empty */ + +/* ALPHA BLENDING MODES */ + +#define ALPHA_MODE_BLEND 0x00000000 + +/*---------------------------------------------------*/ +/* SECOND GENERATION DISPLAY CONTROLLER (REDCLOUD) */ +/*---------------------------------------------------*/ + +#define MDC_UNLOCK 0x00000000 /* Unlock register */ +#define MDC_GENERAL_CFG 0x00000004 /* Config registers */ +#define MDC_DISPLAY_CFG 0x00000008 +#define MDC_GFX_SCL 0x0000000C /* Graphics scaling */ + +#define MDC_FB_ST_OFFSET 0x00000010 /* Frame buffer start offset */ +#define MDC_CB_ST_OFFSET 0x00000014 /* Compression start offset */ +#define MDC_CURS_ST_OFFSET 0x00000018 /* Cursor buffer start */ + /* offset */ +#define MDC_ICON_ST_OFFSET 0x0000001C /* Icon buffer start offset */ +#define MDC_VID_Y_ST_OFFSET 0x00000020 /* Video Y Buffer start */ + /* offset */ +#define MDC_VID_U_ST_OFFSET 0x00000024 /* Video U Buffer start */ + /* offset */ +#define MDC_VID_V_ST_OFFSET 0x00000028 /* Video V Buffer start */ + /* offset */ +#define MDC_LINE_SIZE 0x00000030 /* Video, CB, and FB line */ + /* sizes */ +#define MDC_GFX_PITCH 0x00000034 /* FB and DB skip counts */ +#define MDC_VID_YUV_PITCH 0x00000038 /* Y, U and V buffer skip */ + /* counts */ + +#define MDC_H_ACTIVE_TIMING 0x00000040 /* Horizontal timings */ +#define MDC_H_BLANK_TIMING 0x00000044 +#define MDC_H_SYNC_TIMING 0x00000048 +#define MDC_V_ACTIVE_TIMING 0x00000050 /* Vertical Timings */ +#define MDC_V_BLANK_TIMING 0x00000054 +#define MDC_V_SYNC_TIMING 0x00000058 + +#define MDC_CURSOR_X 0x00000060 /* Cursor X position */ +#define MDC_CURSOR_Y 0x00000064 /* Cursor Y Position */ +#define MDC_ICON_X 0x00000068 /* Icon X Position */ +#define MDC_LINE_CNT_STATUS 0x0000006C /* Icon Y Position */ + +#define MDC_PAL_ADDRESS 0x00000070 /* Palette Address */ +#define MDC_PAL_DATA 0x00000074 /* Palette Data */ +#define MDC_DFIFO_DIAG 0x00000078 /* Display FIFO diagnostic */ +#define MDC_CFIFO_DIAG 0x0000007C /* Compression FIFO */ + /* diagnostic */ + +#define MDC_VID_DS_DELTA 0x00000080 /* Vertical Downscaling */ + /* fraction */ + +#define MDC_PHY_MEM_OFFSET 0x00000084 /* VG Base Address Register */ +#define MDC_DV_CTL 0x00000088 /* Dirty-Valid Control */ + /* Register */ +#define MDC_DV_ACC 0x0000008C /* Dirty-Valid RAM Access */ + +/* UNLOCK VALUE */ + +#define MDC_UNLOCK_VALUE 0x00004758 /* used to unlock DC regs */ + +/* VG MBUS DEVICE SMI MSR FIELDS */ + +#define MDC_VG_BL_MASK 0x00000001 +#define MDC_MISC_MASK 0x00000002 +#define MDC_ISR0_MASK 0x00000004 +#define MDC_VGA_BL_MASK 0x00000008 +#define MDC_CRTCIO_MSK 0x00000010 +#define MDC_VG_BLANK_SMI 0x00000001 +#define MDC_MISC_SMI 0x00000002 +#define MDC_ISR0_SMI 0x00000004 +#define MDC_VGA_BLANK_SMI 0x00000008 +#define MDC_CRTCIO_SMI 0x00000010 + +/* MDC_GENERAL_CFG BIT FIELDS */ + +#define MDC_GCFG_DBUG 0x80000000 +#define MDC_GCFG_DBSL 0x40000000 +#define MDC_GCFG_CFRW 0x20000000 +#define MDC_GCFG_DIAG 0x10000000 +#define MDC_GCFG_GXRFS4 0x08000000 +#define MDC_GCFG_SGFR 0x04000000 +#define MDC_GCFG_SGRE 0x02000000 +#define MDC_GCFG_SIGE 0x01000000 +#define MDC_GCFG_YUVM 0x00100000 +#define MDC_GCFG_VDSE 0x00080000 +#define MDC_GCFG_VGAFT 0x00040000 +#define MDC_GCFG_FDTY 0x00020000 +#define MDC_GCFG_STFM 0x00010000 +#define MDC_GCFG_DFHPEL_MASK 0x0000F000 +#define MDC_GCFG_DFHPSL_MASK 0x00000F00 +#define MDC_GCFG_VGAE 0x00000080 +#define MDC_GCFG_DECE 0x00000040 +#define MDC_GCFG_CMPE 0x00000020 +#define MDC_GCFG_VIDE 0x00000008 +#define MDC_GCFG_ICNE 0x00000004 +#define MDC_GCFG_CURE 0x00000002 +#define MDC_GCFG_DFLE 0x00000001 + +/* MDC_DISPLAY_CFG BIT FIELDS */ + +#define MDC_DCFG_A20M 0x80000000 +#define MDC_DCFG_A18M 0x40000000 +#define MDC_DCFG_VISL 0x08000000 +#define MDC_DCFG_FRLK 0x04000000 +#define MDC_DCFG_PALB 0x02000000 +#define MDC_DCFG_PIX_PAN_MASK 0x00F00000 +#define MDC_DCFG_DCEN 0x00080000 +#define MDC_DCFG_16BPP_MODE_MASK 0x00000C00 +#define MDC_DCFG_16BPP 0x00000000 +#define MDC_DCFG_15BPP 0x00000400 +#define MDC_DCFG_12BPP 0x00000800 +#define MDC_DCFG_DISP_MODE_MASK 0x00000300 +#define MDC_DCFG_DISP_MODE_8BPP 0x00000000 +#define MDC_DCFG_DISP_MODE_16BPP 0x00000100 +#define MDC_DCFG_DISP_MODE_24BPP 0x00000200 +#define MDC_DCFG_SCLE 0x00000080 +#define MDC_DCFG_TRUP 0x00000040 +#define MDC_DCFG_VIEN 0x00000020 +#define MDC_DCFG_VDEN 0x00000010 +#define MDC_DCFG_GDEN 0x00000008 +#define MDC_DCFG_VCKE 0x00000004 +#define MDC_DCFG_PCKE 0x00000002 +#define MDC_DCFG_TGEN 0x00000001 + +/* MDC_LINE_CNT BIT FIELDS */ + +#define MDC_LNCNT_DNA 0x80000000 +#define MDC_LNCNT_VNA 0x40000000 +#define MDC_LNCNT_VSA 0x20000000 +#define MDC_LNCNT_VINT 0x10000000 +#define MDC_LNCNT_FLIP 0x08000000 +#define MDC_LNCNT_V_LINE_CNT 0x07FF0000 +#define MDC_LNCNT_VFLIP 0x00008000 +#define MDC_LNCNT_SIGC 0x00004000 +#define MDC_LNCNT_SS_LINE_CMP 0x000007FF + +/* MDC_FB_ST_OFFSET BIT FIELDS */ + +#define MDC_FB_ST_OFFSET_MASK 0x0FFFFFFF + +/* MDC_CB_ST_OFFSET BIT FIELDS */ + +#define MDC_CB_ST_OFFSET_MASK 0x0FFFFFFF + +/* MDC_CURS_ST_OFFSET BIT FIELDS */ + +#define MDC_CURS_ST_OFFSET_MASK 0x0FFFFFFF + +/* MDC_ICON_ST_OFFSET BIT FIELDS */ + +#define MDC_ICON_ST_OFFSET_MASK 0x0FFFFFFF + +/* MDC_VID_Y_ST_OFFSET BIT FIELDS */ + +#define MDC_VID_Y_ST_OFFSET_MASK 0x0FFFFFFF + +/* MDC_VID_U_ST_OFFSET BIT FIELDS */ + +#define MDC_VID_U_ST_OFFSET_MASK 0x0FFFFFFF + +/* MDC_VID_V_ST_OFFSET BIT FIELDS */ + +#define MDC_VID_V_ST_OFFSET_MASK 0x0FFFFFFF + +/* MDC_LINE_SIZE BIT FIELDS */ + +#define MDC_LINE_SIZE_VLS_MASK 0xFF000000 +#define MDC_LINE_SIZE_CBLS_MASK 0x007F0000 +#define MDC_LINE_SIZE_FBLS_MASK 0x000007FF + +/* MDC_GFX_PITCH BIT FIELDS */ + +#define MDC_GFX_PITCH_CBP_MASK 0xFFFF0000 +#define MDC_GFX_PITCH_FBP_MASK 0x0000FFFF + +/* MDC_VID_YUV_PITCH BIT FIELDS */ + +#define MDC_YUV_PITCH_UVP_MASK 0xFFFF0000 +#define MDC_YUV_PITCH_YBP_MASK 0x0000FFFF + +/* MDC_H_ACTIVE_TIMING BIT FIELDS */ + +#define MDC_HAT_HT_MASK 0x0FF80000 +#define MDC_HAT_HA_MASK 0x00000FF8 + +/* MDC_H_BLANK_TIMING BIT FIELDS */ + +#define MDC_HBT_HBE_MASK 0x0FF80000 +#define MDC_HBT_HBS_MASK 0x00000FF8 + +/* MDC_H_SYNC_TIMING BIT FIELDS */ + +#define MDC_HST_HSE_MASK 0x0FF80000 +#define MDC_HST_HSS_MASK 0x00000FF8 + +/* MDC_V_ACTIVE_TIMING BIT FIELDS */ + +#define MDC_VAT_VT_MASK 0x07FF0000 +#define MDC_VAT_VA_MASK 0x000007FF + +/* MDC_V_BLANK_TIMING BIT FIELDS */ + +#define MDC_VBT_VBE_MASK 0x07FF0000 +#define MDC_VBT_VBS_MASK 0x000007FF + +/* MDC_V_SYNC_TIMING BIT FIELDS */ + +#define MDC_VST_VSE_MASK 0x07FF0000 +#define MDC_VST_VSS_MASK 0x000007FF + +/* MDC_DV_CTL BIT DEFINITIONS */ + +#define MDC_DV_LINE_SIZE_MASK 0x00000C00 +#define MDC_DV_LINE_SIZE_1024 0x00000000 +#define MDC_DV_LINE_SIZE_2048 0x00000400 +#define MDC_DV_LINE_SIZE_4096 0x00000800 +#define MDC_DV_LINE_SIZE_8192 0x00000C00 + +/* VGA DEFINITIONS */ + +#define MDC_SEQUENCER_INDEX 0x03C4 +#define MDC_SEQUENCER_DATA 0x03C5 +#define MDC_SEQUENCER_RESET 0x00 +#define MDC_SEQUENCER_CLK_MODE 0x01 + +#define MDC_RESET_VGA_DISP_ENABLE 0x03 +#define MDC_CLK_MODE_SCREEN_OFF 0x20 + +/*---------------------------------------------------*/ +/* REDCLOUD DISPLAY FILTER */ +/*---------------------------------------------------*/ + +/* RCDF VIDEO REGISTER DEFINITIONS */ + +#define RCDF_VIDEO_CONFIG 0x000 +#define RCDF_DISPLAY_CONFIG 0x008 +#define RCDF_VIDEO_X_POS 0x010 +#define RCDF_VIDEO_Y_POS 0x018 +#define RCDF_VIDEO_SCALE 0x020 +#define RCDF_VIDEO_COLOR_KEY 0x028 +#define RCDF_VIDEO_COLOR_MASK 0x030 +#define RCDF_PALETTE_ADDRESS 0x038 +#define RCDF_PALETTE_DATA 0x040 +#define RCDF_VID_MISC 0x050 +#define RCDF_VID_CLOCK_SELECT 0x058 +#define RCDF_VIDEO_DOWNSCALER_CONTROL 0x078 +#define RCDF_VIDEO_DOWNSCALER_COEFFICIENTS 0x080 +#define RCDF_VID_CRC 0x088 +#define RCDF_VID_CRC32 0x090 +#define RCDF_VID_ALPHA_CONTROL 0x098 +#define RCDF_CURSOR_COLOR_KEY 0x0A0 +#define RCDF_CURSOR_COLOR_MASK 0x0A8 +#define RCDF_CURSOR_COLOR_1 0x0B0 +#define RCDF_CURSOR_COLOR_2 0x0B8 +#define RCDF_ALPHA_XPOS_1 0x0C0 +#define RCDF_ALPHA_YPOS_1 0x0C8 +#define RCDF_ALPHA_COLOR_1 0x0D0 +#define RCDF_ALPHA_CONTROL_1 0x0D8 +#define RCDF_ALPHA_XPOS_2 0x0E0 +#define RCDF_ALPHA_YPOS_2 0x0E8 +#define RCDF_ALPHA_COLOR_2 0x0F0 +#define RCDF_ALPHA_CONTROL_2 0x0F8 +#define RCDF_ALPHA_XPOS_3 0x100 +#define RCDF_ALPHA_YPOS_3 0x108 +#define RCDF_ALPHA_COLOR_3 0x110 +#define RCDF_ALPHA_CONTROL_3 0x118 +#define RCDF_VIDEO_REQUEST 0x120 +#define RCDF_ALPHA_WATCH 0x128 +#define RCDF_VIDEO_TEST_MODE 0x210 +#define RCDF_POWER_MANAGEMENT 0x410 + +/* DISPLAY FILTER POWER MANAGEMENT DEFINITIONS */ + +#define RCDF_PM_PANEL_POWER_ON 0x01000000 + +/* DISPLAY FILTER MSRS */ + +#define RCDF_MBD_MSR_DIAG_DF 0x2010 +#define RCDF_DIAG_32BIT_CRC 0x80000000 + +/* "RCDF_VIDEO_CONFIG" BIT DEFINITIONS */ + +#define RCDF_VCFG_VID_EN 0x00000001 +#define RCDF_VCFG_VID_INP_FORMAT 0x0000000C +#define RCDF_VCFG_X_FILTER_EN 0x00000040 +#define RCDF_VCFG_Y_FILTER_EN 0x00000080 +#define RCDF_VCFG_LINE_SIZE_LOWER_MASK 0x0000FF00 +#define RCDF_VCFG_INIT_READ_MASK 0x01FF0000 +#define RCDF_VCFG_LINE_SIZE_UPPER 0x08000000 +#define RCDF_VCFG_4_2_0_MODE 0x10000000 +#define RCDF_VCFG_UYVY_FORMAT 0x00000000 +#define RCDF_VCFG_Y2YU_FORMAT 0x00000004 +#define RCDF_VCFG_YUYV_FORMAT 0x00000008 +#define RCDF_VCFG_YVYU_FORMAT 0x0000000C + +/* "RCDF_DISPLAY_CONFIG" BIT DEFINITIONS */ + +#define RCDF_DCFG_DIS_EN 0x00000001 +#define RCDF_DCFG_HSYNC_EN 0x00000002 +#define RCDF_DCFG_VSYNC_EN 0x00000004 +#define RCDF_DCFG_DAC_BL_EN 0x00000008 +#define RCDF_DCFG_FP_PWR_EN 0x00000040 +#define RCDF_DCFG_FP_DATA_EN 0x00000080 +#define RCDF_DCFG_CRT_HSYNC_POL 0x00000100 +#define RCDF_DCFG_CRT_VSYNC_POL 0x00000200 +#define RCDF_DCFG_CRT_SYNC_SKW_MASK 0x0001C000 +#define RCDF_DCFG_CRT_SYNC_SKW_INIT 0x00010000 +#define RCDF_DCFG_PWR_SEQ_DLY_MASK 0x000E0000 +#define RCDF_DCFG_PWR_SEQ_DLY_INIT 0x00080000 +#define RCDF_DCFG_VG_CK 0x00100000 +#define RCDF_DCFG_GV_PAL_BYP 0x00200000 +#define RCDF_DAC_VREF 0x04000000 +#define RCDF_FP_ON_STATUS 0x08000000 + +/* "RCDF_VID_MISC" BIT DEFINITIONS */ + +#define RCDF_GAMMA_BYPASS_BOTH 0x00000001 +#define RCDF_DAC_POWER_DOWN 0x00000400 +#define RCDF_ANALOG_POWER_DOWN 0x00000800 + +/* "RCDF_VIDEO_DOWNSCALER_CONTROL" BIT DEFINITIONS */ + +#define RCDF_VIDEO_DOWNSCALE_ENABLE 0x00000001 +#define RCDF_VIDEO_DOWNSCALE_FACTOR_POS 1 +#define RCDF_VIDEO_DOWNSCALE_FACTOR_MASK 0x0000001E +#define RCDF_VIDEO_DOWNSCALE_TYPE_A 0x00000000 +#define RCDF_VIDEO_DOWNSCALE_TYPE_B 0x00000040 +#define RCDF_VIDEO_DOWNSCALE_TYPE_MASK 0x00000040 + +/* "RCDF_VIDEO_DOWNSCALER_COEFFICIENTS" BIT DEFINITIONS */ + +#define RCDF_VIDEO_DOWNSCALER_COEF1_POS 0 +#define RCDF_VIDEO_DOWNSCALER_COEF2_POS 8 +#define RCDF_VIDEO_DOWNSCALER_COEF3_POS 16 +#define RCDF_VIDEO_DOWNSCALER_COEF4_POS 24 +#define RCDF_VIDEO_DOWNSCALER_COEF_MASK 0xF + +/* VIDEO DE-INTERLACING AND ALPHA CONTROL */ + +#define RCDF_NO_CK_OUTSIDE_ALPHA 0x00000100 +#define RCDF_CSC_VIDEO_YUV_TO_RGB 0x00000400 +#define RCDF_VIDEO_INPUT_IS_RGB 0x00002000 +#define RCDF_ALPHA1_PRIORITY_POS 16 +#define RCDF_ALPHA1_PRIORITY_MASK 0x00030000 +#define RCDF_ALPHA2_PRIORITY_POS 18 +#define RCDF_ALPHA2_PRIORITY_MASK 0x000C0000 +#define RCDF_ALPHA3_PRIORITY_POS 20 +#define RCDF_ALPHA3_PRIORITY_MASK 0x00300000 + +/* VIDEO CURSOR COLOR KEY DEFINITIONS */ + +#define RCDF_CURSOR_COLOR_KEY_ENABLE 0x20000000 +#define RCDF_CURSOR_COLOR_KEY_OFFSET_POS 24 +#define RCDF_CURSOR_COLOR_BITS 23 +#define RCDF_COLOR_MASK 0x00FFFFFF + /* 24 significant bits */ + +/* ALPHA COLOR BIT DEFINITION (REGISTERS 0x68, 0x78, AND 0x88) */ + +#define RCDF_ALPHA_COLOR_ENABLE 0x01000000 + +/* ALPHA CONTROL BIT DEFINITIONS (REGISTERS 0x6C, 0x7C, AND 0x8C) */ + +#define RCDF_ACTRL_WIN_ENABLE 0x00010000 +#define RCDF_ACTRL_LOAD_ALPHA 0x00020000 + +/* VIDEO REQUEST DEFINITIONS (REGISTER 0x90) */ + +#define RCDF_VIDEO_Y_REQUEST_POS 0 +#define RCDF_VIDEO_X_REQUEST_POS 16 +#define RCDF_VIDEO_REQUEST_MASK 0x000007FF + +/* GEODELINK DEVICE MSR REGISTER SUMMARY */ + +#define MBD_MSR_CAP 0x2000 /* Device Capabilities */ +#define MBD_MSR_CONFIG 0x2001 /* Device Master Configuration */ + /* Register */ +#define MBD_MSR_SMI 0x2002 /* MBus Device SMI Register */ +#define MBD_MSR_ERROR 0x2003 /* MBus Device Error */ +#define MBD_MSR_PM 0x2004 /* MBus Device Power Management */ + /* Register */ +#define MBD_MSR_DIAG 0x2005 /* Mbus Device Diagnostic Register */ + +/* DISPLAY FILTER MBD_MSR_DIAG DEFINITIONS */ + +#define RCDF_MBD_DIAG_SEL0 0x00007FFF /* Lower 32-bits of Diag Bus + * Select */ +#define RCDF_MBD_DIAG_EN0 0x00008000 /* Enable for lower 32-bits of + * diag bus */ +#define RCDF_MBD_DIAG_SEL1 0x7FFF0000 /* Upper 32-bits of Diag Bus + * Select */ +#define RCDF_MBD_DIAG_EN1 0x80000000 /* Enable for upper 32-bits of + * diag bus */ + +/* DISPLAY FILTER MBD_MSR_CONFIG DEFINITIONS */ + +#define RCDF_CONFIG_FMT_MASK 0x00000038 /* Output Format */ +#define RCDF_CONFIG_FMT_CRT 0x00000000 +#define RCDF_CONFIG_FMT_FP 0x00000008 + +/* MCP MSR DEFINITIONS */ + +#define MCP_CLKOFF 0x0010 +#define MCP_CLKACTIVE 0x0011 +#define MCP_CLKDISABLE 0x0012 +#define MCP_CLK4ACK 0x0013 +#define MCP_SYS_RSTPLL 0x0014 +#define MCP_DOTPLL 0x0015 +#define MCP_DBGCLKCTL 0x0016 +#define MCP_RC_REVID 0x0017 +#define MCP_SETM0CTL 0x0040 +#define MCP_SETN0CTL 0x0048 +#define MCP_CMPVAL0 0x0050 +#define MCP_CMPMASK0 0x0051 +#define MCP_REGA 0x0058 +#define MCP_REGB 0x0059 +#define MCP_REGAMASK 0x005A +#define MCP_REGAVAL 0x005B +#define MCP_REGBMASK 0x005C +#define MCP_REGBVAL 0x005D +#define MCP_FIFOCTL 0x005E +#define MCP_DIAGCTL 0x005F +#define MCP_H0CTL 0x0060 +#define MCP_XSTATE 0x0066 +#define MCP_YSTATE 0x0067 +#define MCP_ACTION0 0x0068 + +/* MCP_SYS_RSTPLL DEFINITIONS */ + +#define MCP_DOTPOSTDIV3 0x00000008 +#define MCP_DOTPREMULT2 0x00000004 +#define MCP_DOTPREDIV2 0x00000002 +#define MCP_DOTPLL_HALFPIX 0x01000000 + +/* MCP MBD_MSR_DIAG DEFINITIONS */ + +#define MCP_MBD_DIAG_SEL0 0x00000007 +#define MCP_MBD_DIAG_EN0 0x00008000 +#define MCP_MBD_DIAG_SEL1 0x00070000 +#define MCP_MBD_DIAG_EN1 0x80000000 + +/* MCP_DOTPLL DEFINITIONS */ + +#define MCP_DOTPLL_P 0x00000003 +#define MCP_DOTPLL_N 0x000001FC +#define MCP_DOTPLL_M 0x00001E00 +#define MCP_DOTPLL_LOCK 0x02000000 +#define MCP_DOTPLL_BYPASS 0x00008000 + +/*---------------------------------------------------*/ +/* THIRD GENERATION DISPLAY CONTROLLER (CASTLE) */ +/*---------------------------------------------------*/ + +#define DC3_VG_SPARE_MSR 0x2011 + +#define DC3_UNLOCK 0x00000000 /* Unlock register */ +#define DC3_GENERAL_CFG 0x00000004 /* Config registers */ +#define DC3_DISPLAY_CFG 0x00000008 +#define DC3_ARB_CFG 0x0000000C + +#define DC3_FB_ST_OFFSET 0x00000010 /* Frame buffer start offset */ +#define DC3_CB_ST_OFFSET 0x00000014 /* Compression start offset */ +#define DC3_CURS_ST_OFFSET 0x00000018 /* Cursor buffer start + * offset */ +#define DC3_VID_Y_ST_OFFSET 0x00000020 /* Video Y Buffer start + * offset */ +#define DC3_VID_U_ST_OFFSET 0x00000024 /* Video U Buffer start + * offset */ +#define DC3_VID_V_ST_OFFSET 0x00000028 /* Video V Buffer start + * offset */ +#define DC3_LINE_SIZE 0x00000030 /* Video, CB, and FB line + * sizes */ +#define DC3_GFX_PITCH 0x00000034 /* FB and DB skip counts */ +#define DC3_VID_YUV_PITCH 0x00000038 /* Y, U and V buffer skip + * counts */ + +#define DC3_H_ACTIVE_TIMING 0x00000040 /* Horizontal timings */ +#define DC3_H_BLANK_TIMING 0x00000044 +#define DC3_H_SYNC_TIMING 0x00000048 +#define DC3_V_ACTIVE_TIMING 0x00000050 /* Vertical Timings */ +#define DC3_V_BLANK_TIMING 0x00000054 +#define DC3_V_SYNC_TIMING 0x00000058 + +#define DC3_CURSOR_X 0x00000060 /* Cursor X position */ +#define DC3_CURSOR_Y 0x00000064 /* Cursor Y Position */ +#define DC3_LINE_CNT_STATUS 0x0000006C /* Icon Y Position */ + +#define DC3_PAL_ADDRESS 0x00000070 /* Palette Address */ +#define DC3_PAL_DATA 0x00000074 /* Palette Data */ +#define DC3_DFIFO_DIAG 0x00000078 /* Display FIFO diagnostic */ +#define DC3_CFIFO_DIAG 0x0000007C /* Compression FIFO + * diagnostic */ + +#define DC3_VID_DS_DELTA 0x00000080 /* Vertical Downscaling + * fraction */ + +#define DC3_PHY_MEM_OFFSET 0x00000084 /* VG Base Address Register */ +#define DC3_DV_CTL 0x00000088 /* Dirty-Valid Control + * Register */ +#define DC3_DV_ACC 0x0000008C /* Dirty-Valid RAM Access */ + +#define DC3_GFX_SCALE 0x00000090 +#define DC3_IRQ_CTL 0x00000094 + +#define DC3_COLOR_KEY 0x000000B8 /* Graphics color key */ +#define DC3_COLOR_MASK 0x000000BC /* Graphics color key mask */ +#define DC3_COLOR_KEY_X 0x000000C0 /* Color Key X Region */ +#define DC3_COLOR_KEY_Y 0x000000C4 /* Color Key Y Region */ + +/* UNLOCK VALUE */ + +#define DC3_UNLOCK_VALUE 0x00004758 /* used to unlock DC regs */ + +/* VG SPARE MSR FIELDS */ + +#define VG_SPARE_DISABLE_CFIFO_HGO 0x00000800 +#define VG_SPARE_VFIFO_ARB_SELECT 0x00000400 +#define VG_SPARE_WM_LPEN_OVRD 0x00000200 +#define VG_SPARE_LOAD_WM_LPEN_MASK 0x00000100 +#define VG_SPARE_DISABLE_INIT_VID_PRI 0x00000080 +#define VG_SPARE_DISABLE_VFIFO_WM 0x00000040 +#define VG_SPARE_DISABLE_CWD_CHECK 0x00000020 +#define VG_SPARE_PIX8_PAN_FIX 0x00000010 +#define VG_SPARE_FIRST_REQ_MASK 0x00000020 + +/* VG MBUS DEVICE SMI MSR FIELDS */ + +#define DC3_VG_BL_MASK 0x00000001 +#define DC3_MISC_MASK 0x00000002 +#define DC3_ISR0_MASK 0x00000004 +#define DC3_VGA_BL_MASK 0x00000008 +#define DC3_CRTCIO_MSK 0x00000010 +#define DC3_VG_BLANK_SMI 0x00000001 +#define DC3_MISC_SMI 0x00000002 +#define DC3_ISR0_SMI 0x00000004 +#define DC3_VGA_BLANK_SMI 0x00000008 +#define DC3_CRTCIO_SMI 0x00000010 + +/* DC3_GENERAL_CFG BIT FIELDS */ + +#define DC3_GCFG_DBUG 0x80000000 +#define DC3_GCFG_DBSL 0x40000000 +#define DC3_GCFG_CFRW 0x20000000 +#define DC3_GCFG_DIAG 0x10000000 +#define DC3_GCFG_SGFR 0x04000000 +#define DC3_GCFG_SGRE 0x02000000 +#define DC3_GCFG_SIGE 0x01000000 +#define DC3_GCFG_YUVM 0x00100000 +#define DC3_GCFG_VDSE 0x00080000 +#define DC3_GCFG_VGAFT 0x00040000 +#define DC3_GCFG_FDTY 0x00020000 +#define DC3_GCFG_STFM 0x00010000 +#define DC3_GCFG_DFHPEL_MASK 0x0000F000 +#define DC3_GCFG_DFHPSL_MASK 0x00000F00 +#define DC3_GCFG_VGAE 0x00000080 +#define DC3_GCFG_DECE 0x00000040 +#define DC3_GCFG_CMPE 0x00000020 +#define DC3_GCFG_VIDE 0x00000008 +#define DC3_GCFG_CURE 0x00000002 +#define DC3_GCFG_DFLE 0x00000001 + +/* DC3_DISPLAY_CFG BIT FIELDS */ + +#define DC3_DCFG_VISL 0x08000000 +#define DC3_DCFG_FRLK 0x04000000 +#define DC3_DCFG_PALB 0x02000000 +#define DC3_DCFG_PIX_PAN_MASK 0x00F00000 +#define DC3_DCFG_DCEN 0x00080000 +#define DC3_DCFG_16BPP_MODE_MASK 0x00000C00 +#define DC3_DCFG_16BPP 0x00000000 +#define DC3_DCFG_15BPP 0x00000400 +#define DC3_DCFG_12BPP 0x00000800 +#define DC3_DCFG_DISP_MODE_MASK 0x00000300 +#define DC3_DCFG_DISP_MODE_8BPP 0x00000000 +#define DC3_DCFG_DISP_MODE_16BPP 0x00000100 +#define DC3_DCFG_DISP_MODE_24BPP 0x00000200 +#define DC3_DCFG_SCLE 0x00000080 +#define DC3_DCFG_TRUP 0x00000040 +#define DC3_DCFG_VIEN 0x00000020 +#define DC3_DCFG_VDEN 0x00000010 +#define DC3_DCFG_GDEN 0x00000008 +#define DC3_DCFG_VCKE 0x00000004 +#define DC3_DCFG_PCKE 0x00000002 +#define DC3_DCFG_TGEN 0x00000001 + +/* DC3_LINE_CNT BIT FIELDS */ + +#define DC3_LNCNT_DNA 0x80000000 +#define DC3_LNCNT_VNA 0x40000000 +#define DC3_LNCNT_VSA 0x20000000 +#define DC3_LNCNT_VINT 0x10000000 +#define DC3_LNCNT_FLIP 0x08000000 +#define DC3_LNCNT_V_LINE_CNT 0x07FF0000 +#define DC3_LNCNT_VFLIP 0x00008000 +#define DC3_LNCNT_SIGC 0x00004000 +#define DC3_LNCNT_SS_LINE_CMP 0x000007FF + +/* DC3_FB_ST_OFFSET BIT FIELDS */ + +#define DC3_FB_ST_OFFSET_MASK 0x0FFFFFFF + +/* DC3_CB_ST_OFFSET BIT FIELDS */ + +#define DC3_CB_ST_OFFSET_MASK 0x0FFFFFFF + +/* DC3_CURS_ST_OFFSET BIT FIELDS */ + +#define DC3_CURS_ST_OFFSET_MASK 0x0FFFFFFF + +/* DC3_ICON_ST_OFFSET BIT FIELDS */ + +#define DC3_ICON_ST_OFFSET_MASK 0x0FFFFFFF + +/* DC3_VID_Y_ST_OFFSET BIT FIELDS */ + +#define DC3_VID_Y_ST_OFFSET_MASK 0x0FFFFFFF + +/* DC3_VID_U_ST_OFFSET BIT FIELDS */ + +#define DC3_VID_U_ST_OFFSET_MASK 0x0FFFFFFF + +/* DC3_VID_V_ST_OFFSET BIT FIELDS */ + +#define DC3_VID_V_ST_OFFSET_MASK 0x0FFFFFFF + +/* DC3_LINE_SIZE BIT FIELDS */ + +#define DC3_LINE_SIZE_VLS_MASK 0x3FF00000 +#define DC3_LINE_SIZE_CBLS_MASK 0x0007F000 +#define DC3_LINE_SIZE_FBLS_MASK 0x000003FF +#define DC3_LINE_SIZE_CB_SHIFT 12 +#define DC3_LINE_SIZE_VB_SHIFT 20 + +/* DC3_GFX_PITCH BIT FIELDS */ + +#define DC3_GFX_PITCH_CBP_MASK 0xFFFF0000 +#define DC3_GFX_PITCH_FBP_MASK 0x0000FFFF + +/* DC3_VID_YUV_PITCH BIT FIELDS */ + +#define DC3_YUV_PITCH_UVP_MASK 0xFFFF0000 +#define DC3_YUV_PITCH_YBP_MASK 0x0000FFFF + +/* DC3_H_ACTIVE_TIMING BIT FIELDS */ + +#define DC3_HAT_HT_MASK 0x0FF80000 +#define DC3_HAT_HA_MASK 0x00000FF8 + +/* DC3_H_BLANK_TIMING BIT FIELDS */ + +#define DC3_HBT_HBE_MASK 0x0FF80000 +#define DC3_HBT_HBS_MASK 0x00000FF8 + +/* DC3_H_SYNC_TIMING BIT FIELDS */ + +#define DC3_HST_HSE_MASK 0x0FF80000 +#define DC3_HST_HSS_MASK 0x00000FF8 + +/* DC3_V_ACTIVE_TIMING BIT FIELDS */ + +#define DC3_VAT_VT_MASK 0x07FF0000 +#define DC3_VAT_VA_MASK 0x000007FF + +/* DC3_V_BLANK_TIMING BIT FIELDS */ + +#define DC3_VBT_VBE_MASK 0x07FF0000 +#define DC3_VBT_VBS_MASK 0x000007FF + +/* DC3_V_SYNC_TIMING BIT FIELDS */ + +#define DC3_VST_VSE_MASK 0x07FF0000 +#define DC3_VST_VSS_MASK 0x000007FF + +/* DC3_DV_CTL BIT DEFINITIONS */ + +#define DC3_DV_LINE_SIZE_MASK 0x00000C00 +#define DC3_DV_LINE_SIZE_1024 0x00000000 +#define DC3_DV_LINE_SIZE_2048 0x00000400 +#define DC3_DV_LINE_SIZE_4096 0x00000800 +#define DC3_DV_LINE_SIZE_8192 0x00000C00 + +#define DC3_CLR_KEY_DATA_MASK 0x00FFFFFF +#define DC3_CLR_KEY_ENABLE 0x01000000 +#define DC3_CLR_KEY_INVERT 0x02000000 + +/* VGA DEFINITIONS */ + +#define DC3_SEQUENCER_INDEX 0x03C4 +#define DC3_SEQUENCER_DATA 0x03C5 +#define DC3_SEQUENCER_RESET 0x00 +#define DC3_SEQUENCER_CLK_MODE 0x01 + +#define DC3_RESET_VGA_DISP_ENABLE 0x03 +#define DC3_CLK_MODE_SCREEN_OFF 0x20 + +/*---------------------------------------------------*/ +/* CASTLE DISPLAY FILTER */ +/*---------------------------------------------------*/ + +/* CASTLE VIDEO REGISTER DEFINITIONS */ + +#define CASTLE_VIDEO_CONFIG 0x000 +#define CASTLE_DISPLAY_CONFIG 0x008 +#define CASTLE_VIDEO_X_POS 0x010 +#define CASTLE_VIDEO_Y_POS 0x018 +#define CASTLE_VIDEO_SCALER 0x020 +#define CASTLE_VIDEO_COLOR_KEY 0x028 +#define CASTLE_VIDEO_COLOR_MASK 0x030 +#define CASTLE_PALETTE_ADDRESS 0x038 +#define CASTLE_PALETTE_DATA 0x040 +#define CASTLE_VID_MISC 0x050 +#define CASTLE_VIDEO_YSCALE 0x060 +#define CASTLE_VIDEO_XSCALE 0x068 +#define CASTLE_VIDEO_DOWNSCALER_CONTROL 0x078 +#define CASTLE_VID_CRC 0x088 +#define CASTLE_VID_CRC32 0x090 +#define CASTLE_VID_ALPHA_CONTROL 0x098 +#define CASTLE_CURSOR_COLOR_KEY 0x0A0 +#define CASTLE_CURSOR_COLOR_MASK 0x0A8 +#define CASTLE_CURSOR_COLOR_1 0x0B0 +#define CASTLE_CURSOR_COLOR_2 0x0B8 +#define CASTLE_ALPHA_XPOS_1 0x0C0 +#define CASTLE_ALPHA_YPOS_1 0x0C8 +#define CASTLE_ALPHA_COLOR_1 0x0D0 +#define CASTLE_ALPHA_CONTROL_1 0x0D8 +#define CASTLE_ALPHA_XPOS_2 0x0E0 +#define CASTLE_ALPHA_YPOS_2 0x0E8 +#define CASTLE_ALPHA_COLOR_2 0x0F0 +#define CASTLE_ALPHA_CONTROL_2 0x0F8 +#define CASTLE_ALPHA_XPOS_3 0x100 +#define CASTLE_ALPHA_YPOS_3 0x108 +#define CASTLE_ALPHA_COLOR_3 0x110 +#define CASTLE_ALPHA_CONTROL_3 0x118 +#define CASTLE_VIDEO_REQUEST 0x120 +#define CASTLE_ALPHA_WATCH 0x128 +#define CASTLE_VIDEO_TEST_MODE 0x210 +#define CASTLE_POWER_MANAGEMENT 0x410 +#define CASTLE_COEFFICIENT_BASE 0x1000 + +/* DISPLAY FILTER POWER MANAGEMENT DEFINITIONS */ + +#define CASTLE_PM_PANEL_POWER_ON 0x01000000 + +/* DISPLAY FILTER MSRS */ + +#define CASTLE_MBD_MSR_DIAG_DF 0x2010 +#define CASTLE_DIAG_32BIT_CRC 0x80000000 + +/* "CASTLE_VIDEO_CONFIG" BIT DEFINITIONS */ + +#define CASTLE_VCFG_VID_EN 0x00000001 +#define CASTLE_VCFG_VID_INP_FORMAT 0x0000000C +#define CASTLE_VCFG_SC_BYP 0x00000020 +#define CASTLE_VCFG_LINE_SIZE_LOWER_MASK 0x0000FF00 +#define CASTLE_VCFG_INIT_READ_MASK 0x01FF0000 +#define CASTLE_VCFG_LINE_SIZE_BIT9 0x04000000 +#define CASTLE_VCFG_LINE_SIZE_UPPER 0x08000000 +#define CASTLE_VCFG_4_2_0_MODE 0x10000000 +#define CASTLE_VCFG_UYVY_FORMAT 0x00000000 +#define CASTLE_VCFG_Y2YU_FORMAT 0x00000004 +#define CASTLE_VCFG_YUYV_FORMAT 0x00000008 +#define CASTLE_VCFG_YVYU_FORMAT 0x0000000C + +/* "CASTLE_DISPLAY_CONFIG" BIT DEFINITIONS */ + +#define CASTLE_DCFG_DIS_EN 0x00000001 +#define CASTLE_DCFG_HSYNC_EN 0x00000002 +#define CASTLE_DCFG_VSYNC_EN 0x00000004 +#define CASTLE_DCFG_DAC_BL_EN 0x00000008 +#define CASTLE_DCFG_CRT_HSYNC_POL 0x00000100 +#define CASTLE_DCFG_CRT_VSYNC_POL 0x00000200 +#define CASTLE_DCFG_CRT_SYNC_SKW_MASK 0x0001C000 +#define CASTLE_DCFG_CRT_SYNC_SKW_INIT 0x00010000 +#define CASTLE_DCFG_PWR_SEQ_DLY_MASK 0x000E0000 +#define CASTLE_DCFG_PWR_SEQ_DLY_INIT 0x00080000 +#define CASTLE_DCFG_VG_CK 0x00100000 +#define CASTLE_DCFG_GV_PAL_BYP 0x00200000 +#define CASTLE_DAC_VREF 0x04000000 + +/* "CASTLE_VID_MISC" BIT DEFINITIONS */ + +#define CASTLE_GAMMA_BYPASS_BOTH 0x00000001 +#define CASTLE_DAC_POWER_DOWN 0x00000400 +#define CASTLE_ANALOG_POWER_DOWN 0x00000800 + +/* VIDEO DE-INTERLACING AND ALPHA CONTROL */ + +#define CASTLE_NO_CK_OUTSIDE_ALPHA 0x00000100 +#define CASTLE_CSC_VIDEO_YUV_TO_RGB 0x00000400 +#define CASTLE_CSC_GRAPHICS_RGB_TO_YUV 0x00000800 +#define CASTLE_VIDEO_INPUT_IS_RGB 0x00002000 +#define CASTLE_ALPHA1_PRIORITY_POS 16 +#define CASTLE_ALPHA1_PRIORITY_MASK 0x00030000 +#define CASTLE_ALPHA2_PRIORITY_POS 18 +#define CASTLE_ALPHA2_PRIORITY_MASK 0x000C0000 +#define CASTLE_ALPHA3_PRIORITY_POS 20 +#define CASTLE_ALPHA3_PRIORITY_MASK 0x00300000 + +/* VIDEO CURSOR COLOR KEY DEFINITIONS */ + +#define CASTLE_CURSOR_COLOR_KEY_ENABLE 0x20000000 +#define CASTLE_CURSOR_COLOR_KEY_OFFSET_POS 24 +#define CASTLE_CURSOR_COLOR_BITS 23 +#define CASTLE_COLOR_MASK 0x00FFFFFF /* 24 significant + * bits */ + +/* ALPHA COLOR BIT DEFINITION (REGISTERS 0x68, 0x78, AND 0x88) */ + +#define CASTLE_ALPHA_COLOR_ENABLE 0x01000000 + +/* ALPHA CONTROL BIT DEFINITIONS (REGISTERS 0x6C, 0x7C, AND 0x8C) */ + +#define CASTLE_ACTRL_WIN_ENABLE 0x00010000 +#define CASTLE_ACTRL_LOAD_ALPHA 0x00020000 + +/* CASTLE_VIDEO_SCALER DEFINITIONS */ + +#define CASTLE_SCALE_128_PHASES 0x00002000 + +/* VIDEO REQUEST DEFINITIONS (REGISTER 0x90) */ + +#define CASTLE_VIDEO_Y_REQUEST_POS 0 +#define CASTLE_VIDEO_X_REQUEST_POS 16 +#define CASTLE_VIDEO_REQUEST_MASK 0x000007FF + +/* END OF FILE */ diff --git a/src/gfx/gfx_rndr.c b/src/gfx/gfx_rndr.c new file mode 100644 index 0000000..c5a46ac --- /dev/null +++ b/src/gfx/gfx_rndr.c @@ -0,0 +1,671 @@ +/* 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 to program the 2D acceleration hardware: + * + * gfx_set_bpp + * gfx_set_solid_pattern + * gfx_set_mono_pattern + * gfx_set_color_pattern + * gfx_load_color_pattern_line + * gfx_set_solid_source + * gfx_set_mono_source + * gfx_set_raster_operation + * gfx_pattern_fill + * gfx_color_pattern_fill + * gfx_screen_to_screen_blt + * gfx_screen_to_screen_xblt + * gfx_color_bitmap_to_screen_blt + * gfx_color_bitmap_to_screen_xblt + * gfx_mono_bitmap_to_screen_blt + * gfx_bresenham_line + * gfx_wait_until_idle + * */ + +/* STATIC VARIABLES */ + +unsigned short GFXbpp = 16; +unsigned short GFXbb0Base = 0x400; +unsigned short GFXbb1Base = 0x930; +unsigned short GFXbufferWidthPixels = 400; + +unsigned short GFXpatternFlags = 0; +unsigned short GFXsourceFlags = 0; +unsigned long GFXsavedColor = 0; +unsigned short GFXsavedRop = 0; +unsigned short GFXusesDstData = 0; + +/* INCLUDE SUPPORT FOR FIRST GENERATION, IF SPECIFIED. */ + +#if GFX_2DACCEL_GU1 +#include "rndr_gu1.c" +#endif + +/* INCLUDE SUPPORT FOR SECOND GENERATION, IF SPECIFIED. */ + +#if GFX_2DACCEL_GU2 +#include "rndr_gu2.c" +#endif + +/* WRAPPERS IF DYNAMIC SELECTION */ +/* Extra layer to call either first or second generation routines. */ + +#if GFX_2DACCEL_DYNAMIC + +/*--------------------------------------------------------------------------- + * gfx_reset_pitch (PRIVATE ROUTINE - NOT PART OF API) + *--------------------------------------------------------------------------- + */ +void +gfx_reset_pitch(unsigned short pitch) +{ +#if GFX_2DACCEL_GU2 + if (gfx_2daccel_type & GFX_2DACCEL_TYPE_GU2) + gu2_reset_pitch(pitch); +#endif +} + +/*--------------------------------------------------------------------------- + * gfx_set_bpp + *--------------------------------------------------------------------------- + */ +void +gfx_set_bpp(unsigned short bpp) +{ +#if GFX_2DACCEL_GU1 + if (gfx_2daccel_type & GFX_2DACCEL_TYPE_GU1) + gu1_set_bpp(bpp); +#endif +#if GFX_2DACCEL_GU2 + if (gfx_2daccel_type & GFX_2DACCEL_TYPE_GU2) + gu2_set_bpp(bpp); +#endif +} + +/*--------------------------------------------------------------------------- + * gfx_set_solid_source + *--------------------------------------------------------------------------- + */ +void +gfx_set_solid_source(unsigned long color) +{ +#if GFX_2DACCEL_GU1 + if (gfx_2daccel_type & GFX_2DACCEL_TYPE_GU1) + gu1_set_solid_source(color); +#endif +#if GFX_2DACCEL_GU2 + if (gfx_2daccel_type & GFX_2DACCEL_TYPE_GU2) + gu2_set_solid_source(color); +#endif +} + +/*--------------------------------------------------------------------------- + * gfx_set_mono_source + *--------------------------------------------------------------------------- + */ +void +gfx_set_mono_source(unsigned long bgcolor, unsigned long fgcolor, + unsigned short transparent) +{ +#if GFX_2DACCEL_GU1 + if (gfx_2daccel_type & GFX_2DACCEL_TYPE_GU1) + gu1_set_mono_source(bgcolor, fgcolor, transparent); +#endif +#if GFX_2DACCEL_GU2 + if (gfx_2daccel_type & GFX_2DACCEL_TYPE_GU2) + gu2_set_mono_source(bgcolor, fgcolor, transparent); +#endif +} + +void +gfx_set_pattern_flags(unsigned short flags) +{ + GFXpatternFlags |= flags; +} + +/*--------------------------------------------------------------------------- + * gfx_set_solid_pattern + *--------------------------------------------------------------------------- + */ +void +gfx_set_solid_pattern(unsigned long color) +{ +#if GFX_2DACCEL_GU1 + if (gfx_2daccel_type & GFX_2DACCEL_TYPE_GU1) + gu1_set_solid_pattern(color); +#endif +#if GFX_2DACCEL_GU2 + if (gfx_2daccel_type & GFX_2DACCEL_TYPE_GU2) + gu2_set_solid_pattern(color); +#endif +} + +/*--------------------------------------------------------------------------- + * gfx_set_mono_pattern + *--------------------------------------------------------------------------- + */ +void +gfx_set_mono_pattern(unsigned long bgcolor, unsigned long fgcolor, + unsigned long data0, unsigned long data1, unsigned char transparent) +{ +#if GFX_2DACCEL_GU1 + if (gfx_2daccel_type & GFX_2DACCEL_TYPE_GU1) + gu1_set_mono_pattern(bgcolor, fgcolor, data0, data1, transparent); +#endif +#if GFX_2DACCEL_GU2 + if (gfx_2daccel_type & GFX_2DACCEL_TYPE_GU2) + gu2_set_mono_pattern(bgcolor, fgcolor, data0, data1, transparent); +#endif +} + +/*--------------------------------------------------------------------------- + * gfx_set_color_pattern + *--------------------------------------------------------------------------- + */ +void +gfx_set_color_pattern(unsigned long bgcolor, unsigned long fgcolor, + unsigned long data0, unsigned long data1, + unsigned long data2, unsigned long data3, unsigned char transparent) +{ +#if GFX_2DACCEL_GU1 + if (gfx_2daccel_type & GFX_2DACCEL_TYPE_GU1) + gu1_set_color_pattern(bgcolor, fgcolor, data0, data1, data2, data3, + transparent); +#endif +#if GFX_2DACCEL_GU2 + if (gfx_2daccel_type & GFX_2DACCEL_TYPE_GU2) + gu2_set_color_pattern(bgcolor, fgcolor, data0, data1, data2, data3, + transparent); +#endif +} + +/*--------------------------------------------------------------------------- + * gfx_load_color_pattern_line + *--------------------------------------------------------------------------- + */ +void +gfx_load_color_pattern_line(short y, unsigned long *pattern_8x8) +{ +#if GFX_2DACCEL_GU1 + if (gfx_2daccel_type & GFX_2DACCEL_TYPE_GU1) + gu1_load_color_pattern_line(y, pattern_8x8); +#endif +#if GFX_2DACCEL_GU2 + if (gfx_2daccel_type & GFX_2DACCEL_TYPE_GU2) + gu2_load_color_pattern_line(y, pattern_8x8); +#endif +} + +/*--------------------------------------------------------------------------- + * gfx_set_raster_operation + *--------------------------------------------------------------------------- + */ +void +gfx_set_raster_operation(unsigned char rop) +{ +#if GFX_2DACCEL_GU1 + if (gfx_2daccel_type & GFX_2DACCEL_TYPE_GU1) + gu1_set_raster_operation(rop); +#endif +#if GFX_2DACCEL_GU2 + if (gfx_2daccel_type & GFX_2DACCEL_TYPE_GU2) + gu2_set_raster_operation(rop); +#endif +} + +/*--------------------------------------------------------------------------- + * gfx_pattern_fill + *--------------------------------------------------------------------------- + */ +void +gfx_pattern_fill(unsigned short x, unsigned short y, + unsigned short width, unsigned short height) +{ +#if GFX_2DACCEL_GU1 + if (gfx_2daccel_type & GFX_2DACCEL_TYPE_GU1) + gu1_pattern_fill(x, y, width, height); +#endif +#if GFX_2DACCEL_GU2 + if (gfx_2daccel_type & GFX_2DACCEL_TYPE_GU2) + gu2_pattern_fill(x, y, width, height); +#endif +} + +/*--------------------------------------------------------------------------- + * gfx_color_pattern_fill + *--------------------------------------------------------------------------- + */ +void +gfx_color_pattern_fill(unsigned short x, unsigned short y, + unsigned short width, unsigned short height, unsigned long *pattern) +{ +#if GFX_2DACCEL_GU1 + if (gfx_2daccel_type & GFX_2DACCEL_TYPE_GU1) + gu1_color_pattern_fill(x, y, width, height, pattern); +#endif +#if GFX_2DACCEL_GU2 + if (gfx_2daccel_type & GFX_2DACCEL_TYPE_GU2) + gu2_color_pattern_fill(x, y, width, height, pattern); +#endif +} + +/*--------------------------------------------------------------------------- + * gfx_screen_to_screen_blt + *--------------------------------------------------------------------------- + */ +void +gfx_screen_to_screen_blt(unsigned short srcx, unsigned short srcy, + unsigned short dstx, unsigned short dsty, unsigned short width, + unsigned short height) +{ +#if GFX_2DACCEL_GU1 + if (gfx_2daccel_type & GFX_2DACCEL_TYPE_GU1) + gu1_screen_to_screen_blt(srcx, srcy, dstx, dsty, width, height); +#endif +#if GFX_2DACCEL_GU2 + if (gfx_2daccel_type & GFX_2DACCEL_TYPE_GU2) + gu2_screen_to_screen_blt(srcx, srcy, dstx, dsty, width, height); +#endif +} + +/*--------------------------------------------------------------------------- + * gfx_screen_to_screen_xblt + *--------------------------------------------------------------------------- + */ +void +gfx_screen_to_screen_xblt(unsigned short srcx, unsigned short srcy, + unsigned short dstx, unsigned short dsty, unsigned short width, + unsigned short height, unsigned long color) +{ +#if GFX_2DACCEL_GU1 + if (gfx_2daccel_type & GFX_2DACCEL_TYPE_GU1) + gu1_screen_to_screen_xblt(srcx, srcy, dstx, dsty, width, height, + color); +#endif +#if GFX_2DACCEL_GU2 + if (gfx_2daccel_type & GFX_2DACCEL_TYPE_GU2) + gu2_screen_to_screen_xblt(srcx, srcy, dstx, dsty, width, height, + color); +#endif +} + +/*--------------------------------------------------------------------------- + * gfx_color_bitmap_to_screen_blt + *--------------------------------------------------------------------------- + */ +void +gfx_color_bitmap_to_screen_blt(unsigned short srcx, unsigned short srcy, + unsigned short dstx, unsigned short dsty, unsigned short width, + unsigned short height, unsigned char *data, long pitch) +{ +#if GFX_2DACCEL_GU1 + if (gfx_2daccel_type & GFX_2DACCEL_TYPE_GU1) + gu1_color_bitmap_to_screen_blt(srcx, srcy, dstx, dsty, width, height, + data, pitch); +#endif +#if GFX_2DACCEL_GU2 + if (gfx_2daccel_type & GFX_2DACCEL_TYPE_GU2) + gu2_color_bitmap_to_screen_blt(srcx, srcy, dstx, dsty, width, height, + data, pitch); +#endif +} + +/*--------------------------------------------------------------------------- + * gfx_color_bitmap_to_screen_xblt + *--------------------------------------------------------------------------- + */ +void +gfx_color_bitmap_to_screen_xblt(unsigned short srcx, unsigned short srcy, + unsigned short dstx, unsigned short dsty, unsigned short width, + unsigned short height, unsigned char *data, long pitch, + unsigned long color) +{ +#if GFX_2DACCEL_GU1 + if (gfx_2daccel_type & GFX_2DACCEL_TYPE_GU1) + gu1_color_bitmap_to_screen_xblt(srcx, srcy, dstx, dsty, width, height, + data, pitch, color); +#endif +#if GFX_2DACCEL_GU2 + if (gfx_2daccel_type & GFX_2DACCEL_TYPE_GU2) + gu2_color_bitmap_to_screen_xblt(srcx, srcy, dstx, dsty, width, height, + data, pitch, color); +#endif +} + +/*--------------------------------------------------------------------------- + * gfx_mono_bitmap_to_screen_blt + *--------------------------------------------------------------------------- + */ +void +gfx_mono_bitmap_to_screen_blt(unsigned short srcx, unsigned short srcy, + unsigned short dstx, unsigned short dsty, unsigned short width, + unsigned short height, unsigned char *data, short pitch) +{ +#if GFX_2DACCEL_GU1 + if (gfx_2daccel_type & GFX_2DACCEL_TYPE_GU1) + gu1_mono_bitmap_to_screen_blt(srcx, srcy, dstx, dsty, width, height, + data, pitch); +#endif +#if GFX_2DACCEL_GU2 + if (gfx_2daccel_type & GFX_2DACCEL_TYPE_GU2) + gu2_mono_bitmap_to_screen_blt(srcx, srcy, dstx, dsty, width, height, + data, pitch); +#endif +} + +/*--------------------------------------------------------------------------- + * gfx_text_blt + *--------------------------------------------------------------------------- + */ +void +gfx_text_blt(unsigned short dstx, unsigned short dsty, unsigned short width, + unsigned short height, unsigned char *data) +{ +#if GFX_2DACCEL_GU1 + if (gfx_2daccel_type & GFX_2DACCEL_TYPE_GU1) + gu1_text_blt(dstx, dsty, width, height, data); +#endif +#if GFX_2DACCEL_GU2 + if (gfx_2daccel_type & GFX_2DACCEL_TYPE_GU2) + gu2_text_blt(dstx, dsty, width, height, data); +#endif +} + +/*--------------------------------------------------------------------------- + * gfx_bresenham_line + *--------------------------------------------------------------------------- + */ +void +gfx_bresenham_line(unsigned short x, unsigned short y, + unsigned short length, unsigned short initerr, + unsigned short axialerr, unsigned short diagerr, unsigned short flags) +{ +#if GFX_2DACCEL_GU1 + if (gfx_2daccel_type & GFX_2DACCEL_TYPE_GU1) + gu1_bresenham_line(x, y, length, initerr, axialerr, diagerr, flags); +#endif +#if GFX_2DACCEL_GU2 + if (gfx_2daccel_type & GFX_2DACCEL_TYPE_GU2) + gu2_bresenham_line(x, y, length, initerr, axialerr, diagerr, flags); +#endif +} + +/*--------------------------------------------------------------------------- + * gfx_wait_until_idle + *--------------------------------------------------------------------------- + */ +void +gfx_wait_until_idle(void) +{ +#if GFX_2DACCEL_GU1 + if (gfx_2daccel_type & GFX_2DACCEL_TYPE_GU1) + gu1_wait_until_idle(); +#endif +#if GFX_2DACCEL_GU2 + if (gfx_2daccel_type & GFX_2DACCEL_TYPE_GU2) + gu2_wait_until_idle(); +#endif +} + +/*--------------------------------------------------------------------------- + * gfx_test_blt_pending + *--------------------------------------------------------------------------- + */ +int +gfx_test_blt_pending(void) +{ + int retval = 0; + +#if GFX_2DACCEL_GU1 + if (gfx_2daccel_type & GFX_2DACCEL_TYPE_GU1) + retval = gu1_test_blt_pending(); +#endif +#if GFX_2DACCEL_GU2 + if (gfx_2daccel_type & GFX_2DACCEL_TYPE_GU2) + retval = gu2_test_blt_pending(); +#endif + return (retval); +} + +/*--------------------------------------------------------------------------- + * NEW ROUTINES FOR REDCLOUD + *--------------------------------------------------------------------------- + */ + +/*--------------------------------------------------------------------------- + * gfx2_set_source_stride + *--------------------------------------------------------------------------- + */ +void +gfx2_set_source_stride(unsigned short stride) +{ +#if GFX_2DACCEL_GU2 + if (gfx_2daccel_type & GFX_2DACCEL_TYPE_GU2) + gu22_set_source_stride(stride); +#endif +} + +/*--------------------------------------------------------------------------- + * gfx2_set_destination_stride + *--------------------------------------------------------------------------- + */ +void +gfx2_set_destination_stride(unsigned short stride) +{ +#if GFX_2DACCEL_GU2 + if (gfx_2daccel_type & GFX_2DACCEL_TYPE_GU2) + gu22_set_destination_stride(stride); +#endif +} + +/*--------------------------------------------------------------------------- + * gfx2_set_pattern_origin + *--------------------------------------------------------------------------- + */ +void +gfx2_set_pattern_origin(int x, int y) +{ +#if GFX_2DACCEL_GU2 + if (gfx_2daccel_type & GFX_2DACCEL_TYPE_GU2) + gu22_set_pattern_origin(x, y); +#endif +} + +/*--------------------------------------------------------------------------- + * gfx2_set_source_transparency + *--------------------------------------------------------------------------- + */ +void +gfx2_set_source_transparency(unsigned long color, unsigned long mask) +{ +#if GFX_2DACCEL_GU2 + if (gfx_2daccel_type & GFX_2DACCEL_TYPE_GU2) + gu22_set_source_transparency(color, mask); +#endif +} + +/*--------------------------------------------------------------------------- + * gfx2_set_alpha_mode + *--------------------------------------------------------------------------- + */ +void +gfx2_set_alpha_mode(int mode) +{ +#if GFX_2DACCEL_GU2 + if (gfx_2daccel_type & GFX_2DACCEL_TYPE_GU2) + gu22_set_alpha_mode(mode); +#endif +} + +/*--------------------------------------------------------------------------- + * gfx2_set_alpha_value + *--------------------------------------------------------------------------- + */ +void +gfx2_set_alpha_value(unsigned char value) +{ +#if GFX_2DACCEL_GU2 + if (gfx_2daccel_type & GFX_2DACCEL_TYPE_GU2) + gu22_set_alpha_value(value); +#endif +} + +/*--------------------------------------------------------------------------- + * gfx2_pattern_fill + *--------------------------------------------------------------------------- + */ +void +gfx2_pattern_fill(unsigned long dstoffset, unsigned short width, + unsigned short height) +{ +#if GFX_2DACCEL_GU2 + if (gfx_2daccel_type & GFX_2DACCEL_TYPE_GU2) + gu22_pattern_fill(dstoffset, width, height); +#endif +} + +/*--------------------------------------------------------------------------- + * gfx2_color_pattern_fill + *--------------------------------------------------------------------------- + */ +void +gfx2_color_pattern_fill(unsigned long dstoffset, unsigned short width, + unsigned short height, unsigned long *pattern) +{ +#if GFX_2DACCEL_GU2 + if (gfx_2daccel_type & GFX_2DACCEL_TYPE_GU2) + gu22_color_pattern_fill(dstoffset, width, height, pattern); +#endif +} + +/*--------------------------------------------------------------------------- + * gfx2_screen_to_screen_blt + *--------------------------------------------------------------------------- + */ +void +gfx2_screen_to_screen_blt(unsigned long srcoffset, unsigned long dstoffset, + unsigned short width, unsigned short height, int flags) +{ +#if GFX_2DACCEL_GU2 + if (gfx_2daccel_type & GFX_2DACCEL_TYPE_GU2) + gu22_screen_to_screen_blt(srcoffset, dstoffset, width, height, flags); +#endif +} + +/*--------------------------------------------------------------------------- + * gfx2_mono_expand_blt + *--------------------------------------------------------------------------- + */ +void +gfx2_mono_expand_blt(unsigned long srcbase, unsigned short srcx, + unsigned short srcy, unsigned long dstoffset, unsigned short width, + unsigned short height, int byte_packed) +{ +#if GFX_2DACCEL_GU2 + if (gfx_2daccel_type & GFX_2DACCEL_TYPE_GU2) + gu22_mono_expand_blt(srcbase, srcx, srcy, dstoffset, width, height, + byte_packed); +#endif +} + +/*--------------------------------------------------------------------------- + * gfx2_color_bitmap_to_screen_blt + *--------------------------------------------------------------------------- + */ +void +gfx2_color_bitmap_to_screen_blt(unsigned short srcx, unsigned short srcy, + unsigned long dstoffset, unsigned short width, unsigned short height, + unsigned char *data, short pitch) +{ +#if GFX_2DACCEL_GU2 + if (gfx_2daccel_type & GFX_2DACCEL_TYPE_GU2) + gu22_color_bitmap_to_screen_blt(srcx, srcy, dstoffset, width, height, + data, pitch); +#endif +} + +/*--------------------------------------------------------------------------- + * gfx2_text_blt + *--------------------------------------------------------------------------- + */ +void +gfx2_text_blt(unsigned long dstoffset, unsigned short width, + unsigned short height, unsigned char *data) +{ +#if GFX_2DACCEL_GU2 + if (gfx_2daccel_type & GFX_2DACCEL_TYPE_GU2) + gu22_text_blt(dstoffset, width, height, data); +#endif +} + +/*--------------------------------------------------------------------------- + * gfx2_mono_bitmap_to_screen_blt + *--------------------------------------------------------------------------- + */ +void +gfx2_mono_bitmap_to_screen_blt(unsigned short srcx, unsigned short srcy, + unsigned long dstoffset, unsigned short width, unsigned short height, + unsigned char *data, short pitch) +{ +#if GFX_2DACCEL_GU2 + if (gfx_2daccel_type & GFX_2DACCEL_TYPE_GU2) + gu22_mono_bitmap_to_screen_blt(srcx, srcy, dstoffset, width, height, + data, pitch); +#endif +} + +/*--------------------------------------------------------------------------- + * gfx2_bresenham_line + *--------------------------------------------------------------------------- + */ +void +gfx2_bresenham_line(unsigned long dstoffset, + unsigned short length, unsigned short initerr, + unsigned short axialerr, unsigned short diagerr, unsigned short flags) +{ +#if GFX_2DACCEL_GU2 + if (gfx_2daccel_type & GFX_2DACCEL_TYPE_GU2) + gu22_bresenham_line(dstoffset, length, initerr, axialerr, diagerr, + flags); +#endif +} + +/*--------------------------------------------------------------------------- + * gfx2_sync_to_vblank + *--------------------------------------------------------------------------- + */ +void +gfx2_sync_to_vblank(void) +{ +#if GFX_2DACCEL_GU2 + if (gfx_2daccel_type & GFX_2DACCEL_TYPE_GU2) + gu22_sync_to_vblank(); +#endif +} + +#endif /* GFX_2DACCEL_DYNAMIC */ + +/* END OF FILE */ diff --git a/src/gfx/gfx_rtns.h b/src/gfx/gfx_rtns.h new file mode 100644 index 0000000..ad759f4 --- /dev/null +++ b/src/gfx/gfx_rtns.h @@ -0,0 +1,604 @@ +/* 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 header file defines the Durango routines and variables used + * to access the memory mapped regions. + * */ + +#ifndef _gfx_rtns_h +#define _gfx_rtns_h + +/* INCLUDE DURANGO DEFINITIONS */ +/* These definitions are placed in another file to allow their inclusion + * in a user application. Such applications generally work through driver + * shell routines that simply pass their parameters to Durango routines. + * An external file provides an easy way to provide the definitions for these + * parameters without the applications gaining any Durango visisbility. + * */ + +#include "gfx_type.h" + +/* COMPILER OPTION FOR C++ PROGRAMS */ + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* DURANGO MEMORY POINTERS */ + + extern unsigned char *gfx_virt_regptr; + extern unsigned char *gfx_virt_fbptr; + extern unsigned char *gfx_virt_vidptr; + extern unsigned char *gfx_virt_vipptr; + extern unsigned char *gfx_virt_spptr; + extern unsigned char *gfx_virt_gpptr; + + extern unsigned char *gfx_phys_regptr; + extern unsigned char *gfx_phys_fbptr; + extern unsigned char *gfx_phys_vidptr; + extern unsigned char *gfx_phys_vipptr; + extern unsigned char *gfx_phys_spptr; + extern unsigned char *gfx_phys_gpptr; + +/* DURANGO VARIBLES FOR RUNTIME SELECTION AND POSSIBLE VALUES */ + + extern int gfx_display_type; +#define GFX_DISPLAY_TYPE_GU1 0x0001 +#define GFX_DISPLAY_TYPE_GU2 0x0002 +#define GFX_DISPLAY_TYPE_GU3 0x0004 + + extern int gfx_init_type; +#define GFX_INIT_TYPE_GU1 0x0001 +#define GFX_INIT_TYPE_GU2 0x0002 +#define GFX_INIT_TYPE_GU3 0x0004 + + extern int gfx_msr_type; +#define GFX_MSR_TYPE_REDCLOUD 0x0001 + + extern int gfx_2daccel_type; +#define GFX_2DACCEL_TYPE_GU1 0x0001 +#define GFX_2DACCEL_TYPE_GU2 0x0002 + + extern int gfx_video_type; +#define GFX_VIDEO_TYPE_CS5530 0x0001 +#define GFX_VIDEO_TYPE_SC1200 0x0002 +#define GFX_VIDEO_TYPE_REDCLOUD 0x0004 +#define GFX_VIDEO_TYPE_CASTLE 0x0008 + + extern int gfx_vip_type; +#define GFX_VIP_TYPE_SC1200 0x0001 + + extern int gfx_decoder_type; +#define GFX_DECODER_TYPE_SAA7114 0x0001 + + extern int gfx_tv_type; +#define GFX_TV_TYPE_SC1200 0x0001 +#define GFX_TV_TYPE_FS451 0x0002 + + extern int gfx_i2c_type; +#define GFX_I2C_TYPE_ACCESS 0x0001 +#define GFX_I2C_TYPE_GPIO 0x0002 + +/* GLOBAL CPU INFORMATION */ + + extern unsigned long gfx_cpu_version; + extern unsigned long gfx_cpu_frequency; + extern unsigned long gfx_vid_version; + extern ChipType gfx_chip_revision; + +/* ROUTINES IN GFX_INIT.C */ + + unsigned long gfx_pci_config_read(unsigned long address); + void gfx_pci_config_write(unsigned long address, unsigned long data); + unsigned long gfx_get_core_freq(void); + unsigned long gfx_detect_cpu(void); + unsigned long gfx_detect_video(void); + unsigned long gfx_get_cpu_register_base(void); + unsigned long gfx_get_graphics_register_base(void); + unsigned long gfx_get_frame_buffer_base(void); + unsigned long gfx_get_frame_buffer_size(void); + unsigned long gfx_get_vid_register_base(void); + unsigned long gfx_get_vip_register_base(void); + +/* ROUTINES IN GFX_MSR.C */ + + int gfx_msr_init(void); + DEV_STATUS gfx_id_msr_device(MSR * pDev, unsigned long address); + DEV_STATUS gfx_get_msr_dev_address(unsigned int device, + unsigned long *address); + DEV_STATUS gfx_get_glink_id_at_address(unsigned int *device, + unsigned long address); + DEV_STATUS gfx_msr_read(unsigned int device, unsigned int msrRegister, + Q_WORD * msrValue); + DEV_STATUS gfx_msr_write(unsigned int device, unsigned int msrRegister, + Q_WORD * msrValue); + +/* ROUTINES IN GFX_DISP.C */ + + int gfx_set_display_bpp(unsigned short bpp); + int gfx_is_display_mode_supported(int xres, int yres, int bpp, int hz); + int gfx_set_display_mode(int xres, int yres, int bpp, int hz); + int gfx_set_display_timings(unsigned short bpp, unsigned short flags, + unsigned short hactive, unsigned short hblank_start, + unsigned short hsync_start, unsigned short hsync_end, + unsigned short hblank_end, unsigned short htotal, + unsigned short vactive, unsigned short vblank_start, + unsigned short vsync_start, unsigned short vsync_end, + unsigned short vblank_end, unsigned short vtotal, + unsigned long frequency); + int gfx_set_vtotal(unsigned short vtotal); + void gfx_set_display_pitch(unsigned short pitch); + void gfx_set_display_offset(unsigned long offset); + int gfx_set_display_palette_entry(unsigned long index, + unsigned long palette); + int gfx_set_display_palette(unsigned long *palette); + void gfx_video_shutdown(void); + void gfx_set_clock_frequency(unsigned long frequency); + int gfx_set_crt_enable(int enable); + void gfx_set_cursor_enable(int enable); + void gfx_set_cursor_colors(unsigned long bkcolor, unsigned long fgcolor); + void gfx_set_cursor_position(unsigned long memoffset, + unsigned short xpos, unsigned short ypos, + unsigned short xhotspot, unsigned short yhotspot); + void gfx_set_cursor_shape32(unsigned long memoffset, + unsigned long *andmask, unsigned long *xormask); + void gfx_set_cursor_shape64(unsigned long memoffset, + unsigned long *andmask, unsigned long *xormask); + void gfx_set_icon_enable(int enable); + void gfx_set_icon_colors(unsigned long color0, unsigned long color1, + unsigned long color2); + void gfx_set_icon_position(unsigned long memoffset, unsigned short xpos); + void gfx_set_icon_shape64(unsigned long memoffset, unsigned long *andmask, + unsigned long *xormask, unsigned int lines); + + int gfx_set_compression_enable(int enable); + int gfx_set_compression_offset(unsigned long offset); + int gfx_set_compression_pitch(unsigned short pitch); + int gfx_set_compression_size(unsigned short size); + void gfx_set_display_priority_high(int enable); + int gfx_test_timing_active(void); + int gfx_test_vertical_active(void); + int gfx_wait_vertical_blank(void); + void gfx_delay_milliseconds(unsigned long milliseconds); + void gfx_delay_microseconds(unsigned long microseconds); + void gfx_enable_panning(int x, int y); + int gfx_is_panel_mode_supported(int panelResX, int panelResY, + unsigned short width, unsigned short height, unsigned short bpp); + int gfx_set_fixed_timings(int panelResX, int panelResY, + unsigned short width, unsigned short height, unsigned short bpp); + int gfx_set_panel_present(int panelResX, int panelResY, + unsigned short width, unsigned short height, unsigned short bpp); + void gfx_reset_timing_lock(void); + +/* "READ" ROUTINES IN GFX_DISP.C */ + + int gfx_get_display_details(unsigned int mode, int *xres, int *yres, + int *hz); + unsigned short gfx_get_display_pitch(void); + int gfx_get_vsa2_softvga_enable(void); + int gfx_get_sync_polarities(void); + unsigned long gfx_get_clock_frequency(void); + unsigned long gfx_get_max_supported_pixel_clock(void); + int gfx_mode_frequency_supported(int xres, int yres, int bpp, + unsigned long frequency); + int gfx_get_refreshrate_from_frequency(int xres, int yres, int bpp, + int *hz, unsigned long frequency); + int gfx_get_refreshrate_from_mode(int xres, int yres, int bpp, int *hz, + unsigned long frequency); + int gfx_get_frequency_from_refreshrate(int xres, int yres, int bpp, + int hz, int *frequency); + int gfx_get_display_mode_count(void); + int gfx_get_display_mode(int *xres, int *yres, int *bpp, int *hz); + unsigned long gfx_get_frame_buffer_line_size(void); + unsigned short gfx_get_hactive(void); + unsigned short gfx_get_hblank_start(void); + unsigned short gfx_get_hsync_start(void); + unsigned short gfx_get_hsync_end(void); + unsigned short gfx_get_hblank_end(void); + unsigned short gfx_get_htotal(void); + unsigned short gfx_get_vactive(void); + unsigned short gfx_get_vline(void); + unsigned short gfx_get_vblank_start(void); + unsigned short gfx_get_vsync_start(void); + unsigned short gfx_get_vsync_end(void); + unsigned short gfx_get_vblank_end(void); + unsigned short gfx_get_vtotal(void); + unsigned short gfx_get_display_bpp(void); + unsigned long gfx_get_display_offset(void); + int gfx_get_display_palette_entry(unsigned long index, + unsigned long *palette); + void gfx_get_display_palette(unsigned long *palette); + unsigned long gfx_get_cursor_enable(void); + unsigned long gfx_get_cursor_offset(void); + unsigned long gfx_get_cursor_position(void); + unsigned long gfx_get_cursor_clip(void); + unsigned long gfx_get_cursor_color(int color); + unsigned long gfx_get_icon_enable(void); + unsigned long gfx_get_icon_offset(void); + unsigned long gfx_get_icon_position(void); + unsigned long gfx_get_icon_color(int color); + int gfx_get_compression_enable(void); + unsigned long gfx_get_compression_offset(void); + unsigned short gfx_get_compression_pitch(void); + unsigned short gfx_get_compression_size(void); + int gfx_get_display_priority_high(void); + int gfx_get_valid_bit(int line); + +/* ROUTINES IN GFX_RNDR.C */ + + void gfx_set_bpp(unsigned short bpp); + void gfx_set_solid_pattern(unsigned long color); + void gfx_set_mono_pattern(unsigned long bgcolor, unsigned long fgcolor, + unsigned long data0, unsigned long data1, unsigned char transparency); + void gfx_set_color_pattern(unsigned long bgcolor, unsigned long fgcolor, + unsigned long data0, unsigned long data1, unsigned long data2, + unsigned long data3, unsigned char transparency); + void gfx_load_color_pattern_line(short y, unsigned long *pattern_8x8); + void gfx_set_solid_source(unsigned long color); + void gfx_set_mono_source(unsigned long bgcolor, unsigned long fgcolor, + unsigned short transparent); + void gfx_set_pattern_flags(unsigned short flags); + void gfx_set_raster_operation(unsigned char rop); + void gfx_pattern_fill(unsigned short x, unsigned short y, + unsigned short width, unsigned short height); + void gfx_color_pattern_fill(unsigned short x, unsigned short y, + unsigned short width, unsigned short height, unsigned long *pattern); + void gfx_screen_to_screen_blt(unsigned short srcx, unsigned short srcy, + unsigned short dstx, unsigned short dsty, unsigned short width, + unsigned short height); + void gfx_screen_to_screen_xblt(unsigned short srcx, unsigned short srcy, + unsigned short dstx, unsigned short dsty, unsigned short width, + unsigned short height, unsigned long color); + void gfx_color_bitmap_to_screen_blt(unsigned short srcx, + unsigned short srcy, unsigned short dstx, unsigned short dsty, + unsigned short width, unsigned short height, unsigned char *data, + long pitch); + void gfx_color_bitmap_to_screen_xblt(unsigned short srcx, + unsigned short srcy, unsigned short dstx, unsigned short dsty, + unsigned short width, unsigned short height, unsigned char *data, + long pitch, unsigned long color); + void gfx_mono_bitmap_to_screen_blt(unsigned short srcx, + unsigned short srcy, unsigned short dstx, unsigned short dsty, + unsigned short width, unsigned short height, unsigned char *data, + short pitch); + void gfx_text_blt(unsigned short dstx, unsigned short dsty, + unsigned short width, unsigned short height, unsigned char *data); + void gfx_bresenham_line(unsigned short x, unsigned short y, + unsigned short length, unsigned short initerr, + unsigned short axialerr, unsigned short diagerr, + unsigned short flags); + void gfx_wait_until_idle(void); + int gfx_test_blt_pending(void); + +/* SECOND GENERATION RENDERING ROUTINES */ + + void gfx2_set_source_stride(unsigned short stride); + void gfx2_set_destination_stride(unsigned short stride); + void gfx2_set_pattern_origin(int x, int y); + void gfx2_set_source_transparency(unsigned long color, + unsigned long mask); + void gfx2_set_alpha_mode(int mode); + void gfx2_set_alpha_value(unsigned char value); + void gfx2_pattern_fill(unsigned long dstoffset, unsigned short width, + unsigned short height); + void gfx2_color_pattern_fill(unsigned long dstoffset, + unsigned short width, unsigned short height, unsigned long *pattern); + void gfx2_screen_to_screen_blt(unsigned long srcoffset, + unsigned long dstoffset, unsigned short width, unsigned short height, + int flags); + void gfx2_mono_expand_blt(unsigned long srcbase, unsigned short srcx, + unsigned short srcy, unsigned long dstoffset, unsigned short width, + unsigned short height, int byte_packed); + void gfx2_color_bitmap_to_screen_blt(unsigned short srcx, + unsigned short srcy, unsigned long dstoffset, unsigned short width, + unsigned short height, unsigned char *data, short pitch); + void gfx2_mono_bitmap_to_screen_blt(unsigned short srcx, + unsigned short srcy, unsigned long dstoffset, unsigned short width, + unsigned short height, unsigned char *data, short pitch); + void gfx2_text_blt(unsigned long dstoffset, unsigned short width, + unsigned short height, unsigned char *data); + void gfx2_bresenham_line(unsigned long dstoffset, unsigned short length, + unsigned short initerr, unsigned short axialerr, + unsigned short diagerr, unsigned short flags); + void gfx2_sync_to_vblank(void); + +/* ROUTINES IN GFX_VID.C */ + + int gfx_set_video_enable(int enable); + int gfx_set_video_format(unsigned long format); + int gfx_set_video_size(unsigned short width, unsigned short height); + int gfx_set_video_yuv_pitch(unsigned long ypitch, unsigned long uvpitch); + int gfx_set_video_offset(unsigned long offset); + int gfx_set_video_yuv_offsets(unsigned long yoffset, + unsigned long uoffset, unsigned long voffset); + int gfx_set_video_window(short x, short y, unsigned short w, + unsigned short h); + int gfx_set_video_left_crop(unsigned short x); + int gfx_set_video_upscale(unsigned short srcw, unsigned short srch, + unsigned short dstw, unsigned short dsth); + int gfx_set_video_scale(unsigned short srcw, unsigned short srch, + unsigned short dstw, unsigned short dsth); + int gfx_set_video_vertical_downscale(unsigned short srch, + unsigned short dsth); + void gfx_set_video_vertical_downscale_enable(int enable); + int gfx_set_video_downscale_config(unsigned short type, unsigned short m); + int gfx_set_video_color_key(unsigned long key, unsigned long mask, + int bluescreen); + int gfx_set_video_filter(int xfilter, int yfilter); + int gfx_set_video_palette(unsigned long *palette); + int gfx_set_graphics_palette(unsigned long *palette); + int gfx_set_video_palette_bypass(int enable); + int gfx_set_video_palette_entry(unsigned long index, unsigned long color); + int gfx_set_graphics_palette_entry(unsigned long index, + unsigned long color); + int gfx_set_video_downscale_coefficients(unsigned short coef1, + unsigned short coef2, unsigned short coef3, unsigned short coef4); + int gfx_set_video_downscale_enable(int enable); + int gfx_set_video_source(VideoSourceType source); + int gfx_set_vbi_source(VbiSourceType source); + int gfx_set_vbi_lines(unsigned long even, unsigned long odd); + int gfx_set_vbi_total(unsigned long even, unsigned long odd); + int gfx_set_video_interlaced(int enable); + int gfx_set_color_space_YUV(int enable); + int gfx_set_vertical_scaler_offset(char offset); + int gfx_set_top_line_in_odd(int enable); + int gfx_set_genlock_delay(unsigned long delay); + int gfx_set_genlock_enable(int flags); + int gfx_set_video_cursor(unsigned long key, unsigned long mask, + unsigned short select_color2, unsigned long color1, + unsigned long color2); + int gfx_set_video_cursor_enable(int enable); + int gfx_set_video_request(short x, short y); + + int gfx_select_alpha_region(int region); + int gfx_set_alpha_enable(int enable); + int gfx_set_alpha_window(short x, short y, + unsigned short width, unsigned short height); + int gfx_set_alpha_value(unsigned char alpha, char delta); + int gfx_set_alpha_priority(int priority); + int gfx_set_alpha_color(unsigned long color); + int gfx_set_alpha_color_enable(int enable); + int gfx_set_no_ck_outside_alpha(int enable); + int gfx_disable_softvga(void); + int gfx_enable_softvga(void); + int gfx_set_macrovision_enable(int enable); + unsigned long gfx_get_max_video_width(void); + +/* READ ROUTINES IN GFX_VID.C */ + + int gfx_get_video_enable(void); + int gfx_get_video_format(void); + unsigned long gfx_get_video_src_size(void); + unsigned long gfx_get_video_line_size(void); + unsigned long gfx_get_video_xclip(void); + unsigned long gfx_get_video_offset(void); + void gfx_get_video_yuv_offsets(unsigned long *yoffset, + unsigned long *uoffset, unsigned long *voffset); + void gfx_get_video_yuv_pitch(unsigned long *ypitch, + unsigned long *uvpitch); + unsigned long gfx_get_video_upscale(void); + unsigned long gfx_get_video_scale(void); + unsigned long gfx_get_video_downscale_delta(void); + int gfx_get_video_vertical_downscale_enable(void); + int gfx_get_video_downscale_config(unsigned short *type, + unsigned short *m); + void gfx_get_video_downscale_coefficients(unsigned short *coef1, + unsigned short *coef2, unsigned short *coef3, unsigned short *coef4); + void gfx_get_video_downscale_enable(int *enable); + unsigned long gfx_get_video_dst_size(void); + unsigned long gfx_get_video_position(void); + unsigned long gfx_get_video_color_key(void); + unsigned long gfx_get_video_color_key_mask(void); + int gfx_get_video_palette_entry(unsigned long index, + unsigned long *palette); + int gfx_get_video_color_key_src(void); + int gfx_get_video_filter(void); + int gfx_get_video_request(short *x, short *y); + int gfx_get_video_source(VideoSourceType * source); + int gfx_get_vbi_source(VbiSourceType * source); + unsigned long gfx_get_vbi_lines(int odd); + unsigned long gfx_get_vbi_total(int odd); + int gfx_get_video_interlaced(void); + int gfx_get_color_space_YUV(void); + int gfx_get_vertical_scaler_offset(char *offset); + unsigned long gfx_get_genlock_delay(void); + int gfx_get_genlock_enable(void); + int gfx_get_video_cursor(unsigned long *key, unsigned long *mask, + unsigned short *select_color2, unsigned long *color1, + unsigned short *color2); + unsigned long gfx_read_crc(void); + unsigned long gfx_read_crc32(void); + unsigned long gfx_read_window_crc(int source, unsigned short x, + unsigned short y, unsigned short width, unsigned short height, + int crc32); + int gfx_get_macrovision_enable(void); + + void gfx_get_alpha_enable(int *enable); + void gfx_get_alpha_size(unsigned short *x, unsigned short *y, + unsigned short *width, unsigned short *height); + void gfx_get_alpha_value(unsigned char *alpha, char *delta); + void gfx_get_alpha_priority(int *priority); + void gfx_get_alpha_color(unsigned long *color); + +/* ROUTINES IN GFX_VIP.C */ + + int gfx_set_vip_enable(int enable); + int gfx_set_vip_capture_run_mode(int mode); + int gfx_set_vip_base(unsigned long even, unsigned long odd); + int gfx_set_vip_pitch(unsigned long pitch); + int gfx_set_vip_mode(int mode); + int gfx_set_vbi_enable(int enable); + int gfx_set_vbi_mode(int mode); + int gfx_set_vbi_base(unsigned long even, unsigned long odd); + int gfx_set_vbi_pitch(unsigned long pitch); + int gfx_set_vbi_direct(unsigned long even_lines, unsigned long odd_lines); + int gfx_set_vbi_interrupt(int enable); + int gfx_set_vip_bus_request_threshold_high(int enable); + int gfx_set_vip_last_line(int last_line); + int gfx_test_vip_odd_field(void); + int gfx_test_vip_bases_updated(void); + int gfx_test_vip_fifo_overflow(void); + int gfx_get_vip_line(void); + +/* READ ROUTINES IN GFX_VIP.C */ + + int gfx_get_vip_enable(void); + unsigned long gfx_get_vip_base(int odd); + unsigned long gfx_get_vip_pitch(void); + int gfx_get_vip_mode(void); + int gfx_get_vbi_enable(void); + int gfx_get_vbi_mode(void); + unsigned long gfx_get_vbi_base(int odd); + unsigned long gfx_get_vbi_pitch(void); + unsigned long gfx_get_vbi_direct(int odd); + int gfx_get_vbi_interrupt(void); + int gfx_get_vip_bus_request_threshold_high(void); + +/* ROUTINES IN GFX_DCDR.C */ + + int gfx_set_decoder_defaults(void); + int gfx_set_decoder_analog_input(unsigned char input); + int gfx_set_decoder_brightness(unsigned char brightness); + int gfx_set_decoder_contrast(unsigned char contrast); + int gfx_set_decoder_hue(char hue); + int gfx_set_decoder_saturation(unsigned char saturation); + int gfx_set_decoder_input_offset(unsigned short x, unsigned short y); + int gfx_set_decoder_input_size(unsigned short width, + unsigned short height); + int gfx_set_decoder_output_size(unsigned short width, + unsigned short height); + int gfx_set_decoder_scale(unsigned short srcw, unsigned short srch, + unsigned short dstw, unsigned short dsth); + int gfx_set_decoder_vbi_format(int start, int end, int format); + int gfx_set_decoder_vbi_enable(int enable); + int gfx_set_decoder_vbi_upscale(void); + int gfx_set_decoder_TV_standard(TVStandardType TVStandard); + int gfx_set_decoder_luminance_filter(unsigned char lufi); + int gfx_decoder_software_reset(void); + int gfx_decoder_detect_macrovision(void); + int gfx_decoder_detect_video(void); + +/* READ ROUTINES IN GFX_DCDR.C */ + + unsigned char gfx_get_decoder_brightness(void); + unsigned char gfx_get_decoder_contrast(void); + char gfx_get_decoder_hue(void); + unsigned char gfx_get_decoder_saturation(void); + unsigned long gfx_get_decoder_input_offset(void); + unsigned long gfx_get_decoder_input_size(void); + unsigned long gfx_get_decoder_output_size(void); + int gfx_get_decoder_vbi_format(int line); + +/* ROUTINES IN GFX_I2C.C */ + + int gfx_i2c_reset(unsigned char busnum, short adr, char freq); + int gfx_i2c_write(unsigned char busnum, unsigned char chipadr, + unsigned char subadr, unsigned char bytes, unsigned char *data); + int gfx_i2c_read(unsigned char busnum, unsigned char chipadr, + unsigned char subadr, unsigned char bytes, unsigned char *data); + int gfx_i2c_select_gpio(int clock, int data); + int gfx_i2c_init(void); + void gfx_i2c_cleanup(void); + +/* ROUTINES IN GFX_TV.C */ + + int gfx_set_tv_format(TVStandardType format, GfxOnTVType resolution); + int gfx_set_tv_output(int output); + int gfx_set_tv_enable(int enable); + int gfx_set_tv_flicker_filter(int ff); + int gfx_set_tv_sub_carrier_reset(int screset); + int gfx_set_tv_vphase(int vphase); + int gfx_set_tv_YC_delay(int delay); + int gfx_set_tvenc_reset_interval(int interval); + int gfx_set_tv_cc_enable(int enable); + int gfx_set_tv_cc_data(unsigned char data1, unsigned char data2); + int gfx_set_tv_display(int width, int height); + int gfx_test_tvout_odd_field(void); + int gfx_test_tvenc_odd_field(void); + int gfx_set_tv_field_status_invert(int enable); + int gfx_get_tv_vphase(void); + int gfx_get_tv_enable(unsigned int *p_on); + int gfx_get_tv_output(void); + int gfx_get_tv_mode_count(TVStandardType format); + int gfx_get_tv_display_mode(int *width, int *height, int *bpp, int *hz); + int gfx_get_tv_display_mode_frequency(unsigned short width, + unsigned short height, TVStandardType format, int *frequency); + int gfx_is_tv_display_mode_supported(unsigned short width, + unsigned short height, TVStandardType format); + + int gfx_get_tv_standard(unsigned long *p_standard); + int gfx_get_available_tv_standards(unsigned long *p_standards); + int gfx_set_tv_standard(unsigned long standard); + int gfx_get_tv_vga_mode(unsigned long *p_vga_mode); + int gfx_get_available_tv_vga_modes(unsigned long *p_vga_modes); + int gfx_set_tv_vga_mode(unsigned long vga_mode); + int gfx_get_tvout_mode(unsigned long *p_tvout_mode); + int gfx_set_tvout_mode(unsigned long tvout_mode); + int gfx_get_sharpness(int *p_sharpness); + int gfx_set_sharpness(int sharpness); + int gfx_get_flicker_filter(int *p_flicker); + int gfx_set_flicker_filter(int flicker); + int gfx_get_overscan(int *p_x, int *p_y); + int gfx_set_overscan(int x, int y); + int gfx_get_position(int *p_x, int *p_y); + int gfx_set_position(int x, int y); + int gfx_get_color(int *p_color); + int gfx_set_color(int color); + int gfx_get_brightness(int *p_brightness); + int gfx_set_brightness(int brightness); + int gfx_get_contrast(int *p_contrast); + int gfx_set_contrast(int constrast); + int gfx_get_yc_filter(unsigned int *p_yc_filter); + int gfx_set_yc_filter(unsigned int yc_filter); + int gfx_get_aps_trigger_bits(unsigned int *p_trigger_bits); + int gfx_set_aps_trigger_bits(unsigned int trigger_bits); + +/* ROUTINES IN GFX_VGA.C */ + + int gfx_get_softvga_active(void); + int gfx_vga_test_pci(void); + unsigned char gfx_vga_get_pci_command(void); + int gfx_vga_set_pci_command(unsigned char command); + int gfx_vga_seq_reset(int reset); + int gfx_vga_set_graphics_bits(void); + int gfx_vga_mode(gfx_vga_struct * vga, int xres, int yres, int bpp, + int hz); + int gfx_vga_pitch(gfx_vga_struct * vga, unsigned short pitch); + int gfx_vga_save(gfx_vga_struct * vga, int flags); + int gfx_vga_restore(gfx_vga_struct * vga, int flags); + int gfx_vga_mode_switch(int active); + void gfx_vga_clear_extended(void); + +/* CLOSE BRACKET FOR C++ COMPLILATION */ + +#ifdef __cplusplus +} +#endif + +#endif /* !_gfx_rtns_h */ + +/* END OF FILE */ diff --git a/src/gfx/gfx_tv.c b/src/gfx/gfx_tv.c new file mode 100644 index 0000000..fb34d60 --- /dev/null +++ b/src/gfx/gfx_tv.c @@ -0,0 +1,836 @@ +/* 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 to program TVOUT and TV encoder. + * + * Routines: + * + * gfx_set_tv_format + * gfx_set_tv_output + * gfx_set_tv_enable + * gfx_set_tv_flicker_filter + * gfx_set_tv_sub_carrier_reset + * gfx_set_tv_vphase + * gfx_set_tv_YC_delay + * gfx_set_tvenc_reset_interval + * gfx_set_tv_cc_enable + * gfx_set_tv_cc_data + * gfx_test_tvout_odd_field + * gfx_test_tvenc_odd_field + * gfx_set_tv_field_status_invert + * gfx_get_tv_vphase + * */ + +/* TV TIMINGS */ + +DISPLAYMODE TVTimings[] = { + +/* NTSC resolution */ + + {0x3 | /* negative syncs */ + GFX_MODE_TV_NTSC, /* NTSC format */ + 640, 640, 656, 744, 792, 792, /* horizontal timings */ + 480, 480, 490, 492, 517, 525, /* vertical timings */ + 0x0018EC4D, /* freq = 24.923052 MHz */ + } + , + +/* PAL resolution */ + + {0x3 | /* negative syncs */ + GFX_MODE_TV_PAL, /* PAL format */ + 768, 768, 800, 848, 864, 864, /* horizontal timings */ + 576, 576, 586, 588, 625, 625, /* vertical timings */ + 0x001B0000, /* freq = 27.00 MHz */ + } + , + +/* NTSC resolution non-square pixels */ + + {0x3 | /* negative syncs */ + GFX_MODE_TV_NTSC, /* NTSC format */ + 720, 720, 736, 752, 792, 792, /* horizontal timings */ + 480, 480, 490, 492, 517, 525, /* vertical timings */ + 0x0018EC4D, /* freq = 24.923052 MHz */ + } + , + +/* PAL resolution non-square pixels */ + + {0x3 | /* negative syncs */ + GFX_MODE_TV_PAL, /* PAL format */ + 720, 720, 752, 816, 864, 864, /* horizontal timings */ + 576, 576, 586, 588, 625, 625, /* vertical timings */ + 0x001B0000, /* freq = 27.00 MHz */ + } +}; + +#define NUM_TV_MODES sizeof(TVTimings)/sizeof(DISPLAYMODE) + +/* INCLUDE SUPPORT FOR SC1200 TV ENCODER, IF SPECIFIED */ + +#if GFX_TV_SC1200 +#include "tv_1200.c" +#endif + +/* INCLUDE SUPPORT FOR FS450 TV ENCODER, IF SPECIFIED */ + +#if GFX_TV_FS451 +#include "tv_fs450.c" +#endif + +/* WRAPPERS IF DYNAMIC SELECTION */ +/* Extra layer to call either SC1200 or FS450 TV encoder routines. */ + +#if GFX_TV_DYNAMIC + +/*---------------------------------------------------------------------------- + * gfx_set_tv_format + *---------------------------------------------------------------------------- + */ +int +gfx_set_tv_format(TVStandardType format, GfxOnTVType resolution) +{ + int retval = GFX_STATUS_UNSUPPORTED; + +#if GFX_TV_SC1200 + if (gfx_tv_type & GFX_TV_TYPE_SC1200) + retval = sc1200_set_tv_format(format, resolution); +#endif +#if GFX_TV_FS451 + if (gfx_tv_type & GFX_TV_TYPE_FS451) + retval = fs450_set_tv_format(format, resolution); +#endif + return (retval); +} + +/*---------------------------------------------------------------------------- + * gfx_set_tv_output + *---------------------------------------------------------------------------- + */ +int +gfx_set_tv_output(int output) +{ + int retval = GFX_STATUS_UNSUPPORTED; + +#if GFX_TV_SC1200 + if (gfx_tv_type & GFX_TV_TYPE_SC1200) + retval = sc1200_set_tv_output(output); +#endif +#if GFX_TV_FS451 + if (gfx_tv_type & GFX_TV_TYPE_FS451) + retval = fs450_set_tv_output(output); +#endif + return (retval); +} + +/*---------------------------------------------------------------------------- + * gfx_set_tv_enable + *---------------------------------------------------------------------------- + */ +int +gfx_set_tv_enable(int enable) +{ + int retval = GFX_STATUS_UNSUPPORTED; + +#if GFX_TV_SC1200 + if (gfx_tv_type & GFX_TV_TYPE_SC1200) + retval = sc1200_set_tv_enable(enable); +#endif +#if GFX_TV_FS451 + if (gfx_tv_type & GFX_TV_TYPE_FS451) + retval = fs450_set_tv_enable(enable); +#endif + return (retval); +} + +/*---------------------------------------------------------------------------- + * gfx_set_tv_flicker_filter + *---------------------------------------------------------------------------- + */ +int +gfx_set_tv_flicker_filter(int ff) +{ + int retval = GFX_STATUS_UNSUPPORTED; + +#if GFX_TV_SC1200 + if (gfx_tv_type & GFX_TV_TYPE_SC1200) + retval = sc1200_set_tv_flicker_filter(ff); +#endif + return (retval); +} + +/*---------------------------------------------------------------------------- + * gfx_set_tv_sub_carrier_reset + *---------------------------------------------------------------------------- + */ +int +gfx_set_tv_sub_carrier_reset(int screset) +{ + int retval = GFX_STATUS_UNSUPPORTED; + +#if GFX_TV_SC1200 + if (gfx_tv_type & GFX_TV_TYPE_SC1200) + retval = sc1200_set_tv_sub_carrier_reset(screset); +#endif + return (retval); +} + +/*---------------------------------------------------------------------------- + * gfx_set_tv_vphase + *---------------------------------------------------------------------------- + */ +int +gfx_set_tv_vphase(int vphase) +{ + int retval = GFX_STATUS_UNSUPPORTED; + +#if GFX_TV_SC1200 + if (gfx_tv_type & GFX_TV_TYPE_SC1200) + retval = sc1200_set_tv_vphase(vphase); +#endif + return (retval); +} + +/*---------------------------------------------------------------------------- + * gfx_set_tv_YC_delay + *---------------------------------------------------------------------------- + */ +int +gfx_set_tv_YC_delay(int delay) +{ + int retval = GFX_STATUS_UNSUPPORTED; + +#if GFX_TV_SC1200 + if (gfx_tv_type & GFX_TV_TYPE_SC1200) + retval = sc1200_set_tv_YC_delay(delay); +#endif + return (retval); +} + +/*---------------------------------------------------------------------------- + * gfx_set_tvenc_reset_interval + *---------------------------------------------------------------------------- + */ +int +gfx_set_tvenc_reset_interval(int interval) +{ + int retval = GFX_STATUS_UNSUPPORTED; + +#if GFX_TV_SC1200 + if (gfx_tv_type & GFX_TV_TYPE_SC1200) + retval = sc1200_set_tvenc_reset_interval(interval); +#endif + return (retval); +} + +/*---------------------------------------------------------------------------- + * gfx_set_tv_cc_enable + *---------------------------------------------------------------------------- + */ +int +gfx_set_tv_cc_enable(int enable) +{ + int retval = GFX_STATUS_UNSUPPORTED; + +#if GFX_TV_SC1200 + if (gfx_tv_type & GFX_TV_TYPE_SC1200) + retval = sc1200_set_tv_cc_enable(enable); +#endif + return (retval); +} + +/*---------------------------------------------------------------------------- + * gfx_set_tv_cc_data + * + * This routine writes the two specified characters to the CC data register + * of the TV encoder. + *---------------------------------------------------------------------------- + */ +int +gfx_set_tv_cc_data(unsigned char data1, unsigned char data2) +{ + int retval = GFX_STATUS_UNSUPPORTED; + +#if GFX_TV_SC1200 + if (gfx_tv_type & GFX_TV_TYPE_SC1200) + retval = sc1200_set_tv_cc_data(data1, data2); +#endif + return (retval); +} + +/*--------------------------------------------------------------------------- + * gfx_set_tv_display + * + * Set the timings in the display controller to support a TV resolution. + *--------------------------------------------------------------------------- + */ +int +gfx_set_tv_display(int width, int height) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_TV_SC1200 + if (gfx_tv_type & GFX_TV_TYPE_SC1200) + status = sc1200_set_tv_display(width, height); +#endif + return (status); +} + +/*--------------------------------------------------------------------------- + * gfx_test_tvout_odd_field + *--------------------------------------------------------------------------- + */ +int +gfx_test_tvout_odd_field(void) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_TV_SC1200 + if (gfx_tv_type & GFX_TV_TYPE_SC1200) + status = sc1200_test_tvout_odd_field(); +#endif + return (status); +} + +/*--------------------------------------------------------------------------- + * gfx_test_tvenc_odd_field + *--------------------------------------------------------------------------- + */ +int +gfx_test_tvenc_odd_field(void) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_TV_SC1200 + if (gfx_tv_type & GFX_TV_TYPE_SC1200) + status = sc1200_test_tvenc_odd_field(); +#endif + return (status); +} + +/*---------------------------------------------------------------------------- + * gfx_set_tv_field_status_invert + *---------------------------------------------------------------------------- + */ +int +gfx_set_tv_field_status_invert(int enable) +{ + int retval = GFX_STATUS_UNSUPPORTED; + +#if GFX_TV_SC1200 + if (gfx_tv_type & GFX_TV_TYPE_SC1200) + retval = sc1200_set_tv_field_status_invert(enable); +#endif + return (retval); +} + +/*--------------------------------------------------------------------------- + * gfx_get_tv_vphase + *--------------------------------------------------------------------------- + */ +int +gfx_get_tv_vphase(void) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_TV_SC1200 + if (gfx_tv_type & GFX_TV_TYPE_SC1200) + status = sc1200_get_tv_vphase(); +#endif + return (status); +} + +/*--------------------------------------------------------------------------- + * gfx_get_tv_enable + *--------------------------------------------------------------------------- + */ +int +gfx_get_tv_enable(unsigned int *p_on) +{ + int retval = -1; + +#if GFX_TV_FS451 + if (gfx_tv_type & GFX_TV_TYPE_FS451) + retval = fs450_get_tv_enable(p_on); +#endif +#if GFX_TV_SC1200 + if (gfx_tv_type & GFX_TV_TYPE_SC1200) + retval = sc1200_get_tv_enable(p_on); +#endif + return (retval); +} + +/*--------------------------------------------------------------------------- + * gfx_get_tv_output + *--------------------------------------------------------------------------- + */ +int +gfx_get_tv_output() +{ + int retval = -1; + +#if GFX_TV_SC1200 + if (gfx_tv_type & GFX_TV_TYPE_SC1200) + retval = sc1200_get_tv_output(); +#endif + return (retval); +} + +/*--------------------------------------------------------------------------- + * gfx_get_tv_mode_count + *--------------------------------------------------------------------------- + */ +int +gfx_get_tv_mode_count(TVStandardType format) +{ + int retval = -1; + +#if GFX_TV_SC1200 + if (gfx_tv_type & GFX_TV_TYPE_SC1200) + retval = sc1200_get_tv_mode_count(format); +#endif + return (retval); +} + +/*--------------------------------------------------------------------------- + * gfx_get_tv_display_mode + *--------------------------------------------------------------------------- + */ +int +gfx_get_tv_display_mode(int *width, int *height, int *bpp, int *hz) +{ + int retval = -1; + +#if GFX_TV_SC1200 + if (gfx_tv_type & GFX_TV_TYPE_SC1200) + retval = sc1200_get_tv_display_mode(width, height, bpp, hz); +#endif + return (retval); +} + +/*--------------------------------------------------------------------------- + * gfx_get_tv_display_mode_frequency + *--------------------------------------------------------------------------- + */ +int +gfx_get_tv_display_mode_frequency(unsigned short width, unsigned short height, + TVStandardType format, int *frequency) +{ + int retval = -1; + +#if GFX_TV_SC1200 + if (gfx_tv_type & GFX_TV_TYPE_SC1200) + retval = + sc1200_get_tv_display_mode_frequency(width, height, format, + frequency); +#endif + return (retval); +} + +/*--------------------------------------------------------------------------- + * gfx_is_tv_display_mode_supported + *--------------------------------------------------------------------------- + */ +int +gfx_is_tv_display_mode_supported(unsigned short width, unsigned short height, + TVStandardType format) +{ + int retval = -1; + +#if GFX_TV_SC1200 + if (gfx_tv_type & GFX_TV_TYPE_SC1200) + retval = sc1200_is_tv_display_mode_supported(width, height, format); +#endif + return (retval); +} + +/*------------------------------------------ + * The following functions were added to support + * the FS450 and will eventually be removed. There + * is no equivalent support in the SC1200. + *----------------------------------------------*/ + +/*========================================================================== + * TV standard + *========================================================================== + */ +int +gfx_get_tv_standard(unsigned long *p_standard) +{ + int retval = -1; + +#if GFX_TV_FS451 + if (gfx_tv_type & GFX_TV_TYPE_FS451) + retval = fs450_get_tv_standard(p_standard); +#endif + return (retval); +} + +int +gfx_get_available_tv_standards(unsigned long *p_standards) +{ + int retval = -1; + +#if GFX_TV_FS451 + if (gfx_tv_type & GFX_TV_TYPE_FS451) + retval = fs450_get_available_tv_standards(p_standards); +#endif + return (retval); +} + +int +gfx_set_tv_standard(unsigned long standard) +{ + int retval = -1; + +#if GFX_TV_FS451 + if (gfx_tv_type & GFX_TV_TYPE_FS451) + retval = fs450_set_tv_standard(standard); +#endif + return (retval); +} + +/* + *========================================================================== + * vga mode as known by the driver + *========================================================================== + */ +int +gfx_get_tv_vga_mode(unsigned long *p_vga_mode) +{ + int retval = -1; + +#if GFX_TV_FS451 + if (gfx_tv_type & GFX_TV_TYPE_FS451) + retval = fs450_get_tv_vga_mode(p_vga_mode); +#endif + return (retval); +} + +int +gfx_get_available_tv_vga_modes(unsigned long *p_vga_modes) +{ + int retval = -1; + +#if GFX_TV_FS451 + if (gfx_tv_type & GFX_TV_TYPE_FS451) + retval = fs450_get_available_tv_vga_modes(p_vga_modes); +#endif + return (retval); +} + +int +gfx_set_tv_vga_mode(unsigned long vga_mode) +{ + int re tval = -1; + +#if GFX_TV_FS451 + if (gfx_tv_type & GFX_TV_TYPE_FS451) + retval = fs450_set_tv_vga_mode(vga_mode); +#endif + return (retval); +} + +/* + *========================================================================== + * + * tvout mode + */ + +int +gfx_get_tvout_mode(unsigned long *p_tvout_mode) +{ + int retval = -1; + +#if GFX_TV_FS451 + if (gfx_tv_type & GFX_TV_TYPE_FS451) + retval = fs450_get_tvout_mode(p_tvout_mode); +#endif + return (retval); +} + +int +gfx_set_tvout_mode(unsigned long tvout_mode) +{ + int retval = -1; + +#if GFX_TV_FS451 + if (gfx_tv_type & GFX_TV_TYPE_FS451) + retval = fs450_set_tvout_mode(tvout_mode); +#endif + return (retval); +} + +/* + *========================================================================== + * + * Sharpness + */ +int +gfx_get_sharpness(int *p_sharpness) +{ + int retval = -1; + +#if GFX_TV_FS451 + if (gfx_tv_type & GFX_TV_TYPE_FS451) + retval = fs450_get_sharpness(p_sharpness); +#endif + return (retval); +} + +int +gfx_set_sharpness(int sharpness) +{ + int retval = -1; + +#if GFX_TV_FS451 + if (gfx_tv_type & GFX_TV_TYPE_FS451) + retval = fs450_set_sharpness(sharpness); +#endif + return (retval); +} + +/* + *========================================================================== + * + * flicker filter control. + */ + +int +gfx_get_flicker_filter(int *p_flicker) +{ + int retval = -1; + +#if GFX_TV_FS451 + if (gfx_tv_type & GFX_TV_TYPE_FS451) + retval = fs450_get_flicker_filter(p_flicker); +#endif + return (retval); +} + +int +gfx_set_flicker_filter(int flicker) +{ + int retval = -1; + +#if GFX_TV_FS451 + if (gfx_tv_type & GFX_TV_TYPE_FS451) + retval = fs450_set_flicker_filter(flicker); +#endif + return (retval); +} + +/* + *========================================================================== + * + * Overscan and Position + */ + +int +gfx_get_overscan(int *p_x, int *p_y) +{ + int retval = -1; + +#if GFX_TV_FS451 + if (gfx_tv_type & GFX_TV_TYPE_FS451) + retval = fs450_get_overscan(p_x, p_y); +#endif + return (retval); + +} + +int +gfx_set_overscan(int x, int y) +{ + int retval = -1; + +#if GFX_TV_FS451 + if (gfx_tv_type & GFX_TV_TYPE_FS451) + retval = fs450_set_overscan(x, y); +#endif + return (retval); +} + +int +gfx_get_position(int *p_x, int *p_y) +{ + int retval = -1; + +#if GFX_TV_FS451 + if (gfx_tv_type & GFX_TV_TYPE_FS451) + retval = fs450_get_position(p_x, p_y); +#endif + return (retval); +} + +int +gfx_set_position(int x, int y) +{ + int retval = -1; + +#if GFX_TV_FS451 + if (gfx_tv_type & GFX_TV_TYPE_FS451) + retval = fs450_set_position(x, y); +#endif + return (retval); +} + +/* + *========================================================================== + * + * Color, Brightness, and Contrast + */ + +int +gfx_get_color(int *p_color) +{ + int retval = -1; + +#if GFX_TV_FS451 + if (gfx_tv_type & GFX_TV_TYPE_FS451) + retval = fs450_get_color(p_color); +#endif + return (retval); +} + +int +gfx_set_color(int color) +{ + int retval = -1; + +#if GFX_TV_FS451 + if (gfx_tv_type & GFX_TV_TYPE_FS451) + retval = fs450_set_color(color); +#endif + return (retval); +} + +int +gfx_get_brightness(int *p_brightness) +{ + int retval = -1; + +#if GFX_TV_FS451 + if (gfx_tv_type & GFX_TV_TYPE_FS451) + retval = fs450_get_brightness(p_brightness); +#endif + return (retval); +} + +int +gfx_set_brightness(int brightness) +{ + int retval = -1; + +#if GFX_TV_FS451 + if (gfx_tv_type & GFX_TV_TYPE_FS451) + retval = fs450_set_brightness(brightness); +#endif + return (retval); +} + +int +gfx_get_contrast(int *p_contrast) +{ + int retval = -1; + +#if GFX_TV_FS451 + if (gfx_tv_type & GFX_TV_TYPE_FS451) + retval = fs450_get_contrast(p_contrast); +#endif + return (retval); +} + +int +gfx_set_contrast(int contrast) +{ + int retval = -1; + +#if GFX_TV_FS451 + if (gfx_tv_type & GFX_TV_TYPE_FS451) + retval = fs450_set_contrast(contrast); +#endif + return (retval); +} + +/* + *========================================================================== + * + * YC filters + */ + +int +gfx_get_yc_filter(unsigned int *p_yc_filter) +{ + int retval = -1; + +#if GFX_TV_FS451 + if (gfx_tv_type & GFX_TV_TYPE_FS451) + retval = fs450_get_yc_filter(p_yc_filter); +#endif + return (retval); +} + +int +gfx_set_yc_filter(unsigned int yc_filter) +{ + int retval = -1; + +#if GFX_TV_FS451 + if (gfx_tv_type & GFX_TV_TYPE_FS451) + retval = fs450_set_yc_filter(yc_filter); +#endif + return (retval); +} + +int +gfx_get_aps_trigger_bits(unsigned int *p_trigger_bits) +{ + int retval = -1; + +#if GFX_TV_FS451 + if (gfx_tv_type & GFX_TV_TYPE_FS451) + retval = fs450_get_aps_trigger_bits(p_trigger_bits); +#endif + return (retval); +} + +int +gfx_set_aps_trigger_bits(unsigned int trigger_bits) +{ + int retval = -1; + +#if GFX_TV_FS451 + if (gfx_tv_type & GFX_TV_TYPE_FS451) + retval = fs450_set_aps_trigger_bits(trigger_bits); +#endif + return (retval); +} + +#endif /* GFX_TV_DYNAMIC */ + +/* END OF FILE */ diff --git a/src/gfx/gfx_type.h b/src/gfx/gfx_type.h new file mode 100644 index 0000000..fbedd62 --- /dev/null +++ b/src/gfx/gfx_type.h @@ -0,0 +1,331 @@ +/* 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 header file defines the pneumonics used when calling Durango routines. + * This file is automatically included by gfx_rtns.h + * */ + +#ifndef _gfx_type_h +#define _gfx_type_h + +/* MSR DEFINITIONS */ + +typedef enum DevStatus +{ FOUND, NOT_KNOWN, REQ_NOT_FOUND, REQ_NOT_INSTALLED } DEV_STATUS; + +typedef struct msr +{ + DEV_STATUS Present; /* Node enumeration status */ + unsigned char Id; /* Device ID (from MSR specs) */ + unsigned long Address; /* Address - 32-bit MBus address at */ + /* which 'Id' is found */ +} MSR; + +typedef struct mValue +{ + unsigned long high; + unsigned long low; +} Q_WORD; + +typedef struct mbusNode +{ + unsigned long address; + unsigned int deviceId; + unsigned int claimed; +} MBUS_NODE; + +/* MSR ARRAY INDEXES */ +/* These are indexes into the array of MBus devices. These */ +/* should not be confused with the class codes at MSR register */ +/* 0x2000. */ + +#define RC_ID_MBIU0 0x00 +#define RC_ID_MBIU1 0x01 +#define RC_ID_MCP 0x02 +#define RC_ID_MPCI 0x03 +#define RC_ID_MC 0x04 +#define RC_ID_GP 0x05 +#define RC_ID_VG 0x06 +#define RC_ID_DF 0x07 +#define RC_ID_FG 0x08 +#define RC_ID_VA 0x09 +#define CP_ID_MBIU 0x0A +#define CP_ID_MPCI 0x0B +#define CP_ID_USB2 0x0C +#define CP_ID_ATAC 0x0D +#define CP_ID_MDD 0x0E +#define CP_ID_ACC 0x0F +#define CP_ID_USB1 0x10 +#define CP_ID_MCP 0x11 + +/* MBUS DEVICE CLASS CODES */ +/* These are the device ids for the known Redcloud MBus devices. */ + +#define RC_CC_MBIU 0x01 +#define RC_CC_MCP 0x02 +#define RC_CC_MPCI 0x05 +#define RC_CC_MC 0x20 +#define RC_CC_GP 0x3D +#define RC_CC_VG 0x3E +#define RC_CC_DF 0x3F +#define RC_CC_FG 0xF0 +#define RC_CC_VA 0x86 +#define CP_CC_MBIU 0x01 +#define CP_CC_MPCI 0x05 +#define CP_CC_USB2 0x42 +#define CP_CC_ATAC 0x47 +#define CP_CC_MDD 0xDF +#define CP_CC_ACC 0x33 +#define CP_CC_USB1 0x42 +#define CP_CC_MCP 0x02 + +/* VAIL AND MBIUS ARE AT KNOWN ADDRESSES */ +/* We can initialize the addresses of these devices in advance, */ +/* as their location should never change. */ + +#define RC_MB0_MBIU0 0x10000000 +#define RC_MB0_MBIU1 0x40000000 +#define CP_MB0_MBIU0 0x51010000 +#define RC_MB0_CPU 0x00000000 +#define FAKE_ADDRESS 0xFFFFFFFF + +/* MSR PORT DESCRIPTORS */ + +#define NOT_POPULATED 0 +#define NOT_INSTALLED 0xFFFE +#define REFLECTIVE 0xFFFF + +/* CRC DATA SOURCES */ + +#define CRC_SOURCE_GFX_DATA 0x00 +#define CRC_SOURCE_CRT_RGB 0x01 +#define CRC_SOURCE_FP_DATA 0x02 + +/* TV DEFINITIONS */ + +typedef enum TVStandardType +{ + TV_STANDARD_NTSC = 1, + TV_STANDARD_PAL +} TVStandardType; + +typedef enum GfxOnTVType +{ + GFX_ON_TV_SQUARE_PIXELS = 1, + GFX_ON_TV_NO_SCALING +} GfxOnTVType; + +#define CRT_DISABLE 0x00 +#define CRT_ENABLE 0x01 +#define CRT_STANDBY 0x02 +#define CRT_SUSPEND 0x03 + +#define TV_OUTPUT_COMPOSITE 0x01 +#define TV_OUTPUT_S_VIDEO 0x02 +#define TV_OUTPUT_YUV 0x03 +#define TV_OUTPUT_SCART 0x04 + +#define TV_FLICKER_FILTER_NONE 0x01 +#define TV_FLICKER_FILTER_NORMAL 0x02 +#define TV_FLICKER_FILTER_INTERLACED 0x03 + +#define TV_YC_DELAY_NONE 0x01 +#define TV_Y_DELAY_ONE_PIXEL 0x02 +#define TV_C_DELAY_ONE_PIXEL 0x03 +#define TV_C_DELAY_TWO_PIXELS 0x04 + +#define TV_SUB_CARRIER_RESET_NEVER 0x01 +#define TV_SUB_CARRIER_RESET_EVERY_TWO_LINES 0x02 +#define TV_SUB_CARRIER_RESET_EVERY_TWO_FRAMES 0x03 +#define TV_SUB_CARRIER_RESET_EVERY_FOUR_FRAMES 0x04 + +#define TVENC_RESET_EVERY_ODD_FIELD 0x01 +#define TVENC_RESET_EVERY_EVEN_FIELD 0x02 +#define TVENC_RESET_NEXT_ODD_FIELD 0x03 +#define TVENC_RESET_NEXT_EVEN_FIELD 0x04 +#define TVENC_RESET_EVERY_FIELD 0x05 +#define TVENC_RESET_EVERY_X_ODD_FIELDS 0x06 +#define TVENC_RESET_EVERY_X_EVEN_FIELDS 0x07 + +/* VBI FORMATS */ + +#define VBI_FORMAT_VIDEO 0x1 +#define VBI_FORMAT_RAW 0x2 +#define VBI_FORMAT_CC 0x4 +#define VBI_FORMAT_NABTS 0x8 + +/* VIDEO DEFINITIONS */ + +#define VIDEO_FORMAT_UYVY 0x0 +#define VIDEO_FORMAT_Y2YU 0x1 +#define VIDEO_FORMAT_YUYV 0x2 +#define VIDEO_FORMAT_YVYU 0x3 +#define VIDEO_FORMAT_Y0Y1Y2Y3 0x4 +#define VIDEO_FORMAT_Y3Y2Y1Y0 0x5 +#define VIDEO_FORMAT_Y1Y0Y3Y2 0x6 +#define VIDEO_FORMAT_Y1Y2Y3Y0 0x7 +#define VIDEO_FORMAT_RGB 0x8 +#define VIDEO_FORMAT_P2M_P2L_P1M_P1L 0x9 +#define VIDEO_FORMAT_P1M_P1L_P2M_P2L 0xA +#define VIDEO_FORMAT_P1M_P2L_P2M_P1L 0xB + +#define VIDEO_DOWNSCALE_KEEP_1_OF 0x1 +#define VIDEO_DOWNSCALE_DROP_1_OF 0x2 + +typedef enum VideoSourceType +{ /* The source from which the video processor shows full screen video */ + VIDEO_SOURCE_MEMORY = 1, + VIDEO_SOURCE_DVIP +} VideoSourceType; + +typedef enum VbiSourceType +{ /* The source from which the video processor takes VBI */ + VBI_SOURCE_MEMORY = 1, + VBI_SOURCE_DVIP +} VbiSourceType; + +/* GENLOCK DEFINITIONS */ + +#define GENLOCK_SINGLE 0x001 +#define GENLOCK_FIELD_SYNC 0x001 +#define GENLOCK_CONTINUOUS 0x002 +#define GENLOCK_SYNCED_EDGE_FALLING 0x004 +#define GENLOCK_SYNCING_EDGE_FALLING 0x008 +#define GENLOCK_TIMEOUT 0x010 +#define GENLOCK_TVENC_RESET_EVEN_FIELD 0x020 +#define GENLOCK_TVENC_RESET_BEFORE_DELAY 0x040 +#define GENLOCK_TVENC_RESET 0x080 +#define GENLOCK_SYNC_TO_TVENC 0x100 + +/* VIP DEFINITIONS */ + +#define VIP_MODE_C 0x1 + +#define VIP_CAPTURE_STOP_LINE 0x1 +#define VIP_CAPTURE_STOP_FIELD 0x2 +#define VIP_CAPTURE_START_FIELD 0x4 + +#define VBI_ANCILLARY 0x1 +#define VBI_TASK_A 0x2 +#define VBI_TASK_B 0x4 + +/* VGA STRUCTURE */ + +#define GFX_STD_CRTC_REGS 25 +#define GFX_EXT_CRTC_REGS 16 + +#define GFX_VGA_FLAG_MISC_OUTPUT 0x00000001 +#define GFX_VGA_FLAG_STD_CRTC 0x00000002 +#define GFX_VGA_FLAG_EXT_CRTC 0x00000004 + +/* FS450 TV Standard flags */ + +#define GFX_TV_STANDARD_NTSC_M 0x0001 +#define GFX_TV_STANDARD_NTSC_M_J 0x0002 +#define GFX_TV_STANDARD_PAL_B 0x0004 +#define GFX_TV_STANDARD_PAL_D 0x0008 +#define GFX_TV_STANDARD_PAL_H 0x0010 +#define GFX_TV_STANDARD_PAL_I 0x0020 +#define GFX_TV_STANDARD_PAL_M 0x0040 +#define GFX_TV_STANDARD_PAL_N 0x0080 +#define GFX_TV_STANDARD_PAL_G 0x0100 + +/* FS450 VGA Mode flags */ + +#define GFX_VGA_MODE_UNKNOWN 0 +#define GFX_VGA_MODE_640X480 0x0001 +#define GFX_VGA_MODE_720X487 0x0002 +#define GFX_VGA_MODE_720X576 0x0004 +#define GFX_VGA_MODE_800X600 0x0008 +#define GFX_VGA_MODE_1024X768 0x0010 + +/* FS450 TVout mode flags */ + +#define GFX_TVOUT_MODE_CVBS 0x0001 +#define GFX_TVOUT_MODE_YC 0x0002 +#define GFX_TVOUT_MODE_RGB 0x0004 +#define GFX_TVOUT_MODE_CVBS_YC (GFX_TVOUT_MODE_CVBS | GFX_TVOUT_MODE_YC) + +/* FS450 Luma and Chroma Filters */ + +#define GFX_LUMA_FILTER 0x0001 +#define GFX_CHROMA_FILTER 0x0002 + +/* APS Trigger Bits */ + +#define GFX_APS_TRIGGER_OFF 0 +#define GFX_APS_TRIGGER_AGC_ONLY 1 +#define GFX_APS_TRIGGER_AGC_2_LINE 2 +#define GFX_APS_TRIGGER_AGC_4_LINE 3 + +typedef struct +{ + int xsize; + int ysize; + int hz; + int clock; + unsigned char miscOutput; + unsigned char stdCRTCregs[GFX_STD_CRTC_REGS]; + unsigned char extCRTCregs[GFX_EXT_CRTC_REGS]; +} gfx_vga_struct; + +/* POSSIBLE STATUS VALUES */ + +#define GFX_STATUS_UNSUPPORTED (-3) +#define GFX_STATUS_BAD_PARAMETER (-2) +#define GFX_STATUS_ERROR (-1) +#define GFX_STATUS_OK 0 + +/* CPU AND VIDEO TYPES */ + +#define GFX_CPU_GXLV 1 +#define GFX_CPU_SC1200 2 +#define GFX_CPU_REDCLOUD 3 +#define GFX_CPU_CASTLE 4 +#define GFX_CPU_PYRAMID 0x20801 + +#define GFX_VID_CS5530 1 +#define GFX_VID_SC1200 2 +#define GFX_VID_REDCLOUD 3 +#define GFX_VID_CASTLE 4 + +/* CHIP NAME AND REVISION */ + +typedef enum ChipType +{ + CHIP_NOT_DETECTED, + SC1200_REV_A, + SC1200_REV_B1_B2, + SC1200_REV_B3, + SC1200_REV_C1, + SC1200_REV_D1, + SC1200_REV_D1_1, + SC1200_REV_D2_MVD, /* Macrovision disabled */ + SC1200_REV_D2_MVE, /* Macrovision enabled */ + SC1200_FUTURE_REV +} ChipType; + +#endif /* !_gfx_type_h */ diff --git a/src/gfx/gfx_vga.c b/src/gfx/gfx_vga.c new file mode 100644 index 0000000..8ab9b6a --- /dev/null +++ b/src/gfx/gfx_vga.c @@ -0,0 +1,45 @@ +/* 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 to interface to the VGA registers. Some + * operating systems require mode sets be done through VGA, rather than + * directly using the "gfx_set_display_mode" routine. + * */ + +/* INCLUDE SUPPORT FOR FIRST GENERATION, IF SPECIFIED. */ + +#if GFX_VGA_GU1 +#include "vga_gu1.c" +#endif + +/* WRAPPERS IF DYNAMIC SELECTION */ +/* Extra layer to call either first or second generation routines. */ + +#if GFX_VGA_DYNAMIC + +#endif /* GFX_DISPLAY_DYNAMIC */ + +/* END OF FILE */ diff --git a/src/gfx/gfx_vid.c b/src/gfx/gfx_vid.c new file mode 100644 index 0000000..ec1acbc --- /dev/null +++ b/src/gfx/gfx_vid.c @@ -0,0 +1,2319 @@ +/* <LIC_AMD_STD> + * Copyright (C) 2005 Advanced Micro Devices, Inc. All Rights Reserved. + * </LIC_AMD_STD> */ +/* <CTL_AMD_STD> + * </CTL_AMD_STD> */ +/* 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 to control the video overlay window. + * + * Video overlay routines: + * + * gfx_set_clock_frequency + * gfx_set_crt_enable + * gfx_set_video_enable + * gfx_set_video_format + * gfx_set_video_size + * gfx_set_video_offset + * gfx_set_video_yuv_offsets + * gfx_set_video_yuv_pitch + * gfx_set_video_scale + * gfx_set_video_upscale + * gfx_set_video_downscale_config + * gfx_set_video_downscale_coefficients + * gfx_set_video_downscale_enable + * gfx_set_video_vertical_downscale + * gfx_set_video_vertical_downscale_enable + * gfx_set_video_window + * gfx_set_video_left_crop + * gfx_set_video_color_key + * gfx_set_video_filter + * gfx_set_video_palette + * gfx_set_video_request + * gfx_set_video_source + * gfx_set_vbi_source + * gfx_set_vbi_lines + * gfx_set_vbi_total + * gfx_set_video_interlaced + * gfx_set_color_space_YUV + * gfx_set_vertical_scaler_offset + * gfx_set_top_line_in_odd + * gfx_set_genlock_delay + * gfx_set_genlock_enable + * gfx_set_video_cursor + * gfx_set_video_cursor_enable + * + * Alpha blending routines (SC1200 ONLY): + * + * gfx_select_alpha_region + * gfx_set_alpha_enable + * gfx_set_alpha_window + * gfx_set_alpha_value + * gfx_set_alpha_priority + * gfx_set_alpha_color + * gfx_set_alpha_color_enable + * gfx_set_no_ck_outside_alpha + * gfx_test_tvout_odd_field + * + * And the following routines if GFX_READ_ROUTINES is set: + * + * gfx_get_sync_polarities + * gfx_get_video_enable + * gfx_get_video_format + * gfx_get_video_src_size + * gfx_get_video_line_size + * gfx_get_video_xclip + * gfx_get_video_offset + * gfx_get_video_yuv_offsets + * gfx_get_video_yuv_pitch + * gfx_get_video_scale + * gfx_get_video_upscale + * gfx_get_video_downscale_config + * gfx_get_video_downscale_coefficients + * gfx_get_video_downscale_enable + * gfx_get_video_downscale_delta + * gfx_get_video_vertical_downscale_enable + * gfx_get_video_dst_size + * gfx_get_video_position + * gfx_get_video_color_key + * gfx_get_video_color_key_mask + * gfx_get_video_color_key_src + * gfx_get_video_filter + * gfx_get_video_request + * gfx_get_video_source + * gfx_get_vbi_source + * gfx_get_vbi_lines + * gfx_get_vbi_total + * gfx_get_video_interlaced + * gfx_get_color_space_YUV + * gfx_get_vertical_scaler_offset + * gfx_get_genlock_delay + * gfx_get_genlock_enable + * gfx_get_video_cursor + * gfx_get_clock_frequency + * gfx_read_crc + * + * Alpha blending read routines (SC1200 ONLY): + * + * gfx_get_alpha_enable + * gfx_get_alpha_size + * gfx_get_alpha_value + * gfx_get_alpha_priority + * gfx_get_alpha_color + * */ + +/* STATIC VARIABLES FOR VIDEO OVERLAY CONTROL */ +/* These are saved to allow these routines to do clipping. */ + +unsigned long gfx_vid_offset = 0; /* copy from last gfx_set_video_offset */ +unsigned long gfx_vid_uoffset = 0; /* copy from last + * gfx_set_video_yuv_offsets */ +unsigned long gfx_vid_voffset = 0; /* copy from last + * gfx_set_video_yuv_offsets */ +unsigned long gfx_vid_srcw = 300; /* copy from last gfx_set_video_scale */ +unsigned long gfx_vid_srch = 300; /* copy from last gfx_set_video_scale */ +unsigned long gfx_vid_dstw = 300; /* copy from last gfx_set_video_scale */ +unsigned long gfx_vid_dsth = 300; /* copy from last gfx_set_video_scale */ +short gfx_vid_xpos = 0; /* copy from last gfx_set_video_window */ +short gfx_vid_ypos = 0; /* copy from last gfx_set_video_window */ +unsigned short gfx_vid_width = 0; /* copy from last gfx_set_video_window */ +unsigned short gfx_vid_height = 0; /* copy from last gfx_set_video_window */ + +int gfx_alpha_select = 0; /* currently selected alpha region */ + +int gfx_set_screen_enable(int enable); /* forward declaration */ + +/* INCLUDE SUPPORT FOR CS5530, IF SPECIFIED. */ + +#if GFX_VIDEO_CS5530 +#include "vid_5530.c" +#endif + +/* INCLUDE SUPPORT FOR SC1200, IF SPECIFIED. */ + +#if GFX_VIDEO_SC1200 +#include "vid_1200.c" +#endif + +/* INLUDE SUPPORT FOR REDCLOUD, IF SPECIFIED. */ + +#if GFX_VIDEO_REDCLOUD +#include "vid_rdcl.c" +#endif + +/* INLUDE SUPPORT FOR CASTLE, IF SPECIFIED. */ + +#if GFX_VIDEO_CASTLE +#include "vid_cstl.c" +#endif + +/*--------------------------------------------------------------------------- + * gfx_select_alpha_region + * + * This routine selects which alpha region should be used for future + * updates. The SC1200, for example, has 3 alpha windows available, + * so valid parameter values are 0..2. + *--------------------------------------------------------------------------- + */ +int +gfx_select_alpha_region(int region) +{ + if (region > 2) + return (GFX_STATUS_BAD_PARAMETER); + + gfx_alpha_select = region; + return (GFX_STATUS_OK); +} + +/* WRAPPERS IF DYNAMIC SELECTION */ +/* Extra layer to call either CS5530 or SC1200 routines. */ + +#if GFX_VIDEO_DYNAMIC + +/*--------------------------------------------------------------------------- + * gfx_reset_video (PRIVATE ROUTINE: NOT PART OF DURANGO API) + * + * This routine is used to disable all components of video overlay before + * performing a mode switch. + *--------------------------------------------------------------------------- + */ +void +gfx_reset_video(void) +{ +#if GFX_VIDEO_CS5530 + if (gfx_video_type == GFX_VIDEO_TYPE_CS5530) + cs5530_reset_video(); +#endif +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + sc1200_reset_video(); +#endif +#if GFX_VIDEO_REDCLOUD + if (gfx_video_type == GFX_VIDEO_TYPE_REDCLOUD) + redcloud_reset_video(); +#endif +#if GFX_VIDEO_CASTLE + if (gfx_video_type == GFX_VIDEO_TYPE_CASTLE) + castle_reset_video(); +#endif +} + +/*--------------------------------------------------------------------------- + * gfx_set_display_control (PRIVATE ROUTINE: NOT PART OF DURANGO API) + * + * This routine is used to configure the display output during a modeset + *--------------------------------------------------------------------------- + */ +int +gfx_set_display_control(int sync_polarities) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_VIDEO_CS5530 + if (gfx_video_type == GFX_VIDEO_TYPE_CS5530) + status = cs5530_set_display_control(sync_polarities); +#endif +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + status = sc1200_set_display_control(sync_polarities); +#endif +#if GFX_VIDEO_REDCLOUD + if (gfx_video_type == GFX_VIDEO_TYPE_REDCLOUD) + status = redcloud_set_display_control(sync_polarities); +#endif +#if GFX_VIDEO_CASTLE + if (gfx_video_type == GFX_VIDEO_TYPE_CASTLE) + status = castle_set_display_control(sync_polarities); +#endif + return (status); +} + +/*---------------------------------------------------------------------------- + * gfx_set_clock_frequency + *---------------------------------------------------------------------------- + */ +void +gfx_set_clock_frequency(unsigned long frequency) +{ +#if GFX_VIDEO_CS5530 + if (gfx_video_type == GFX_VIDEO_TYPE_CS5530) + cs5530_set_clock_frequency(frequency); +#endif +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + sc1200_set_clock_frequency(frequency); +#endif +#if GFX_VIDEO_REDCLOUD + if (gfx_video_type == GFX_VIDEO_TYPE_REDCLOUD) + redcloud_set_clock_frequency(frequency); +#endif +#if GFX_VIDEO_CASTLE + if (gfx_video_type == GFX_VIDEO_TYPE_CASTLE) + castle_set_clock_frequency(frequency); +#endif +} + +/*---------------------------------------------------------------------------- + * gfx_set_crt_enable + *---------------------------------------------------------------------------- + */ +int +gfx_set_crt_enable(int enable) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + status = sc1200_set_crt_enable(enable); +#endif +#if GFX_VIDEO_CS5530 + if (gfx_video_type == GFX_VIDEO_TYPE_CS5530) + status = cs5530_set_crt_enable(enable); +#endif +#if GFX_VIDEO_REDCLOUD + if (gfx_video_type == GFX_VIDEO_TYPE_REDCLOUD) + status = redcloud_set_crt_enable(enable); +#endif +#if GFX_VIDEO_CASTLE + if (gfx_video_type == GFX_VIDEO_TYPE_CASTLE) + status = castle_set_crt_enable(enable); +#endif + return (status); +} + +/*---------------------------------------------------------------------------- + * gfx_set_video_enable + *---------------------------------------------------------------------------- + */ +int +gfx_set_video_enable(int enable) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_VIDEO_CS5530 + if (gfx_video_type == GFX_VIDEO_TYPE_CS5530) + status = cs5530_set_video_enable(enable); +#endif +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + status = sc1200_set_video_enable(enable); +#endif +#if GFX_VIDEO_REDCLOUD + if (gfx_video_type == GFX_VIDEO_TYPE_REDCLOUD) + status = redcloud_set_video_enable(enable); +#endif +#if GFX_VIDEO_CASTLE + if (gfx_video_type == GFX_VIDEO_TYPE_CASTLE) + status = castle_set_video_enable(enable); +#endif + return (status); +} + +/*--------------------------------------------------------------------------- + * gfx_set_screen_enable (PRIVATE ROUTINE: NOT PART OF DURANGO API) + * + * This routine enables or disables the graphics display logic of the video + * processor. + *--------------------------------------------------------------------------- + */ +int +gfx_set_screen_enable(int enable) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + status = sc1200_set_screen_enable(enable); +#endif + return (status); +} + +/*---------------------------------------------------------------------------- + * gfx_set_video_format + *---------------------------------------------------------------------------- + */ +int +gfx_set_video_format(unsigned long format) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_VIDEO_CS5530 + if (gfx_video_type == GFX_VIDEO_TYPE_CS5530) + status = cs5530_set_video_format(format); +#endif +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + status = sc1200_set_video_format(format); +#endif +#if GFX_VIDEO_REDCLOUD + if (gfx_video_type == GFX_VIDEO_TYPE_REDCLOUD) + status = redcloud_set_video_format(format); +#endif +#if GFX_VIDEO_CASTLE + if (gfx_video_type == GFX_VIDEO_TYPE_CASTLE) + status = castle_set_video_format(format); +#endif + return (status); +} + +/*---------------------------------------------------------------------------- + * gfx_set_video_size + *---------------------------------------------------------------------------- + */ +int +gfx_set_video_size(unsigned short width, unsigned short height) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_VIDEO_CS5530 + if (gfx_video_type == GFX_VIDEO_TYPE_CS5530) + status = cs5530_set_video_size(width, height); +#endif +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + status = sc1200_set_video_size(width, height); +#endif +#if GFX_VIDEO_REDCLOUD + if (gfx_video_type == GFX_VIDEO_TYPE_REDCLOUD) + status = redcloud_set_video_size(width, height); +#endif +#if GFX_VIDEO_CASTLE + if (gfx_video_type == GFX_VIDEO_TYPE_CASTLE) + status = castle_set_video_size(width, height); +#endif + return (status); +} + +/*---------------------------------------------------------------------------- + * gfx_set_video_yuv_pitch + *---------------------------------------------------------------------------- + */ +int +gfx_set_video_yuv_pitch(unsigned long ypitch, unsigned long uvpitch) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_VIDEO_REDCLOUD + if (gfx_video_type == GFX_VIDEO_TYPE_REDCLOUD) + status = redcloud_set_video_yuv_pitch(ypitch, uvpitch); +#endif +#if GFX_VIDEO_CASTLE + if (gfx_video_type == GFX_VIDEO_TYPE_CASTLE) + status = castle_set_video_yuv_pitch(ypitch, uvpitch); +#endif + return (status); +} + +/*---------------------------------------------------------------------------- + * gfx_set_video_offset + *---------------------------------------------------------------------------- + */ +int +gfx_set_video_offset(unsigned long offset) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_VIDEO_CS5530 + if (gfx_video_type == GFX_VIDEO_TYPE_CS5530) + status = cs5530_set_video_offset(offset); +#endif +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + status = sc1200_set_video_offset(offset); +#endif +#if GFX_VIDEO_REDCLOUD + if (gfx_video_type == GFX_VIDEO_TYPE_REDCLOUD) + status = redcloud_set_video_offset(offset); +#endif +#if GFX_VIDEO_CASTLE + if (gfx_video_type == GFX_VIDEO_TYPE_CASTLE) + status = castle_set_video_offset(offset); +#endif + return (status); +} + +/*---------------------------------------------------------------------------- + * gfx_set_video_yuv_offsets + *---------------------------------------------------------------------------- + */ +int +gfx_set_video_yuv_offsets(unsigned long yoffset, unsigned long uoffset, + unsigned long voffset) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_VIDEO_REDCLOUD + if (gfx_video_type == GFX_VIDEO_TYPE_REDCLOUD) + status = redcloud_set_video_yuv_offsets(yoffset, uoffset, voffset); +#endif +#if GFX_VIDEO_CASTLE + if (gfx_video_type == GFX_VIDEO_TYPE_CASTLE) + status = castle_set_video_yuv_offsets(yoffset, uoffset, voffset); +#endif + return (status); +} + +/*--------------------------------------------------------------------------- + * gfx_set_video_scale + *--------------------------------------------------------------------------- + */ +int +gfx_set_video_scale(unsigned short srcw, unsigned short srch, + unsigned short dstw, unsigned short dsth) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_VIDEO_CS5530 + if (gfx_video_type == GFX_VIDEO_TYPE_CS5530) + status = cs5530_set_video_scale(srcw, srch, dstw, dsth); +#endif +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + status = sc1200_set_video_scale(srcw, srch, dstw, dsth); +#endif +#if GFX_VIDEO_REDCLOUD + if (gfx_video_type == GFX_VIDEO_TYPE_REDCLOUD) + status = redcloud_set_video_scale(srcw, srch, dstw, dsth); +#endif +#if GFX_VIDEO_CASTLE + if (gfx_video_type == GFX_VIDEO_TYPE_CASTLE) + status = castle_set_video_scale(srcw, srch, dstw, dsth); +#endif + return (status); +} + +/*--------------------------------------------------------------------------- + * gfx_set_video_upscale + *--------------------------------------------------------------------------- + */ +int +gfx_set_video_upscale(unsigned short srcw, unsigned short srch, + unsigned short dstw, unsigned short dsth) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + status = sc1200_set_video_upscale(srcw, srch, dstw, dsth); +#endif + return (status); +} + +/*--------------------------------------------------------------------------- + * gfx_set_video_vertical_downscale + *--------------------------------------------------------------------------- + */ +int +gfx_set_video_vertical_downscale(unsigned short srch, unsigned short dsth) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_VIDEO_REDCLOUD + if (gfx_video_type == GFX_VIDEO_TYPE_REDCLOUD) + status = redcloud_set_video_vertical_downscale(srch, dsth); +#endif + return (status); +} + +/*--------------------------------------------------------------------------- + * gfx_set_video_vertical_downscale_enable + *--------------------------------------------------------------------------- + */ +void +gfx_set_video_vertical_downscale_enable(int enable) +{ +#if GFX_VIDEO_REDCLOUD + if (gfx_video_type == GFX_VIDEO_TYPE_REDCLOUD) + redcloud_set_video_vertical_downscale_enable(enable); +#endif +} + +/*--------------------------------------------------------------------------- + * gfx_set_video_downscale_config + *--------------------------------------------------------------------------- + */ +int +gfx_set_video_downscale_config(unsigned short type, unsigned short m) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + status = sc1200_set_video_downscale_config(type, m); +#endif +#if GFX_VIDEO_REDCLOUD + if (gfx_video_type == GFX_VIDEO_TYPE_REDCLOUD) + status = redcloud_set_video_downscale_config(type, m); +#endif + return (status); +} + +/*--------------------------------------------------------------------------- + * gfx_set_video_downscale_coefficients + *--------------------------------------------------------------------------- + */ +int +gfx_set_video_downscale_coefficients(unsigned short coef1, + unsigned short coef2, unsigned short coef3, unsigned short coef4) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + status = + sc1200_set_video_downscale_coefficients(coef1, coef2, coef3, + coef4); +#endif +#if GFX_VIDEO_REDCLOUD + if (gfx_video_type == GFX_VIDEO_TYPE_REDCLOUD) + status = + redcloud_set_video_downscale_coefficients(coef1, coef2, coef3, + coef4); +#endif + return (status); +} + +/*--------------------------------------------------------------------------- + * gfx_set_video_downscale_enable + *--------------------------------------------------------------------------- + */ +int +gfx_set_video_downscale_enable(int enable) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + status = sc1200_set_video_downscale_enable(enable); +#endif +#if GFX_VIDEO_REDCLOUD + if (gfx_video_type == GFX_VIDEO_TYPE_REDCLOUD) + status = redcloud_set_video_downscale_enable(enable); +#endif + return (status); +} + +/*--------------------------------------------------------------------------- + * gfx_set_video_window + *--------------------------------------------------------------------------- + */ +int +gfx_set_video_window(short x, short y, unsigned short w, unsigned short h) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_VIDEO_CS5530 + if (gfx_video_type == GFX_VIDEO_TYPE_CS5530) + status = cs5530_set_video_window(x, y, w, h); +#endif +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + status = sc1200_set_video_window(x, y, w, h); +#endif +#if GFX_VIDEO_REDCLOUD + if (gfx_video_type == GFX_VIDEO_TYPE_REDCLOUD) + status = redcloud_set_video_window(x, y, w, h); +#endif +#if GFX_VIDEO_CASTLE + if (gfx_video_type == GFX_VIDEO_TYPE_CASTLE) + status = castle_set_video_window(x, y, w, h); +#endif + return (status); +} + +/*--------------------------------------------------------------------------- + * gfx_set_video_left_crop + *--------------------------------------------------------------------------- + */ +int +gfx_set_video_left_crop(unsigned short x) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + status = sc1200_set_video_left_crop(x); +#endif +#if GFX_VIDEO_CS5530 + if (gfx_video_type == GFX_VIDEO_TYPE_CS5530) + status = cs5530_set_video_left_crop(x); +#endif +#if GFX_VIDEO_REDCLOUD + if (gfx_video_type == GFX_VIDEO_TYPE_REDCLOUD) + status = redcloud_set_video_left_crop(x); +#endif +#if GFX_VIDEO_CASTLE + if (gfx_video_type == GFX_VIDEO_TYPE_CASTLE) + status = castle_set_video_left_crop(x); +#endif + return (status); +} + +/*--------------------------------------------------------------------------- + * gfx_set_video_color_key + *--------------------------------------------------------------------------- + */ +int +gfx_set_video_color_key(unsigned long key, unsigned long mask, int graphics) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_VIDEO_CS5530 + if (gfx_video_type == GFX_VIDEO_TYPE_CS5530) + status = cs5530_set_video_color_key(key, mask, graphics); +#endif +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + status = sc1200_set_video_color_key(key, mask, graphics); +#endif +#if GFX_VIDEO_REDCLOUD + if (gfx_video_type == GFX_VIDEO_TYPE_REDCLOUD) + status = redcloud_set_video_color_key(key, mask, graphics); +#endif +#if GFX_VIDEO_CASTLE + if (gfx_video_type == GFX_VIDEO_TYPE_CASTLE) + status = castle_set_video_color_key(key, mask, graphics); +#endif + return (status); +} + +/*--------------------------------------------------------------------------- + * gfx_set_video_filter + *--------------------------------------------------------------------------- + */ +int +gfx_set_video_filter(int xfilter, int yfilter) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_VIDEO_CS5530 + if (gfx_video_type == GFX_VIDEO_TYPE_CS5530) + status = cs5530_set_video_filter(xfilter, yfilter); +#endif +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + status = sc1200_set_video_filter(xfilter, yfilter); +#endif +#if GFX_VIDEO_REDCLOUD + if (gfx_video_type == GFX_VIDEO_TYPE_REDCLOUD) + status = redcloud_set_video_filter(xfilter, yfilter); +#endif + return (status); +} + +/*--------------------------------------------------------------------------- + * gfx_set_video_palette + *--------------------------------------------------------------------------- + */ +int +gfx_set_video_palette(unsigned long *palette) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_VIDEO_CS5530 + if (gfx_video_type == GFX_VIDEO_TYPE_CS5530) + status = cs5530_set_video_palette(palette); +#endif +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + status = sc1200_set_video_palette(palette); +#endif +#if GFX_VIDEO_REDCLOUD + if (gfx_video_type == GFX_VIDEO_TYPE_REDCLOUD) + status = redcloud_set_video_palette(palette); +#endif +#if GFX_VIDEO_CASTLE + if (gfx_video_type == GFX_VIDEO_TYPE_CASTLE) + status = castle_set_video_palette(palette); +#endif + return (status); +} + +/*--------------------------------------------------------------------------- + * gfx_set_graphics_palette + *--------------------------------------------------------------------------- + */ +int +gfx_set_graphics_palette(unsigned long *palette) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_VIDEO_REDCLOUD + if (gfx_video_type == GFX_VIDEO_TYPE_REDCLOUD) + status = redcloud_set_graphics_palette(palette); +#endif + + return (status); +} + +/*--------------------------------------------------------------------------- + * gfx_set_video_palette_entry + *--------------------------------------------------------------------------- + */ +int +gfx_set_video_palette_entry(unsigned long index, unsigned long palette) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_VIDEO_CS5530 + if (gfx_video_type == GFX_VIDEO_TYPE_CS5530) + status = cs5530_set_video_palette_entry(index, palette); +#endif +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + status = sc1200_set_video_palette_entry(index, palette); +#endif +#if GFX_VIDEO_REDCLOUD + if (gfx_video_type == GFX_VIDEO_TYPE_REDCLOUD) + status = redcloud_set_video_palette_entry(index, palette); +#endif +#if GFX_VIDEO_CASTLE + if (gfx_video_type == GFX_VIDEO_TYPE_CASTLE) + status = castle_set_video_palette_entry(index, palette); +#endif + return (status); +} + +/*--------------------------------------------------------------------------- + * gfx_set_graphics_palette_entry + *--------------------------------------------------------------------------- + */ +int +gfx_set_graphics_palette_entry(unsigned long index, unsigned long palette) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_VIDEO_REDCLOUD + if (gfx_video_type == GFX_VIDEO_TYPE_REDCLOUD) + status = redcloud_set_graphics_palette_entry(index, palette); +#endif + + return (status); +} + +/*--------------------------------------------------------------------------- + * gfx_set_video_palette_bypass + *--------------------------------------------------------------------------- + */ +int +gfx_set_video_palette_bypass(int enable) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + status = sc1200_set_video_palette_bypass(enable); +#endif +#if GFX_VIDEO_REDCLOUD + if (gfx_video_type == GFX_VIDEO_TYPE_REDCLOUD) + status = redcloud_set_video_palette_bypass(enable); +#endif + return (status); +} + +/*--------------------------------------------------------------------------- + * gfx_set_video_request + *--------------------------------------------------------------------------- + */ +int +gfx_set_video_request(short x, short y) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + status = sc1200_set_video_request(x, y); +#endif +#if GFX_VIDEO_REDCLOUD + if (gfx_video_type == GFX_VIDEO_TYPE_REDCLOUD) + status = redcloud_set_video_request(x, y); +#endif +#if GFX_VIDEO_CASTLE + if (gfx_video_type == GFX_VIDEO_TYPE_CASTLE) + status = castle_set_video_request(x, y); +#endif + return (status); +} + +/*--------------------------------------------------------------------------- + * gfx_set_video_source + *--------------------------------------------------------------------------- + */ +int +gfx_set_video_source(VideoSourceType source) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + status = sc1200_set_video_source(source); +#endif + return (status); +} + +/*--------------------------------------------------------------------------- + * gfx_set_vbi_source + *--------------------------------------------------------------------------- + */ +int +gfx_set_vbi_source(VbiSourceType source) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + status = sc1200_set_vbi_source(source); +#endif + return (status); +} + +/*--------------------------------------------------------------------------- + * gfx_set_vbi_lines + *--------------------------------------------------------------------------- + */ +int +gfx_set_vbi_lines(unsigned long even, unsigned long odd) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + status = sc1200_set_vbi_lines(even, odd); +#endif + return (status); +} + +/*--------------------------------------------------------------------------- + * gfx_set_vbi_total + *--------------------------------------------------------------------------- + */ +int +gfx_set_vbi_total(unsigned long even, unsigned long odd) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + status = sc1200_set_vbi_total(even, odd); +#endif + return (status); +} + +/*--------------------------------------------------------------------------- + * gfx_set_video_interlaced + *--------------------------------------------------------------------------- + */ +int +gfx_set_video_interlaced(int enable) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + status = sc1200_set_video_interlaced(enable); +#endif + return (status); +} + +/*--------------------------------------------------------------------------- + * gfx_set_color_space_YUV + *--------------------------------------------------------------------------- + */ +int +gfx_set_color_space_YUV(int enable) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + status = sc1200_set_color_space_YUV(enable); +#endif + return (status); +} + +/*--------------------------------------------------------------------------- + * gfx_set_vertical_scaler_offset + *--------------------------------------------------------------------------- + */ +int +gfx_set_vertical_scaler_offset(char offset) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + status = sc1200_set_vertical_scaler_offset(offset); +#endif + return (status); +} + +/*--------------------------------------------------------------------------- + * gfx_set_top_line_in_odd + *--------------------------------------------------------------------------- + */ +int +gfx_set_top_line_in_odd(int enable) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + status = sc1200_set_top_line_in_odd(enable); +#endif + return (status); +} + +/*--------------------------------------------------------------------------- + * gfx_set_genlock_delay + *--------------------------------------------------------------------------- + */ +int +gfx_set_genlock_delay(unsigned long delay) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + status = sc1200_set_genlock_delay(delay); +#endif + return (status); +} + +/*--------------------------------------------------------------------------- + * gfx_set_genlock_enable + *--------------------------------------------------------------------------- + */ +int +gfx_set_genlock_enable(int flags) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + status = sc1200_set_genlock_enable(flags); +#endif + return (status); +} + +/*--------------------------------------------------------------------------- + * gfx_set_video_cursor + *--------------------------------------------------------------------------- + */ +int +gfx_set_video_cursor(unsigned long key, unsigned long mask, + unsigned short select_color2, unsigned long color1, unsigned long color2) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + status = + sc1200_set_video_cursor(key, mask, select_color2, color1, color2); +#endif +#if GFX_VIDEO_REDCLOUD + if (gfx_video_type == GFX_VIDEO_TYPE_REDCLOUD) + status = + redcloud_set_video_cursor(key, mask, select_color2, color1, + color2); +#endif +#if GFX_VIDEO_CASTLE + if (gfx_video_type == GFX_VIDEO_TYPE_CASTLE) + status = + castle_set_video_cursor(key, mask, select_color2, color1, color2); +#endif + return (status); +} + +/*--------------------------------------------------------------------------- + * gfx_set_video_cursor_enable + *--------------------------------------------------------------------------- + */ +int +gfx_set_video_cursor_enable(int enable) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_VIDEO_REDCLOUD + if (gfx_video_type == GFX_VIDEO_TYPE_REDCLOUD) + status = redcloud_set_video_cursor_enable(enable); +#endif +#if GFX_VIDEO_CASTLE + if (gfx_video_type == GFX_VIDEO_TYPE_CASTLE) + status = castle_set_video_cursor_enable(enable); +#endif + return (status); +} + +/*--------------------------------------------------------------------------- + * gfx_set_alpha_enable + *--------------------------------------------------------------------------- + */ +int +gfx_set_alpha_enable(int enable) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + status = sc1200_set_alpha_enable(enable); +#endif +#if GFX_VIDEO_REDCLOUD + if (gfx_video_type == GFX_VIDEO_TYPE_REDCLOUD) + status = redcloud_set_alpha_enable(enable); +#endif +#if GFX_VIDEO_CASTLE + if (gfx_video_type == GFX_VIDEO_TYPE_CASTLE) + status = castle_set_alpha_enable(enable); +#endif + return (status); +} + +/*--------------------------------------------------------------------------- + * gfx_set_alpha_window + *--------------------------------------------------------------------------- + */ +int +gfx_set_alpha_window(short x, short y, + unsigned short width, unsigned short height) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + status = sc1200_set_alpha_window(x, y, width, height); +#endif +#if GFX_VIDEO_REDCLOUD + if (gfx_video_type == GFX_VIDEO_TYPE_REDCLOUD) + status = redcloud_set_alpha_window(x, y, width, height); +#endif +#if GFX_VIDEO_CASTLE + if (gfx_video_type == GFX_VIDEO_TYPE_CASTLE) + status = castle_set_alpha_window(x, y, width, height); +#endif + return (status); +} + +/*--------------------------------------------------------------------------- + * gfx_set_alpha_value + *--------------------------------------------------------------------------- + */ +int +gfx_set_alpha_value(unsigned char alpha, char delta) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + status = sc1200_set_alpha_value(alpha, delta); +#endif +#if GFX_VIDEO_REDCLOUD + if (gfx_video_type == GFX_VIDEO_TYPE_REDCLOUD) + status = redcloud_set_alpha_value(alpha, delta); +#endif +#if GFX_VIDEO_CASTLE + if (gfx_video_type == GFX_VIDEO_TYPE_CASTLE) + status = castle_set_alpha_value(alpha, delta); +#endif + return (status); +} + +/*--------------------------------------------------------------------------- + * gfx_set_alpha_priority + *--------------------------------------------------------------------------- + */ +int +gfx_set_alpha_priority(int priority) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + status = sc1200_set_alpha_priority(priority); +#endif +#if GFX_VIDEO_REDCLOUD + if (gfx_video_type == GFX_VIDEO_TYPE_REDCLOUD) + status = redcloud_set_alpha_priority(priority); +#endif +#if GFX_VIDEO_CASTLE + if (gfx_video_type == GFX_VIDEO_TYPE_CASTLE) + status = castle_set_alpha_priority(priority); +#endif + return (status); +} + +/*--------------------------------------------------------------------------- + * gfx_set_alpha_color + *--------------------------------------------------------------------------- + */ +int +gfx_set_alpha_color(unsigned long color) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + status = sc1200_set_alpha_color(color); +#endif +#if GFX_VIDEO_REDCLOUD + if (gfx_video_type == GFX_VIDEO_TYPE_REDCLOUD) + status = redcloud_set_alpha_color(color); +#endif +#if GFX_VIDEO_CASTLE + if (gfx_video_type == GFX_VIDEO_TYPE_CASTLE) + status = castle_set_alpha_color(color); +#endif + return (status); +} + +/*--------------------------------------------------------------------------- + * gfx_set_alpha_color_enable + *--------------------------------------------------------------------------- + */ +int +gfx_set_alpha_color_enable(int enable) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + status = sc1200_set_alpha_color_enable(enable); +#endif +#if GFX_VIDEO_REDCLOUD + if (gfx_video_type == GFX_VIDEO_TYPE_REDCLOUD) + status = redcloud_set_alpha_color_enable(enable); +#endif +#if GFX_VIDEO_CASTLE + if (gfx_video_type == GFX_VIDEO_TYPE_CASTLE) + status = castle_set_alpha_color_enable(enable); +#endif + return (status); +} + +/*--------------------------------------------------------------------------- + * gfx_set_no_ck_outside_alpha + *--------------------------------------------------------------------------- + */ +int +gfx_set_no_ck_outside_alpha(int enable) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + status = sc1200_set_no_ck_outside_alpha(enable); +#endif +#if GFX_VIDEO_REDCLOUD + if (gfx_video_type == GFX_VIDEO_TYPE_REDCLOUD) + status = redcloud_set_no_ck_outside_alpha(enable); +#endif +#if GFX_VIDEO_CASTLE + if (gfx_video_type == GFX_VIDEO_TYPE_CASTLE) + status = castle_set_no_ck_outside_alpha(enable); +#endif + return (status); +} + +/*--------------------------------------------------------------------------- + * gfx_set_macrovision_enable + *--------------------------------------------------------------------------- + */ +int +gfx_set_macrovision_enable(int enable) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + status = sc1200_set_macrovision_enable(enable); +#endif + return (status); +} + +/*--------------------------------------------------------------------------- + * gfx_disable_softvga + *--------------------------------------------------------------------------- + */ +int +gfx_disable_softvga(void) +{ + int status = 0; + +#if GFX_VIDEO_CS5530 + if (gfx_video_type == GFX_VIDEO_TYPE_CS5530) + status = cs5530_disable_softvga(); +#endif +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + status = sc1200_disable_softvga(); +#endif + return (status); +} + +/*--------------------------------------------------------------------------- + * gfx_enable_softvga + *--------------------------------------------------------------------------- + */ +int +gfx_enable_softvga(void) +{ + int status = 0; + +#if GFX_VIDEO_CS5530 + if (gfx_video_type == GFX_VIDEO_TYPE_CS5530) + status = cs5530_enable_softvga(); +#endif +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + status = sc1200_enable_softvga(); +#endif + return (status); +} + +/*--------------------------------------------------------------------------- + * gfx_get_clock_frequency + *--------------------------------------------------------------------------- + */ +unsigned long +gfx_get_clock_frequency(void) +{ + unsigned long frequency = 0; + +#if GFX_VIDEO_CS5530 + if (gfx_video_type == GFX_VIDEO_TYPE_CS5530) + frequency = cs5530_get_clock_frequency(); +#endif +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + frequency = sc1200_get_clock_frequency(); +#endif +#if GFX_VIDEO_REDCLOUD + if (gfx_video_type == GFX_VIDEO_TYPE_REDCLOUD) + frequency = redcloud_get_clock_frequency(); +#endif +#if GFX_VIDEO_CASTLE + if (gfx_video_type == GFX_VIDEO_TYPE_CASTLE) + frequency = castle_get_clock_frequency(); +#endif + return (frequency); +} + +/*--------------------------------------------------------------------------- + * gfx_get_max_video_width + *--------------------------------------------------------------------------- + */ +unsigned long +gfx_get_max_video_width(void) +{ + unsigned long width = 0; + +#if GFX_VIDEO_CS5530 + if (gfx_video_type == GFX_VIDEO_TYPE_CS5530) + width = cs5530_get_max_video_width(); +#endif +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + width = sc1200_get_max_video_width(); +#endif + return (width); +} + +/*************************************************************/ +/* READ ROUTINES | INCLUDED FOR DIAGNOSTIC PURPOSES ONLY */ +/*************************************************************/ + +#if GFX_READ_ROUTINES + +/*--------------------------------------------------------------------------- + * gfx_get_vsa2_softvga_enable + *--------------------------------------------------------------------------- + */ +int +gfx_get_vsa2_softvga_enable(void) +{ + int enable = 0; + +#if GFX_VIDEO_CS5530 + if (gfx_video_type == GFX_VIDEO_TYPE_CS5530) + enable = cs5530_get_vsa2_softvga_enable(); +#endif +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + enable = sc1200_get_vsa2_softvga_enable(); +#endif + return enable; + +} + +/*--------------------------------------------------------------------------- + * gfx_get_sync_polarities + *--------------------------------------------------------------------------- + */ +int +gfx_get_sync_polarities(void) +{ + int polarities = 0; + +#if GFX_VIDEO_CS5530 + if (gfx_video_type == GFX_VIDEO_TYPE_CS5530) + polarities = cs5530_get_sync_polarities(); +#endif +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + polarities = sc1200_get_sync_polarities(); +#endif +#if GFX_VIDEO_REDCLOUD + if (gfx_video_type == GFX_VIDEO_TYPE_REDCLOUD) + polarities = redcloud_get_sync_polarities(); +#endif +#if GFX_VIDEO_CASTLE + if (gfx_video_type == GFX_VIDEO_TYPE_CASTLE) + polarities = castle_get_sync_polarities(); +#endif + return (polarities); +} + +/*--------------------------------------------------------------------------- + * gfx_get_video_palette_entry + *--------------------------------------------------------------------------- + */ +int +gfx_get_video_palette_entry(unsigned long index, unsigned long *palette) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_VIDEO_CS5530 + if (gfx_video_type == GFX_VIDEO_TYPE_CS5530) + status = cs5530_get_video_palette_entry(index, palette); +#endif +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + status = sc1200_get_video_palette_entry(index, palette); +#endif +#if GFX_VIDEO_REDCLOUD + if (gfx_video_type == GFX_VIDEO_TYPE_REDCLOUD) + status = redcloud_get_video_palette_entry(index, palette); +#endif +#if GFX_VIDEO_CASTLE + if (gfx_video_type == GFX_VIDEO_TYPE_CASTLE) + status = castle_get_video_palette_entry(index, palette); +#endif + return (status); +} + +/*---------------------------------------------------------------------------- + * gfx_get_video_enable + *---------------------------------------------------------------------------- + */ +int +gfx_get_video_enable(void) +{ + int enable = 0; + +#if GFX_VIDEO_CS5530 + if (gfx_video_type == GFX_VIDEO_TYPE_CS5530) + enable = cs5530_get_video_enable(); +#endif +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + enable = sc1200_get_video_enable(); +#endif +#if GFX_VIDEO_REDCLOUD + if (gfx_video_type == GFX_VIDEO_TYPE_REDCLOUD) + enable = redcloud_get_video_enable(); +#endif +#if GFX_VIDEO_CASTLE + if (gfx_video_type == GFX_VIDEO_TYPE_CASTLE) + enable = castle_get_video_enable(); +#endif + return (enable); +} + +/*---------------------------------------------------------------------------- + * gfx_get_video_format + *---------------------------------------------------------------------------- + */ +int +gfx_get_video_format(void) +{ + int format = 0; + +#if GFX_VIDEO_CS5530 + if (gfx_video_type == GFX_VIDEO_TYPE_CS5530) + format = cs5530_get_video_format(); +#endif +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + format = sc1200_get_video_format(); +#endif +#if GFX_VIDEO_REDCLOUD + if (gfx_video_type == GFX_VIDEO_TYPE_REDCLOUD) + format = redcloud_get_video_format(); +#endif +#if GFX_VIDEO_CASTLE + if (gfx_video_type == GFX_VIDEO_TYPE_CASTLE) + format = castle_get_video_format(); +#endif + return (format); +} + +/*---------------------------------------------------------------------------- + * gfx_get_video_src_size + *---------------------------------------------------------------------------- + */ +unsigned long +gfx_get_video_src_size(void) +{ + unsigned long size = 0; + +#if GFX_VIDEO_CS5530 + if (gfx_video_type == GFX_VIDEO_TYPE_CS5530) + size = cs5530_get_video_src_size(); +#endif +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + size = sc1200_get_video_src_size(); +#endif +#if GFX_VIDEO_REDCLOUD + if (gfx_video_type == GFX_VIDEO_TYPE_REDCLOUD) + size = redcloud_get_video_src_size(); +#endif +#if GFX_VIDEO_CASTLE + if (gfx_video_type == GFX_VIDEO_TYPE_CASTLE) + size = castle_get_video_src_size(); +#endif + return (size); +} + +/*---------------------------------------------------------------------------- + * gfx_get_video_line_size + *---------------------------------------------------------------------------- + */ +unsigned long +gfx_get_video_line_size(void) +{ + unsigned long size = 0; + +#if GFX_VIDEO_CS5530 + if (gfx_video_type == GFX_VIDEO_TYPE_CS5530) + size = cs5530_get_video_line_size(); +#endif +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + size = sc1200_get_video_line_size(); +#endif +#if GFX_VIDEO_REDCLOUD + if (gfx_video_type == GFX_VIDEO_TYPE_REDCLOUD) + size = redcloud_get_video_line_size(); +#endif +#if GFX_VIDEO_CASTLE + if (gfx_video_type == GFX_VIDEO_TYPE_CASTLE) + size = castle_get_video_line_size(); +#endif + return (size); +} + +/*---------------------------------------------------------------------------- + * gfx_get_video_xclip + *---------------------------------------------------------------------------- + */ +unsigned long +gfx_get_video_xclip(void) +{ + unsigned long size = 0; + +#if GFX_VIDEO_CS5530 + if (gfx_video_type == GFX_VIDEO_TYPE_CS5530) + size = cs5530_get_video_xclip(); +#endif +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + size = sc1200_get_video_xclip(); +#endif +#if GFX_VIDEO_REDCLOUD + if (gfx_video_type == GFX_VIDEO_TYPE_REDCLOUD) + size = redcloud_get_video_xclip(); +#endif +#if GFX_VIDEO_CASTLE + if (gfx_video_type == GFX_VIDEO_TYPE_CASTLE) + size = castle_get_video_xclip(); +#endif + return (size); +} + +/*---------------------------------------------------------------------------- + * gfx_get_video_offset + *---------------------------------------------------------------------------- + */ +unsigned long +gfx_get_video_offset(void) +{ + unsigned long offset = 0; + +#if GFX_VIDEO_CS5530 + if (gfx_video_type == GFX_VIDEO_TYPE_CS5530) + offset = cs5530_get_video_offset(); +#endif +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + offset = sc1200_get_video_offset(); +#endif +#if GFX_VIDEO_REDCLOUD + if (gfx_video_type == GFX_VIDEO_TYPE_REDCLOUD) + offset = redcloud_get_video_offset(); +#endif +#if GFX_VIDEO_CASTLE + if (gfx_video_type == GFX_VIDEO_TYPE_CASTLE) + offset = castle_get_video_offset(); +#endif + return (offset); +} + +/*---------------------------------------------------------------------------- + * gfx_get_video_yuv_offsets + *---------------------------------------------------------------------------- + */ +void +gfx_get_video_yuv_offsets(unsigned long *yoffset, unsigned long *uoffset, + unsigned long *voffset) +{ +#if GFX_VIDEO_REDCLOUD + if (gfx_video_type == GFX_VIDEO_TYPE_REDCLOUD) + redcloud_get_video_yuv_offsets(yoffset, uoffset, voffset); +#endif +#if GFX_VIDEO_CASTLE + if (gfx_video_type == GFX_VIDEO_TYPE_CASTLE) + castle_get_video_yuv_offsets(yoffset, uoffset, voffset); +#endif +} + +/*---------------------------------------------------------------------------- + * gfx_get_video_yuv_pitch + *---------------------------------------------------------------------------- + */ +void +gfx_get_video_yuv_pitch(unsigned long *ypitch, unsigned long *uvpitch) +{ +#if GFX_VIDEO_REDCLOUD + if (gfx_video_type == GFX_VIDEO_TYPE_REDCLOUD) + redcloud_get_video_yuv_pitch(ypitch, uvpitch); +#endif +#if GFX_VIDEO_CASTLE + if (gfx_video_type == GFX_VIDEO_TYPE_CASTLE) + castle_get_video_yuv_pitch(ypitch, uvpitch); +#endif +} + +/*--------------------------------------------------------------------------- + * gfx_get_video_upscale + *--------------------------------------------------------------------------- + */ +unsigned long +gfx_get_video_upscale(void) +{ + unsigned long scale = 0; + +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + scale = sc1200_get_video_upscale(); +#endif + return (scale); +} + +/*--------------------------------------------------------------------------- + * gfx_get_video_scale + *--------------------------------------------------------------------------- + */ +unsigned long +gfx_get_video_scale(void) +{ + unsigned long scale = 0; + +#if GFX_VIDEO_CS5530 + if (gfx_video_type == GFX_VIDEO_TYPE_CS5530) + scale = cs5530_get_video_scale(); +#endif +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + scale = sc1200_get_video_scale(); +#endif +#if GFX_VIDEO_REDCLOUD + if (gfx_video_type == GFX_VIDEO_TYPE_REDCLOUD) + scale = redcloud_get_video_scale(); +#endif + return (scale); +} + +/*--------------------------------------------------------------------------- + * gfx_get_video_downscale_delta + *--------------------------------------------------------------------------- + */ +unsigned long +gfx_get_video_downscale_delta(void) +{ + unsigned long delta = 0; + +#if GFX_VIDEO_REDCLOUD + if (gfx_video_type == GFX_VIDEO_TYPE_REDCLOUD) + delta = redcloud_get_video_downscale_delta(); +#endif + return (delta); +} + +/*--------------------------------------------------------------------------- + * gfx_get_video_vertical_downscale_enable + *--------------------------------------------------------------------------- + */ +int +gfx_get_video_vertical_downscale_enable(void) +{ + int enable = 0; + +#if GFX_VIDEO_REDCLOUD + if (gfx_video_type == GFX_VIDEO_TYPE_REDCLOUD) + enable = redcloud_get_video_vertical_downscale_enable(); +#endif + return (enable); +} + +/*--------------------------------------------------------------------------- + * gfx_get_video_downscale_config + *--------------------------------------------------------------------------- + */ +int +gfx_get_video_downscale_config(unsigned short *type, unsigned short *m) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + status = sc1200_get_video_downscale_config(type, m); +#endif +#if GFX_VIDEO_REDCLOUD + if (gfx_video_type == GFX_VIDEO_TYPE_REDCLOUD) + status = redcloud_get_video_downscale_config(type, m); +#endif + return (status); +} + +/*--------------------------------------------------------------------------- + * gfx_get_video_downscale_coefficients + *--------------------------------------------------------------------------- + */ +void +gfx_get_video_downscale_coefficients(unsigned short *coef1, + unsigned short *coef2, unsigned short *coef3, unsigned short *coef4) +{ +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + sc1200_get_video_downscale_coefficients(coef1, coef2, coef3, coef4); +#endif +#if GFX_VIDEO_REDCLOUD + if (gfx_video_type == GFX_VIDEO_TYPE_REDCLOUD) + redcloud_get_video_downscale_coefficients(coef1, coef2, coef3, coef4); +#endif +} + +/*--------------------------------------------------------------------------- + * gfx_get_video_downscale_enable + *--------------------------------------------------------------------------- + */ +void +gfx_get_video_downscale_enable(int *enable) +{ +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + sc1200_get_video_downscale_enable(enable); +#endif +#if GFX_VIDEO_REDCLOUD + if (gfx_video_type == GFX_VIDEO_TYPE_REDCLOUD) + redcloud_get_video_downscale_enable(enable); +#endif +} + +/*--------------------------------------------------------------------------- + * gfx_get_video_dst_size + *--------------------------------------------------------------------------- + */ +unsigned long +gfx_get_video_dst_size(void) +{ + unsigned long size = 0; + +#if GFX_VIDEO_CS5530 + if (gfx_video_type == GFX_VIDEO_TYPE_CS5530) + size = cs5530_get_video_dst_size(); +#endif +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + size = sc1200_get_video_dst_size(); +#endif +#if GFX_VIDEO_REDCLOUD + if (gfx_video_type == GFX_VIDEO_TYPE_REDCLOUD) + size = redcloud_get_video_dst_size(); +#endif +#if GFX_VIDEO_CASTLE + if (gfx_video_type == GFX_VIDEO_TYPE_CASTLE) + size = castle_get_video_dst_size(); +#endif + return (size); +} + +/*--------------------------------------------------------------------------- + * gfx_get_video_position + *--------------------------------------------------------------------------- + */ +unsigned long +gfx_get_video_position(void) +{ + unsigned long position = 0; + +#if GFX_VIDEO_CS5530 + if (gfx_video_type == GFX_VIDEO_TYPE_CS5530) + position = cs5530_get_video_position(); +#endif +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + position = sc1200_get_video_position(); +#endif +#if GFX_VIDEO_REDCLOUD + if (gfx_video_type == GFX_VIDEO_TYPE_REDCLOUD) + position = redcloud_get_video_position(); +#endif +#if GFX_VIDEO_CASTLE + if (gfx_video_type == GFX_VIDEO_TYPE_CASTLE) + position = castle_get_video_position(); +#endif + return (position); +} + +/*--------------------------------------------------------------------------- + * gfx_get_video_color_key + *--------------------------------------------------------------------------- + */ +unsigned long +gfx_get_video_color_key(void) +{ + unsigned long key = 0; + +#if GFX_VIDEO_CS5530 + if (gfx_video_type == GFX_VIDEO_TYPE_CS5530) + key = cs5530_get_video_color_key(); +#endif +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + key = sc1200_get_video_color_key(); +#endif +#if GFX_VIDEO_REDCLOUD + if (gfx_video_type == GFX_VIDEO_TYPE_REDCLOUD) + key = redcloud_get_video_color_key(); +#endif +#if GFX_VIDEO_CASTLE + if (gfx_video_type == GFX_VIDEO_TYPE_CASTLE) + key = castle_get_video_color_key(); +#endif + return (key); +} + +/*--------------------------------------------------------------------------- + * gfx_get_video_color_key_mask + *--------------------------------------------------------------------------- + */ +unsigned long +gfx_get_video_color_key_mask(void) +{ + unsigned long mask = 0; + +#if GFX_VIDEO_CS5530 + if (gfx_video_type == GFX_VIDEO_TYPE_CS5530) + mask = cs5530_get_video_color_key_mask(); +#endif +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + mask = sc1200_get_video_color_key_mask(); +#endif +#if GFX_VIDEO_REDCLOUD + if (gfx_video_type == GFX_VIDEO_TYPE_REDCLOUD) + mask = redcloud_get_video_color_key_mask(); +#endif +#if GFX_VIDEO_CASTLE + if (gfx_video_type == GFX_VIDEO_TYPE_CASTLE) + mask = castle_get_video_color_key_mask(); +#endif + return (mask); +} + +/*--------------------------------------------------------------------------- + * gfx_get_video_color_key_src + *--------------------------------------------------------------------------- + */ +int +gfx_get_video_color_key_src(void) +{ + int src = 0; + +#if GFX_VIDEO_CS5530 + if (gfx_video_type == GFX_VIDEO_TYPE_CS5530) + src = cs5530_get_video_color_key_src(); +#endif +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + src = sc1200_get_video_color_key_src(); +#endif +#if GFX_VIDEO_REDCLOUD + if (gfx_video_type == GFX_VIDEO_TYPE_REDCLOUD) + src = redcloud_get_video_color_key_src(); +#endif +#if GFX_VIDEO_CASTLE + if (gfx_video_type == GFX_VIDEO_TYPE_CASTLE) + src = castle_get_video_color_key_src(); +#endif + return (src); +} + +/*--------------------------------------------------------------------------- + * gfx_get_video_filter + *--------------------------------------------------------------------------- + */ +int +gfx_get_video_filter(void) +{ + int filter = 0; + +#if GFX_VIDEO_CS5530 + if (gfx_video_type == GFX_VIDEO_TYPE_CS5530) + filter = cs5530_get_video_filter(); +#endif +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + filter = sc1200_get_video_filter(); +#endif +#if GFX_VIDEO_REDCLOUD + if (gfx_video_type == GFX_VIDEO_TYPE_REDCLOUD) + filter = redcloud_get_video_filter(); +#endif + return (filter); +} + +/*--------------------------------------------------------------------------- + * gfx_get_video_request + *--------------------------------------------------------------------------- + */ +int +gfx_get_video_request(short *x, short *y) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + status = sc1200_get_video_request(x, y); +#endif +#if GFX_VIDEO_REDCLOUD + if (gfx_video_type == GFX_VIDEO_TYPE_REDCLOUD) + status = redcloud_get_video_request(x, y); +#endif +#if GFX_VIDEO_CASTLE + if (gfx_video_type == GFX_VIDEO_TYPE_CASTLE) + status = castle_get_video_request(x, y); +#endif + return (status); +} + +/*--------------------------------------------------------------------------- + * gfx_get_video_source + *--------------------------------------------------------------------------- + */ +int +gfx_get_video_source(VideoSourceType * source) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + status = sc1200_get_video_source(source); +#endif + return (status); +} + +/*--------------------------------------------------------------------------- + * gfx_get_vbi_source + *--------------------------------------------------------------------------- + */ +int +gfx_get_vbi_source(VbiSourceType * source) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + status = sc1200_get_vbi_source(source); +#endif + return (status); +} + +/*--------------------------------------------------------------------------- + * gfx_get_vbi_lines + *--------------------------------------------------------------------------- + */ +unsigned long +gfx_get_vbi_lines(int odd) +{ + unsigned long lines = (unsigned long)GFX_STATUS_UNSUPPORTED; + +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + lines = sc1200_get_vbi_lines(odd); +#endif + return (lines); +} + +/*--------------------------------------------------------------------------- + * gfx_get_vbi_total + *--------------------------------------------------------------------------- + */ +unsigned long +gfx_get_vbi_total(int odd) +{ + unsigned long total = (unsigned long)GFX_STATUS_UNSUPPORTED; + +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + total = sc1200_get_vbi_total(odd); +#endif + return (total); +} + +/*--------------------------------------------------------------------------- + * gfx_get_video_interlaced + *--------------------------------------------------------------------------- + */ +int +gfx_get_video_interlaced(void) +{ + int interlaced = GFX_STATUS_UNSUPPORTED; + +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + interlaced = sc1200_get_video_interlaced(); +#endif + return (interlaced); +} + +/*--------------------------------------------------------------------------- + * gfx_get_color_space_YUV + *--------------------------------------------------------------------------- + */ +int +gfx_get_color_space_YUV(void) +{ + int color_space = GFX_STATUS_UNSUPPORTED; + +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + color_space = sc1200_get_color_space_YUV(); +#endif + return (color_space); +} + +/*--------------------------------------------------------------------------- + * gfx_get_vertical_scaler_offset + *--------------------------------------------------------------------------- + */ +int +gfx_get_vertical_scaler_offset(char *offset) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + status = sc1200_get_vertical_scaler_offset(offset); +#endif + return (status); +} + +/*--------------------------------------------------------------------------- + * gfx_get_genlock_delay + *--------------------------------------------------------------------------- + */ +unsigned long +gfx_get_genlock_delay(void) +{ + unsigned long delay = (unsigned long)GFX_STATUS_UNSUPPORTED; + +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + delay = sc1200_get_genlock_delay(); +#endif + return (delay); +} + +/*--------------------------------------------------------------------------- + * gfx_get_genlock_enable + *--------------------------------------------------------------------------- + */ +int +gfx_get_genlock_enable(void) +{ + int enable = GFX_STATUS_UNSUPPORTED; + +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + enable = sc1200_get_genlock_enable(); +#endif + return (enable); +} + +/*--------------------------------------------------------------------------- + * gfx_get_video_cursor + *--------------------------------------------------------------------------- + */ +int +gfx_get_video_cursor(unsigned long *key, unsigned long *mask, + unsigned short *select_color2, unsigned long *color1, + unsigned short *color2) +{ + int enable = GFX_STATUS_UNSUPPORTED; + +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + enable = + sc1200_get_video_cursor(key, mask, select_color2, color1, color2); +#endif +#if GFX_VIDEO_REDCLOUD + if (gfx_video_type == GFX_VIDEO_TYPE_REDCLOUD) + enable = + redcloud_get_video_cursor(key, mask, select_color2, color1, + color2); +#endif +#if GFX_VIDEO_CASTLE + if (gfx_video_type == GFX_VIDEO_TYPE_CASTLE) + enable = + castle_get_video_cursor(key, mask, select_color2, color1, color2); +#endif + return (enable); +} + +/*--------------------------------------------------------------------------- + * gfx_read_crc + *--------------------------------------------------------------------------- + */ +unsigned long +gfx_read_crc(void) +{ + unsigned long crc = 0; + +#if GFX_VIDEO_CS5530 + if (gfx_video_type == GFX_VIDEO_TYPE_CS5530) + crc = cs5530_read_crc(); +#endif +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + crc = sc1200_read_crc(); +#endif +#if GFX_VIDEO_REDCLOUD + if (gfx_video_type == GFX_VIDEO_TYPE_REDCLOUD) + crc = redcloud_read_crc(); +#endif +#if GFX_VIDEO_CASTLE + if (gfx_video_type == GFX_VIDEO_TYPE_CASTLE) + crc = castle_read_crc(); +#endif + return (crc); +} + +/*--------------------------------------------------------------------------- + * gfx_read_crc32 + *--------------------------------------------------------------------------- + */ +unsigned long +gfx_read_crc32(void) +{ + unsigned long crc = 0; + +#if GFX_VIDEO_REDCLOUD + if (gfx_video_type == GFX_VIDEO_TYPE_REDCLOUD) + crc = redcloud_read_crc32(); +#endif +#if GFX_VIDEO_CASTLE + if (gfx_video_type == GFX_VIDEO_TYPE_CASTLE) + crc = castle_read_crc32(); +#endif + return (crc); +} + +/*--------------------------------------------------------------------------- + * gfx_read_window_crc + *--------------------------------------------------------------------------- + */ +unsigned long +gfx_read_window_crc(int source, unsigned short x, unsigned short y, + unsigned short width, unsigned short height, int crc32) +{ + unsigned long crc = 0; + +#if GFX_VIDEO_REDCLOUD + if (gfx_video_type == GFX_VIDEO_TYPE_REDCLOUD) + crc = redcloud_read_window_crc(source, x, y, width, height, crc32); +#endif +#if GFX_VIDEO_CASTLE + if (gfx_video_type == GFX_VIDEO_TYPE_CASTLE) + crc = castle_read_window_crc(source, x, y, width, height, crc32); +#endif + return (crc); +} + +/*----------------------------------------------------------------------------- + * gfx_get_macrovision_enable + *----------------------------------------------------------------------------- + */ +int +gfx_get_macrovision_enable(void) +{ + int enable = 0; + +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + enable = sc1200_get_video_enable(); +#endif + return (enable); +} + +/*--------------------------------------------------------------------------- + * gfx_get_alpha_enable + *--------------------------------------------------------------------------- + */ +void +gfx_get_alpha_enable(int *enable) +{ +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + sc1200_get_alpha_enable(enable); +#endif +#if GFX_VIDEO_REDCLOUD + if (gfx_video_type == GFX_VIDEO_TYPE_REDCLOUD) + redcloud_get_alpha_enable(enable); +#endif +#if GFX_VIDEO_CASTLE + if (gfx_video_type == GFX_VIDEO_TYPE_CASTLE) + castle_get_alpha_enable(enable); +#endif + return; +} + +/*--------------------------------------------------------------------------- + * gfx_get_alpha_size + *--------------------------------------------------------------------------- + */ +void +gfx_get_alpha_size(unsigned short *x, unsigned short *y, + unsigned short *width, unsigned short *height) +{ +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + sc1200_get_alpha_size(x, y, width, height); +#endif +#if GFX_VIDEO_REDCLOUD + if (gfx_video_type == GFX_VIDEO_TYPE_REDCLOUD) + redcloud_get_alpha_size(x, y, width, height); +#endif +#if GFX_VIDEO_CASTLE + if (gfx_video_type == GFX_VIDEO_TYPE_CASTLE) + castle_get_alpha_size(x, y, width, height); +#endif + return; +} + +/*--------------------------------------------------------------------------- + * gfx_get_alpha_value + *--------------------------------------------------------------------------- + */ +void +gfx_get_alpha_value(unsigned char *alpha, char *delta) +{ +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + sc1200_get_alpha_value(alpha, delta); +#endif +#if GFX_VIDEO_REDCLOUD + if (gfx_video_type == GFX_VIDEO_TYPE_REDCLOUD) + redcloud_get_alpha_value(alpha, delta); +#endif +#if GFX_VIDEO_CASTLE + if (gfx_video_type == GFX_VIDEO_TYPE_CASTLE) + castle_get_alpha_value(alpha, delta); +#endif + return; +} + +/*--------------------------------------------------------------------------- + * gfx_get_alpha_priority + *--------------------------------------------------------------------------- + */ +void +gfx_get_alpha_priority(int *priority) +{ +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + sc1200_get_alpha_priority(priority); +#endif +#if GFX_VIDEO_REDCLOUD + if (gfx_video_type == GFX_VIDEO_TYPE_REDCLOUD) + redcloud_get_alpha_priority(priority); +#endif +#if GFX_VIDEO_CASTLE + if (gfx_video_type == GFX_VIDEO_TYPE_CASTLE) + castle_get_alpha_priority(priority); +#endif + return; +} + +/*--------------------------------------------------------------------------- + * gfx_get_alpha_color + *--------------------------------------------------------------------------- + */ +void +gfx_get_alpha_color(unsigned long *color) +{ +#if GFX_VIDEO_SC1200 + if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) + sc1200_get_alpha_color(color); +#endif +#if GFX_VIDEO_REDCLOUD + if (gfx_video_type == GFX_VIDEO_TYPE_REDCLOUD) + redcloud_get_alpha_color(color); +#endif +#if GFX_VIDEO_CASTLE + if (gfx_video_type == GFX_VIDEO_TYPE_CASTLE) + castle_get_alpha_color(color); +#endif + return; +} + +#endif /* GFX_READ_ROUTINES */ + +#endif /* GFX_VIDEO_DYNAMIC */ + +/* END OF FILE */ diff --git a/src/gfx/gfx_vip.c b/src/gfx/gfx_vip.c new file mode 100644 index 0000000..e38c2f7 --- /dev/null +++ b/src/gfx/gfx_vip.c @@ -0,0 +1,531 @@ +/* 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 to control the video input port (VIP). + * + * gfx_set_vip_enable + * gfx_set_vip_capture_run_mode + * gfx_set_vip_base + * gfx_set_vip_pitch + * gfx_set_vip_mode + * gfx_set_vbi_enable + * gfx_set_vbi_mode + * gfx_set_vbi_base + * gfx_set_vbi_pitch + * gfx_set_vbi_direct + * gfx_set_vbi_interrupt + * gfx_set_vip_bus_request_threshold_high + * gfx_set_vip_last_line + * gfx_test_vip_odd_field + * gfx_test_vip_bases_updated + * gfx_test_vip_fifo_overflow + * gfx_get_vip_line + * gfx_get_vip_base + * gfx_get_vbi_pitch + * + * And the following routines if GFX_READ_ROUTINES is set: + * + * gfx_get_vip_enable + * gfx_get_vip_pitch + * gfx_get_vip_mode + * gfx_get_vbi_enable + * gfx_get_vbi_mode + * gfx_get_vbi_base + * gfx_get_vbi_direct + * gfx_get_vbi_interrupt + * gfx_get_vip_bus_request_threshold_high + * */ + +/* INCLUDE SUPPORT FOR SC1200, IF SPECIFIED. */ + +#if GFX_VIP_SC1200 +#include "vip_1200.c" +#endif + +/* WRAPPERS IF DYNAMIC SELECTION */ +/* Extra layer to call either CS5530 or SC1200 routines. */ + +#if GFX_VIP_DYNAMIC + +/*--------------------------------------------------------------------------- + * gfx_set_vip_enable + *---------------------------------------------------------------------------- + */ +int +gfx_set_vip_enable(int enable) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_VIP_SC1200 + if (gfx_vip_type == GFX_VIP_TYPE_SC1200) + status = sc1200_set_vip_enable(enable); +#endif + return (status); +} + +/*---------------------------------------------------------------------------- + * gfx_set_vip_capture_run_mode + *---------------------------------------------------------------------------- + */ +int +gfx_set_vip_capture_run_mode(int mode) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_VIP_SC1200 + if (gfx_vip_type == GFX_VIP_TYPE_SC1200) + status = sc1200_set_vip_capture_run_mode(mode); +#endif + return (status); +} + +/*---------------------------------------------------------------------------- + * gfx_set_vip_base + *---------------------------------------------------------------------------- + */ +int +gfx_set_vip_base(unsigned long even, unsigned long odd) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_VIP_SC1200 + if (gfx_vip_type == GFX_VIP_TYPE_SC1200) + status = sc1200_set_vip_base(even, odd); +#endif + return (status); +} + +/*---------------------------------------------------------------------------- + * gfx_set_vip_pitch + *---------------------------------------------------------------------------- + */ +int +gfx_set_vip_pitch(unsigned long pitch) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_VIP_SC1200 + if (gfx_vip_type == GFX_VIP_TYPE_SC1200) + status = sc1200_set_vip_pitch(pitch); +#endif + return (status); +} + +/*---------------------------------------------------------------------------- + * gfx_set_vip_mode + *---------------------------------------------------------------------------- + */ +int +gfx_set_vip_mode(int mode) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_VIP_SC1200 + if (gfx_vip_type == GFX_VIP_TYPE_SC1200) + status = sc1200_set_vip_mode(mode); +#endif + return (status); +} + +/*---------------------------------------------------------------------------- + * gfx_set_vbi_enable + *---------------------------------------------------------------------------- + */ +int +gfx_set_vbi_enable(int enable) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_VIP_SC1200 + if (gfx_vip_type == GFX_VIP_TYPE_SC1200) + status = sc1200_set_vbi_enable(enable); +#endif + return (status); +} + +/*---------------------------------------------------------------------------- + * gfx_set_vbi_mode + *---------------------------------------------------------------------------- + */ +int +gfx_set_vbi_mode(int mode) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_VIP_SC1200 + if (gfx_vip_type == GFX_VIP_TYPE_SC1200) + status = sc1200_set_vbi_mode(mode); +#endif + return (status); +} + +/*---------------------------------------------------------------------------- + * gfx_set_vbi_base + *---------------------------------------------------------------------------- + */ +int +gfx_set_vbi_base(unsigned long even, unsigned long odd) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_VIP_SC1200 + if (gfx_vip_type == GFX_VIP_TYPE_SC1200) + status = sc1200_set_vbi_base(even, odd); +#endif + return (status); +} + +/*---------------------------------------------------------------------------- + * gfx_set_vbi_pitch + *---------------------------------------------------------------------------- + */ +int +gfx_set_vbi_pitch(unsigned long pitch) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_VIP_SC1200 + if (gfx_vip_type == GFX_VIP_TYPE_SC1200) + status = sc1200_set_vbi_pitch(pitch); +#endif + return (status); +} + +/*---------------------------------------------------------------------------- + * gfx_set_vbi_direct + *---------------------------------------------------------------------------- + */ +int +gfx_set_vbi_direct(unsigned long even_lines, unsigned long odd_lines) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_VIP_SC1200 + if (gfx_vip_type == GFX_VIP_TYPE_SC1200) + status = sc1200_set_vbi_direct(even_lines, odd_lines); +#endif + return (status); +} + +/*---------------------------------------------------------------------------- + * gfx_set_vbi_interrupt + *---------------------------------------------------------------------------- + */ +int +gfx_set_vbi_interrupt(int enable) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_VIP_SC1200 + if (gfx_vip_type == GFX_VIP_TYPE_SC1200) + status = sc1200_set_vbi_interrupt(enable); +#endif + return (status); +} + +/*---------------------------------------------------------------------------- + * gfx_set_vip_bus_request_threshold_high + *---------------------------------------------------------------------------- + */ +int +gfx_set_vip_bus_request_threshold_high(int enable) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_VIP_SC1200 + if (gfx_vip_type == GFX_VIP_TYPE_SC1200) + status = sc1200_set_vip_bus_request_threshold_high(enable); +#endif + return (status); +} + +/*---------------------------------------------------------------------------- + * gfx_set_vip_last_line + *---------------------------------------------------------------------------- + */ +int +gfx_set_vip_last_line(int last_line) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_VIP_SC1200 + if (gfx_vip_type == GFX_VIP_TYPE_SC1200) + status = sc1200_set_vip_last_line(last_line); +#endif + return (status); +} + +/*---------------------------------------------------------------------------- + * gfx_test_vip_odd_field + *---------------------------------------------------------------------------- + */ +int +gfx_test_vip_odd_field(void) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_VIP_SC1200 + if (gfx_vip_type == GFX_VIP_TYPE_SC1200) + status = sc1200_test_vip_odd_field(); +#endif + return (status); +} + +/*---------------------------------------------------------------------------- + * gfx_test_vip_bases_updated + *---------------------------------------------------------------------------- + */ +int +gfx_test_vip_bases_updated(void) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_VIP_SC1200 + if (gfx_vip_type == GFX_VIP_TYPE_SC1200) + status = sc1200_test_vip_bases_updated(); +#endif + return (status); +} + +/*---------------------------------------------------------------------------- + * gfx_test_vip_fifo_overflow + *---------------------------------------------------------------------------- + */ +int +gfx_test_vip_fifo_overflow(void) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_VIP_SC1200 + if (gfx_vip_type == GFX_VIP_TYPE_SC1200) + status = sc1200_test_vip_fifo_overflow(); +#endif + return (status); +} + +/*---------------------------------------------------------------------------- + * gfx_get_vip_line + *---------------------------------------------------------------------------- + */ +int +gfx_get_vip_line(void) +{ + int status = GFX_STATUS_UNSUPPORTED; + +#if GFX_VIP_SC1200 + if (gfx_vip_type == GFX_VIP_TYPE_SC1200) + status = sc1200_get_vip_line(); +#endif + return (status); +} + +/*---------------------------------------------------------------------------- + * gfx_get_vip_base + *---------------------------------------------------------------------------- + */ +unsigned long +gfx_get_vip_base(int odd) +{ + unsigned long base = 0; + +#if GFX_VIP_SC1200 + if (gfx_vip_type == GFX_VIP_TYPE_SC1200) + base = sc1200_get_vip_base(odd); +#endif + return (base); +} + +/*---------------------------------------------------------------------------- + * gfx_get_vbi_pitch + *---------------------------------------------------------------------------- + */ +unsigned long +gfx_get_vbi_pitch(void) +{ + unsigned long pitch = 0; + +#if GFX_VIP_SC1200 + if (gfx_vip_type == GFX_VIP_TYPE_SC1200) + pitch = sc1200_get_vbi_pitch(); +#endif + return (pitch); +} + +/*************************************************************/ +/* READ ROUTINES | INCLUDED FOR DIAGNOSTIC PURPOSES ONLY */ +/*************************************************************/ + +#if GFX_READ_ROUTINES + +/*---------------------------------------------------------------------------- + * gfx_get_vip_enable + *---------------------------------------------------------------------------- + */ +int +gfx_get_vip_enable(void) +{ + int enable = 0; + +#if GFX_VIP_SC1200 + if (gfx_vip_type == GFX_VIP_TYPE_SC1200) + enable = sc1200_get_vip_enable(); +#endif + return (enable); +} + +/*---------------------------------------------------------------------------- + * gfx_get_vip_pitch + *---------------------------------------------------------------------------- + */ +unsigned long +gfx_get_vip_pitch(void) +{ + unsigned long pitch = 0; + +#if GFX_VIP_SC1200 + if (gfx_vip_type == GFX_VIP_TYPE_SC1200) + pitch = sc1200_get_vip_pitch(); +#endif + return (pitch); +} + +/*---------------------------------------------------------------------------- + * gfx_get_vip_mode + *---------------------------------------------------------------------------- + */ +int +gfx_get_vip_mode(void) +{ + int mode = 0; + +#if GFX_VIP_SC1200 + if (gfx_vip_type == GFX_VIP_TYPE_SC1200) + mode = sc1200_get_vip_mode(); +#endif + return (mode); +} + +/*---------------------------------------------------------------------------- + * gfx_get_vbi_enable + *---------------------------------------------------------------------------- + */ +int +gfx_get_vbi_enable(void) +{ + int enable = 0; + +#if GFX_VIP_SC1200 + if (gfx_vip_type == GFX_VIP_TYPE_SC1200) + enable = sc1200_get_vbi_enable(); +#endif + return (enable); +} + +/*---------------------------------------------------------------------------- + * gfx_get_vbi_mode + *---------------------------------------------------------------------------- + */ +int +gfx_get_vbi_mode(void) +{ + int mode = 0; + +#if GFX_VIP_SC1200 + if (gfx_vip_type == GFX_VIP_TYPE_SC1200) + mode = sc1200_get_vbi_mode(); +#endif + return (mode); +} + +/*---------------------------------------------------------------------------- + * gfx_get_vbi_base + *---------------------------------------------------------------------------- + */ +unsigned long +gfx_get_vbi_base(int odd) +{ + unsigned long base = 0; + +#if GFX_VIP_SC1200 + if (gfx_vip_type == GFX_VIP_TYPE_SC1200) + base = sc1200_get_vbi_base(odd); +#endif + return (base); +} + +/*---------------------------------------------------------------------------- + * gfx_get_vbi_direct + *---------------------------------------------------------------------------- + */ +unsigned long +gfx_get_vbi_direct(int odd) +{ + unsigned long vbi_direct_lines = 0; + +#if GFX_VIP_SC1200 + if (gfx_vip_type == GFX_VIP_TYPE_SC1200) + vbi_direct_lines = sc1200_get_vbi_direct(odd); +#endif + return (vbi_direct_lines); +} + +/*---------------------------------------------------------------------------- + * gfx_get_vbi_interrupt + *---------------------------------------------------------------------------- + */ +int +gfx_get_vbi_interrupt(void) +{ + int enable = 0; + +#if GFX_VIP_SC1200 + if (gfx_vip_type == GFX_VIP_TYPE_SC1200) + enable = sc1200_get_vbi_interrupt(); +#endif + return (enable); +} + +/*---------------------------------------------------------------------------- + * gfx_get_vip_bus_request_threshold_high + *---------------------------------------------------------------------------- + */ +int +gfx_get_vip_bus_request_threshold_high(void) +{ + int enable = 0; + +#if GFX_VIP_SC1200 + if (gfx_vip_type == GFX_VIP_TYPE_SC1200) + enable = sc1200_get_vip_bus_request_threshold_high(); +#endif + return (enable); +} + +#endif /* GFX_READ_ROUTINES */ + +#endif /* GFX_VIP_DYNAMIC */ + +/* END OF FILE */ diff --git a/src/gfx/history.h b/src/gfx/history.h new file mode 100644 index 0000000..ccb8d6a --- /dev/null +++ b/src/gfx/history.h @@ -0,0 +1,33 @@ +/* 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. + * */ + +/* Version is in the format of MMmmpp + * where in MM is the Major version, mm is the minor version + * and pp is the patch number (0 - 99) + */ + +#define DURANGO_VERSION 30003 + +/* END OF FILE */ diff --git a/src/gfx/i2c_acc.c b/src/gfx/i2c_acc.c new file mode 100644 index 0000000..a45a2c3 --- /dev/null +++ b/src/gfx/i2c_acc.c @@ -0,0 +1,876 @@ +/* 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 to write to and read from the I2C bus using + * the ACCESS.bus hardware in the SC1200. + * */ + +/* SUPER IO DEFINITIONS */ + +#define INDEX_1 0x15C /* base address 1 selected */ +#define DATA_1 0x15D +#define INDEX_2 0x2E /* base address 2 selected */ +#define DATA_2 0x2F +#define PCI_INDEX 0xCF8 /* PCI configuration space INDEX */ +#define PCI_DATA 0xCFC /* PCI configuration space DATA */ +#define BASE_ADR_MSB_REG 0x60 /* base address MSB register */ +#define BASE_ADR_LSB_REG 0x61 /* base address LSB register */ + +#define SIO_BASE_ADR_15C_15D 0x6000000 +#define SIO_BASE_ADR_2E_2F 0x4000000 + +/* SUPER IO GLOBALS */ + +unsigned short index_reg, data_reg; + +/* ACCESS BUS DEFINITIONS */ + +#define ACC_I2C_TIMEOUT 1000000 /* Number of reads before timing out */ +#define ACB1_BASE 0x810 /* ACCESS.bus base addresses */ +#define ACB2_BASE 0x820 +#define ACBSDA 0 /* ACB serial data */ +#define ACBST 1 /* ACB status */ +#define ACBCST 2 /* ACB control status */ +#define ACBCTL1 3 /* ACB control 1 */ +#define ACBADDR 4 /* ACB own address */ +#define ACBCTL2 5 /* ACB control 2 */ +#define LDN 0x7 /* Logical Device Numbers */ +#define ACB1_LDN 0x5 +#define ACB2_LDN 0x6 + +/* INITIAL ACCESS.bus BASE ADDRESS VALUES */ + +unsigned short base_address_array[3] = { 0, ACB1_BASE, ACB2_BASE }; +char Freq = 0x71; + +/* LOCAL ACCESS.bus FUNCTION DECLARATIONS */ + +void acc_i2c_start(unsigned char busnum); +void acc_i2c_stop(unsigned char busnum); +void acc_i2c_abort_data(unsigned char busnum); +void acc_i2c_bus_recovery(unsigned char busnum); +void acc_i2c_stall_after_start(unsigned char busnum, int state); +void acc_i2c_send_address(unsigned char busnum, unsigned char cData); +int acc_i2c_ack(unsigned char busnum, int fPut, int negAck); +void acc_i2c_stop_clock(unsigned char busnum); +void acc_i2c_activate_clock(unsigned char busnum); +void acc_i2c_write_byte(unsigned char busnum, unsigned char cData); +unsigned char acc_i2c_read_byte(unsigned char busnum, int last_byte); +void acc_i2c_reset_bus(unsigned char busnum); +int acc_i2c_request_master(unsigned char busnum); +void acc_i2c_config(unsigned char busnum, short adr, char freq); +char acc_i2c_set_freq(unsigned char busnum, char freq); +unsigned short acc_i2c_set_base_address(unsigned char busnum, short adr); + +/* LOCAL HELPER ROUTINES */ + +void OsPciReadDWord(int bus, int dev, int func, int address, + unsigned long *data); +int sio_set_index_data_reg(void); +void sio_write_reg(unsigned char reg, unsigned char data); +unsigned char sio_read_reg(unsigned char reg); + +/*--------------------------------------------------------------------------- + * OsPciReadDWord + * + * This routine reads one double word from the PCI configuration header + * defined by 'bus', 'dev', 'func' and 'address' to the double word + * pointed to by 'data'. + * + * Returns : None. + *--------------------------------------------------------------------------- + */ +void +OsPciReadDWord(int bus, int dev, int func, int address, unsigned long *data) +{ + /* + * The address of a double word in the Configuration Header is built in + * the following way : + * {10000000,bus[23:16],device[15:11],function[10:8],address[7:2],00} + */ + long addr = (0x80000000 | + ((bus & 0xff) << 16) | + ((dev & 0x1f) << 11) | ((func & 0x7) << 8) | (address & 0xff)); + OUTD(PCI_INDEX, addr); + *data = IND(PCI_DATA); +} + +/*--------------------------------------------------------------------------- + * sio_set_index_data_reg + * + * This routine checks which index and data registers to use + * in order to access the Super I/O registers + * + * Returns : 1 - OK + * 0 - Super I/O disabled or configuration access disabled + *--------------------------------------------------------------------------- + */ +int +sio_set_index_data_reg(void) +{ + unsigned long xbus_expention_bar, io_control_reg1; + + OsPciReadDWord(0, 0x12, 5, 0x10, &xbus_expention_bar); + xbus_expention_bar = xbus_expention_bar & 0xfffffffe; + io_control_reg1 = IND((unsigned short)xbus_expention_bar); + + if ((io_control_reg1) & (SIO_BASE_ADR_15C_15D)) { + index_reg = INDEX_1; + data_reg = DATA_1; + return (1); + } + + if ((io_control_reg1) & (SIO_BASE_ADR_2E_2F)) { + index_reg = INDEX_2; + data_reg = DATA_2; + return (1); + } + + return (0); +} + +/*--------------------------------------------------------------------------- + * sio_write_reg + * + * This routine writes 'data' to 'reg' Super I/O register + * + * Returns : None + *--------------------------------------------------------------------------- + */ +void +sio_write_reg(unsigned char reg, unsigned char data) +{ + OUTB(index_reg, reg); + OUTB(data_reg, data); +} + +/*--------------------------------------------------------------------------- + * sio_read_reg + * + * This routine reads data from 'reg' Super I/O register + * + * Returns : The data read from the requested register + *--------------------------------------------------------------------------- + */ +unsigned char +sio_read_reg(unsigned char reg) +{ + OUTB(index_reg, reg); + return INB(data_reg); +} + +/*--------------------------------------------------------------------------- + * gfx_i2c_reset + * + * This routine resets the I2C bus as follows : + * · Sets the base address of the ACCESS.bus + * · Sets the frequency of the ACCESS.bus + * · Resets the ACCESS.bus + * + * If 'adr' is -1 the address is read from the hardware. + * If 'freq' is -1 the frequency is set to 56 clock cycles. + *--------------------------------------------------------------------------- + */ +#if GFX_I2C_DYNAMIC +int +acc_i2c_reset(unsigned char busnum, short adr, char freq) +#else +int +gfx_i2c_reset(unsigned char busnum, short adr, char freq) +#endif +{ + if ((busnum != 1) && (busnum != 2)) + return GFX_STATUS_BAD_PARAMETER; + acc_i2c_config(busnum, adr, freq); + if (base_address_array[busnum] == 0) + return GFX_STATUS_ERROR; + acc_i2c_reset_bus(busnum); + return GFX_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * gfx_i2c_select_gpio + * + * This routine selects which GPIO pins to use. + *--------------------------------------------------------------------------- + */ +#if GFX_I2C_DYNAMIC +int +acc_i2c_select_gpio(int clock, int data) +#else +int +gfx_i2c_select_gpio(int clock, int data) +#endif +{ + /* THIS ROUTINE DOES NOT APPLY TO THE ACCESS.bus IMPLEMENTATION. */ + + return (GFX_STATUS_OK); +} + +/*--------------------------------------------------------------------------- + * gfx_i2c_write + * + * This routine writes data to the specified I2C address. + * busnum - ACCESS.bus number (1 or 2). + *--------------------------------------------------------------------------- + */ +#if GFX_I2C_DYNAMIC +int +acc_i2c_write(unsigned char busnum, unsigned char chipadr, + unsigned char subadr, unsigned char bytes, unsigned char *data) +#else +int +gfx_i2c_write(unsigned char busnum, unsigned char chipadr, + unsigned char subadr, unsigned char bytes, unsigned char *data) +#endif +{ + int loop = 0; + + if ((busnum != 1) && (busnum != 2)) + return GFX_STATUS_BAD_PARAMETER; + + /* REQUEST MASTER */ + + if (!acc_i2c_request_master(busnum)) + return (GFX_STATUS_ERROR); + + /* WRITE ADDRESS COMMAND */ + + acc_i2c_ack(busnum, 1, 0); + acc_i2c_stall_after_start(busnum, 1); + acc_i2c_send_address(busnum, (unsigned char)(chipadr & 0xFE)); + acc_i2c_stall_after_start(busnum, 0); + if (!acc_i2c_ack(busnum, 0, 0)) + return (GFX_STATUS_ERROR); + + /* WRITE COMMAND */ + + acc_i2c_write_byte(busnum, subadr); + if (!acc_i2c_ack(busnum, 0, 0)) + return (GFX_STATUS_ERROR); + + /* WRITE DATA */ + + for (loop = 0; loop < bytes; loop++) { + acc_i2c_write_byte(busnum, *data); + if (loop < (bytes - 1)) + data += sizeof(unsigned char); + if (!acc_i2c_ack(busnum, 0, 0)) + return (GFX_STATUS_ERROR); + } + data -= (bytes - 1); + acc_i2c_stop(busnum); + + return GFX_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * gfx_i2c_read + * + * This routine reads data from the specified I2C address. + * busnum - ACCESS.bus number (1 or 2). + *--------------------------------------------------------------------------- + */ +#if GFX_I2C_DYNAMIC +int +acc_i2c_read(unsigned char busnum, unsigned char chipadr, + unsigned char subadr, unsigned char bytes, unsigned char *data) +#else +int +gfx_i2c_read(unsigned char busnum, unsigned char chipadr, + unsigned char subadr, unsigned char bytes, unsigned char *data) +#endif +{ + unsigned char bytesRead; + + if ((busnum != 1) && (busnum != 2)) + return GFX_STATUS_BAD_PARAMETER; + + if (bytes == 0) + return GFX_STATUS_OK; + + /* REQUEST MASTER */ + + if (!acc_i2c_request_master(busnum)) + return (GFX_STATUS_ERROR); + + /* WRITE ADDRESS COMMAND */ + + acc_i2c_ack(busnum, 1, 0); + acc_i2c_stall_after_start(busnum, 1); + acc_i2c_send_address(busnum, (unsigned char)(chipadr & 0xFE)); + acc_i2c_stall_after_start(busnum, 0); + if (!acc_i2c_ack(busnum, 0, 0)) + return (GFX_STATUS_ERROR); + + /* WRITE COMMAND */ + + acc_i2c_write_byte(busnum, subadr); + if (!acc_i2c_ack(busnum, 0, 0)) + return (GFX_STATUS_ERROR); + + /* START THE READ */ + + acc_i2c_start(busnum); + + /* WRITE ADDRESS COMMAND */ + + acc_i2c_ack(busnum, 1, 1); + acc_i2c_stall_after_start(busnum, 1); + acc_i2c_send_address(busnum, (unsigned char)(chipadr | 0x01)); + + /* IF LAST BYTE */ + + if (bytes == 1) + acc_i2c_ack(busnum, 1, 1); + else + acc_i2c_ack(busnum, 1, 0); + + acc_i2c_stall_after_start(busnum, 0); + + if (!acc_i2c_ack(busnum, 0, 0)) + return (GFX_STATUS_ERROR); + + /* READ COMMAND */ + + for (bytesRead = 0; bytesRead < bytes; bytesRead += 1) { + if (bytesRead < (bytes - 2)) { + data[bytesRead] = acc_i2c_read_byte(busnum, 0); + acc_i2c_ack(busnum, 1, 0); + } else if (bytesRead == (bytes - 2)) { /* TWO BYTES LEFT */ + acc_i2c_ack(busnum, 1, 1); + data[bytesRead] = acc_i2c_read_byte(busnum, 0); + acc_i2c_ack(busnum, 1, 1); + } else { /* LAST BYTE */ + + data[bytesRead] = acc_i2c_read_byte(busnum, 1); + acc_i2c_stop(busnum); + } + + /* WHILE NOT LAST BYTE */ + + if ((!(bytesRead == (bytes - 1))) && (!acc_i2c_ack(busnum, 0, 0))) + return (bytesRead); + } + + return GFX_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * gfx_i2c_init + * + * This routine initializes the use of the ACCESS.BUS. + *--------------------------------------------------------------------------- + */ +#if GFX_I2C_DYNAMIC +int +acc_i2c_init(void) +#else +int +gfx_i2c_init(void) +#endif +{ + /* ### ADD ### THIS ROUTINE IS NOT YET IMPLEMENTED FOR ACCESS.bus */ + return (GFX_STATUS_OK); +} + +/*--------------------------------------------------------------------------- + * gfx_i2c_cleanup + * + * This routine ends the use of the ACCESS.BUS. + *--------------------------------------------------------------------------- + */ +#if GFX_I2C_DYNAMIC +void +acc_i2c_cleanup(void) +#else +void +gfx_i2c_cleanup(void) +#endif +{ + /* ### ADD ### THIS ROUTINE IS NOT YET IMPLEMENTED FOR ACCESS.bus */ +} + +/*--------------------------------------------------------*/ +/* LOCAL ROUTINES SPECIFIC TO ACCESS.bus IMPLEMENTATION */ +/*--------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + * acc_i2c_reset_bus + * + * This routine resets the I2C bus. + *--------------------------------------------------------------------------- + */ +void +acc_i2c_reset_bus(unsigned char busnum) +{ + unsigned char reg; + unsigned short bus_base_address = base_address_array[busnum]; + + /* Disable the ACCESS.bus device and */ + /* Configure the SCL frequency */ + OUTB((unsigned short)(bus_base_address + ACBCTL2), + (unsigned char)(Freq & 0xFE)); + + /* Configure no interrupt mode (polling) and */ + /* Disable global call address */ + OUTB((unsigned short)(bus_base_address + ACBCTL1), 0x0); + + /* Disable slave address */ + OUTB((unsigned short)(bus_base_address + ACBADDR), 0x0); + + /* Enable the ACCESS.bus device */ + reg = INB((unsigned short)(bus_base_address + ACBCTL2)); + reg |= 0x01; + OUTB((unsigned short)(bus_base_address + ACBCTL2), reg); + + /* Issue STOP event */ + + acc_i2c_stop(busnum); + + /* Clear NEGACK, STASTR and BER bits */ + OUTB((unsigned short)(bus_base_address + ACBST), 0x38); + + /* Clear BB (BUS BUSY) bit */ + reg = INB((unsigned short)(bus_base_address + ACBCST)); + reg |= 0x02; + OUTB((unsigned short)(bus_base_address + ACBCST), reg); +} + +/*--------------------------------------------------------------------------- + * acc_i2c_start + * + * This routine starts a transfer on the I2C bus. + *--------------------------------------------------------------------------- + */ +void +acc_i2c_start(unsigned char busnum) +{ + unsigned char reg; + unsigned short bus_base_address = base_address_array[busnum]; + + reg = INB((unsigned short)(bus_base_address + ACBCTL1)); + reg |= 0x01; + OUTB((unsigned short)(bus_base_address + ACBCTL1), reg); +} + +/*--------------------------------------------------------------------------- + * acc_i2c_stop + * + * This routine stops a transfer on the I2C bus. + *--------------------------------------------------------------------------- + */ +void +acc_i2c_stop(unsigned char busnum) +{ + unsigned char reg; + unsigned short bus_base_address = base_address_array[busnum]; + + reg = INB((unsigned short)(bus_base_address + ACBCTL1)); + reg |= 0x02; + OUTB((unsigned short)(bus_base_address + ACBCTL1), reg); +} + +/*--------------------------------------------------------------------------- + * acc_i2c_abort_data + *--------------------------------------------------------------------------- + */ +void +acc_i2c_abort_data(unsigned char busnum) +{ + unsigned char reg; + unsigned short bus_base_address = base_address_array[busnum]; + + acc_i2c_stop(busnum); + reg = INB((unsigned short)(bus_base_address + ACBCTL1)); + reg |= 0x10; + OUTB((unsigned short)(bus_base_address + ACBCTL1), reg); +} + +/*--------------------------------------------------------------------------- + * acc_i2c_bus_recovery + *--------------------------------------------------------------------------- + */ +void +acc_i2c_bus_recovery(unsigned char busnum) +{ + acc_i2c_abort_data(busnum); + acc_i2c_reset_bus(busnum); +} + +/*--------------------------------------------------------------------------- + * acc_i2c_stall_after_start + *--------------------------------------------------------------------------- + */ +void +acc_i2c_stall_after_start(unsigned char busnum, int state) +{ + unsigned char reg; + unsigned short bus_base_address = base_address_array[busnum]; + + reg = INB((unsigned short)(bus_base_address + ACBCTL1)); + if (state) + reg |= 0x80; + else + reg &= 0x7F; + OUTB((unsigned short)(bus_base_address + ACBCTL1), reg); + + if (!state) { + reg = INB((unsigned short)(bus_base_address + ACBST)); + reg |= 0x08; + OUTB((unsigned short)(bus_base_address + ACBST), reg); + } +} + +/*--------------------------------------------------------------------------- + * acc_i2c_send_address + *--------------------------------------------------------------------------- + */ +void +acc_i2c_send_address(unsigned char busnum, unsigned char cData) +{ + unsigned char reg; + unsigned short bus_base_address = base_address_array[busnum]; + unsigned long timeout = 0; + + /* WRITE THE DATA */ + + OUTB((unsigned short)(bus_base_address + ACBSDA), cData); + while (1) { + reg = INB((unsigned short)(bus_base_address + ACBST)); + if ((reg & 0x38) != 0) /* check STASTR, BER and NEGACK */ + break; + if (timeout++ == ACC_I2C_TIMEOUT) { + acc_i2c_bus_recovery(busnum); + return; + } + } + + /* CHECK FOR BUS ERROR */ + + if (reg & 0x20) { + acc_i2c_bus_recovery(busnum); + return; + } + + /* CHECK NEGATIVE ACKNOWLEDGE */ + + if (reg & 0x10) { + acc_i2c_abort_data(busnum); + return; + } + +} + +/*--------------------------------------------------------------------------- + * acc_i2c_ack + * + * This routine looks for acknowledge on the I2C bus. + *--------------------------------------------------------------------------- + */ +int +acc_i2c_ack(unsigned char busnum, int fPut, int negAck) +{ + unsigned char reg; + unsigned short bus_base_address = base_address_array[busnum]; + unsigned long timeout = 0; + + if (fPut) { /* read operation */ + if (!negAck) { + /* Push Ack onto I2C bus */ + reg = INB((unsigned short)(bus_base_address + ACBCTL1)); + reg &= 0xE7; + OUTB((unsigned short)(bus_base_address + ACBCTL1), reg); + } else { + /* Push negAck onto I2C bus */ + reg = INB((unsigned short)(bus_base_address + ACBCTL1)); + reg |= 0x10; + OUTB((unsigned short)(bus_base_address + ACBCTL1), reg); + } + } else { /* write operation */ + /* Receive Ack from I2C bus */ + while (1) { + reg = INB((unsigned short)(bus_base_address + ACBST)); + if ((reg & 0x70) != 0) /* check SDAST, BER and NEGACK */ + break; + if (timeout++ == ACC_I2C_TIMEOUT) { + acc_i2c_bus_recovery(busnum); + return (0); + } + } + + /* CHECK FOR BUS ERROR */ + + if (reg & 0x20) { + acc_i2c_bus_recovery(busnum); + return (0); + } + + /* CHECK NEGATIVE ACKNOWLEDGE */ + + if (reg & 0x10) { + acc_i2c_abort_data(busnum); + return (0); + } + } + return (1); +} + +/*--------------------------------------------------------------------------- + * acc_i2c_stop_clock + * + * This routine stops the ACCESS.bus clock. + *--------------------------------------------------------------------------- + */ +void +acc_i2c_stop_clock(unsigned char busnum) +{ + unsigned char reg; + unsigned short bus_base_address = base_address_array[busnum]; + + reg = INB((unsigned short)(bus_base_address + ACBCTL2)); + reg &= ~0x01; + OUTB((unsigned short)(bus_base_address + ACBCTL2), reg); +} + +/*--------------------------------------------------------------------------- + * acc_i2c_activate_clock + * + * This routine activates the ACCESS.bus clock. + *--------------------------------------------------------------------------- + */ +void +acc_i2c_activate_clock(unsigned char busnum) +{ + unsigned char reg; + unsigned short bus_base_address = base_address_array[busnum]; + + reg = INB((unsigned short)(bus_base_address + ACBCTL2)); + reg |= 0x01; + OUTB((unsigned short)(bus_base_address + ACBCTL2), reg); +} + +/*--------------------------------------------------------------------------- + * acc_i2c_write_byte + * + * This routine writes a byte to the I2C bus + *--------------------------------------------------------------------------- + */ +void +acc_i2c_write_byte(unsigned char busnum, unsigned char cData) +{ + unsigned char reg; + unsigned short bus_base_address = base_address_array[busnum]; + unsigned long timeout = 0; + + while (1) { + reg = INB((unsigned short)(bus_base_address + ACBST)); + if (reg & 0x70) + break; + if (timeout++ == ACC_I2C_TIMEOUT) { + acc_i2c_bus_recovery(busnum); + return; + } + } + + /* CHECK FOR BUS ERROR */ + + if (reg & 0x20) { + acc_i2c_bus_recovery(busnum); + return; + } + + /* CHECK NEGATIVE ACKNOWLEDGE */ + + if (reg & 0x10) { + acc_i2c_abort_data(busnum); + return; + } + + /* WRITE THE DATA */ + + OUTB((unsigned short)(bus_base_address + ACBSDA), cData); +} + +/*--------------------------------------------------------------------------- + * acc_i2c_read_byte + * + * This routine reads a byte from the I2C bus + *--------------------------------------------------------------------------- + */ +unsigned char +acc_i2c_read_byte(unsigned char busnum, int last_byte) +{ + unsigned char cData, reg; + unsigned short bus_base_address = base_address_array[busnum]; + unsigned long timeout = 0; + + while (1) { + reg = INB((unsigned short)(bus_base_address + ACBST)); + if (reg & 0x60) + break; + if (timeout++ == ACC_I2C_TIMEOUT) { + acc_i2c_bus_recovery(busnum); + return (0xEF); + } + } + + /* CHECK FOR BUS ERROR */ + + if (reg & 0x20) { + acc_i2c_bus_recovery(busnum); + return (0xEE); + } + + /* READ DATA */ + if (last_byte) + acc_i2c_stop_clock(busnum); + cData = INB((unsigned short)(bus_base_address + ACBSDA)); + if (last_byte) + acc_i2c_activate_clock(busnum); + + return (cData); +} + +/*--------------------------------------------------------------------------- + * acc_i2c_request_master + *--------------------------------------------------------------------------- + */ +int +acc_i2c_request_master(unsigned char busnum) +{ + unsigned char reg; + unsigned short bus_base_address = base_address_array[busnum]; + unsigned long timeout = 0; + + acc_i2c_start(busnum); + while (1) { + reg = INB((unsigned short)(bus_base_address + ACBST)); + if (reg & 0x60) + break; + if (timeout++ == ACC_I2C_TIMEOUT) { + acc_i2c_bus_recovery(busnum); + return (0); + } + } + + /* CHECK FOR BUS ERROR */ + + if (reg & 0x20) { + acc_i2c_abort_data(busnum); + return (0); + } + + /* CHECK NEGATIVE ACKNOWLEDGE */ + + if (reg & 0x10) { + acc_i2c_abort_data(busnum); + return (0); + } + return (1); +} + +/*--------------------------------------------------------*/ +/* LOCAL ROUTINES SPECIFIC TO ACCESS.bus INITIALIZATION */ +/*--------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- + * acc_i2c_config + * + * This routine configures the I2C bus + *---------------------------------------------------------------------------- + */ +void +acc_i2c_config(unsigned char busnum, short adr, char freq) +{ + base_address_array[busnum] = acc_i2c_set_base_address(busnum, adr); + Freq = acc_i2c_set_freq(busnum, freq); +} + +/*---------------------------------------------------------------------------- + * acc_i2c_set_freq + * + * This routine sets the frequency of the I2C bus + *---------------------------------------------------------------------------- + */ +char +acc_i2c_set_freq(unsigned char busnum, char freq) +{ + unsigned short bus_base_address = base_address_array[busnum]; + + OUTB((unsigned short)(bus_base_address + ACBCTL2), 0x0); + + if (freq == -1) + freq = 0x71; + else { + freq = freq << 1; + freq |= 0x01; + } + + OUTB((unsigned short)(bus_base_address + ACBCTL2), freq); + return (freq); +} + +/*--------------------------------------------------------------------------- + * acc_i2c_set_base_address + * + * This routine sets the base address of the I2C bus + *--------------------------------------------------------------------------- + */ +unsigned short +acc_i2c_set_base_address(unsigned char busnum, short adr) +{ + unsigned short ab_base_addr; + + /* Get Super I/O Index and Data registers */ + if (!sio_set_index_data_reg()) + return (0); + + /* Configure LDN to current ACB */ + if (busnum == 1) + sio_write_reg(LDN, ACB1_LDN); + if (busnum == 2) + sio_write_reg(LDN, ACB2_LDN); + + if (adr == -1) { + /* Get ACCESS.bus base address */ + ab_base_addr = sio_read_reg(BASE_ADR_MSB_REG); + ab_base_addr = ab_base_addr << 8; + ab_base_addr |= sio_read_reg(BASE_ADR_LSB_REG); + if (ab_base_addr != 0) + return ab_base_addr; + else + adr = (busnum == 1 ? ACB1_BASE : ACB2_BASE); + } + + /* Set ACCESS.bus base address */ + sio_write_reg(BASE_ADR_LSB_REG, (unsigned char)(adr & 0xFF)); + sio_write_reg(BASE_ADR_MSB_REG, (unsigned char)(adr >> 8)); + + return adr; +} + +/* END OF FILE */ diff --git a/src/gfx/i2c_gpio.c b/src/gfx/i2c_gpio.c new file mode 100644 index 0000000..7614cd0 --- /dev/null +++ b/src/gfx/i2c_gpio.c @@ -0,0 +1,639 @@ +/* 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 to write to and read from the I2C bus using + * the GPIO pins of the CS5530. + * */ + +/* STATIC VARIABLES TO STORE WHAT GPIO PINS TO USE */ + +int gpio_clock = 0; +int gpio_data = 0; + +static int g_initialized = 0; + +#define I2CWRITE 0x00 /* Write address */ +#define I2CREAD 0x01 /* Read address */ + +#define I2CACK 0x00 /* Ack value */ +#define I2CNACK 0x01 /* Not - ack value */ + +#define CS5530_ID (0x80000000 | (0x00<<16) | (0x12<<11) | (0<<8) | 0x00) +#define CS5530_GPIO (0x80000000 | (0x00<<16) | (0x12<<11) | (0<<8) | 0x90) +#define SDA 0x0800 +#define SCL 0x0400 +#define SDADIR 0x0008 +#define SCLDIR 0x0004 + +int I2C_init(void); +void I2C_cleanup(void); + +int I2C_Read(unsigned char address, unsigned int reg, unsigned long *p_value, + unsigned int bytes); +int I2C_Write(unsigned char address, unsigned int reg, unsigned long value, + unsigned int bytes); +int I2CAL_init(void); +void I2CAL_cleanup(void); + +void I2CAL_output_clock(int state); +void I2CAL_output_data(int state); +unsigned char I2CAL_input_data(void); + +void I2CAL_set_data_for_input(void); +void I2CAL_set_data_for_output(void); + +void SendI2CStart(void); +void SendI2CData(unsigned char inData); + +unsigned char ReceiveI2CAck(void); +void SendI2CStop(void); +void SendI2CNack(void); +void SendI2CAck(void); +unsigned char ReceiveI2CData(void); + +/* ### ADD ### ANY LOCAL ROUTINE DEFINITIONS SPECIFIC TO GPIO */ + +/*--------------------------------------------------------------------------- + * gfx_i2c_reset + * + * This routine resets the I2C bus. + *--------------------------------------------------------------------------- + */ + +#if GFX_I2C_DYNAMIC +int +gpio_i2c_reset(unsigned char busnum, short adr, char freq) +#else +int +gfx_i2c_reset(unsigned char busnum, short adr, char freq) +#endif +{ + /* ### ADD ### Any code needed to reset the state of the GPIOs. */ + return GFX_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * gfx_i2c_select_gpio + * + * This routine selects which GPIO pins to use. + *--------------------------------------------------------------------------- + */ +#if GFX_I2C_DYNAMIC +int +gpio_i2c_select_gpio(int clock, int data) +#else +int +gfx_i2c_select_gpio(int clock, int data) +#endif +{ + gpio_clock = clock; + gpio_data = data; + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_i2c_write + * + * This routine writes data to the specified I2C address. + *--------------------------------------------------------------------------- + */ +#if GFX_I2C_DYNAMIC +int +gpio_i2c_write(unsigned char busnum, unsigned char address, unsigned char reg, + unsigned char bytes, unsigned char *value) +#else +int +gfx_i2c_write(unsigned char busnum, unsigned char address, unsigned char reg, + unsigned char bytes, unsigned char *value) +#endif +{ + /* ### ADD ### CODE TO WRITE BYTE TO I2B BUS */ + + int restart_count = 0; + + while (restart_count++ < 5) { + /* set the access pointer register. */ + /* The address is shifted left by one to make room for Read/Write + * bit */ + SendI2CStart(); + SendI2CData((char)((address << 1) | I2CWRITE)); + if (!ReceiveI2CAck()) { + SendI2CStop(); + gfx_delay_milliseconds(10); + continue; + } + SendI2CData((unsigned char)reg); + if (!ReceiveI2CAck()) { + SendI2CStop(); + gfx_delay_milliseconds(10); + continue; + } + + /* write the first byte */ + SendI2CData(*value); + if (!ReceiveI2CAck()) { + SendI2CStop(); + gfx_delay_milliseconds(10); + continue; + } + + /* write the second byte. */ + if (bytes == 2) { + SendI2CData(*(value + 1)); + if (!ReceiveI2CAck()) { + SendI2CStop(); + gfx_delay_milliseconds(10); + continue; + } + } + + /* done. */ + SendI2CStop(); + + return 0; + } + + return (0); + +} + +/*--------------------------------------------------------------------------- + * gfx_i2c_read + * + * This routine reads data from the specified I2C address. + *--------------------------------------------------------------------------- + */ +#if GFX_I2C_DYNAMIC +int +gpio_i2c_read(unsigned char busnum, unsigned char address, unsigned char reg, + unsigned char bytes, unsigned char *p_value) +#else +int +gfx_i2c_read(unsigned char busnum, unsigned char address, unsigned char reg, + unsigned char bytes, unsigned char *p_value) +#endif +{ + /* ### ADD ### CODE TO WRITE BYTE TO I2B BUS */ + /* For now return clock and data pins */ + + int restart_count = 0; + + if (!p_value) + return (1); + + while (restart_count++ < 5) { + /* set the access pointer register. */ + /* The address is shifted left by one to make room for Read/Write + * bit */ + SendI2CStart(); + SendI2CData((char)((address << 1) | I2CWRITE)); + if (!ReceiveI2CAck()) { + SendI2CStop(); + gfx_delay_milliseconds(10); + continue; + } + SendI2CData((unsigned char)(reg & 0xFF)); + SendI2CNack(); + + /* read the first data byte. */ + SendI2CStart(); + SendI2CData((char)((address << 1) | I2CREAD)); + if (!ReceiveI2CAck()) { + SendI2CStop(); + gfx_delay_milliseconds(10); + continue; + } + *p_value = ReceiveI2CData(); + + /* read the second byte. */ + if (bytes == 2) { + SendI2CAck(); + *(p_value + 1) = ReceiveI2CData(); + } + + /* done. */ + SendI2CNack(); + SendI2CStop(); + + return 0; + } + + return (1); +} + +/* Added i2c/gpio code to test fs451 chip. */ + +/* + * ---------------------------------------------------------------------- + * + * void SendI2CStart(void) + * + * Sends an I2C start signal on the bus. + * + *---------------------------------------------------------------------- + */ +void +SendI2CStart(void) +{ + I2CAL_output_data(1); + I2CAL_output_clock(1); + I2CAL_output_data(0); + I2CAL_output_clock(0); +} + +/* + *---------------------------------------------------------------------- + * + * void SendI2CStop(void) + * + * Sends an I2C stop signal on the bus. + * + *---------------------------------------------------------------------- + */ +void +SendI2CStop(void) +{ + I2CAL_output_data(0); + I2CAL_output_clock(1); + I2CAL_output_data(1); +} + +/* + *---------------------------------------------------------------------- + * + * void SendI2CAck(void) + * + * Sends the Ack signal on the I2C bus. + * + *---------------------------------------------------------------------- + */ +void +SendI2CAck(void) +{ + I2CAL_output_data(0); + I2CAL_output_clock(1); + I2CAL_output_clock(0); +} + +/* + *---------------------------------------------------------------------- + * + * void SendI2CNack(void) + * + * Sends the Nt-Ack signal on the I2C bus. + * + *---------------------------------------------------------------------- + */ +void +SendI2CNack(void) +{ + I2CAL_output_data(1); + I2CAL_output_clock(1); + I2CAL_output_clock(0); +} + +/* + *---------------------------------------------------------------------- + * + * UInt8 SendI2CData( UInt8 inData ) + * + * Sends a byte of data on the I2C bus and returns the TRUE if the slave + * ACK'dthe data. + * + * Input: inData - the byte of data to send + * Output: (return) - TRUE (1) if ACK was received, FALSE (0) if not + * + *---------------------------------------------------------------------- + */ +void +SendI2CData(unsigned char inData) +{ + unsigned char bit; + + /* Send all 8 bits of data byte, MSB to LSB */ + for (bit = 0x80; bit != 0; bit >>= 1) { + if (inData & bit) + I2CAL_output_data(1); + else + I2CAL_output_data(0); + + I2CAL_output_clock(1); + I2CAL_output_clock(0); + } +} + +/* + *---------------------------------------------------------------------- + * + * UInt8 ReceiveI2CAck( ) + * + * Receives the Ack (or Nack) from the slave. + * + * Output: (return) - TRUE (1) if ACK was received, FALSE (0) if not + * + *---------------------------------------------------------------------- + */ +unsigned char +ReceiveI2CAck(void) +{ + unsigned char bit; + + /* Test for Ack/Nack */ + I2CAL_set_data_for_input(); + I2CAL_output_data(1); + I2CAL_output_clock(1); + bit = I2CAL_input_data(); + I2CAL_output_clock(0); + I2CAL_set_data_for_output(); + return !bit; +} + +/* + *---------------------------------------------------------------------- + * + * unsigned char ReceiveI2CData(void) + * + * Receives a byte of data from the I2C bus. + * + * Output: (return) - The data byte recehved from the bus + * + *---------------------------------------------------------------------- + */ +unsigned char +ReceiveI2CData(void) +{ + unsigned char data = 0; + unsigned char x; + + /* make sure the data line is released */ + I2CAL_set_data_for_input(); + I2CAL_output_data(1); + + /* shift in the data */ + for (x = 0; x < 8; x++) { + /* shift the data left */ + I2CAL_output_clock(1); + data <<= 1; + data |= I2CAL_input_data(); + I2CAL_output_clock(0); + } + + I2CAL_set_data_for_output(); + I2CAL_output_data(1); + return data; +} + +/* + *---------------------------------------------------------------------- + * + * void I2C_init(void) + * + * This routine initializes the I2C interface. Clients of the I2C.c + * will call this routine before calling any other routine in the I2C.c + * + *---------------------------------------------------------------------- + */ + +#if GFX_I2C_DYNAMIC +int +gpio_i2c_init(void) +#else +int +gfx_i2c_init(void) +#endif +{ + int errc; + + /* init I2CAL */ + errc = I2CAL_init(); + if (errc) + return errc; + + /* set the clock and data lines to the proper states */ + I2CAL_output_clock(1); + I2CAL_output_data(1); + I2CAL_set_data_for_output(); + + SendI2CStart(); + SendI2CStop(); + SendI2CStop(); + + g_initialized = 1; + + return 0; +} + +/* + *---------------------------------------------------------------------- + * + * void I2C_cleanup(void) + * + * This routine disables the I2C interface. Clients of the I2C.c will not + * call any other I2C routine after calling this routine. + * + *---------------------------------------------------------------------- + */ + +#if GFX_I2C_DYNAMIC +void +gpio_i2c_cleanup(void) +#else +void +gfx_i2c_cleanup(void) +#endif +{ + if (g_initialized) { + + /* set the clock and data lines to a harmless state */ + I2CAL_output_clock(1); + I2CAL_output_data(1); + + g_initialized = 0; + } + + I2CAL_cleanup(); +} + +int +I2CAL_init(void) +{ + unsigned long l_reg; + unsigned short reg; + + /* initialize the i2c port. */ + l_reg = gfx_pci_config_read(CS5530_GPIO); + + if (l_reg != 0x01001078) + return 1; + + l_reg = gfx_pci_config_read(CS5530_GPIO); + reg = (unsigned short)l_reg; + + /* both outputs, both high. */ + reg |= (SDADIR | SCLDIR | SDA | SCL); + l_reg = reg; + gfx_pci_config_write(CS5530_GPIO, l_reg); + + g_initialized = 1; + + return 0; +} + +void +I2CAL_cleanup(void) +{ + if (g_initialized) { + + g_initialized = 0; + } +} + +/* + *---------------------------------------------------------------------------- + * + * set the I2C clock line state + * + *---------------------------------------------------------------------------- + */ +void +I2CAL_output_clock(int inState) +{ + unsigned short reg; + unsigned long value; + + value = gfx_pci_config_read(CS5530_GPIO); + reg = (unsigned short)value; + + if (inState) { /* write a 1. */ + reg |= SCL; + } else { /* write a 0. */ + reg &= ~SCL; + } + + value = reg; + gfx_pci_config_write(CS5530_GPIO, value); + + /* hold it for a minimum of 4.7us */ + gfx_delay_microseconds(5); +} + +/* + *---------------------------------------------------------------------------- + * + * set the I2C data line state + * + *---------------------------------------------------------------------------- + */ +void +I2CAL_output_data(int inState) +{ + unsigned short reg; + unsigned long value; + + value = gfx_pci_config_read(CS5530_GPIO); + reg = (unsigned short)value; + + if (inState) { /* write a 1. */ + reg |= SDA; + } else { + /* write a 0. */ + reg &= ~SDA; + } + value = reg; + gfx_pci_config_write(CS5530_GPIO, value); + + /* 250 ns setup time */ + gfx_delay_microseconds(1); +} + +/* + *---------------------------------------------------------------------------- + * + * read the state of the data line + * + *---------------------------------------------------------------------------- + */ +unsigned char +I2CAL_input_data(void) +{ + unsigned short reg; + unsigned long value; + + value = gfx_pci_config_read(CS5530_GPIO); + reg = (unsigned short)value; + + if (reg & SDA) + return 1; + else + return 0; +} + +/* + *---------------------------------------------------------------------------- + * + * set the I2C data for input mode + * + *---------------------------------------------------------------------------- + */ +void +I2CAL_set_data_for_input(void) +{ + unsigned short reg; + unsigned long value; + + value = gfx_pci_config_read(CS5530_GPIO); + reg = (unsigned short)value; + + reg &= ~SDADIR; + + value = reg; + + gfx_pci_config_write(CS5530_GPIO, value); +} + +/* + *---------------------------------------------------------------------------- + * + * set the I2C data for output mode + * + *---------------------------------------------------------------------------- + */ +void +I2CAL_set_data_for_output(void) +{ + unsigned short reg; + unsigned long value; + + value = gfx_pci_config_read(CS5530_GPIO); + reg = (unsigned short)value; + reg |= SDADIR; + value = reg; + + gfx_pci_config_write(CS5530_GPIO, value); + +} + +/* END OF FILE */ diff --git a/src/gfx/init_gu1.c b/src/gfx/init_gu1.c new file mode 100644 index 0000000..e7d9987 --- /dev/null +++ b/src/gfx/init_gu1.c @@ -0,0 +1,265 @@ +/* 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 used in the initialization of Geode-family + * processors. + * */ + +/*---------------------------------------------------------------------------- + * gfx_gxm_config_read + * + * This routine reads the value of the specified GXm configuration register. + *---------------------------------------------------------------------------- + */ +unsigned char +gfx_gxm_config_read(unsigned char index) +{ + unsigned char value = 0xFF; + unsigned char lock; + + OUTB(0x22, GXM_CONFIG_CCR3); + lock = INB(0x23); + OUTB(0x22, GXM_CONFIG_CCR3); + OUTB(0x23, (unsigned char)(lock | 0x10)); + OUTB(0x22, index); + value = INB(0x23); + OUTB(0x22, GXM_CONFIG_CCR3); + OUTB(0x23, lock); + return (value); +} + +/*---------------------------------------------------------------------------- + * gfx_get_core_freq + * + * This routine returns the core clock frequency of a GXm if valid jumper + * settings are detected; 0 It assumes that a 33.3 MHz PCI clock is being used + * for GX1. + * For SCx2xx, the fast PCI divisor is read. + *---------------------------------------------------------------------------- + */ +#if GFX_INIT_DYNAMIC +unsigned long +gu1_get_core_freq(void) +#else +unsigned long +gfx_get_core_freq(void) +#endif +{ + unsigned char dir0, dir1; + unsigned long cpu_speed; + + dir0 = gfx_gxm_config_read(GXM_CONFIG_DIR0) & 0x0F; + dir1 = gfx_gxm_config_read(GXM_CONFIG_DIR1); + + /* REVISION 4.0 AND UP */ + + if (dir1 >= 0x50) { + switch (dir0) { + case 0: + case 2: + cpu_speed = 133; + break; + case 5: + cpu_speed = 166; + break; + case 3: + cpu_speed = 200; + break; + case 6: + cpu_speed = 233; + break; + case 7: + cpu_speed = 266; + break; + case 4: + cpu_speed = 300; + break; + case 1: + cpu_speed = 333; + break; + default: + return (0); + } + } else { + switch (dir0) { + case 0: + case 2: + cpu_speed = 133; + break; + case 7: + cpu_speed = 166; + break; + case 1: + case 3: + cpu_speed = 200; + break; + case 4: + case 6: + cpu_speed = 233; + break; + case 5: + cpu_speed = 266; + break; + default: + return (0); + } + } + + if ((gfx_cpu_version & 0xFF) == GFX_CPU_SC1200) { + cpu_speed = (cpu_speed * gfx_pci_speed_khz) / 33300; + } + return (cpu_speed); +} + +/*---------------------------------------------------------------------------- + * gfx_get_cpu_register_base + * + * This routine returns the base address for graphics registers. + *---------------------------------------------------------------------------- + */ +#if GFX_INIT_DYNAMIC +unsigned long +gu1_get_cpu_register_base(void) +#else +unsigned long +gfx_get_cpu_register_base(void) +#endif +{ + unsigned long base; + + base = (unsigned long)gfx_gxm_config_read(GXM_CONFIG_GCR); + base = (base & 0x03) << 30; + return (base); +} + +/*---------------------------------------------------------------------------- + * gfx_get_frame_buffer_base + * + * This routine returns the base address for graphics memory. This is an + * offset of 0x00800000 from the base address specified in the GCR register. + * + * The function returns zero if the GCR indicates the graphics subsystem + * is disabled. + *---------------------------------------------------------------------------- + */ +#if GFX_INIT_DYNAMIC +unsigned long +gu1_get_frame_buffer_base(void) +#else +unsigned long +gfx_get_frame_buffer_base(void) +#endif +{ + unsigned long base; + + base = (unsigned long)gfx_gxm_config_read(GXM_CONFIG_GCR); + base = (base & 0x03) << 30; + if (base) + base |= 0x00800000; + return (base); +} + +/*---------------------------------------------------------------------------- + * gfx_get_frame_buffer_size + * + * This routine returns the total size of graphics memory, in bytes. + * + * Currently this routine is hardcoded to return 2 Meg. + *---------------------------------------------------------------------------- + */ +#if GFX_INIT_DYNAMIC +unsigned long +gu1_get_frame_buffer_size(void) +#else +unsigned long +gfx_get_frame_buffer_size(void) +#endif +{ +#if FB4MB + return (0x00400000); +#else + return (0x00200000); +#endif +} + +/*---------------------------------------------------------------------------- + * gfx_get_vid_register_base + * + * This routine returns the base address for the video hardware. It assumes + * an offset of 0x00010000 from the base address specified by the GCR. + * + * The function returns zero if the GCR indicates the graphics subsystem + * is disabled. + *---------------------------------------------------------------------------- + */ +#if GFX_INIT_DYNAMIC +unsigned long +gu1_get_vid_register_base(void) +#else +unsigned long +gfx_get_vid_register_base(void) +#endif +{ + unsigned long base; + + base = (unsigned long)gfx_gxm_config_read(GXM_CONFIG_GCR); + base = (base & 0x03) << 30; + if (base) + base |= 0x00010000; + return (base); +} + +/*---------------------------------------------------------------------------- + * gfx_get_vip_register_base + * + * This routine returns the base address for the VIP hardware. This is + * only applicable to the SC1200, for which this routine assumes an offset + * of 0x00015000 from the base address specified by the GCR. + * + * The function returns zero if the GCR indicates the graphics subsystem + * is disabled. + *---------------------------------------------------------------------------- + */ +#if GFX_INIT_DYNAMIC +unsigned long +gu1_get_vip_register_base(void) +#else +unsigned long +gfx_get_vip_register_base(void) +#endif +{ + unsigned long base = 0; + + if ((gfx_cpu_version & 0xFF) == GFX_CPU_SC1200) { + base = (unsigned long)gfx_gxm_config_read(GXM_CONFIG_GCR); + base = (base & 0x03) << 30; + if (base) + base |= 0x00015000; + } + return (base); +} + +/* END OF FILE */ diff --git a/src/gfx/init_gu2.c b/src/gfx/init_gu2.c new file mode 100644 index 0000000..0bbb064 --- /dev/null +++ b/src/gfx/init_gu2.c @@ -0,0 +1,154 @@ +/* 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 used in Redcloud initialization. + * */ + +/*---------------------------------------------------------------------------- + * gfx_get_core_freq + * + * Returns the core clock frequency of a GX2. + *---------------------------------------------------------------------------- + */ +#if GFX_INIT_DYNAMIC +unsigned long +gu2_get_core_freq(void) +#else +unsigned long +gfx_get_core_freq(void) +#endif +{ + unsigned long value; + + /* CPU SPEED IS REPORTED BY A VSM IN VSA II */ + /* Virtual Register Class = 0x12 (Sysinfo) */ + /* CPU Speed Register = 0x01 */ + + OUTW(0xAC1C, 0xFC53); + OUTW(0xAC1C, 0x1201); + + value = (unsigned long)(INW(0xAC1E)); + + return (value); +} + +/*---------------------------------------------------------------------------- + * gfx_get_cpu_register_base + * + * This routine returns the base address for display controller registers. + *---------------------------------------------------------------------------- + */ +#if GFX_INIT_DYNAMIC +unsigned long +gu2_get_cpu_register_base(void) +#else +unsigned long +gfx_get_cpu_register_base(void) +#endif +{ + return gfx_pci_config_read(0x80000918); +} + +/*---------------------------------------------------------------------------- + * gfx_get_graphics_register_base + * + * This routine returns the base address for the graphics acceleration. + *---------------------------------------------------------------------------- + */ +#if GFX_INIT_DYNAMIC +unsigned long +gu2_get_graphics_register_base(void) +#else +unsigned long +gfx_get_graphics_register_base(void) +#endif +{ + return gfx_pci_config_read(0x80000914); +} + +/*---------------------------------------------------------------------------- + * gfx_get_frame_buffer_base + * + * This routine returns the base address for graphics memory. + *---------------------------------------------------------------------------- + */ +#if GFX_INIT_DYNAMIC +unsigned long +gu2_get_frame_buffer_base(void) +#else +unsigned long +gfx_get_frame_buffer_base(void) +#endif +{ + return gfx_pci_config_read(0x80000910); +} + +/*---------------------------------------------------------------------------- + * gfx_get_frame_buffer_size + * + * This routine returns the total size of graphics memory, in bytes. + *---------------------------------------------------------------------------- + */ +#if GFX_INIT_DYNAMIC +unsigned long +gu2_get_frame_buffer_size(void) +#else +unsigned long +gfx_get_frame_buffer_size(void) +#endif +{ + unsigned long value; + + /* FRAME BUFFER SIZE IS REPORTED BY A VSM IN VSA II */ + /* Virtual Register Class = 0x02 */ + /* VG_MEM_SIZE (512KB units) = 0x00 */ + + OUTW(0xAC1C, 0xFC53); + OUTW(0xAC1C, 0x0200); + + value = (unsigned long)(INW(0xAC1E)) & 0xFFl; + + return (value << 19); +} + +/*---------------------------------------------------------------------------- + * gfx_get_vid_register_base + * + * This routine returns the base address for the video hardware. + *---------------------------------------------------------------------------- + */ +#if GFX_INIT_DYNAMIC +unsigned long +gu2_get_vid_register_base(void) +#else +unsigned long +gfx_get_vid_register_base(void) +#endif +{ + return gfx_pci_config_read(0x8000091C); +} + +/* END OF FILE */ diff --git a/src/gfx/init_gu3.c b/src/gfx/init_gu3.c new file mode 100644 index 0000000..daf1513 --- /dev/null +++ b/src/gfx/init_gu3.c @@ -0,0 +1,159 @@ +/* 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 used in Redcloud initialization. + * */ + +/*---------------------------------------------------------------------------- + * gfx_get_core_freq + * + * Returns the core clock frequency of a GX3. + *---------------------------------------------------------------------------- + */ +#if GFX_INIT_DYNAMIC +unsigned long +gu3_get_core_freq(void) +#else +unsigned long +gfx_get_core_freq(void) +#endif +{ + unsigned long value; + + /* CPU SPEED IS REPORTED BY A VSM IN VSA II */ + /* Virtual Register Class = 0x12 (Sysinfo) */ + /* CPU Speed Register = 0x01 */ + + OUTW(0xAC1C, 0xFC53); + OUTW(0xAC1C, 0x1201); + + value = (unsigned long)(INW(0xAC1E)); + + return (value); +} + +/*---------------------------------------------------------------------------- + * gfx_get_cpu_register_base + * + * This routine returns the base address for display controller registers. + *---------------------------------------------------------------------------- + */ +#if GFX_INIT_DYNAMIC +unsigned long +gu3_get_cpu_register_base(void) +#else +unsigned long +gfx_get_cpu_register_base(void) +#endif +{ + return gfx_pci_config_read(0x80000918); +} + +/*---------------------------------------------------------------------------- + * gfx_get_graphics_register_base + * + * This routine returns the base address for the graphics acceleration. + *---------------------------------------------------------------------------- + */ +#if GFX_INIT_DYNAMIC +unsigned long +gu3_get_graphics_register_base(void) +#else +unsigned long +gfx_get_graphics_register_base(void) +#endif +{ + return gfx_pci_config_read(0x80000914); +} + +/*---------------------------------------------------------------------------- + * gfx_get_frame_buffer_base + * + * This routine returns the base address for graphics memory. + *---------------------------------------------------------------------------- + */ +#if GFX_INIT_DYNAMIC +unsigned long +gu3_get_frame_buffer_base(void) +#else +unsigned long +gfx_get_frame_buffer_base(void) +#endif +{ + return gfx_pci_config_read(0x80000910); +} + +/*---------------------------------------------------------------------------- + * gfx_get_frame_buffer_size + * + * This routine returns the total size of graphics memory, in bytes. + *---------------------------------------------------------------------------- + */ +#if GFX_INIT_DYNAMIC +unsigned long +gu3_get_frame_buffer_size(void) +#else +unsigned long +gfx_get_frame_buffer_size(void) +#endif +{ + unsigned long value; + + /* FRAME BUFFER SIZE IS REPORTED BY A VSM IN VSA II */ + /* Virtual Register Class = 0x02 */ + /* VG_MEM_SIZE (1MB units) = 0x00 */ + + OUTW(0xAC1C, 0xFC53); + OUTW(0xAC1C, 0x0200); + + value = (unsigned long)(INW(0xAC1E)) & 0xFEl; + + /* LIMIT FRAME BUFFER SIZE TO 16MB TO MATCH LEGACY */ + + if ((value << 20) > 0x1000000) + return 0x1000000; + + return (value << 20); +} + +/*---------------------------------------------------------------------------- + * gfx_get_vid_register_base + * + * This routine returns the base address for the video hardware. + *---------------------------------------------------------------------------- + */ +#if GFX_INIT_DYNAMIC +unsigned long +gu3_get_vid_register_base(void) +#else +unsigned long +gfx_get_vid_register_base(void) +#endif +{ + return gfx_pci_config_read(0x8000091C); +} + +/* END OF FILE */ diff --git a/src/gfx/msr_rdcl.c b/src/gfx/msr_rdcl.c new file mode 100644 index 0000000..8c927a4 --- /dev/null +++ b/src/gfx/msr_rdcl.c @@ -0,0 +1,632 @@ +/* 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 MSR access routines for Redcloud. + * */ + +void redcloud_build_mbus_tree(void); /* private routine definition */ +int redcloud_init_msr_devices(MSR aDev[], unsigned int array_size); + + /* private routine definition */ +DEV_STATUS redcloud_find_msr_device(MSR * pDev); + + /* private routine definition */ + +/* REDCLOUD MSR BITMASKS */ + +#define MBD_MSR_CAP 0x2000 +#define MSR_CAP_ID_MASK 0xFF000 +#define MSR_CAP_ID_SHIFT 12 +#define MSR_CAP_REV_MASK 0x0F +#define MBIU_CAP 0x86 +#define NUM_PORTS_MASK 0x00380000 +#define NUM_PORTS_SHIFT 19 +#define MBIU_WHOAMI 0x8B +#define WHOAMI_MASK 0x07 + +/* REDCLOUD and CS5535 MSR DEVICES */ + +MSR msrDev[] = { + {FOUND, RC_CC_MBIU, RC_MB0_MBIU0}, + {FOUND, RC_CC_MBIU, RC_MB0_MBIU1}, + {NOT_KNOWN, RC_CC_MCP, FAKE_ADDRESS}, + {NOT_KNOWN, RC_CC_MPCI, FAKE_ADDRESS}, + {NOT_KNOWN, RC_CC_MC, FAKE_ADDRESS}, + {NOT_KNOWN, RC_CC_GP, FAKE_ADDRESS}, + {NOT_KNOWN, RC_CC_VG, FAKE_ADDRESS}, + {NOT_KNOWN, RC_CC_DF, FAKE_ADDRESS}, + {NOT_KNOWN, RC_CC_FG, FAKE_ADDRESS}, + {FOUND, RC_CC_VA, RC_MB0_CPU}, + {FOUND, CP_CC_MBIU, CP_MB0_MBIU0}, + {NOT_KNOWN, CP_CC_MPCI, FAKE_ADDRESS}, + {NOT_KNOWN, CP_CC_USB2, FAKE_ADDRESS}, + {NOT_KNOWN, CP_CC_ATAC, FAKE_ADDRESS}, + {NOT_KNOWN, CP_CC_MDD, FAKE_ADDRESS}, + {NOT_KNOWN, CP_CC_ACC, FAKE_ADDRESS}, + {NOT_KNOWN, CP_CC_USB1, FAKE_ADDRESS}, + {NOT_KNOWN, CP_CC_MCP, FAKE_ADDRESS}, +}; + +#define NUM_DEVS sizeof(msrDev) / sizeof(struct msr) + +/* CAPISTRANO DEVICE INDEX LIMITS */ +/* These defines represent the start and stop indexes into the device array + * for all Capistrano devices. These should be updated whenever a device is + * added or removed to the Capistrano list. + * */ + +#define CP_INDEX_START CP_ID_MBIU +#define CP_INDEX_STOP CP_ID_MCP + +/* GLOBAL MBUS CACHE STRUCTURES */ +/* These structures contain a "cached" copy of the MBUS topology */ +/* for easy future lookup. */ + +MBUS_NODE MBIU0[8], MBIU1[8], MBIU2[8]; + +/* REGISTER MACROS */ + +#define GET_DEVICE_ID( CAPABILITIES_HIGH, CAPABILITIES_LOW ) \ + ((unsigned int)(( (CAPABILITIES_LOW) & MSR_CAP_ID_MASK ) >> MSR_CAP_ID_SHIFT )) + +#define GET_NUM_PORTS( MBIU_CAP_HIGH, MBIU_CAP_LOW ) (((MBIU_CAP_HIGH) & NUM_PORTS_MASK ) >> NUM_PORTS_SHIFT) + +/*---------------------------------------------------------------------------- + * gfx_msr_init + * + * This routine initializes the base addresses of all known MBUS devices. + *---------------------------------------------------------------------------- + */ +#if GFX_MSR_DYNAMIC +int +redcloud_msr_init(void) +#else +int +gfx_msr_init(void) +#endif +{ + Q_WORD msrValue; + int return_value = 1; + + /* CHECK FOR VALID MBUS CONFIGURATION */ + /* The CPU and the two MBIUs are assumed to be at known static addresses, + * so we will check the device IDs at these addresses as proof of a valid + * mbus configuration. + * */ + + MSR_READ(MBD_MSR_CAP, RC_MB0_CPU, &(msrValue.high), &(msrValue.low)); + if (GET_DEVICE_ID(msrValue.high, msrValue.low) != RC_CC_VA) + return_value = 0; + + MSR_READ(MBD_MSR_CAP, RC_MB0_MBIU0, &(msrValue.high), &(msrValue.low)); + if (GET_DEVICE_ID(msrValue.high, msrValue.low) != RC_CC_MBIU) + return_value = 0; + + MSR_READ(MBD_MSR_CAP, RC_MB0_MBIU1, &(msrValue.high), &(msrValue.low)); + if (GET_DEVICE_ID(msrValue.high, msrValue.low) != RC_CC_MBIU) + return_value = 0; + + /* ENUMERATE VALID BUS */ + /* If all static devices were identified, continue with the enumeration */ + + if (return_value) { + /* OPTIMIZATION */ + /* Build a local copy of the MBUS topology. This allows us to */ + /* quickly search the entire MBUS for a given device ID without */ + /* repeated MSR accesses. */ + + redcloud_build_mbus_tree(); + + /* INITIALIZE MSR DEVICES */ + + return_value = redcloud_init_msr_devices(msrDev, NUM_DEVS); + + } + + return return_value; + +} + +/*-------------------------------------------------------------------------- + * void redcloud_build_mbus_tree() (PRIVATE ROUTINE - NOT PART OF DURANGO API) + * + * This routine walks through the MBUS and records the address value and + * device ID found at each node. If a node (aka port) is not populated, + * that node returns '0'. The deviceID for that node is set to '0' + * (NOT_POPULATED) to reflect this. If the node being queried points back to + * Vail or MBIU0, the deviceID for that node is set to 'REFLECTIVE'. + * Reflective nodes are nodes that forward the given MBUS address BACK to the + * initiator. + *---------------------------------------------------------------------------- + */ +void +redcloud_build_mbus_tree(void) +{ + unsigned long mbiu_port_count, reflective; + unsigned long port; + Q_WORD msrValue; + + /* */ + /* ENUMERATE MBIU0 */ + /* */ + + /* COUNT MBIU PORTS */ + + MSR_READ(MBIU_CAP, RC_MB0_MBIU0, &(msrValue.high), &(msrValue.low)); + mbiu_port_count = GET_NUM_PORTS(msrValue.high, msrValue.low); + + /* FIND REFLECTIVE PORT */ + /* Query the MBIU for the port through which we are communicating. */ + /* We will avoid accesses to this port to avoid a self-reference. */ + + MSR_READ(MBIU_WHOAMI, RC_MB0_MBIU0, &(msrValue.high), &(msrValue.low)); + reflective = msrValue.low & WHOAMI_MASK; + + /* ENUMERATE ALL PORTS */ + /* For every possible port, set the MBIU.deviceId to something. */ + + for (port = 0; port < 8; port++) { + /* FILL IN CLAIMED FIELD */ + /* All MBIU ports can only be assigned to one device from the */ + /* Durango table */ + + MBIU0[port].claimed = 0; + + /* MBIU0 PORT NUMBERS ARE IN ADDRESS BITS 31:29 */ + + MBIU0[port].address = port << 29; + + /* SPECIAL CASE FOR MBIU0 */ + /* MBIU0 port 0 is a special case, as it points back to MBIU0. MBIU0 + * responds at address 0x40000xxx, which does not equal 0 << 29. + * */ + + if (port == 0) + MBIU0[port].deviceId = RC_CC_MBIU; + else if (port == reflective) + MBIU0[port].deviceId = REFLECTIVE; + else if (port > mbiu_port_count) + MBIU0[port].deviceId = NOT_POPULATED; + else { + MSR_READ(MBD_MSR_CAP, MBIU0[port].address, &(msrValue.high), + &(msrValue.low)); + MBIU0[port].deviceId = GET_DEVICE_ID(msrValue.high, msrValue.low); + } + } + + /* */ + /* ENUMERATE MBIU1 */ + /* */ + + /* COUNT MBIU PORTS */ + + MSR_READ(MBIU_CAP, RC_MB0_MBIU1, &(msrValue.high), &(msrValue.low)); + mbiu_port_count = GET_NUM_PORTS(msrValue.high, msrValue.low); + + /* FIND REFLECTIVE PORT */ + /* Query the MBIU for the port through which we are communicating. */ + /* We will avoid accesses to this port to avoid a self-reference. */ + + MSR_READ(MBIU_WHOAMI, RC_MB0_MBIU1, &(msrValue.high), &(msrValue.low)); + reflective = msrValue.low & WHOAMI_MASK; + + /* ENUMERATE ALL PORTS */ + /* For every possible port, set the MBIU.deviceId to something. */ + + for (port = 0; port < 8; port++) { + /* FILL IN CLAIMED FIELD */ + /* All MBIU ports can only be assigned to one device from the */ + /* Durango table */ + + MBIU1[port].claimed = 0; + + /* MBIU1 PORT NUMBERS ARE IN 28:26 AND 31:29 = 010B */ + + MBIU1[port].address = (0x02l << 29) + (port << 26); + + if (port == reflective) + MBIU1[port].deviceId = REFLECTIVE; + else if (port > mbiu_port_count) + MBIU1[port].deviceId = NOT_POPULATED; + else { + MSR_READ(MBD_MSR_CAP, MBIU1[port].address, &(msrValue.high), + &(msrValue.low)); + MBIU1[port].deviceId = GET_DEVICE_ID(msrValue.high, msrValue.low); + } + } + + /* */ + /* ENUMERATE MBIU2 (CS5535) */ + /* (if present) */ + + MSR_READ(MBD_MSR_CAP, CP_MB0_MBIU0, &(msrValue.high), &(msrValue.low)); + if (GET_DEVICE_ID(msrValue.high, msrValue.low) == CP_CC_MBIU) { + /* COUNT MBIU PORTS */ + + MSR_READ(MBIU_CAP, CP_MB0_MBIU0, &(msrValue.high), &(msrValue.low)); + mbiu_port_count = GET_NUM_PORTS(msrValue.high, msrValue.low); + + /* FIND REFLECTIVE PORT */ + /* Query the MBIU for the port through which we are communicating. */ + /* We will avoid accesses to this port to avoid a self-reference. */ + + MSR_READ(MBIU_WHOAMI, CP_MB0_MBIU0, &(msrValue.high), + &(msrValue.low)); + reflective = msrValue.low & WHOAMI_MASK; + + /* ENUMERATE ALL PORTS */ + /* For every possible port, set the MBIU.deviceId to something. */ + + for (port = 0; port < 8; port++) { + /* FILL IN CLAIMED FIELD */ + /* All MBIU ports can only be assigned to one device from the */ + /* Durango table */ + + MBIU2[port].claimed = 0; + + /* MBIU2 PORT NUMBERS ARE IN 22:20 AND 31:23 = 010100010B */ + + MBIU2[port].address = + (0x02l << 29) + (0x04l << 26) + (0x02l << 23) + (port << 20); + + if (port == reflective) + MBIU2[port].deviceId = REFLECTIVE; + else if (port > mbiu_port_count) + MBIU2[port].deviceId = NOT_POPULATED; + else { + MSR_READ(MBD_MSR_CAP, MBIU2[port].address, &(msrValue.high), + &(msrValue.low)); + MBIU2[port].deviceId = + GET_DEVICE_ID(msrValue.high, msrValue.low); + } + } + } else { + /* NO 5535 */ + /* If the CS5535 is not installed, fill in the cached table */ + /* with the 'NOT_INSTALLED' flag. Also, fill in the device */ + /* status from NOT_KNOWN to REQ_NOT_INSTALLED. */ + + for (port = 0; port < 8; port++) { + MBIU2[port].claimed = 0; + MBIU2[port].deviceId = NOT_INSTALLED; + MBIU2[port].address = + (0x02l << 29) + (0x04l << 26) + (0x02l << 23) + (port << 20); + } + for (port = CP_INDEX_START; port <= CP_INDEX_STOP; port++) { + msrDev[port].Present = REQ_NOT_INSTALLED; + } + } +} + +/*------------------------------------------------------------------ + * redcloud_init_msr_devices (PRIVATE ROUTINE - NOT PART OF DURANGO API) + * + * Handles the details of finding each possible device on the MBUS. + * If a given device is not found, its structure is left uninitialized. + * If a given device is found, its structure is updated. + * + * This init routine only checks for devices in aDev[]. + * + * Passed: + * aDev - is a pointer to the array of MBUS devices. + * arraySize - number of elements in aDev. + * + * Returns: + * 1 - If, for every device, its address was found. + * 0 - If, for any device, an error was encountered. + *------------------------------------------------------------------ + */ +int +redcloud_init_msr_devices(MSR aDev[], unsigned int array_size) +{ + unsigned int i, issues = 0; + + /* TRY TO FIND EACH ITEM IN THE ARRAY */ + + for (i = 0; i < array_size; i++) { + /* IGNORE DEVICES THAT ARE ALREADY FOUND */ + /* The addresses for "found" devices are already known. */ + + if (aDev[i].Present == FOUND || aDev[i].Present == REQ_NOT_INSTALLED) + continue; + + /* TRY TO FIND THE DEVICE ON THE MBUS */ + + aDev[i].Present = redcloud_find_msr_device(&aDev[i]); + + /* INCREMENT ERROR COUNT IF DEVICE NOT FOUND */ + + if (aDev[i].Present != FOUND) + issues++; + } + + return (issues == 0); +} + +/*------------------------------------------------------------------ + * redcloud_find_msr_device (PRIVATE ROUTINE - NOT PART OF DURANGO API) + * + * Passed: + * pDev - is a pointer to one element in the array of MBUS devices + * + * Returns: + * FOUND - Device was found and pDev->Address has been updated. + * + * REQ_NOT_FOUND - Device was not found and pDev->Address has not + * been updated. + * + *------------------------------------------------------------------ + */ +DEV_STATUS +redcloud_find_msr_device(MSR * pDev) +{ + unsigned int i; + + /* SEARCH DURANGO'S CACHED MBUS TOPOLOGY */ + /* This gets a little tricky. As the only identifier we have for each + * device is the device ID and we have multiple devices of the same type + * MCP, MPCI, USB, etc. we need to make some assumptions based on table + * order. These are as follows: + * 1. All Redcloud nodes are searched first, as we assume that they + * are first in the table. + * 2. If two devices have the same device ID and are found on the same + * device (GX2, CS5535, etc.) we assume that they are listed such + * that the first device in the table with this device ID has a lower + * port address. + * 3. After a device ID has been matched, the port is marked as + * 'claimed', such that future enumerations continue searching the + * GeodeLink topology. + */ + + /* SEARCH MBIU0 */ + + for (i = 0; i < 8; i++) { + if (MBIU0[i].deviceId == pDev->Id && !(MBIU0[i].claimed)) { + MBIU0[i].claimed = 1; + pDev->Address = MBIU0[i].address; + return FOUND; + } + } + + /* SEARCH MBIU1 */ + + for (i = 0; i < 8; i++) { + if (MBIU1[i].deviceId == pDev->Id && !(MBIU1[i].claimed)) { + MBIU1[i].claimed = 1; + pDev->Address = MBIU1[i].address; + return FOUND; + } + } + + /* SEARCH MBIU2 */ + + for (i = 0; i < 8; i++) { + if (MBIU2[i].deviceId == pDev->Id && !(MBIU2[i].claimed)) { + MBIU2[i].claimed = 1; + pDev->Address = MBIU2[i].address; + return FOUND; + } + } + + return REQ_NOT_FOUND; +} + +/*-------------------------------------------------------------------- + * gfx_id_msr_device + * + * This routine handles reading the capabilities MSR register (typically + * 0x2000) and checking if the 'id' field matchs pDev.Id. This routine is + * used by applications/drivers that need to extend the list of known + * MBUS devices beyond those known by Durango. + * + * Passed: + * pDev - Pointer to MSR structure containing the device's ID. + * address - device address. + * + * Returns: + * FOUND - The IDs do match. + * REQ_NOT_FOUND - There was not a match. + * + *-------------------------------------------------------------------- + */ +#if GFX_MSR_DYNAMIC +DEV_STATUS +redcloud_id_msr_device(MSR * pDev, unsigned long address) +#else +DEV_STATUS +gfx_id_msr_device(MSR * pDev, unsigned long address) +#endif +{ + Q_WORD msrValue; + + MSR_READ(MBD_MSR_CAP, address, &(msrValue.high), &(msrValue.low)); + + if (GET_DEVICE_ID(msrValue.high, msrValue.low) == pDev->Id) + return FOUND; + else + return REQ_NOT_FOUND; +} + +/*-------------------------------------------------------------------- + * gfx_get_msr_dev_address + * + * This function returns the 32-bit address of the requested device. + * The device must be a known MBUS device. (It must be in Durango's + * device table.) DEV_STATUS should be checked to verify that the address + * was updated. + * + * + * Passed: + * device - device index of the device in question. + * *address - ptr to location where address should be stored. + * + * Returns: + * DEV_STATUS of device in question. (NOT_KNOWN if device is out of range.) + * *address - updated if 'device' is within range + * + * Notes: + * This function should only be called after gfx_msr_init + * + *-------------------------------------------------------------------- + */ +#if GFX_MSR_DYNAMIC +DEV_STATUS +redcloud_get_msr_dev_address(unsigned int device, unsigned long *address) +#else +DEV_STATUS +gfx_get_msr_dev_address(unsigned int device, unsigned long *address) +#endif +{ + if (device < NUM_DEVS) { + if (msrDev[device].Present == FOUND) + *address = msrDev[device].Address; + + return msrDev[device].Present; + } + return NOT_KNOWN; + +} + +/*-------------------------------------------------------------------- + * gfx_get_glink_id_at_address + * + * This function returns the 16-bit deviceId at the requested address. + * DEV_STATUS should be checked to make sure that device was updated. + * + * Passed: + * device - ptr to location where device ID should be stored. + * address - address of desired device ID. + * + * Returns: + * FOUND if address is a valid address, NOT_KNOWN if address cannot be + * found on the mbus. + * *device - updated with device Id info. + * + * Notes: + * This function should be called after gfx_msr_init + * + *-------------------------------------------------------------------- + */ +#if GFX_MSR_DYNAMIC +DEV_STATUS +redcloud_get_glink_id_at_address(unsigned int *device, unsigned long address) +#else +DEV_STATUS +gfx_get_glink_id_at_address(unsigned int *device, unsigned long address) +#endif +{ + int port; + + for (port = 0; port < 8; port++) { + if (MBIU0[port].address == address) { + *device = MBIU0[port].deviceId; + return FOUND; + } else if (MBIU1[port].address == address) { + *device = MBIU1[port].deviceId; + return FOUND; + } else if (MBIU2[port].address == address) { + *device = MBIU2[port].deviceId; + return FOUND; + } + } + + return NOT_KNOWN; + +} + +/*-------------------------------------------------------------------- + * gfx_msr_read + * + * Performs a 64-bit read from 'msrRegister' in device 'device'. 'device' is + * an index into Durango's table of known MBUS devices. + * + * Returns: + * FOUND - if no errors were detected and msrValue has been + * updated. + * NOT_KNOWN - an error was detected. msrValue is not updated. + * REQ_NOT_FOUND - 'msrAddress' for 'devID' is unknown. Caller + * should call msrInit() first. msrValue is not + * updated. + * Notes: + * This function should be called after gfx_msr_init + *-------------------------------------------------------------------- + */ +#if GFX_MSR_DYNAMIC +DEV_STATUS +redcloud_msr_read(unsigned int device, unsigned int msrRegister, + Q_WORD * msrValue) +#else +DEV_STATUS +gfx_msr_read(unsigned int device, unsigned int msrRegister, Q_WORD * msrValue) +#endif +{ + if (device < NUM_DEVS) { + if (msrDev[device].Present == FOUND) + MSR_READ(msrRegister, msrDev[device].Address, &(msrValue->high), + &(msrValue->low)); + + return msrDev[device].Present; + } + return NOT_KNOWN; +} + +/*-------------------------------------------------------------------- + * gfx_msr_write + * + * Performs a 64-bit write to 'msrRegister' in device 'devID'. + * + * Returns: + * FOUND - if no errors were detected and msrValue has been + * updated. + * NOT_KNOWN - an error was detected. msrValue is not updated. + * REQ_NOT_FOUND - 'msrAddress' for 'devID' is unknown. Caller + * should call msrInit() first. msrValue is not + * updated. + * + *Notes: + * This function is valid to call after initMSR_API() + * + *-------------------------------------------------------------------- + */ +#if GFX_MSR_DYNAMIC +DEV_STATUS +redcloud_msr_write(unsigned int device, unsigned int msrRegister, + Q_WORD * msrValue) +#else +DEV_STATUS +gfx_msr_write(unsigned int device, unsigned int msrRegister, + Q_WORD * msrValue) +#endif +{ + if (device < NUM_DEVS) { + if (msrDev[device].Present == FOUND) + MSR_WRITE(msrRegister, msrDev[device].Address, &(msrValue->high), + &(msrValue->low)); + + return msrDev[device].Present; + } + return NOT_KNOWN; +} diff --git a/src/gfx/release.txt b/src/gfx/release.txt new file mode 100644 index 0000000..805b847 --- /dev/null +++ b/src/gfx/release.txt @@ -0,0 +1,630 @@ +Durango Release Notes +Version 2.57.00 +Win98/WinXP/DOS/Linux +April 5, 2003 + +----------------------------------------------------------------------------- +PRODUCT INFORMATION +----------------------------------------------------------------------------- +Durango is a graphics/video software support package designed to assist in the +development of display drivers and embedded applications. The core of this +package is source code that performs most of the graphics related +functionality for the National Semiconductor (c) Geode family of products. +Development time for new software is reduced by using these routines to access +the hardware. + +----------------------------------------------------------------------------- +INSTALLATION INSTRUCTIONS +----------------------------------------------------------------------------- +Download the file to a directory. Modify and include the file durango.c +according to the needs of the application. + +----------------------------------------------------------------------------- +REVISION HISTORY +----------------------------------------------------------------------------- + +04/05/04 Version 2.57.00 + +----------------------------------------------------------------------------- +FUNCTIONAL CHANGES +----------------------------------------------------------------------------- + +* Fixed the PLL setting for 1280x1024@70Hz and 1152x864@70Hz. + +============================================================================= + +03/30/04 Version 2.56.00 + +----------------------------------------------------------------------------- +FUNCTIONAL CHANGES +----------------------------------------------------------------------------- + +* Updated the GX2 render code such that BLTs that involve source will work + correctly even if source is not involved in the ROP. + +============================================================================= + +03/26/04 Version 2.55.00 + +----------------------------------------------------------------------------- +FUNCTIONAL CHANGES +----------------------------------------------------------------------------- + +* Filled in all missing refresh rates in the mode table for Redcloud and Castle. +* Added a new routine gfx_is_panel_mode_supported. +* Added new routines gfx_set_graphics_palette and gfx_set_graphics_palette_entry + to support using the video palette to gamma correct graphics data. + +============================================================================= + +03/11/04 Version 2.54.00 + +----------------------------------------------------------------------------- +FUNCTIONAL CHANGES +----------------------------------------------------------------------------- + +* Updated the video palette routines to clear the bypass both bit before + updating the palette. + +============================================================================= + +03/02/04 Version 2.53.00 + +----------------------------------------------------------------------------- +FUNCTIONAL CHANGES +----------------------------------------------------------------------------- + +* Added 1152x864@60, 85, 90 and 100Hz to the mode table. + +============================================================================= + +02/07/04 Version 2.52.00 + +----------------------------------------------------------------------------- +FUNCTIONAL CHANGES +----------------------------------------------------------------------------- + +* Updated Durango to support Castle, including a 48MHz dotref. +* Added 90 and 100Hz modes for Redcloud. +* Updated the PLL table to remove any pre-divides by 2. + +============================================================================= + +10/24/03 Version 2.51.08 + +----------------------------------------------------------------------------- +FUNCTIONAL CHANGES +----------------------------------------------------------------------------- + +* Removed GX2 1.0 support from the PLL routines, gfx_set_clock_frequency and + gfx_get_clock_frequency. +* Fixed a bug in gfx_set_clock_frequency, wherein the last three PLL values in + Durango's PLL table could never be set. + +============================================================================= + +09/22/03 Version 2.51.07 + +----------------------------------------------------------------------------- +FUNCTIONAL CHANGES +----------------------------------------------------------------------------- + +* Changed gfx_set_video_palette and gfx_set_video_palette_entry such that calling + one of these routines will also configure the video hardware to route video + data through the DF palette RAM. +* Added a new routine, gfx_set_video_palette_bypass to toggle the 'Bypass Both' + functionality of the SC1200 and GX2 palette RAMs. + +============================================================================= + +09/02/03 Version 2.51.06 + +----------------------------------------------------------------------------- +FUNCTIONAL CHANGES +----------------------------------------------------------------------------- + +* Added new routine gfx_get_max_video_width for SC1200 and CS5530. This routine + calculates the maximum theoretical video width based on the current display + mode and video clock. + +============================================================================= + +08/07/03 Version 2.51.05 + +----------------------------------------------------------------------------- +FUNCTIONAL CHANGES +----------------------------------------------------------------------------- + +* Fixed gfx_get_core_freq for SCx2xx when the fast PCI frequency is not 33MHz. +* Fixed gfx_get_compression_pitch to mask correct bits. +* Changed CS5530 and SCx2xx code to always enable video in the display + controller. +* Modified GX2 PLL code to only update the PLL when the value has not already + been programmed. + +============================================================================= + +06/17/03 Version 2.51.04 + +----------------------------------------------------------------------------- +FUNCTIONAL CHANGES +----------------------------------------------------------------------------- + +* Fixed code to set default gamma RAM for SCx2xx. + +============================================================================= + +06/02/03 Version 2.51.03 + +----------------------------------------------------------------------------- +FUNCTIONAL CHANGES +----------------------------------------------------------------------------- + +* Fixed gfx_get_cursor_position for GX2 to support large display resolutions. +* Added default gamma RAM table for SCx2xx and GX2 to correct CSC hardware. + +============================================================================= + +03/20/03 Version 2.51.02 + +----------------------------------------------------------------------------- +FUNCTIONAL CHANGES +----------------------------------------------------------------------------- + +* Changed all preprocessor statements to conform to K and R standard. +* Added support for 56Hz modes to all Durango routines. +* Added missing header file to gfx_priv.h + +============================================================================= + +03/13/03 Version 2.51.01 + +----------------------------------------------------------------------------- +FUNCTIONAL CHANGES +----------------------------------------------------------------------------- + +* Updated file headers to NSC standard headers. +* Added routine definitions for private and local routines. +* Minor fixes for compilation without warnings. +* Fixed panel timings for 640x480 panels and 1024x768 panels. + +============================================================================= + +02/05/03 Version 2.49.02 + +----------------------------------------------------------------------------- +FUNCTIONAL CHANGES +----------------------------------------------------------------------------- + +* Fixed GX2 left clipping for 4:2:0 video. + +============================================================================= + +01/29/03 Version 2.49.01 + +----------------------------------------------------------------------------- +FUNCTIONAL CHANGES +----------------------------------------------------------------------------- + +* Removed unused variable in CS5530 video code. +* Changed max supported pixel clock for SCx2xx to 157.5 MHz. + +============================================================================= + +01/10/03 Version 2.49.00 + +----------------------------------------------------------------------------- +FUNCTIONAL CHANGES +----------------------------------------------------------------------------- + +* Added extra wait loop when polling for CRC completion. +* Removed code that sets the pitch offsets for 4:2:0 video within + gfx_set_video_size. +* Fixed panning code to work with any display pitch. +* Added code to clear the PLL bypass bit when setting the dot PLL. +* Fixed panning code so cursor never disappears when panning. +* Changed GX2 delay loops to do a volatile register read to prevent + the entire delay loop from being discarded by a compiler. + +============================================================================= + +11/19/02 Version 2.47.00 + +----------------------------------------------------------------------------- +FUNCTIONAL CHANGES +----------------------------------------------------------------------------- + +* Updated gfx2_* routines to use a signed stride. +* SW workaround for issue #134.8 - Strange horizontal lines appearing while + drawing lines. +* Implemented gfx_set_video_left_crop for CS5530 +* Updated sub carrier reset values for NTSC and PAL. + +============================================================================= + +08/29/02 Version 2.45.00 + +----------------------------------------------------------------------------- +FUNCTIONAL CHANGES +----------------------------------------------------------------------------- + +* Modified gfx_set_cursor_position to use cursor position when panning and not adjust + using hotspots. +* Added new routine gfx_get_refreshrate_from_mode. +* Added gfx_text_blt routine. +* Added gfx_get_tv_display_mode_frequency routine. +* Added gfx_get_frequency_from_refreshrate routine. +* Added gfx_set_video_cursor_enable routine. +* Fixed Linux compilation warnings. +* Updated modeset code to clear panning variables. +* Added panel timings for 1600x1200 desktops. +* Removed wait for VBlank when panning using cursor routines. + +============================================================================= + +07/12/02 Version 2.43.03 + +----------------------------------------------------------------------------- +FUNCTIONAL CHANGES +----------------------------------------------------------------------------- + +* Modified gfx_get_display_mode to support 56 Hz modes. +* Added support for 8K pitch when setting a true color mode above 1024x768 +* Added a byte-packed option to gfx2_mono_expand_blt +* Fix for Carmel D2 alpha blending issue. +* Added typecasts for proper compilation. +* Fixed CS5535 MBIU address. +* Added new GX2 routine, gfx2_text_blt +* Added MSR implementations for Linux. +* Further optimized default GX1 string macros. +* Added new routine, gfx_set_panel_present to allow panning without adjusting panel timings. +* Added assembly macros for 32-bit Windows applications. + +============================================================================= + +03/21/02 Version 2.41.02 + +----------------------------------------------------------------------------- +FUNCTIONAL CHANGES +----------------------------------------------------------------------------- + +* Optimized GX2 Bitmap-to-screen BLTs by using a 2-line offscreen scratch area. +* Fixed a bug in GX2 monochrome bitmap BLTs. +* Fixed gfx_get_clock_frequency for GX2 2.0 +* Added 56 Hz support to gfx_get_clock_frequency +* Changed gfx_set_compression_size to subtract header size +* Changed gfx_get_compression_size to add header size + +============================================================================= + +03/04/02 Version 2.39.01 + +----------------------------------------------------------------------------- +FUNCTIONAL CHANGES +----------------------------------------------------------------------------- + +* Added support for CS5535 MSRs. +* Fixed a bug in monochrome bitmap BLTs. +* Added support for 32-bit CRC mechanism in GX2 2.0. +* First official GX2 release. +* Added support for new Dot PLL mechanism in GX2 2.0 +* Added support for Carmel D1.1 and D2. + +============================================================================= + +01/24/02 Version 2.37.00 + +----------------------------------------------------------------------------- +FUNCTIONAL CHANGES +----------------------------------------------------------------------------- + +* Changed gfx_get_clock_frequency, gfx_get_cursor_offset and gfx_get_display_offset + to be outside the GFX_READ_ROUTINES flag. +* Modified the modeset code to set higher FIFO priority levels for high bandwidth + modes. +* Init code no longer returns Redcloud ID when no chip detected. +* Added fix for Redcloud 1.x rev ID +* New GX2 PLL settings - updates to the 14 MHz table and a new 48 MHz table. +* Optimized all bitmap-to-screen routines. Optimizations include new macros that + allow correct operation in a 16-bit environment. +* 3K cache is now assumed to be the default scratchpad configuration. +* gfx_get_frame_buffer_size for GX2 no longer uses a VGA register. This allows + correct operation even with an external VGA card present in the system. +* Added support for 1152x864 desktop resolution on a flat panel. +* Added 24BPP support for large display modes. +* Modified gfx_set_video_scale such that an identity scale is now default. +* Modifed flat panel modeset code to dynamically determine the size of the mode table. +* Added support for Carmel Rev D2. + +============================================================================= + +10/22/01 Version 2.35.01 + +----------------------------------------------------------------------------- +FUNCTIONAL CHANGES +----------------------------------------------------------------------------- + +* New release notes format. +* Added fix for SC1200 issue #813 (TVOut field indication is reversed. +* Added check for invalid values in video upscale. +* Fixed compilation warnings and run-time errors under DOS. +* Added new macros for word I/O. +* Optimized VSAII MSR code to used DWORD I/O. +* Fixed SoftVG base PCI base addresses. +* Several fixes to Redcloud API found during bringup. +* Modified Durango to support 4-pixel video alignment for Redcloud. +* Added the functions gfx_test_vip_overflow, gfx_get_vip_line, + gfx_set_decoder_luminance_filter, gfx_set_tv_YV_delya and + gfx_set_tv_field_status_invert. +* Added support for Carmel D1 revision ID. +* Moved gfx_get_vip_base and gfx_get_vbi_pitch outside of the + GXF_READ_ROUTINES flag. +* Minor fixes to saa7114.c and gfx_set_tv-enable. +* Added don't care option in gfx_set_vip_base. +* Added fix for SC1200 issue #1121 (VIP FIFO bus request threshold bit + is inverted. + +============================================================================= + +07/31/01 Version 2.33.02 + +----------------------------------------------------------------------------- +FUNCTIONAL CHANGES +----------------------------------------------------------------------------- +* Completed implementation of vertical downscaling support for GX2. +* Added a method to lock the display controller timings. +* Added support for SC1200 Rev C. +* Small modifications to gfx_set_video_format. +* Removed unused and unimplemented I2C functions. +* Changes to prevent errors and compiler warnings in DOS. +* Updated headers to include both BSD and GPL licenses. + +============================================================================= + +06/08/01 Version 2.31.00 + +----------------------------------------------------------------------------- +FUNCTIONAL CHANGES +----------------------------------------------------------------------------- +* Added new routines to manipulate vertical video downscaling on GX2. +* Minor fixes to the function gfx_read_window_crc. +* Implemented all init routines for GX2 except gfx_get_core_freq. +* Added support for 27MHz reference frequency to the GX2 PLL. +* Added new function gfx_get_softvga_active. +* Minor changes to the function sc1200_reset_video. +* Fixed some minor compiler warnings. + +============================================================================= + +04/25/01 Version 2.29.00 + +----------------------------------------------------------------------------- +FUNCTIONAL CHANGES +----------------------------------------------------------------------------- +* Disabled all CSC when setting an RGB video format. +* Modified sc1200_set_video_size to add 2 to the window height. +* Modified code to support the accelerator and cursor in pixel and line double modes. +* Modified gfx_get_core_freq to be a dynamic API routine. +* Added the function gfx_read_window_crc for GX2. +* Added init routine gfx_get_graphics_register_base for GX2. +* Added new macros to access the scratchpad RAM to support Win2K and WinME. +* Added mew macros to access the GP registers for GX2. + +============================================================================= + +04/06/01 Version 2.27.00 + +----------------------------------------------------------------------------- +FUNCTIONAL CHANGES +----------------------------------------------------------------------------- +* Added new TV read functions: + gfx_get_tv_enable, gfx_get_tv_output, gfx_get_tv_display_mode, + gfx_get_tv_mode_count, gfx_is_tv_display_mode_supported +* Added new function gfx_set_display_bpp. +* Added new function gfx_get_frame_buffer_line_size. +* Modified gfx_set_vbi_base to accept pure physical addresses instead of offsets. +* Implemented video and display controller routines for GX2. +* Modified some initialization routines to be dynamic. +* Created new API extension for GX2 MSR accesses. +* Added new icon routines for GX2. +* Modified gfx_set_tv_display to preserve current bpp. +* Minor modifications to gfx_set_tv_format, gfx_set_video_palette and + gfx_set_video_palette entry. +* Added support for 1152x864@75Hz + +============================================================================= + +03/12/01 Version 2.25.00 + +----------------------------------------------------------------------------- +FUNCTIONAL CHANGES +----------------------------------------------------------------------------- +* Adapted new revision format system. +* Synchronized with NSTA Durango. Updated support for all SC1200 features. +* Added support for 640x400 as well as emulated VGA modes. +* Added new routines to access single palette color entries. +* Added new routine to return the maximum supported pixel clock. +* Added new routine gfx_set_crt_enable to manipulate the CRT display logic. +* Added new rendering routine gfx_color_pattern_fill. +* Added 4:2:0 and RGB video format support for CS5530 and SC1200. +* Modified code to allow operation under DOS. + +============================================================================= + +07/21/00 Version 2.04 + +----------------------------------------------------------------------------- +FUNCTIONAL CHANGES +----------------------------------------------------------------------------- +* Verified Xfree86 driver version 1.1.4 under Linux, and ce v2.3. +* Merged sc1200 changes. +* Added routines to support the query of current display mode. +* Added functions gfx_enable_softvga, dfx_disable_softvga. +* Added code optimization in rendering loops to use 32 bit writes where possible. +* Added gfx_is_mode_supported to query if given mode supported by the h/w. +* Added Flat panel support, realy testing with panel done only for 800x600. +* Removed subtraction of 16 from gfx_set_compression_size. +* Added version.h file to reflect the version of the durango used. + +============================================================================= + +03/03/00 Version 2.01 + +----------------------------------------------------------------------------- +FUNCTIONAL CHANGES +----------------------------------------------------------------------------- +* Verified Xfree86 driver version 1.1 under FreeBSD and Linux. +* Added automatic detection of BLT buffer bases in "gfx_set_bpp" routine. +* Fixed improper setting of VGA attrubute controller index register. +* Moved "gfx_get_display_bpp" to always be included. +* Moved "gfx_get_hactive" and "gfx_get_vactive" to always be included. +* Clipped video source size if off bottom or right side. +* Properly adjusted video offset if clipped on the top side. +* Added "gfx_get_video_line_size" and "gfx_get_video_xclip" routines. + +============================================================================= + +02/21/00 Version 2.00 + +----------------------------------------------------------------------------- +FUNCTIONAL CHANGES +----------------------------------------------------------------------------- +* Added gfx_vga.c. +* Added write to GP_BLIT_STATUS in "gfx_set_bpp" routine. +* Verified alpha blending on SC1200. +* Removed "gfx_set_blt_buffers" routine. + +============================================================================= + +02/09/00 Version 1.20 + +----------------------------------------------------------------------------- +FUNCTIONAL CHANGES +----------------------------------------------------------------------------- +* Verified display modes and graphics rendering on SC1200. +* Updated PLL table for SC1200 to set modes. +* DURANGO.C FILE CHANGE!: Modifed and added compiler definitions. +* Split gfx_disp.c file into gu1_disp.c and gu2_disp.c +* Split gfx_rndr.c file into gu1_rndr.c and gu2_rndr.c +* Split gfx_vid.c file into vid_5530.c, vid_1400.c, and vid_1200.c +* Split gfx_vip.c file into vip_1400.c and vip_1200.c +* Split gfx_tv.c file into geode_tv.c and fs451_tv.c +* Split gfx_i2c.c file into acc_i2c.c and gpio_i2c.c. +* Split gfx_dcdr.c file to saa7114.c +* Added GFX_READ_ROUTINES compiler definition. +* Moved routines from gfx_read.c (no longer exists) to other files. +* Abstracted display controller access in the video overlay routines. +* Added routines to control display compression hardware. + +============================================================================= + +01/28/00 Version 1.13 + +----------------------------------------------------------------------------- +FUNCTIONAL CHANGES +----------------------------------------------------------------------------- +* Passes randomly generated rendering tests in Darwin for GXLV. +* Fixed bug for large bitmap to screen BLTs (greater than 64K). +* Fixed bug for pattern fills using solid source data for plane masks. + +============================================================================= + +01/14/00 Version 1.12 + +----------------------------------------------------------------------------- +FUNCTIONAL CHANGES +----------------------------------------------------------------------------- +* Added proper use of hotspot to gfx_set_cursor_position. +* Fixed buffer size to handle all frame buffer start address alignments. +* Added initial version of gfx_tv.c. + +============================================================================= + +01/07/00 Version 1.11 + +----------------------------------------------------------------------------- +FUNCTIONAL CHANGES +----------------------------------------------------------------------------- +* Fixed bug with transparent BLTs (loading transparent color into BB1). +* Added definition of gfx_color_bitmap_to_screen_blt to gfx_rtns.h. +* Added gfx_color_bitmap_to_screen_xblt (transparent bitmap to screen). + +============================================================================= + +12/21/99 Version 1.10 + +----------------------------------------------------------------------------- +FUNCTIONAL CHANGES +----------------------------------------------------------------------------- +* Added additional video decoder routines to gfx_dcdr.c. +* Added VBI routines to gfx_vip.c. +* Added alpha blending routines for SC1200 to gfx_vid.c + +============================================================================= + +10/01/99 Version 1.00 + +----------------------------------------------------------------------------- +FUNCTIONAL CHANGES +----------------------------------------------------------------------------- +* Added video port, video decoder, I2C, and hardware query rouines. +* New files: gfx_vip.c, gfx_dcdr.c, gfx_i2c.c, gfx_read.c. + +============================================================================= + +08/27/99 Version 0.05 + +----------------------------------------------------------------------------- +FUNCTIONAL CHANGES +----------------------------------------------------------------------------- +* INTERFACE CHANGE: Changed "gfx_csptr[]" to "gfx_vidptr" and "gfx_vipptr". +* Added "gfx_get_vid_register_base" and "gfx_get_vip_register_base". +* Added initial PLL table for SC1400. +* Verified mode set and video overlay routines work correctly on SC1400. +* Updated initilization routines. +* Added update of graphics engine in "gfx_set_display_pitch". + +============================================================================= + +08/20/99 Version 0.04 + +----------------------------------------------------------------------------- +FUNCTIONAL CHANGES +----------------------------------------------------------------------------- +* INTERFACE CHANGE: "gfx_load_*" routines changed to "gfx_set_*" for naming + consistency. The "gfx_text_glyph" routine was removed. +* Added video overlay routines. +* Added gfx_vid.c file. + +============================================================================= + +08/16/99 Version 0.03 + +----------------------------------------------------------------------------- +FUNCTIONAL CHANGES +----------------------------------------------------------------------------- +* INTERFACE CHANGE: Access to CS5530 now through separate pointer. Project + must declare and map the gfx_csptr[GFX_CSPTR_SIZE] variable. +* Added durango.c file as template for main source file. +* Added gfx_init.c file. + +============================================================================= + +08/04/99 Version 0.02 + +----------------------------------------------------------------------------- +FUNCTIONAL CHANGES +----------------------------------------------------------------------------- +* Additional modes in gfx_mode.h file. +* Separated register definitions from gfx_defs.h into gfx_regs.h. + +============================================================================= + +07/30/99 Version 0.01 + +----------------------------------------------------------------------------- +FUNCTIONAL CHANGES +----------------------------------------------------------------------------- +* Initial release. +----------------------------------------------------------------------------- + diff --git a/src/gfx/rndr_gu1.c b/src/gfx/rndr_gu1.c new file mode 100644 index 0000000..5ad5af1 --- /dev/null +++ b/src/gfx/rndr_gu1.c @@ -0,0 +1,1584 @@ +/* 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 to program the 2D acceleration hardware for + * the first generation graphics unit (GXLV, SC1200). + * + * gfx_set_bpp + * gfx_set_solid_pattern + * gfx_set_mono_pattern + * gfx_set_color_pattern + * gfx_set_solid_source + * gfx_set_mono_source + * gfx_set_raster_operation + * gfx_pattern_fill + * gfx_screen_to_screen_blt + * gfx_screen_to_screen_xblt + * gfx_color_bitmap_to_screen_blt + * gfx_color_bitmap_to_screen_xblt + * gfx_mono_bitmap_to_screen_blt + * gfx_bresenham_line + * gfx_wait_until_idle + * */ + +#if GFX_NO_IO_IN_WAIT_MACROS +#define GFX_WAIT_PENDING \ + while(READ_REG16(GP_BLIT_STATUS) & BS_BLIT_PENDING) { ; } +#define GFX_WAIT_BUSY \ + while(READ_REG16(GP_BLIT_STATUS) & BS_BLIT_BUSY) { ; } +#define GFX_WAIT_PIPELINE \ + while (READ_REG16(GP_BLIT_STATUS) & BS_PIPELINE_BUSY) { ; } +#else +#define GFX_WAIT_PENDING \ + while(READ_REG16(GP_BLIT_STATUS) & BS_BLIT_PENDING) { INB (0x80); } +#define GFX_WAIT_BUSY \ + while(READ_REG16(GP_BLIT_STATUS) & BS_BLIT_BUSY) { INB (0x80); } +#define GFX_WAIT_PIPELINE \ + while (READ_REG16(GP_BLIT_STATUS) & BS_PIPELINE_BUSY) { INB (0x80); } +#endif + +void gu1_detect_blt_buffer_base(void); + +/*--------------------------------------------------------------------------- + * GFX_SET_BPP + * + * This routine sets the bits per pixel value in the graphics engine. + * It is also stored in a static variable to use in the future calls to + * the rendering routines. + *--------------------------------------------------------------------------- + */ +#if GFX_2DACCEL_DYNAMIC +void +gu1_set_bpp(unsigned short bpp) +#else +void +gfx_set_bpp(unsigned short bpp) +#endif +{ + int control = 0; + unsigned short pitch = gfx_get_display_pitch(); + + GFXbpp = bpp; + + /* DETECT BASE ADDRESSES FOR BLT BUFFERS */ + /* Different for 2K or 3K of scratchpad. Also need to calculate */ + /* the number of pixels that can fit in a BLT buffer - need to */ + /* subtract 16 for alignment considerations. The 2K case, for */ + /* example, is 816 bytes wide, allowing 800 pixels in 8 BPP, which */ + /* means rendering operations won't be split for 800x600. */ + + gu1_detect_blt_buffer_base(); + GFXbufferWidthPixels = GFXbb1Base - GFXbb0Base - 16; + if (bpp > 8) { + /* If 16bpp, divide GFXbufferWidthPixels by 2 */ + GFXbufferWidthPixels >>= 1; + } + + /* SET THE GRAPHICS CONTROLLER BPP AND PITCH */ + if (bpp > 8) { + /* Set the 16bpp bit if necessary */ + control = BC_16BPP; + } + if ((gfx_cpu_version == GFX_CPU_PYRAMID) && (pitch > 2048)) { + control |= BC_FB_WIDTH_4096; + } else if (pitch > 1024) { + control |= BC_FB_WIDTH_2048; + } + GFX_WAIT_BUSY; + WRITE_REG32(GP_BLIT_STATUS, control); +} + +/* + *--------------------------------------------------------------------------- + * GFX_SET_SOLID_SOURCE + * + * This routine is used to specify a solid source color. For the Xfree96 + * display driver, the source color is used to specify a planemask and the + * ROP is adjusted accordingly. + *--------------------------------------------------------------------------- + */ +#if GFX_2DACCEL_DYNAMIC +void +gu1_set_solid_source(unsigned long color) +#else +void +gfx_set_solid_source(unsigned long color) +#endif +{ + /* CLEAR TRANSPARENCY FLAG */ + + GFXsourceFlags = 0; + + /* FORMAT 8 BPP COLOR */ + /* GX requires 8BPP color data be duplicated into bits [15:8]. */ + + if (GFXbpp == 8) { + color &= 0x00FF; + color |= (color << 8); + } + + /* POLL UNTIL ABLE TO WRITE THE SOURCE COLOR */ + + GFX_WAIT_PENDING; + WRITE_REG16(GP_SRC_COLOR_0, (unsigned short)color); + WRITE_REG16(GP_SRC_COLOR_1, (unsigned short)color); +} + +/* + *--------------------------------------------------------------------------- + * GFX_SET_MONO_SOURCE + * + * This routine is used to specify the monochrome source colors. + * It must be called *after* loading any pattern data (those routines + * clear the source flags). + *--------------------------------------------------------------------------- + */ +#if GFX_2DACCEL_DYNAMIC +void +gu1_set_mono_source(unsigned long bgcolor, unsigned long fgcolor, + unsigned short transparent) +#else +void +gfx_set_mono_source(unsigned long bgcolor, unsigned long fgcolor, + unsigned short transparent) +#endif +{ + /* SET TRANSPARENCY FLAG */ + + GFXsourceFlags = transparent ? RM_SRC_TRANSPARENT : 0; + + /* FORMAT 8 BPP COLOR */ + /* GX requires 8BPP color data be duplicated into bits [15:8]. */ + + if (GFXbpp == 8) { + bgcolor &= 0x00FF; + bgcolor |= (bgcolor << 8); + fgcolor &= 0x00FF; + fgcolor |= (fgcolor << 8); + } + + /* POLL UNTIL ABLE TO WRITE THE SOURCE COLOR */ + + GFX_WAIT_PENDING; + WRITE_REG16(GP_SRC_COLOR_0, (unsigned short)bgcolor); + WRITE_REG16(GP_SRC_COLOR_1, (unsigned short)fgcolor); +} + +/* + *--------------------------------------------------------------------------- + * GFX_SET_SOLID_PATTERN + * + * This routine is used to specify a solid pattern color. It is called + * before performing solid rectangle fills or more complicated BLTs that + * use a solid pattern color. + * + * The driver should always call "gfx_load_raster_operation" after a call + * to this routine to make sure that the pattern flags are set appropriately. + *--------------------------------------------------------------------------- + */ +#if GFX_2DACCEL_DYNAMIC +void +gu1_set_solid_pattern(unsigned long color) +#else +void +gfx_set_solid_pattern(unsigned long color) +#endif +{ + /* CLEAR TRANSPARENCY FLAG */ + + GFXsourceFlags = 0; + + /* SET PATTERN FLAGS */ + + GFXpatternFlags = 0; + + /* FORMAT 8 BPP COLOR */ + /* GX requires 8BPP color data be duplicated into bits [15:8]. */ + + if (GFXbpp == 8) { + color &= 0x00FF; + color |= (color << 8); + } + + /* SAVE THE REFORMATTED COLOR FOR LATER */ + /* Used to call the "GFX_solid_fill" routine for special cases. */ + + GFXsavedColor = color; + + /* POLL UNTIL ABLE TO WRITE THE PATTERN COLOR */ + + GFX_WAIT_PENDING; + WRITE_REG16(GP_PAT_COLOR_0, (unsigned short)color); +} + +/* + *--------------------------------------------------------------------------- + * GFX_SET_MONO_PATTERN + * + * This routine is used to specify a monochrome pattern. + *--------------------------------------------------------------------------- + */ +#if GFX_2DACCEL_DYNAMIC +void +gu1_set_mono_pattern(unsigned long bgcolor, unsigned long fgcolor, + unsigned long data0, unsigned long data1, unsigned char transparent) +#else +void +gfx_set_mono_pattern(unsigned long bgcolor, unsigned long fgcolor, + unsigned long data0, unsigned long data1, unsigned char transparent) +#endif +{ + /* CLEAR TRANSPARENCY FLAG */ + + GFXsourceFlags = 0; + + /* SET PATTERN FLAGS */ + + GFXpatternFlags = transparent ? RM_PAT_MONO | RM_PAT_TRANSPARENT : + RM_PAT_MONO; + + /* FORMAT 8 BPP COLOR */ + /* GXm requires 8BPP color data be duplicated into bits [15:8]. */ + + if (GFXbpp == 8) { + bgcolor &= 0x00FF; + bgcolor |= (bgcolor << 8); + fgcolor &= 0x00FF; + fgcolor |= (fgcolor << 8); + } + + /* POLL UNTIL ABLE TO WRITE THE PATTERN COLORS AND DATA */ + + GFX_WAIT_PENDING; + WRITE_REG16(GP_PAT_COLOR_0, (unsigned short)bgcolor); + WRITE_REG16(GP_PAT_COLOR_1, (unsigned short)fgcolor); + WRITE_REG32(GP_PAT_DATA_0, data0); + WRITE_REG32(GP_PAT_DATA_1, data1); +} + +/* + *--------------------------------------------------------------------------- + * GFX_SET_COLOR_PATTERN + * + * This routine is used to specify a color pattern. + *--------------------------------------------------------------------------- + */ +#if GFX_2DACCEL_DYNAMIC +void +gu1_set_color_pattern(unsigned long bgcolor, unsigned long fgcolor, + unsigned long data0, unsigned long data1, unsigned long data2, + unsigned long data3, unsigned char transparent) +#else +void +gfx_set_color_pattern(unsigned long bgcolor, unsigned long fgcolor, + unsigned long data0, unsigned long data1, unsigned long data2, + unsigned long data3, unsigned char transparent) +#endif +{ + /* CLEAR TRANSPARENCY FLAG */ + + GFXsourceFlags = 0; + + /* SET PATTERN FLAGS */ + + GFXpatternFlags = transparent ? RM_PAT_MONO | RM_PAT_TRANSPARENT : + RM_PAT_MONO; + + GFXpatternFlags |= RM_PAT_COLOR; + /* FORMAT 8 BPP COLOR */ + /* GXm requires 8BPP color data be duplicated into bits [15:8]. */ + + if (GFXbpp == 8) { + bgcolor &= 0x00FF; + bgcolor |= (bgcolor << 8); + fgcolor &= 0x00FF; + fgcolor |= (fgcolor << 8); + } + + /* POLL UNTIL ABLE TO WRITE THE PATTERN COLORS AND DATA */ + + GFX_WAIT_PENDING; + WRITE_REG16(GP_PAT_COLOR_0, (unsigned short)bgcolor); + WRITE_REG16(GP_PAT_COLOR_1, (unsigned short)fgcolor); + WRITE_REG32(GP_PAT_DATA_0, data0); + WRITE_REG32(GP_PAT_DATA_1, data1); + if (GFXbpp > 8) { + WRITE_REG32(GP_PAT_DATA_2, data2); + WRITE_REG32(GP_PAT_DATA_3, data3); + } +} + +/* + *--------------------------------------------------------------------------- + * GFX_LOAD_COLOR_PATTERN_LINE + * + * This routine is used to load a single line of a 8x8 color pattern. + *--------------------------------------------------------------------------- + */ +#if GFX_2DACCEL_DYNAMIC +void +gu1_load_color_pattern_line(short y, unsigned long *pattern_8x8) +#else +void +gfx_load_color_pattern_line(short y, unsigned long *pattern_8x8) +#endif +{ + /* CLEAR TRANSPARENCY FLAG */ + + GFXsourceFlags = 0; + + /* SET PATTERN FLAGS */ + + GFXpatternFlags = RM_PAT_COLOR; + + y &= 7; + + if (GFXbpp > 8) + pattern_8x8 += (y << 2); + else + pattern_8x8 += (y << 1); + + /* POLL UNTIL ABLE TO WRITE THE PATTERN COLORS AND DATA */ + + GFX_WAIT_PENDING; + WRITE_REG32(GP_PAT_DATA_0, pattern_8x8[0]); + WRITE_REG32(GP_PAT_DATA_1, pattern_8x8[1]); + if (GFXbpp > 8) { + WRITE_REG32(GP_PAT_DATA_2, pattern_8x8[2]); + WRITE_REG32(GP_PAT_DATA_3, pattern_8x8[3]); + } +} + +/* + *--------------------------------------------------------------------------- + * GFX_SET_RASTER_OPERATION + * + * This routine loads the specified raster operation. It sets the pattern + * flags appropriately. + *--------------------------------------------------------------------------- + */ +#if GFX_2DACCEL_DYNAMIC +void +gu1_set_raster_operation(unsigned char rop) +#else +void +gfx_set_raster_operation(unsigned char rop) +#endif +{ + unsigned short rop16; + + /* GENERATE 16-BIT VERSION OF ROP WITH PATTERN FLAGS */ + + rop16 = (unsigned short)rop | GFXpatternFlags; + if ((rop & 0x33) ^ ((rop >> 2) & 0x33)) + rop16 |= GFXsourceFlags; + + /* SAVE ROP FOR LATER COMPARISONS */ + /* Need to have the pattern flags included */ + + GFXsavedRop = rop16; + + /* SET FLAG INDICATING ROP REQUIRES DESTINATION DATA */ + /* True if even bits (0:2:4:6) do not equal the correspinding */ + /* even bits (1:3:5:7). */ + + GFXusesDstData = ((rop & 0x55) ^ ((rop >> 1) & 0x55)); + + /* POLL UNTIL ABLE TO WRITE THE PATTERN COLOR */ + /* Only one operation can be pending at a time. */ + + GFX_WAIT_PENDING; + WRITE_REG16(GP_RASTER_MODE, rop16); +} + +/* + *--------------------------------------------------------------------------- + * GFX_SOLID_FILL + * + * This routine MUST be used when performing a solid rectangle fill with + * the ROPs of PATCOPY (0xF0), BLACKNESS (0x00), WHITENESS (0xFF), or + * PATINVERT (0x0F). There is a bug in GXm for these cases that requires a + * workaround. + * + * For BLACKNESS (ROP = 0x00), set the color to 0x0000. + * For WHITENESS (ROP = 0xFF), set the color to 0xFFFF. + * For PATINVERT (ROP = 0x0F), invert the desired color. + * + * X screen X position (left) + * Y screen Y position (top) + * WIDTH width of rectangle, in pixels + * HEIGHT height of rectangle, in scanlines + * COLOR fill color + * + * THIS ROUTINE SHOULD NOT BE DIRECTLY CALLED FROM THE DRIVER. The driver + * should always use GFX_pattern_fill and let that routine call this one + * when approipriate. This is to hide quirks specific to MediaGX hardware. + *--------------------------------------------------------------------------- + */ +void +gu1_solid_fill(unsigned short x, unsigned short y, + unsigned short width, unsigned short height, unsigned long color) +{ + unsigned short section; + + /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */ + /* Only one operation can be pending at a time. */ + + GFX_WAIT_PENDING; + + /* SET REGISTERS TO DRAW RECTANGLE */ + + WRITE_REG16(GP_DST_XCOOR, x); + WRITE_REG16(GP_DST_YCOOR, y); + WRITE_REG16(GP_HEIGHT, height); + WRITE_REG16(GP_RASTER_MODE, 0x00F0); /* PATCOPY */ + WRITE_REG16(GP_PAT_COLOR_0, (unsigned short)color); + + /* CHECK WIDTH FOR GX BUG WORKAROUND */ + + if (width <= 16) { + /* OK TO DRAW SMALL RECTANGLE IN ONE PASS */ + + WRITE_REG16(GP_WIDTH, width); + WRITE_REG16(GP_BLIT_MODE, 0); + } else { + /* DRAW FIRST PART OF RECTANGLE */ + /* Get to a 16 pixel boundary. */ + + section = 0x10 - (x & 0x0F); + WRITE_REG16(GP_WIDTH, section); + WRITE_REG16(GP_BLIT_MODE, 0); + + /* POLL UNTIL ABLE TO LOAD THE SECOND RECTANGLE */ + + GFX_WAIT_PENDING; + WRITE_REG16(GP_DST_XCOOR, x + section); + WRITE_REG16(GP_DST_YCOOR, y); + WRITE_REG16(GP_WIDTH, width - section); + WRITE_REG16(GP_BLIT_MODE, 0); + } +} + +/* + *---------------------------------------------------------------------------- + * GFX_PATTERN_FILL + * + * This routine is used to fill a rectangular region. The pattern must + * be previously loaded using one of GFX_load_*_pattern routines. Also, the + * raster operation must be previously specified using the + * "GFX_load_raster_operation" routine. + * + * X screen X position (left) + * Y screen Y position (top) + * WIDTH width of rectangle, in pixels + * HEIGHT height of rectangle, in scanlines + *---------------------------------------------------------------------------- + */ +#if GFX_2DACCEL_DYNAMIC +void +gu1_pattern_fill(unsigned short x, unsigned short y, + unsigned short width, unsigned short height) +#else +void +gfx_pattern_fill(unsigned short x, unsigned short y, + unsigned short width, unsigned short height) +#endif +{ + unsigned short section, buffer_width, blit_mode; + + /* CHECK IF OPTIMIZED SOLID CASES */ + /* Check all 16 bits of the ROP to include solid pattern flags. */ + + switch (GFXsavedRop) { + /* CHECK FOR SPECIAL CASES WITHOUT DESTINATION DATA */ + /* Need hardware workaround for fast "burst write" cases. */ + + case 0x00F0: + gu1_solid_fill(x, y, width, height, (unsigned short)GFXsavedColor); + break; + case 0x000F: + gu1_solid_fill(x, y, width, height, (unsigned short)~GFXsavedColor); + break; + case 0x0000: + gu1_solid_fill(x, y, width, height, 0x0000); + break; + case 0x00FF: + gu1_solid_fill(x, y, width, height, 0xFFFF); + break; + + /* REMAINING CASES REQUIRE DESTINATION DATA OR NOT SOLID COLOR */ + + default: + + /* DETERMINE BLT MODE VALUE */ + /* Still here for non-solid patterns without destination data. */ + + blit_mode = GFXusesDstData ? BM_READ_DST_FB0 : 0; + + /* SET SOURCE EXPANSION MODE */ + /* If the ROP requires source data, then the source data is all 1's */ + /* and then expanded into the desired color in GP_SRC_COLOR_1. */ + + blit_mode |= BM_SOURCE_EXPAND; + + /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */ + /* Write the registers that do not change for each section. */ + + GFX_WAIT_PENDING; + WRITE_REG16(GP_HEIGHT, height); + + /* SINCE ONLY DESTINATION DATA, WE CAN USE BOTH BB0 AND BB1. */ + /* Therefore, width available = BLT buffer width * 2. */ + + buffer_width = GFXbufferWidthPixels << 1; + + /* REPEAT UNTIL FINISHED WITH RECTANGLE */ + /* Perform BLT in vertical sections, as wide as the BLT buffer */ + /* allows. Hardware does not split the operations, so */ + /* software must do it to avoid large scanlines that would */ + /* overflow the BLT buffers. */ + + while (width > 0) { + /* DETERMINE WIDTH OF SECTION */ + + if (width > buffer_width) + section = buffer_width; + else + section = width; + + /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */ + + GFX_WAIT_PENDING; + WRITE_REG16(GP_DST_XCOOR, x); + WRITE_REG16(GP_DST_YCOOR, y); + WRITE_REG16(GP_WIDTH, section); + WRITE_REG16(GP_BLIT_MODE, blit_mode); + + /* ADJUST PARAMETERS FOR NEXT SECTION */ + + width -= section; + x += section; + } + break; + } +} + +/* + *---------------------------------------------------------------------------- + * GFX_COLOR_PATTERN_FILL + * + * This routine is used to render a rectangle using the current raster + * operation and the specified color pattern. It allows an 8x8 color + * pattern to be rendered without multiple calls to the gfx_set_color_pattern + * and gfx_pattern_fill routines. + * + * X screen X position (left) + * Y screen Y position (top) + * WIDTH width of rectangle, in pixels + * HEIGHT height of rectangle, in scanlines + * *PATTERN pointer to 8x8 color pattern data + *---------------------------------------------------------------------------- + */ +#if GFX_2DACCEL_DYNAMIC +void +gu1_color_pattern_fill(unsigned short x, unsigned short y, + unsigned short width, unsigned short height, unsigned long *pattern) +#else +void +gfx_color_pattern_fill(unsigned short x, unsigned short y, + unsigned short width, unsigned short height, unsigned long *pattern) +#endif +{ + unsigned short blit_mode, passes, cur_y, pat_y, i; + unsigned short buffer_width, line_width; + unsigned short bpp_shift, section, cur_x; + + /* SET APPROPRIATE INCREMENT */ + + bpp_shift = (GFXbpp > 8) ? 2 : 1; + + /* SET DESTINATION REQUIRED */ + + blit_mode = GFXusesDstData ? BM_READ_DST_FB0 : 0; + + /* SET SOURCE EXPANSION */ + + blit_mode |= BM_SOURCE_EXPAND; + + /* OVERRIDE RASTER MODE TO FORCE A COLOR PATTERN */ + + GFX_WAIT_PENDING; + WRITE_REG16(GP_RASTER_MODE, + (GFXsavedRop & ~RM_PAT_MASK & ~RM_PAT_TRANSPARENT) | RM_PAT_COLOR); + + /* WRITE THE REGISTERS THAT DO NOT CHANGE */ + /* If destination data is required, the width and */ + /* x position will be overwritten. */ + + WRITE_REG16(GP_HEIGHT, 1); + WRITE_REG16(GP_WIDTH, width); + WRITE_REG16(GP_DST_XCOOR, x); + + /* THE ENTIRE PATTERN WILL NOT BE DRAWN IF THE HEIGHT IS LESS THAN 8 */ + + passes = (height < 8) ? height : 8; + + /* SINCE ONLY DESTINATION DATA, WE CAN USE BOTH BB0 AND BB1. */ + /* Therefore, width available = BLT buffer width * 2. */ + + buffer_width = GFXbufferWidthPixels << 1; + + for (i = 0; i < passes; i++) { + pat_y = ((y + i) & 7) << bpp_shift; + cur_y = y + i; + + /* WRITE THE PATTERN DATA FOR THE ACTIVE LINE */ + + GFX_WAIT_PENDING; + WRITE_REG32(GP_PAT_DATA_0, pattern[pat_y]); + WRITE_REG32(GP_PAT_DATA_1, pattern[pat_y + 1]); + + if (GFXbpp > 8) { + WRITE_REG32(GP_PAT_DATA_2, pattern[pat_y + 2]); + WRITE_REG32(GP_PAT_DATA_3, pattern[pat_y + 3]); + } + + /* SPLIT BLT LINE INTO SECTIONS IF REQUIRED */ + /* If no destination data is required, we can ignore */ + /* the BLT buffers. Otherwise, we must separate the BLT */ + /* so as not to overflow the buffers */ + + if (blit_mode & BM_READ_DST_BB0) { + line_width = width; + cur_x = x; + + while (line_width) { + section = + (line_width > buffer_width) ? buffer_width : line_width; + cur_y = y + i; + + GFX_WAIT_PENDING; + WRITE_REG16(GP_DST_XCOOR, cur_x); + WRITE_REG16(GP_WIDTH, section); + + while (cur_y < y + height) { + GFX_WAIT_PENDING; + WRITE_REG16(GP_DST_YCOOR, cur_y); + WRITE_REG16(GP_BLIT_MODE, blit_mode); + cur_y += 8; + } + + cur_x += section; + line_width -= section; + } + + } else { + while (cur_y < y + height) { + GFX_WAIT_PENDING; + WRITE_REG16(GP_DST_YCOOR, cur_y); + WRITE_REG16(GP_BLIT_MODE, blit_mode); + cur_y += 8; + } + } + + } + + /* RESTORE ORIGINAL ROP AND FLAGS */ + + GFX_WAIT_PENDING; + WRITE_REG16(GP_RASTER_MODE, GFXsavedRop); + +} + +/* + *---------------------------------------------------------------------------- + * SCREEN TO SCREEN BLT + * + * This routine should be used to perform a screen to screen BLT when the + * ROP does not require destination data. + * + * SRCX screen X position to copy from + * SRCY screen Y position to copy from + * DSTX screen X position to copy to + * DSTY screen Y position to copy to + * WIDTH width of rectangle, in pixels + * HEIGHT height of rectangle, in scanlines + *---------------------------------------------------------------------------- + */ +#if GFX_2DACCEL_DYNAMIC +void +gu1_screen_to_screen_blt(unsigned short srcx, unsigned short srcy, + unsigned short dstx, unsigned short dsty, unsigned short width, + unsigned short height) +#else +void +gfx_screen_to_screen_blt(unsigned short srcx, unsigned short srcy, + unsigned short dstx, unsigned short dsty, unsigned short width, + unsigned short height) +#endif +{ + unsigned short section, buffer_width; + unsigned short blit_mode; + + /* CHECK IF RASTER OPERATION REQUIRES DESTINATION DATA */ + + blit_mode = GFXusesDstData ? BM_READ_DST_FB1 | BM_READ_SRC_FB : + BM_READ_SRC_FB; + + /* CHECK Y DIRECTION */ + /* Hardware has support for negative Y direction. */ + + if (dsty > srcy) { + blit_mode |= BM_REVERSE_Y; + srcy += height - 1; + dsty += height - 1; + } + + /* CHECK X DIRECTION */ + /* Hardware does not support negative X direction since at the time */ + /* of development all supported resolutions could fit a scanline of */ + /* data at once into the BLT buffers (using both BB0 and BB1). This */ + /* code is more generic to allow for any size BLT buffer. */ + + if (dstx > srcx) { + srcx += width; + dstx += width; + } + + /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */ + /* Write the registers that do not change for each section. */ + + GFX_WAIT_PENDING; + WRITE_REG16(GP_HEIGHT, height); + + /* CHECK AVAILABLE BLT BUFFER SIZE */ + /* Can use both BLT buffers if no destination data is required. */ + + buffer_width = GFXusesDstData ? GFXbufferWidthPixels : + GFXbufferWidthPixels << 1; + + /* REPEAT UNTIL FINISHED WITH RECTANGLE */ + /* Perform BLT in vertical sections, as wide as the BLT buffer allows. */ + /* Hardware does not split the operations, so software must do it to */ + /* avoid large scanlines that would overflow the BLT buffers. */ + + while (width > 0) { + /* CHECK WIDTH OF CURRENT SECTION */ + + if (width > buffer_width) + section = buffer_width; + else + section = width; + + /* PROGRAM REGISTERS THAT ARE THE SAME FOR EITHER X DIRECTION */ + + GFX_WAIT_PENDING; + WRITE_REG16(GP_SRC_YCOOR, srcy); + WRITE_REG16(GP_DST_YCOOR, dsty); + WRITE_REG16(GP_WIDTH, section); + + /* CHECK X DIRECTION */ + + if (dstx > srcx) { + /* NEGATIVE X DIRECTION */ + /* Still positive X direction within the section. */ + + srcx -= section; + dstx -= section; + WRITE_REG16(GP_SRC_XCOOR, srcx); + WRITE_REG16(GP_DST_XCOOR, dstx); + WRITE_REG16(GP_BLIT_MODE, blit_mode); + } else { + /* POSITIVE X DIRECTION */ + + WRITE_REG16(GP_SRC_XCOOR, srcx); + WRITE_REG16(GP_DST_XCOOR, dstx); + WRITE_REG16(GP_BLIT_MODE, blit_mode); + dstx += section; + srcx += section; + } + width -= section; + } +} + +/* + *---------------------------------------------------------------------------- + * SCREEN TO SCREEN TRANSPARENT BLT + * + * This routine should be used to perform a screen to screen BLT when a + * specified color should by transparent. The only supported ROP is SRCCOPY. + * + * SRCX screen X position to copy from + * SRCY screen Y position to copy from + * DSTX screen X position to copy to + * DSTY screen Y position to copy to + * WIDTH width of rectangle, in pixels + * HEIGHT height of rectangle, in scanlines + * COLOR transparent color + *---------------------------------------------------------------------------- + */ +#if GFX_2DACCEL_DYNAMIC +void +gu1_screen_to_screen_xblt(unsigned short srcx, unsigned short srcy, + unsigned short dstx, unsigned short dsty, unsigned short width, + unsigned short height, unsigned long color) +#else +void +gfx_screen_to_screen_xblt(unsigned short srcx, unsigned short srcy, + unsigned short dstx, unsigned short dsty, unsigned short width, + unsigned short height, unsigned long color) +#endif +{ + unsigned short section, buffer_width; + unsigned short blit_mode = BM_READ_SRC_FB; + + /* CHECK Y DIRECTION */ + /* Hardware has support for negative Y direction. */ + + if (dsty > srcy) { + blit_mode |= BM_REVERSE_Y; + srcy += height - 1; + dsty += height - 1; + } + + /* CHECK X DIRECTION */ + /* Hardware does not support negative X direction since at the time */ + /* of development all supported resolutions could fit a scanline of */ + /* data at once into the BLT buffers (using both BB0 and BB1). This */ + /* code is more generic to allow for any size BLT buffer. */ + + if (dstx > srcx) { + srcx += width; + dstx += width; + } + + /* CALCULATE BLT BUFFER SIZE */ + /* Need to use BB1 to store the BLT buffer data. */ + + buffer_width = GFXbufferWidthPixels; + + /* WRITE TRANSPARENCY COLOR TO BLT BUFFER 1 */ + + if (GFXbpp == 8) { + color &= 0x00FF; + color |= (color << 8); + } + color = (color & 0x0000FFFF) | (color << 16); + + /* WAIT UNTIL PIPELINE IS NOT BUSY BEFORE LOADING DATA INTO BB1 */ + /* Need to make sure any previous BLT using BB1 is complete. */ + /* Only need to load 32 bits of BB1 for the 1 pixel BLT that follows. */ + + GFX_WAIT_BUSY; + WRITE_SCRATCH32(GFXbb1Base, color); + + /* DO BOGUS BLT TO LATCH DATA FROM BB1 */ + /* Already know graphics pipeline is idle. */ + /* Only need to latch data into the holding registers for the current */ + /* data from BB1. A 1 pixel wide BLT will suffice. */ + + WRITE_REG32(GP_DST_XCOOR, 0); + WRITE_REG32(GP_SRC_XCOOR, 0); + WRITE_REG32(GP_WIDTH, 0x00010001); + WRITE_REG16(GP_RASTER_MODE, 0x00CC); + WRITE_REG16(GP_BLIT_MODE, BM_READ_SRC_FB | BM_READ_DST_BB1); + + /* WRITE REGISTERS FOR REAL SCREEN TO SCREEN BLT */ + + GFX_WAIT_PENDING; + WRITE_REG16(GP_HEIGHT, height); + WRITE_REG16(GP_RASTER_MODE, 0x10C6); + WRITE_REG32(GP_PAT_COLOR_0, 0xFFFFFFFF); + + /* REPEAT UNTIL FINISHED WITH RECTANGLE */ + /* Perform BLT in vertical sections, as wide as the BLT buffer allows. */ + /* Hardware does not split the operations, so software must do it to */ + /* avoid large scanlines that would overflow the BLT buffers. */ + + while (width > 0) { + /* CHECK WIDTH OF CURRENT SECTION */ + + if (width > buffer_width) + section = buffer_width; + else + section = width; + + /* PROGRAM REGISTERS THAT ARE THE SAME FOR EITHER X DIRECTION */ + + GFX_WAIT_PENDING; + WRITE_REG16(GP_SRC_YCOOR, srcy); + WRITE_REG16(GP_DST_YCOOR, dsty); + WRITE_REG16(GP_WIDTH, section); + + /* CHECK X DIRECTION */ + /* Again, this must be done in software, and can be removed if the */ + /* display driver knows that the BLT buffers will always be large */ + /* enough to contain an entire scanline of a screen to screen BLT. */ + + if (dstx > srcx) { + /* NEGATIVE X DIRECTION */ + /* Still positive X direction within the section. */ + + srcx -= section; + dstx -= section; + WRITE_REG16(GP_SRC_XCOOR, srcx); + WRITE_REG16(GP_DST_XCOOR, dstx); + WRITE_REG16(GP_BLIT_MODE, blit_mode); + } else { + /* POSITIVE X DIRECTION */ + + WRITE_REG16(GP_SRC_XCOOR, srcx); + WRITE_REG16(GP_DST_XCOOR, dstx); + WRITE_REG16(GP_BLIT_MODE, blit_mode); + dstx += section; + srcx += section; + } + width -= section; + } +} + +/* + *---------------------------------------------------------------------------- + * COLOR BITMAP TO SCREEN BLT + * + * This routine transfers color bitmap data to the screen. For most cases, + * when the ROP is SRCCOPY, it may be faster to write a separate routine that + * copies the data to the frame buffer directly. This routine should be + * used when the ROP requires destination data. + * + * Transparency is handled by another routine. + * + * SRCX X offset within source bitmap + * SRCY Y offset within source bitmap + * DSTX screen X position to render data + * DSTY screen Y position to render data + * WIDTH width of rectangle, in pixels + * HEIGHT height of rectangle, in scanlines + * *DATA pointer to bitmap data + * PITCH pitch of bitmap data (bytes between scanlines) + *---------------------------------------------------------------------------- + */ + +#if GFX_2DACCEL_DYNAMIC +void +gu1_color_bitmap_to_screen_blt(unsigned short srcx, unsigned short srcy, + unsigned short dstx, unsigned short dsty, unsigned short width, + unsigned short height, unsigned char *data, long pitch) +#else +void +gfx_color_bitmap_to_screen_blt(unsigned short srcx, unsigned short srcy, + unsigned short dstx, unsigned short dsty, unsigned short width, + unsigned short height, unsigned char *data, long pitch) +#endif +{ + unsigned short section, buffer_width; + unsigned short blit_mode = BM_READ_SRC_BB0; + unsigned short temp_height; + unsigned long dword_bytes_needed, bytes_extra; + unsigned long bpp_shift; + long array_offset; + + /* CHECK SIZE OF BLT BUFFER */ + + buffer_width = GFXbufferWidthPixels; + + /* CHECK IF RASTER OPERATION REQUIRES DESTINATION DATA */ + /* If no destination data, we have twice the room for */ + /* source data. */ + + if (GFXusesDstData) + blit_mode |= BM_READ_DST_FB1; + else + buffer_width <<= 1; + + /* SET THE SCRATCHPAD BASE */ + + SET_SCRATCH_BASE(GFXbb0Base); + + /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */ + /* Write the registers that do not change for each section. */ + + GFX_WAIT_PENDING; + WRITE_REG16(GP_HEIGHT, 1); + + bpp_shift = (GFXbpp + 7) >> 4; + + while (width > 0) { + if (width > buffer_width) + section = buffer_width; + else + section = width; + + dword_bytes_needed = (section << bpp_shift) & ~3l; + bytes_extra = (section << bpp_shift) & 3l; + + temp_height = height; + + /* WRITE THE REGISTERS FOR EACH SECTION */ + /* The GX hardware will auto-increment the Y coordinate, meaning */ + /* that we don't have to. */ + + WRITE_REG16(GP_WIDTH, section); + WRITE_REG16(GP_DST_XCOOR, dstx); + WRITE_REG16(GP_DST_YCOOR, dsty); + + /* CALCULATE THE BITMAP OFFSET */ + + array_offset = + (unsigned long)srcy *(long)pitch + ((long)srcx << bpp_shift); + + while (temp_height--) { + GFX_WAIT_PIPELINE; + + /* WRITE ALL DATA TO THE BLT BUFFERS */ + /* The WRITE_SCRATCH_STRING macro assumes that the data begins + * at the scratchpad offset set by the SET_SCRATCH_BASE macro. + * */ + + WRITE_SCRATCH_STRING(dword_bytes_needed, bytes_extra, data, + array_offset); + WRITE_REG16(GP_BLIT_MODE, blit_mode); + + array_offset += pitch; + } + + width -= section; + srcx += section; + dstx += section; + } +} + +/* + *---------------------------------------------------------------------------- + * COLOR BITMAP TO SCREEN TRANSPARENT BLT + * + * This routine transfers color bitmap data to the screen with transparency. + * The transparent color is specified. The only supported ROP is SRCCOPY, + * meaning that transparency cannot be applied if the ROP requires + * destination data (this is a hardware restriction). + * + * SRCX X offset within source bitmap + * SRCY Y offset within source bitmap + * DSTX screen X position to render data + * DSTY screen Y position to render data + * WIDTH width of rectangle, in pixels + * HEIGHT height of rectangle, in scanlines + * *DATA pointer to bitmap data + * PITCH pitch of bitmap data (bytes between scanlines) + * COLOR transparent color + *---------------------------------------------------------------------------- + */ +#if GFX_2DACCEL_DYNAMIC +void +gu1_color_bitmap_to_screen_xblt(unsigned short srcx, unsigned short srcy, + unsigned short dstx, unsigned short dsty, unsigned short width, + unsigned short height, unsigned char *data, long pitch, + unsigned long color) +#else +void +gfx_color_bitmap_to_screen_xblt(unsigned short srcx, unsigned short srcy, + unsigned short dstx, unsigned short dsty, unsigned short width, + unsigned short height, unsigned char *data, long pitch, + unsigned long color) +#endif +{ + unsigned short section, buffer_width; + unsigned short temp_height; + unsigned long dword_bytes_needed, bytes_extra; + unsigned long bpp_shift; + long array_offset; + + /* CHECK SIZE OF BLT BUFFER */ + + buffer_width = GFXbufferWidthPixels; + + /* WRITE TRANSPARENCY COLOR TO BLT BUFFER 1 */ + + if (GFXbpp == 8) { + color &= 0x00FF; + color |= (color << 8); + } + color = (color & 0x0000FFFF) | (color << 16); + + /* WAIT UNTIL PIPELINE IS NOT BUSY BEFORE LOADING DATA INTO BB1 */ + /* Need to make sure any previous BLT using BB1 is complete. */ + /* Only need to load 32 bits of BB1 for the 1 pixel BLT that follows. */ + + GFX_WAIT_PIPELINE; + GFX_WAIT_PENDING; + WRITE_SCRATCH32(GFXbb1Base, color); + + /* DO BOGUS BLT TO LATCH DATA FROM BB1 */ + /* Already know graphics pipeline is idle. */ + /* Only need to latch data into the holding registers for the current */ + /* data from BB1. A 1 pixel wide BLT will suffice. */ + + WRITE_REG32(GP_DST_XCOOR, 0); + WRITE_REG32(GP_SRC_XCOOR, 0); + WRITE_REG32(GP_WIDTH, 0x00010001); + WRITE_REG16(GP_RASTER_MODE, 0x00CC); + WRITE_REG16(GP_BLIT_MODE, BM_READ_SRC_FB | BM_READ_DST_BB1); + + /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */ + /* Write the registers that do not change for each section. */ + + GFX_WAIT_PENDING; + WRITE_REG16(GP_HEIGHT, 1); + WRITE_REG16(GP_RASTER_MODE, 0x10C6); + WRITE_REG32(GP_PAT_COLOR_0, 0xFFFFFFFF); + + bpp_shift = (GFXbpp + 7) >> 4; + + /* SET THE SCRATCHPAD BASE */ + + SET_SCRATCH_BASE(GFXbb0Base); + + while (width > 0) { + if (width > buffer_width) + section = buffer_width; + else + section = width; + + dword_bytes_needed = (section << bpp_shift) & ~3l; + bytes_extra = (section << bpp_shift) & 3l; + + temp_height = height; + + /* WRITE THE REGISTERS FOR EACH SECTION */ + /* The GX hardware will auto-increment the Y coordinate, meaning */ + /* that we don't have to. */ + + WRITE_REG16(GP_WIDTH, section); + WRITE_REG16(GP_DST_XCOOR, dstx); + WRITE_REG16(GP_DST_YCOOR, dsty); + + /* CALCULATE THE BITMAP OFFSET */ + + array_offset = + (unsigned long)srcy *(long)pitch + ((long)srcx << bpp_shift); + + while (temp_height--) { + GFX_WAIT_PIPELINE; + + /* WRITE ALL DATA TO THE BLT BUFFERS */ + /* The WRITE_SCRATCH_STRING macro assumes that the data begins at the */ + /* scratchpad offset set by the SET_SCRATCH_BASE macro. */ + + WRITE_SCRATCH_STRING(dword_bytes_needed, bytes_extra, data, + array_offset); + WRITE_REG16(GP_BLIT_MODE, BM_READ_SRC_BB0); + + array_offset += pitch; + } + + width -= section; + srcx += section; + dstx += section; + } +} + +/* + *---------------------------------------------------------------------------- + * MONOCHROME BITMAP TO SCREEN BLT + * + * This routine transfers monochrome bitmap data to the screen. + * + * SRCX X offset within source bitmap + * SRCY Y offset within source bitmap + * DSTX screen X position to render data + * DSTY screen Y position to render data + * WIDTH width of rectangle, in pixels + * HEIGHT height of rectangle, in scanlines + * *DATA pointer to bitmap data + * PITCH pitch of bitmap data (bytes between scanlines) + *---------------------------------------------------------------------------- + */ +#if GFX_2DACCEL_DYNAMIC +void +gu1_mono_bitmap_to_screen_blt(unsigned short srcx, unsigned short srcy, + unsigned short dstx, unsigned short dsty, unsigned short width, + unsigned short height, unsigned char *data, short pitch) +#else +void +gfx_mono_bitmap_to_screen_blt(unsigned short srcx, unsigned short srcy, + unsigned short dstx, unsigned short dsty, unsigned short width, + unsigned short height, unsigned char *data, short pitch) +#endif +{ + unsigned short section, buffer_width; + unsigned short blit_mode = BM_READ_SRC_BB0 | BM_SOURCE_EXPAND; + unsigned short temp_height; + unsigned long dword_bytes_needed, bytes_extra; + long array_offset; + + /* CHECK IF RASTER OPERATION REQUIRES DESTINATION DATA */ + /* If no destination data, the source data will always fit. */ + /* So, in that event we will set the buffer width to a */ + /* fictitiously large value such that the BLT is never split. */ + + if (GFXusesDstData) { + buffer_width = GFXbufferWidthPixels; + blit_mode |= BM_READ_DST_FB1; + } else + buffer_width = 3200; + + /* CHECK IF DATA ALREADY IN BLIT BUFFER */ + /* If the pointer is NULL, data for the full BLT is already there */ + /* WARNING: This could cause problems if destination data is */ + /* involved and it overflows the BLT buffer. Need to remove */ + /* this option and change the drivers to use a temporary buffer. */ + + if (!data) { + GFX_WAIT_PENDING; + WRITE_REG16(GP_SRC_XCOOR, srcx & 7); + WRITE_REG16(GP_DST_XCOOR, dstx); + WRITE_REG16(GP_DST_YCOOR, dsty); + WRITE_REG16(GP_WIDTH, width); + WRITE_REG16(GP_HEIGHT, height); + WRITE_REG16(GP_BLIT_MODE, blit_mode); + return; + } + + /* SET THE SCRATCHPAD BASE */ + + SET_SCRATCH_BASE(GFXbb0Base); + + /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */ + /* Write the registers that do not change for each section. */ + + GFX_WAIT_PENDING; + WRITE_REG16(GP_HEIGHT, 1); + + while (width > 0) { + if (width > buffer_width) + section = buffer_width; + else + section = width; + + /* CALCULATE BYTES NEEDED */ + /* Add 1 for possible alignment issues. */ + + dword_bytes_needed = ((section + 7 + (srcx & 7)) >> 3) & ~3l; + bytes_extra = ((section + 7 + (srcx & 7)) >> 3) & 3l; + + temp_height = height; + + /* WRITE THE REGISTERS FOR EACH SECTION */ + /* The GX hardware will auto-increment the Y coordinate, meaning */ + /* that we don't have to. */ + + WRITE_REG16(GP_WIDTH, section); + WRITE_REG16(GP_DST_XCOOR, dstx); + WRITE_REG16(GP_DST_YCOOR, dsty); + WRITE_REG16(GP_SRC_XCOOR, srcx & 7); + + /* CALCULATE THE BITMAP OFFSET */ + + array_offset = (unsigned long)srcy *(long)pitch + ((long)srcx >> 3); + + while (temp_height--) { + GFX_WAIT_PIPELINE; + + /* WRITE ALL DATA TO THE BLT BUFFERS */ + /* The WRITE_SCRATCH_STRING macro assumes that the data begins at the */ + /* scratchpad offset set by the SET_SCRATCH_BASE macro. */ + + WRITE_SCRATCH_STRING(dword_bytes_needed, bytes_extra, data, + array_offset); + WRITE_REG16(GP_BLIT_MODE, blit_mode); + + array_offset += pitch; + } + + width -= section; + srcx += section; + dstx += section; + } +} + +/* + *---------------------------------------------------------------------------- + * MONOCHROME TEXT BLT + * + * This routine transfers contiguous monochrome text data to the screen. + * + * DSTX screen X position to render data + * DSTY screen Y position to render data + * WIDTH width of rectangle, in pixels + * HEIGHT height of rectangle, in scanlines + * *DATA pointer to bitmap data + *---------------------------------------------------------------------------- + */ +#if GFX_2DACCEL_DYNAMIC +void +gu1_text_blt(unsigned short dstx, unsigned short dsty, unsigned short width, + unsigned short height, unsigned char *data) +#else +void +gfx_text_blt(unsigned short dstx, unsigned short dsty, unsigned short width, + unsigned short height, unsigned char *data) +#endif +{ + unsigned long dword_bytes_needed, bytes_extra; + long pitch, buffer_bytes, data_bytes; + + /* CALCULATE DATA SIZE */ + + pitch = (width + 7) >> 3; + data_bytes = (long)height *pitch; + + /* CHECK FOR SIMPLE CASE */ + /* This routine is designed to render a source copy text glyph. If + * destination data is required or the source data will not fit, we will + * punt the operation to the more versatile (and slow) mono bitmap routine + * */ + + if (GFXbpp > 8) + buffer_bytes = GFXbufferWidthPixels << 1; + else + buffer_bytes = GFXbufferWidthPixels; + + if (GFXusesDstData || data_bytes > buffer_bytes) { + gfx_mono_bitmap_to_screen_blt(0, 0, dstx, dsty, width, height, data, + (short)pitch); + return; + } + + /* SET THE SCRATCHPAD BASE */ + + SET_SCRATCH_BASE(GFXbb0Base); + + /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */ + + dword_bytes_needed = data_bytes & ~3l; + bytes_extra = data_bytes & 3l; + + GFX_WAIT_PENDING; + WRITE_REG16(GP_HEIGHT, height); + WRITE_REG16(GP_WIDTH, width); + WRITE_REG16(GP_DST_XCOOR, dstx); + WRITE_REG16(GP_DST_YCOOR, dsty); + WRITE_REG16(GP_SRC_XCOOR, 0); + + /* WRITE ALL DATA TO THE BLT BUFFERS */ + /* The WRITE_SCRATCH_STRING macro assumes that the data begins at the */ + /* scratchpad offset set by the SET_SCRATCH_BASE macro. */ + + GFX_WAIT_PIPELINE; + + WRITE_SCRATCH_STRING(dword_bytes_needed, bytes_extra, data, 0); + WRITE_REG16(GP_BLIT_MODE, BM_READ_SRC_BB0 | BM_SOURCE_TEXT); +} + +/* + *---------------------------------------------------------------------------- + * BRESENHAM LINE + * + * This routine draws a vector using the specified Bresenham parameters. + * Currently this file does not support a routine that accepts the two + * endpoints of a vector and calculates the Bresenham parameters. If it + * ever does, this routine is still required for vectors that have been + * clipped. + * + * X screen X position to start vector + * Y screen Y position to start vector + * LENGTH length of the vector, in pixels + * INITERR Bresenham initial error term + * AXIALERR Bresenham axial error term + * DIAGERR Bresenham diagonal error term + * FLAGS VM_YMAJOR, VM_MAJOR_INC, VM_MINOR_INC + *---------------------------------------------------------------------------- + */ +#if GFX_2DACCEL_DYNAMIC +void +gu1_bresenham_line(unsigned short x, unsigned short y, + unsigned short length, unsigned short initerr, + unsigned short axialerr, unsigned short diagerr, unsigned short flags) +#else +void +gfx_bresenham_line(unsigned short x, unsigned short y, + unsigned short length, unsigned short initerr, + unsigned short axialerr, unsigned short diagerr, unsigned short flags) +#endif +{ + unsigned short vector_mode = flags; + + if (GFXusesDstData) + vector_mode |= VM_READ_DST_FB; + + /* CHECK NULL LENGTH */ + + if (!length) + return; + + /* LOAD THE REGISTERS FOR THE VECTOR */ + + GFX_WAIT_PENDING; + WRITE_REG16(GP_DST_XCOOR, x); + WRITE_REG16(GP_DST_YCOOR, y); + WRITE_REG16(GP_VECTOR_LENGTH, length); + WRITE_REG16(GP_INIT_ERROR, initerr); + WRITE_REG16(GP_AXIAL_ERROR, axialerr); + WRITE_REG16(GP_DIAG_ERROR, diagerr); + WRITE_REG16(GP_VECTOR_MODE, vector_mode); +} + +/*--------------------------------------------------------------------------- + * GFX_WAIT_UNTIL_IDLE + * + * This routine waits until the graphics engine is idle. This is required + * before allowing direct access to the frame buffer. + *--------------------------------------------------------------------------- + */ +#if GFX_2DACCEL_DYNAMIC +void +gu1_wait_until_idle(void) +#else +void +gfx_wait_until_idle(void) +#endif +{ + GFX_WAIT_BUSY; +} + +/*--------------------------------------------------------------------------- + * GFX_TEST_BLT_PENDING + * + * This routine returns 1 if a BLT is pending, meaning that a call to + * perform a rendering operation would stall. Otherwise it returns 0. + * It is used by Darwin during random testing to only start a BLT + * operation when it knows the Durango routines won't spin on graphics + * (so Darwin can continue to do frame buffer reads and writes). + *--------------------------------------------------------------------------- + */ +#if GFX_2DACCEL_DYNAMIC +int +gu1_test_blt_pending(void) +#else +int +gfx_test_blt_pending(void) +#endif +{ + if (READ_REG16(GP_BLIT_STATUS) & BS_BLIT_PENDING) + return (1); + else + return (0); +} + +/*--------------------------------------------------------------------------- + * BLT BUFFERS!!!!! + *--------------------------------------------------------------------------- + */ + +/* THE BOOT CODE MUST SET THE BLT BUFFER BASES USING THE "CPU_WRITE" */ +/* INSTRUCTION TO ONE OF THE FOLLOWING VALUES: */ + +#define BB0_BASE_2K 0x800 +#define BB1_BASE_2K 0xB30 +#define BB0_BASE_3K 0x400 +#define BB1_BASE_3K 0x930 + +/*--------------------------------------------------------------------------- + * gu1_detect_blt_buffer_base + * + * This detection is hidden from the driver by being called from the + * "gfx_set_bpp" routine. + * + * This is fairly ugly for the following reasons: + * + * - It is the boot code that must set the BLT buffer bases to the + * appropriate values and load the scratchpad tags. + * - The old drivers would also set the base address values to what they + * knew they should be for the 2K or 3K scratchpad configuration. + * - Unfortunately, to set the base addresses requires the use of the + * CPU_WRITE instruction, an instruction specific to GX. + * - Using the CPU_WRITE instruction requires the use of assembly to + * produce the appropriate op codes. + * - Assembly is something that is avoided in Durango because it is not + * platform independent. Some compilers do not support inline assembly. + * - Therefore Durango cannot use the CPU_WRITE instruction. + * - Therefore drivers using Durango must rely on the boot code to set + * the appropriate values. Durango uses this routine to check where + * the base addresses have been set. + * - Unfortunately, it is not as simple as using IO to check for 2K or 3K + * scratchpad size. In VSA1, even though the boot code may set it for + * 3K, SoftVGA comes along and resets it to 2K for it's use in text + * redraws. It used to be that the display driver would set it back + * to 3K. + * - So, the Durango code was changed to just always use 2K. + * - But, the XpressROM code sets it for 3K, and the newer versions of + * SoftVGA do not interfere with that, so then Durango needs to use + * the 3K values to work properly. + * - Therefore, Durango does somewhat of a kludge by writing to directly + * to the scratchpad at both the 2K and 3K locations, then performing + * a unobtrusive BLT that loads data into BB0 (the graphics engine + * always knows the true base). After the BLT, Durango looks to see + * which location changed to know where the base address is. + * - This is a relatively simple way to allow Durango to work on old + * and new platforms without using theCPU_WRITE instructions. + * + * To summarize, the BLT buffers are one of the most painful aspects of + * the GX graphics unit design, and have been removed from future designs + * (the graphics unit has its own dedicated RAM). Durango has tried to + * hide the BLT buffer use from the drivers. + *--------------------------------------------------------------------------- + */ +void +gu1_detect_blt_buffer_base(void) +{ + /* ASSUME 2K */ + + GFXbb0Base = BB0_BASE_2K; + GFXbb1Base = BB1_BASE_2K; + + /* CHECK IF SCRATCHPAD IS SET TO 3K OR 4K */ + /* Boot code should still set 3K values for 4K. */ + + if (gfx_gxm_config_read(GXM_CONFIG_GCR) & 0x08) { + /* WRITE DATA TO 3K LOCATION */ + + GFX_WAIT_BUSY; + WRITE_SCRATCH32(BB0_BASE_3K, 0xFEEDFACE); + + /* HAVE THE GRAPHICS UNIT STORE SOMETHING IN BB0 */ + + WRITE_REG32(GP_DST_XCOOR, 0x00000000); /* AT (0,0) */ + WRITE_REG32(GP_WIDTH, 0x00010004); /* 4x1 BLT */ + WRITE_REG16(GP_RASTER_MODE, 0x00AA); /* KEEP DST */ + WRITE_REG16(GP_BLIT_MODE, BM_READ_DST_FB0); /* STORE IN BB0 */ + + /* CHECK 3K LOCATION */ + /* Breaks if data happened to be 0xFEEDFACE - unlikely. */ + + GFX_WAIT_BUSY; + if (READ_SCRATCH32(BB0_BASE_3K) != 0xFEEDFACE) { + GFXbb0Base = BB0_BASE_3K; + GFXbb1Base = BB1_BASE_3K; + } + } +} + +/* END OF FILE */ diff --git a/src/gfx/rndr_gu2.c b/src/gfx/rndr_gu2.c new file mode 100644 index 0000000..31a26e7 --- /dev/null +++ b/src/gfx/rndr_gu2.c @@ -0,0 +1,2180 @@ +/* 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 to program the 2D acceleration hardware for + * the second generation graphics unit. + * + * Basic rendering routines (common to all Geode processors): + * gfx_set_bpp + * gfx_set_solid_pattern + * gfx_set_mono_pattern + * gfx_set_color_pattern + * gfx_set_solid_source + * gfx_set_mono_source + * gfx_set_raster_operation + * gfx_pattern_fill + * gfx_color_pattern_fill + * gfx_screen_to_screen_blt + * gfx_screen_to_screen_xblt + * gfx_color_bitmap_to_screen_blt + * gfx_color_bitmap_to_screen_xblt + * gfx_mono_bitmap_to_screen_blt + * gfx_bresenham_line + * gfx_wait_until_idle + * + * Extended rendering routines for second generation functionality: + * gfx2_set_source_stride + * gfx2_set_destination_stride + * gfx2_set_pattern_origins + * gfx2_set_source_transparency + * gfx2_set_alpha_mode + * gfx2_set_alpha_value + * gfx2_pattern_fill + * gfx2_color_pattern_fill + * gfx2_screen_to_screen_blt + * gfx2_mono_expand_blt + * gfx2_color_bitmap_to_screen_blt + * gfx2_mono_bitmap_to_screen_blt + * gfx2_bresenham_line + * gfx2_sync_to_vblank + * */ + +#define GU2_WAIT_PENDING \ + while(READ_GP32(MGP_BLT_STATUS) & MGP_BS_BLT_PENDING) +#define GU2_WAIT_BUSY \ + while(READ_GP32(MGP_BLT_STATUS) & MGP_BS_BLT_BUSY) +#define GU2_WAIT_HALF_EMPTY \ + while(!(READ_GP32(MGP_BLT_STATUS) & MGP_BS_HALF_EMPTY)) + +/* PATTERN SWIZZLES */ + +#define WORD_SWIZZLE(x) (((x) << 16) | ((x) >> 16)) +#define BYTE_SWIZZLE(x) (((x) << 24) | ((x) >> 24) | (((x) << 8) & \ + 0x00FF0000) | (((x) >> 8) & 0x0000FF00)) + +/* GLOBAL VARIABLES USED BY THE RENDERING ROUTINES */ + +unsigned long gu2_bpp; +unsigned long gu2_pitch = 1280; +unsigned long gu2_src_pitch = 1280; +unsigned long gu2_dst_pitch = 1280; +unsigned long gu2_xshift = 1; +unsigned long gu2_pattern_origin = 0; +unsigned long gu2_rop32; +unsigned long gu2_alpha32 = 0; +unsigned long gu2_alpha_value = 0; +unsigned long gu2_alpha_mode = 0; +unsigned long gu2_alpha_active = 0; +unsigned short gu2_alpha_blt_mode = 0; +unsigned short gu2_alpha_vec_mode = 0; +unsigned short gu2_blt_mode = 0; +unsigned short gu2_vector_mode = 0; +unsigned short gu2_bm_throttle = 0; +unsigned short gu2_vm_throttle = 0; +int gu2_current_line = 0; + +/*--------------------------------------------------------------------------- + * GFX_RESET_PITCH (PRIVATE ROUTINE - NOT PART OF API) + * + * This routine resets all pitches in the graphics engine to one value. + *--------------------------------------------------------------------------- + */ +#if GFX_2DACCEL_DYNAMIC +void +gu2_reset_pitch(unsigned short pitch) +#else +void +gfx_reset_pitch(unsigned short pitch) +#endif +{ + gu2_pitch = pitch; + gu2_dst_pitch = pitch; + gu2_src_pitch = pitch; +} + +/*--------------------------------------------------------------------------- + * GFX_SET_BPP + * + * This routine sets the bits per pixel value in the graphics engine. + * It is also stored in the static variable "gu2_bpp" to use in the future + * calls to the rendering routines. That variable contains the hardware + * specific value to load into the MGP_RASTER_MODE register. + *--------------------------------------------------------------------------- + */ +#if GFX_2DACCEL_DYNAMIC +void +gu2_set_bpp(unsigned short bpp) +#else +void +gfx_set_bpp(unsigned short bpp) +#endif +{ + GFXbpp = bpp; + + /* COVERT TO BPP/FORMAT VALUE */ + /* Save in global to combine with ROP later. */ + /* Could write register here and then use byte access for */ + /* the ROP, but would need to set other 24 bits to make */ + /* sure all are set to their appropriate values. */ + + switch (bpp) { + case 8: + gu2_bpp = MGP_RM_BPPFMT_332; + gu2_xshift = 0; + break; + case 12: + gu2_bpp = MGP_RM_BPPFMT_4444; + gu2_xshift = 1; + break; + case 15: + gu2_bpp = MGP_RM_BPPFMT_1555; + gu2_xshift = 1; + break; + case 16: + gu2_bpp = MGP_RM_BPPFMT_565; + gu2_xshift = 1; + break; + case 32: + gu2_bpp = MGP_RM_BPPFMT_8888; + gu2_xshift = 2; + break; + } + + /* SET INITIAL ROP BASED ONLY ON BPP */ + /* Needs to be set before loading any pattern or source colors. */ + /* We must wait for BUSY because these bits are not pipelined */ + /* in the hardware. */ + + GU2_WAIT_BUSY; + WRITE_GP32(MGP_RASTER_MODE, gu2_bpp); +} + +/* + *--------------------------------------------------------------------------- + * GFX_SET_SOLID_SOURCE + * + * This routine is used to specify a solid source color. For the Xfree96 + * display driver, the source color is used to specify a planemask and the + * ROP is adjusted accordingly. + *--------------------------------------------------------------------------- + */ +#if GFX_2DACCEL_DYNAMIC +void +gu2_set_solid_source(unsigned long color) +#else +void +gfx_set_solid_source(unsigned long color) +#endif +{ + /* CLEAR TRANSPARENCY FLAG */ + + GFXsourceFlags = 0; + + /* WRITE REGISTERS TO SPECIFY SOURCE COLOR */ + + GU2_WAIT_PENDING; + WRITE_GP32(MGP_SRC_COLOR_FG, color); +} + +/* + *--------------------------------------------------------------------------- + * GFX_SET_MONO_SOURCE + * + * This routine is used to specify the monochrome source colors. + * It must be called *after* loading any pattern data (those routines + * clear the source flags). + *--------------------------------------------------------------------------- + */ +#if GFX_2DACCEL_DYNAMIC +void +gu2_set_mono_source(unsigned long bgcolor, unsigned long fgcolor, + unsigned short transparent) +#else +void +gfx_set_mono_source(unsigned long bgcolor, unsigned long fgcolor, + unsigned short transparent) +#endif +{ + /* SET TRANSPARENCY FLAG */ + + GFXsourceFlags = transparent ? MGP_RM_SRC_TRANS : 0; + + /* WRITE COLOR VALUES */ + + GU2_WAIT_PENDING; + WRITE_GP32(MGP_SRC_COLOR_FG, fgcolor); + WRITE_GP32(MGP_SRC_COLOR_BG, bgcolor); +} + +/* + *--------------------------------------------------------------------------- + * GFX_SET_SOLID_PATTERN + * + * This routine is used to specify a solid pattern color. It is called + * before performing solid rectangle fills or more complicated BLTs that + * use a solid pattern color. + * + * The driver should always call "gfx_load_raster_operation" after a call + * to this routine to make sure that the pattern flags are set appropriately. + *--------------------------------------------------------------------------- + */ +#if GFX_2DACCEL_DYNAMIC +void +gu2_set_solid_pattern(unsigned long color) +#else +void +gfx_set_solid_pattern(unsigned long color) +#endif +{ + /* CLEAR TRANSPARENCY FLAG */ + + GFXsourceFlags = 0; + + /* SET PATTERN FLAGS */ + + GFXpatternFlags = 0; + + /* POLL UNTIL ABLE TO WRITE THE PATTERN COLOR */ + + GU2_WAIT_PENDING; + WRITE_GP32(MGP_RASTER_MODE, gu2_bpp); + WRITE_GP32(MGP_PAT_COLOR_0, color); +} + +/* + *--------------------------------------------------------------------------- + * GFX_SET_MONO_PATTERN + * + * This routine is used to specify a monochrome pattern. + *--------------------------------------------------------------------------- + */ +#if GFX_2DACCEL_DYNAMIC +void +gu2_set_mono_pattern(unsigned long bgcolor, unsigned long fgcolor, + unsigned long data0, unsigned long data1, unsigned char transparent) +#else +void +gfx_set_mono_pattern(unsigned long bgcolor, unsigned long fgcolor, + unsigned long data0, unsigned long data1, unsigned char transparent) +#endif +{ + /* CLEAR TRANSPARENCY FLAG */ + + GFXsourceFlags = 0; + + /* SET PATTERN FLAGS */ + + if (transparent) + GFXpatternFlags = MGP_RM_PAT_MONO | MGP_RM_PAT_TRANS; + else + GFXpatternFlags = MGP_RM_PAT_MONO; + + /* POLL UNTIL ABLE TO WRITE THE PATTERN COLOR */ + + GU2_WAIT_PENDING; + WRITE_GP32(MGP_RASTER_MODE, gu2_bpp | GFXpatternFlags); + WRITE_GP32(MGP_PAT_COLOR_0, bgcolor); + WRITE_GP32(MGP_PAT_COLOR_1, fgcolor); + WRITE_GP32(MGP_PAT_DATA_0, data0); + WRITE_GP32(MGP_PAT_DATA_1, data1); +} + +/* + *--------------------------------------------------------------------------- + * GFX_SET_COLOR_PATTERN + * + * This routine is used to specify a color pattern. + *--------------------------------------------------------------------------- + */ +#if GFX_2DACCEL_DYNAMIC +void +gu2_set_color_pattern(unsigned long bgcolor, unsigned long fgcolor, + unsigned long data0, unsigned long data1, unsigned long data2, + unsigned long data3, unsigned char transparent) +#else +void +gfx_set_color_pattern(unsigned long bgcolor, unsigned long fgcolor, + unsigned long data0, unsigned long data1, unsigned long data2, + unsigned long data3, unsigned char transparent) +#endif +{ + /* REMOVE */ +} + +/* + *--------------------------------------------------------------------------- + * GFX_LOAD_COLOR_PATTERN_LINE + * + * This routine is used to load a single line of a 8x8 color pattern. + *--------------------------------------------------------------------------- */ +#if GFX_2DACCEL_DYNAMIC +void +gu2_load_color_pattern_line(short y, unsigned long *pattern_8x8) +#else +void +gfx_load_color_pattern_line(short y, unsigned long *pattern_8x8) +#endif +{ + unsigned long temp1, temp2, temp3, temp4; + + /* CLEAR TRANSPARENCY FLAG */ + + GFXsourceFlags = 0; + + /* SET PATTERN FLAGS */ + + GFXpatternFlags = MGP_RM_PAT_COLOR; + + /* OVERRIDE THE RASTER MODE REGISTER */ + /* If the pattern format is set to anything but color */ + /* before loading the registers, some of the data will */ + /* be duplicated according to the current mode. */ + + GU2_WAIT_PENDING; + WRITE_GP32(MGP_RASTER_MODE, + (gu2_rop32 & ~MGP_RM_PAT_FLAGS) | MGP_RM_PAT_COLOR); + + /* LOAD THE PATTERN DATA */ + /* This routine is designed to work in tandem with gfx_pattern_fill. */ + /* It is used for cases when multiple BLTs with color pattern data */ + /* are desired on the same line. It would be inefficient to */ + /* repeatedly call gfx_color_pattern_fill for each single-line BLT. */ + /* So, we will simply replicate the pattern data across all available */ + /* lines such that the pattern y origin plays no part in the BLT. */ + + /* 8 BPP */ + + if (gu2_xshift == 0) { + pattern_8x8 += (y & 7) << 1; + temp1 = BYTE_SWIZZLE(pattern_8x8[0]); + temp2 = BYTE_SWIZZLE(pattern_8x8[1]); + WRITE_GP32(MGP_PAT_DATA_1, temp1); + WRITE_GP32(MGP_PAT_DATA_0, temp2); + WRITE_GP32(MGP_PAT_COLOR_1, temp1); + WRITE_GP32(MGP_PAT_COLOR_0, temp2); + + GU2_WAIT_BUSY; + WRITE_GP32(MGP_PAT_COLOR_3, temp1); + WRITE_GP32(MGP_PAT_COLOR_2, temp2); + WRITE_GP32(MGP_PAT_COLOR_5, temp1); + WRITE_GP32(MGP_PAT_COLOR_4, temp2); + } else if (gu2_xshift == 1) { + pattern_8x8 += (y & 7) << 2; + temp1 = WORD_SWIZZLE(pattern_8x8[0]); + temp2 = WORD_SWIZZLE(pattern_8x8[1]); + temp3 = WORD_SWIZZLE(pattern_8x8[2]); + temp4 = WORD_SWIZZLE(pattern_8x8[3]); + + WRITE_GP32(MGP_PAT_COLOR_1, temp1); + WRITE_GP32(MGP_PAT_COLOR_0, temp2); + WRITE_GP32(MGP_PAT_DATA_1, temp3); + WRITE_GP32(MGP_PAT_DATA_0, temp4); + + GU2_WAIT_BUSY; + WRITE_GP32(MGP_PAT_COLOR_5, temp1); + WRITE_GP32(MGP_PAT_COLOR_4, temp2); + WRITE_GP32(MGP_PAT_COLOR_3, temp3); + WRITE_GP32(MGP_PAT_COLOR_2, temp4); + } else { + pattern_8x8 += (y & 7) << 3; + + WRITE_GP32(MGP_PAT_COLOR_1, pattern_8x8[4]); + WRITE_GP32(MGP_PAT_COLOR_0, pattern_8x8[5]); + WRITE_GP32(MGP_PAT_DATA_1, pattern_8x8[6]); + WRITE_GP32(MGP_PAT_DATA_0, pattern_8x8[7]); + + GU2_WAIT_BUSY; + WRITE_GP32(MGP_PAT_COLOR_5, pattern_8x8[0]); + WRITE_GP32(MGP_PAT_COLOR_4, pattern_8x8[1]); + WRITE_GP32(MGP_PAT_COLOR_3, pattern_8x8[2]); + WRITE_GP32(MGP_PAT_COLOR_2, pattern_8x8[3]); + } +} + +/* + *--------------------------------------------------------------------------- + * GFX_SET_RASTER_OPERATION + * + * This routine loads the specified raster operation. It sets the pattern + * flags appropriately. + *--------------------------------------------------------------------------- + */ +#if GFX_2DACCEL_DYNAMIC +void +gu2_set_raster_operation(unsigned char rop) +#else +void +gfx_set_raster_operation(unsigned char rop) +#endif +{ + gu2_blt_mode = 0; + + /* DISABLE ALPHA BLENDING */ + + gu2_alpha_active = 0; + + /* GENERATE 32-BIT VERSION OF ROP WITH PATTERN FLAGS */ + + gu2_rop32 = (unsigned long)rop | GFXpatternFlags | gu2_bpp; + + /* CHECK IF SOURCE FLAGS SHOULD BE MERGED */ + + if ((rop & 0x33) ^ ((rop >> 2) & 0x33)) + gu2_rop32 |= GFXsourceFlags; + else + gu2_blt_mode = 0x40; + + /* SET FLAG INDICATING ROP REQUIRES DESTINATION DATA */ + /* True if even bits (0:2:4:6) do not equal the corresponding */ + /* even bits (1:3:5:7). */ + + if ((rop & 0x55) ^ ((rop >> 1) & 0x55)) { + gu2_blt_mode |= MGP_BM_DST_REQ; + gu2_vector_mode = MGP_VM_DST_REQ; + } else { + gu2_vector_mode = 0; + } +} + +/* + *---------------------------------------------------------------------------- + * GFX_PATTERN_FILL + * + * This routine is used to fill a rectangular region. The pattern must + * be previously loaded using one of GFX_load_*_pattern routines. Also, the + * raster operation must be previously specified using the + * "GFX_load_raster_operation" routine. + * + * X screen X position (left) + * Y screen Y position (top) + * WIDTH width of rectangle, in pixels + * HEIGHT height of rectangle, in scanlines + *---------------------------------------------------------------------------- + */ +#if GFX_2DACCEL_DYNAMIC +void +gu2_pattern_fill(unsigned short x, unsigned short y, + unsigned short width, unsigned short height) +#else +void +gfx_pattern_fill(unsigned short x, unsigned short y, + unsigned short width, unsigned short height) +#endif +{ + unsigned long offset = 0, size; + + size = (((unsigned long)width) << 16) | height; + + /* CALCULATE STARTING OFFSET */ + + offset = (unsigned long)y *gu2_pitch + (((unsigned long)x) << gu2_xshift); + + /* CHECK IF PATTERN ORIGINS NEED TO BE SET */ + + if (GFXpatternFlags) { + /* COMBINE X AND Y PATTERN ORIGINS WITH OFFSET */ + + offset |= ((unsigned long)(x & 7)) << 26; + offset |= ((unsigned long)(y & 7)) << 29; + } + + /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */ + /* Put off poll for as long as possible (do most calculations first). */ + + GU2_WAIT_PENDING; + WRITE_GP32(MGP_RASTER_MODE, gu2_rop32); + WRITE_GP32(MGP_DST_OFFSET, offset); + WRITE_GP32(MGP_WID_HEIGHT, size); + WRITE_GP32(MGP_STRIDE, gu2_pitch); + WRITE_GP32(MGP_BLT_MODE, gu2_blt_mode); +} + +/* + *---------------------------------------------------------------------------- + * GFX_COLOR_PATTERN_FILL + * + * This routine is used to render a rectangle using the current raster + * operation and the specified color pattern. It allows an 8x8 color + * pattern to be rendered without multiple calls to the gfx_set_color_pattern + * and gfx_pattern_fill routines. + * + * X screen X position (left) + * Y screen Y position (top) + * WIDTH width of rectangle, in pixels + * HEIGHT height of rectangle, in scanlines + * *PATTERN pointer to 8x8 color pattern data + *---------------------------------------------------------------------------- + */ +#if GFX_2DACCEL_DYNAMIC +void +gu2_color_pattern_fill(unsigned short x, unsigned short y, + unsigned short width, unsigned short height, unsigned long *pattern) +#else +void +gfx_color_pattern_fill(unsigned short x, unsigned short y, + unsigned short width, unsigned short height, unsigned long *pattern) +#endif +{ + /* CALL GFX2 ROUTINE TO AVOID DUPLICATION OF CODE */ + + unsigned long offset = (unsigned long)y * gu2_pitch + + (((unsigned long)x) << gu2_xshift); + unsigned long origin = gu2_pattern_origin; + unsigned long pitch = gu2_dst_pitch; + + gfx2_set_pattern_origin(x, y); + gfx2_set_destination_stride((unsigned short)gu2_pitch); + gfx2_color_pattern_fill(offset, width, height, pattern); + + /* RESTORE GFX2 VALUES */ + + gu2_pattern_origin = origin; + gu2_dst_pitch = pitch; +} + +/* + *---------------------------------------------------------------------------- + * SCREEN TO SCREEN BLT + * + * This routine should be used to perform a screen to screen BLT when the + * ROP does not require destination data. + * + * SRCX screen X position to copy from + * SRCY screen Y position to copy from + * DSTX screen X position to copy to + * DSTY screen Y position to copy to + * WIDTH width of rectangle, in pixels + * HEIGHT height of rectangle, in scanlines + *---------------------------------------------------------------------------- + */ +#if GFX_2DACCEL_DYNAMIC +void +gu2_screen_to_screen_blt(unsigned short srcx, unsigned short srcy, + unsigned short dstx, unsigned short dsty, unsigned short width, + unsigned short height) +#else +void +gfx_screen_to_screen_blt(unsigned short srcx, unsigned short srcy, + unsigned short dstx, unsigned short dsty, unsigned short width, + unsigned short height) +#endif +{ + unsigned long srcoffset, dstoffset, size; + unsigned short blt_mode; + + size = (((unsigned long)width) << 16) | height; + + /* CALCULATE THE DIRECTION OF THE BLT */ + + blt_mode = (gu2_blt_mode & ~MGP_BM_SRC_TYPE_MASK) | MGP_BM_SRC_FB; + if (dstx > srcx) { + blt_mode |= MGP_BM_NEG_XDIR; + srcx += width - 1; + dstx += width - 1; + } + if (dsty > srcy) { + blt_mode |= MGP_BM_NEG_YDIR; + srcy += height - 1; + dsty += height - 1; + } + + /* CALCULATE STARTING OFFSETS */ + + srcoffset = (unsigned long)srcy *gu2_pitch + + (((unsigned long)srcx) << gu2_xshift); + dstoffset = ((unsigned long)dsty * gu2_pitch + + (((unsigned long)dstx) << gu2_xshift)) & 0xFFFFFF; + + /* MERGE PATTERN INFORMATION */ + /* This must be done after the x and y coordinates have been updated, */ + /* as the x and y pattern origins correspond to the first ROPed pixel. */ + + if (GFXpatternFlags) { + /* COMBINE X AND Y PATTERN ORIGINS WITH OFFSET */ + + dstoffset |= ((unsigned long)(dstx & 7)) << 26; + dstoffset |= ((unsigned long)(dsty & 7)) << 29; + } + + /* TURN INTO BYTE ADDRESS IF NEGATIVE X DIRECTION */ + /* This is a quirk of the hardware. */ + + if (blt_mode & MGP_BM_NEG_XDIR) { + srcoffset += (1 << gu2_xshift) - 1; + dstoffset += (1 << gu2_xshift) - 1; + } + + /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */ + /* Put off poll for as long as possible (do most calculations first). */ + + GU2_WAIT_PENDING; + WRITE_GP32(MGP_RASTER_MODE, gu2_rop32 | GFXsourceFlags); + WRITE_GP32(MGP_SRC_OFFSET, srcoffset); + WRITE_GP32(MGP_DST_OFFSET, dstoffset); + WRITE_GP32(MGP_WID_HEIGHT, size); + WRITE_GP32(MGP_STRIDE, gu2_pitch | (gu2_pitch << 16)); + WRITE_GP16(MGP_BLT_MODE, blt_mode); +} + +/* + *---------------------------------------------------------------------------- + * SCREEN TO SCREEN TRANSPARENT BLT + * + * This routine should be used to perform a screen to screen BLT when a + * specified color should by transparent. The only supported ROP is SRCCOPY. + * + * SRCX screen X position to copy from + * SRCY screen Y position to copy from + * DSTX screen X position to copy to + * DSTY screen Y position to copy to + * WIDTH width of rectangle, in pixels + * HEIGHT height of rectangle, in scanlines + * COLOR transparent color + *---------------------------------------------------------------------------- + */ +#if GFX_2DACCEL_DYNAMIC +void +gu2_screen_to_screen_xblt(unsigned short srcx, unsigned short srcy, + unsigned short dstx, unsigned short dsty, unsigned short width, + unsigned short height, unsigned long color) +#else +void +gfx_screen_to_screen_xblt(unsigned short srcx, unsigned short srcy, + unsigned short dstx, unsigned short dsty, unsigned short width, + unsigned short height, unsigned long color) +#endif +{ + unsigned long rop32; + + /* SAVE ORIGINAL RASTER MODE SETTINGS */ + + rop32 = gu2_rop32; + + /* WRITE REGISTERS TO SPECIFY COLOR TRANSPARENCY */ + /* Match GU1 implementation that only allows SRCCOPY for the ROP. */ + + GU2_WAIT_PENDING; + WRITE_GP32(MGP_SRC_COLOR_FG, color); + WRITE_GP32(MGP_SRC_COLOR_BG, 0xFFFFFFFF); + + /* SET GLOBAL RASTER SETTINGS */ + /* This is needed, as the screen-to-screen BLT */ + /* routine will overwrite the raster mode register. */ + + gu2_rop32 = gu2_bpp | MGP_RM_SRC_TRANS | 0xCC; + + /* CALL NORMAL SCREEN TO SCREEN BLT ROUTINE */ + + gfx_screen_to_screen_blt(srcx, srcy, dstx, dsty, width, height); + + /* RESTORE GLOBAL RASTER SETTINGS */ + + gu2_rop32 = rop32; +} + +/* + *---------------------------------------------------------------------------- + * COLOR BITMAP TO SCREEN BLT + * + * This routine transfers color bitmap data to the screen. + * + * SRCX X offset within source bitmap + * SRCY Y offset within source bitmap + * DSTX screen X position to render data + * DSTY screen Y position to render data + * WIDTH width of rectangle, in pixels + * HEIGHT height of rectangle, in scanlines + * *DATA pointer to bitmap data + * PITCH pitch of bitmap data (bytes between scanlines) + * + * Transparency is handled by another routine. + *---------------------------------------------------------------------------- + */ + +#if GFX_2DACCEL_DYNAMIC +void +gu2_color_bitmap_to_screen_blt(unsigned short srcx, unsigned short srcy, + unsigned short dstx, unsigned short dsty, unsigned short width, + unsigned short height, unsigned char *data, long pitch) +#else +void +gfx_color_bitmap_to_screen_blt(unsigned short srcx, unsigned short srcy, + unsigned short dstx, unsigned short dsty, unsigned short width, + unsigned short height, unsigned char *data, long pitch) +#endif +{ + unsigned long dstoffset, srcoffset, size, bytes; + unsigned long offset, temp_offset; + unsigned long dword_bytes, bytes_extra; + unsigned short blt_mode; + + blt_mode = (gu2_blt_mode & ~MGP_BM_SRC_TYPE_MASK) | MGP_BM_SRC_FB; + size = (((unsigned long)width) << 16) | 1; + + /* CALCULATE STARTING OFFSETS */ + + offset = (unsigned long)srcy *pitch + ((unsigned long)srcx << gu2_xshift); + + dstoffset = (unsigned long)dsty *gu2_pitch + + (((unsigned long)dstx) << gu2_xshift); + + /* CHECK IF PATTERN ORIGINS NEED TO BE SET */ + + if (GFXpatternFlags) { + /* COMBINE X AND Y PATTERN ORIGINS WITH OFFSET */ + + dstoffset |= ((unsigned long)(dstx & 7)) << 26; + dstoffset |= ((unsigned long)(dsty & 7)) << 29; + } + + bytes = width << gu2_xshift; + dword_bytes = bytes & ~0x3L; + bytes_extra = bytes & 0x3L; + + /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */ + /* Put off poll for as long as possible (do most calculations first). */ + /* The source offset is always 0 since we allow misaligned dword reads. */ + /* We must wait for BLT busy because the GP may be executing a screen */ + /* to screen BLT from the scratchpad area. */ + + GU2_WAIT_BUSY; + WRITE_GP32(MGP_RASTER_MODE, gu2_rop32 | GFXsourceFlags); + WRITE_GP32(MGP_WID_HEIGHT, size); + WRITE_GP32(MGP_STRIDE, gu2_pitch); + + /* WRITE DATA ONE LINE AT A TIME */ + /* For speed reasons, data is written to an offscreen scratch area and then */ + /* BLTed using a screen to screen BLT. This is similar to the GX1 BLT buffers, but */ + /* slightly more efficient in that we can queue up data while the GP is rendering */ + /* a line. */ + + while (height--) { + temp_offset = offset; + srcoffset = gfx_gx2_scratch_base; + if (gu2_current_line) + srcoffset += 8192; + + GU2_WAIT_PENDING; + WRITE_GP32(MGP_SRC_OFFSET, srcoffset); + WRITE_GP32(MGP_DST_OFFSET, dstoffset); + dstoffset += gu2_pitch; + dstoffset += 0x20000000; + + WRITE_FRAME_BUFFER_STRING32(srcoffset, dword_bytes, data, + temp_offset); + if (bytes_extra) { + temp_offset += dword_bytes; + srcoffset += dword_bytes; + WRITE_FRAME_BUFFER_STRING8(srcoffset, bytes_extra, data, + temp_offset); + } + WRITE_GP16(MGP_BLT_MODE, blt_mode); + offset += pitch; + gu2_current_line = 1 - gu2_current_line; + } +} + +/* + *---------------------------------------------------------------------------- + * COLOR BITMAP TO SCREEN TRANSPARENT BLT + * + * This routine transfers color bitmap data to the screen with transparency. + * The transparent color is specified. The only supported ROP is SRCCOPY, + * meaning that transparency cannot be applied if the ROP requires + * destination data (this is a hardware restriction). + * + * SRCX X offset within source bitmap + * SRCY Y offset within source bitmap + * DSTX screen X position to render data + * DSTY screen Y position to render data + * WIDTH width of rectangle, in pixels + * HEIGHT height of rectangle, in scanlines + * *DATA pointer to bitmap data + * PITCH pitch of bitmap data (bytes between scanlines) + * COLOR transparent color + *---------------------------------------------------------------------------- + */ +#if GFX_2DACCEL_DYNAMIC +void +gu2_color_bitmap_to_screen_xblt(unsigned short srcx, unsigned short srcy, + unsigned short dstx, unsigned short dsty, unsigned short width, + unsigned short height, unsigned char *data, long pitch, + unsigned long color) +#else +void +gfx_color_bitmap_to_screen_xblt(unsigned short srcx, unsigned short srcy, + unsigned short dstx, unsigned short dsty, unsigned short width, + unsigned short height, unsigned char *data, long pitch, + unsigned long color) +#endif +{ + unsigned long rop32; + + /* SAVE EXISTING RASTER MODE SETTINGS */ + + rop32 = gu2_rop32; + + /* WRITE REGISTERS TO SPECIFY COLOR TRANSPARENCY */ + /* Match GU1 implementation that only allows SRCCOPY for the ROP. */ + + GU2_WAIT_PENDING; + WRITE_GP32(MGP_SRC_COLOR_FG, color); + WRITE_GP32(MGP_SRC_COLOR_BG, 0xFFFFFFFF); + + /* SET GLOBAL RASTER SETTINGS */ + /* This is needed, as the screen-to-screen BLT */ + /* routine will overwrite the raster mode register. */ + + gu2_rop32 = gu2_bpp | MGP_RM_SRC_TRANS | 0xCC; + + /* CALL NORMAL COLOR BITMAP TO SCREEN BLT ROUTINE */ + + gfx_color_bitmap_to_screen_blt(srcx, srcy, dstx, dsty, width, height, + data, pitch); + + /* RESTORE RASTER SETTINGS */ + + gu2_rop32 = rop32; +} + +/* + *---------------------------------------------------------------------------- + * MONOCHROME BITMAP TO SCREEN BLT + * + * This routine transfers monochrome bitmap data to the screen. + * + * SRCX X offset within source bitmap + * SRCY Y offset within source bitmap + * DSTX screen X position to render data + * DSTY screen Y position to render data + * WIDTH width of rectangle, in pixels + * HEIGHT height of rectangle, in scanlines + * *DATA pointer to bitmap data + * PITCH pitch of bitmap data (bytes between scanlines) + *---------------------------------------------------------------------------- + */ +#if GFX_2DACCEL_DYNAMIC +void +gu2_mono_bitmap_to_screen_blt(unsigned short srcx, unsigned short srcy, + unsigned short dstx, unsigned short dsty, unsigned short width, + unsigned short height, unsigned char *data, short pitch) +#else +void +gfx_mono_bitmap_to_screen_blt(unsigned short srcx, unsigned short srcy, + unsigned short dstx, unsigned short dsty, unsigned short width, + unsigned short height, unsigned char *data, short pitch) +#endif +{ + unsigned long dstoffset, size, bytes; + unsigned long offset, temp_offset, temp1 = 0, temp2 = 0; + unsigned long i, j = 0, fifo_lines, dwords_extra, bytes_extra; + unsigned long shift = 0; + + size = (((unsigned long)width) << 16) | height; + + /* CALCULATE STARTING OFFSETS */ + + offset = (unsigned long)srcy *pitch + ((unsigned long)srcx >> 3); + + dstoffset = (unsigned long)dsty *gu2_pitch + + (((unsigned long)dstx) << gu2_xshift); + + /* CHECK IF PATTERN ORIGINS NEED TO BE SET */ + + if (GFXpatternFlags) { + /* COMBINE X AND Y PATTERN ORIGINS WITH OFFSET */ + + dstoffset |= ((unsigned long)(dstx & 7)) << 26; + dstoffset |= ((unsigned long)(dsty & 7)) << 29; + } + + bytes = ((srcx & 7) + width + 7) >> 3; + fifo_lines = bytes >> 5; + dwords_extra = (bytes & 0x0000001Cl) >> 2; + bytes_extra = bytes & 0x00000003l; + + /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */ + /* Put off poll for as long as possible (do most calculations first). */ + /* The source offset is always 0 since we allow misaligned dword reads. */ + /* Need to wait for busy instead of pending, since hardware clears */ + /* the host data FIFO at the beginning of a BLT. */ + + GU2_WAIT_PENDING; + WRITE_GP32(MGP_RASTER_MODE, gu2_rop32 | GFXsourceFlags); + WRITE_GP32(MGP_SRC_OFFSET, ((unsigned long)srcx & 7) << 26); + WRITE_GP32(MGP_DST_OFFSET, dstoffset); + WRITE_GP32(MGP_WID_HEIGHT, size); + WRITE_GP32(MGP_STRIDE, gu2_pitch); + WRITE_GP16(MGP_BLT_MODE, + (gu2_blt_mode & ~MGP_BM_SRC_TYPE_MASK) | MGP_BM_SRC_HOST | + MGP_BM_SRC_MONO); + + /* WAIT FOR BLT TO BE LATCHED */ + + GU2_WAIT_PENDING; + + /* WRITE ALL OF THE DATA TO THE HOST SOURCE REGISTER */ + + while (height--) { + temp_offset = offset; + + /* WRITE ALL FULL FIFO LINES */ + + for (i = 0; i < fifo_lines; i++) { + GU2_WAIT_HALF_EMPTY; + WRITE_GPREG_STRING32(MGP_HST_SOURCE, 8, j, data, temp_offset, + temp1); + temp_offset += 32; + } + + /* WRITE ALL FULL DWORDS */ + + GU2_WAIT_HALF_EMPTY; + if (dwords_extra) { + WRITE_GPREG_STRING32(MGP_HST_SOURCE, dwords_extra, i, data, + temp_offset, temp1); + temp_offset += (dwords_extra << 2); + } + + /* WRITE REMAINING BYTES */ + + shift = 0; + if (bytes_extra) + WRITE_GPREG_STRING8(MGP_HST_SOURCE, bytes_extra, shift, i, data, + temp_offset, temp1, temp2); + + offset += pitch; + } +} + +/*--------------------------------------------------------------------------- + * GFX_TEXT_BLT + * + * This routine is similar to the gfx_mono_bitmap_to_screen_blt routine + * but assumes that source data is byte-packed. + *--------------------------------------------------------------------------- + */ +#if GFX_2DACCEL_DYNAMIC +void +gu2_text_blt(unsigned short dstx, unsigned short dsty, unsigned short width, + unsigned short height, unsigned char *data) +#else +void +gfx_text_blt(unsigned short dstx, unsigned short dsty, unsigned short width, + unsigned short height, unsigned char *data) +#endif +{ + unsigned long size, bytes; + unsigned long dstoffset, temp1 = 0, temp2 = 0, temp_offset = 0; + unsigned long i, j = 0, fifo_lines, dwords_extra, bytes_extra; + unsigned long shift; + + size = (((unsigned long)width) << 16) | height; + + dstoffset = (unsigned long)dsty *gu2_pitch + + (((unsigned long)dstx) << gu2_xshift); + + /* CHECK IF PATTERN ORIGINS NEED TO BE SET */ + + if (GFXpatternFlags) { + /* COMBINE X AND Y PATTERN ORIGINS WITH OFFSET */ + + dstoffset |= ((unsigned long)(dstx & 7)) << 26; + dstoffset |= ((unsigned long)(dsty & 7)) << 29; + } + + /* CALCULATE STARTING OFFSETS */ + + bytes = ((width + 7) >> 3) * height; + fifo_lines = bytes >> 5; + dwords_extra = (bytes & 0x0000001Cl) >> 2; + bytes_extra = bytes & 0x00000003l; + + /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */ + + GU2_WAIT_PENDING; + WRITE_GP32(MGP_RASTER_MODE, gu2_rop32 | GFXsourceFlags); + WRITE_GP32(MGP_SRC_OFFSET, 0); + WRITE_GP32(MGP_DST_OFFSET, dstoffset); + WRITE_GP32(MGP_WID_HEIGHT, size); + WRITE_GP32(MGP_STRIDE, gu2_pitch); + WRITE_GP16(MGP_BLT_MODE, + (gu2_blt_mode & ~MGP_BM_SRC_TYPE_MASK) | MGP_BM_SRC_HOST | + MGP_BM_SRC_BP_MONO); + + /* WAIT FOR BLT TO BE LATCHED */ + + GU2_WAIT_PENDING; + + /* WRITE ALL FULL FIFO LINES */ + + for (i = 0; i < fifo_lines; i++) { + GU2_WAIT_HALF_EMPTY; + WRITE_GPREG_STRING32(MGP_HST_SOURCE, 8, j, data, temp_offset, temp1); + temp_offset += 32; + } + + /* WRITE ALL FULL DWORDS */ + + if (dwords_extra || bytes_extra) { + GU2_WAIT_HALF_EMPTY; + if (dwords_extra) { + WRITE_GPREG_STRING32(MGP_HST_SOURCE, dwords_extra, i, data, + temp_offset, temp1); + temp_offset += (dwords_extra << 2); + } + if (bytes_extra) { + shift = 0; + WRITE_GPREG_STRING8(MGP_HST_SOURCE, bytes_extra, shift, i, data, + temp_offset, temp1, temp2); + } + } +} + +/* + *---------------------------------------------------------------------------- + * BRESENHAM LINE + * + * This routine draws a vector using the specified Bresenham parameters. + * Currently this file does not support a routine that accepts the two + * endpoints of a vector and calculates the Bresenham parameters. If it + * ever does, this routine is still required for vectors that have been + * clipped. + * + * X screen X position to start vector + * Y screen Y position to start vector + * LENGTH length of the vector, in pixels + * INITERR Bresenham initial error term + * AXIALERR Bresenham axial error term + * DIAGERR Bresenham diagonal error term + * FLAGS VM_YMAJOR, VM_MAJOR_INC, VM_MINOR_INC + *---------------------------------------------------------------------------- + */ +#if GFX_2DACCEL_DYNAMIC +void +gu2_bresenham_line(unsigned short x, unsigned short y, + unsigned short length, unsigned short initerr, + unsigned short axialerr, unsigned short diagerr, unsigned short flags) +#else +void +gfx_bresenham_line(unsigned short x, unsigned short y, + unsigned short length, unsigned short initerr, + unsigned short axialerr, unsigned short diagerr, unsigned short flags) +#endif +{ + unsigned long offset; + unsigned long data1 = (((unsigned long)axialerr) << 16) | diagerr; + unsigned long data2 = (((unsigned long)length) << 16) | initerr; + unsigned short vector_mode = gu2_vector_mode | flags; + + /* CALCULATE STARTING OFFSET */ + + offset = (unsigned long)y *gu2_pitch + (((unsigned long)x) << gu2_xshift); + + /* CHECK NULL LENGTH */ + + if (!length) + return; + + /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */ + /* Put off poll for as long as possible (do most calculations first). */ + + GU2_WAIT_PENDING; + WRITE_GP32(MGP_RASTER_MODE, gu2_rop32); + WRITE_GP32(MGP_DST_OFFSET, offset); + WRITE_GP32(MGP_VEC_ERR, data1); + WRITE_GP32(MGP_VEC_LEN, data2); + WRITE_GP32(MGP_STRIDE, gu2_pitch); + WRITE_GP32(MGP_VECTOR_MODE, vector_mode); +} + +/*--------------------------------------------------------------------------- + * GFX_WAIT_UNTIL_IDLE + * + * This routine waits until the graphics engine is idle. This is required + * before allowing direct access to the frame buffer. + *--------------------------------------------------------------------------- + */ +#if GFX_2DACCEL_DYNAMIC +void +gu2_wait_until_idle(void) +#else +void +gfx_wait_until_idle(void) +#endif +{ + while (READ_GP32(MGP_BLT_STATUS) & MGP_BS_BLT_BUSY) ; +} + +/*--------------------------------------------------------------------------- + * GFX_TEST_BLT_PENDING + * + * This routine returns 1 if a BLT is pending, meaning that a call to + * perform a rendering operation would stall. Otherwise it returns 0. + * It is used by Darwin during random testing to only start a BLT + * operation when it knows the Durango routines won't spin on graphics + * (so Darwin can continue to do frame buffer reads and writes). + *--------------------------------------------------------------------------- + */ +#if GFX_2DACCEL_DYNAMIC +int +gu2_test_blt_pending(void) +#else +int +gfx_test_blt_pending(void) +#endif +{ + if (READ_GP32(MGP_BLT_STATUS) & MGP_BS_BLT_PENDING) + return (1); + return (0); +} + +/*--------------------------------------------------------------------------- + * NEW ROUTINES FOR REDCLOUD + *--------------------------------------------------------------------------- + */ + +/*--------------------------------------------------------------------------- + * GFX2_SET_SOURCE_STRIDE + * + * This routine sets the stride to be used in successive screen to screen + * BLTs (used by gfx2_screen_to_screen_blt and gfx2_mono_expand_blt). + *--------------------------------------------------------------------------- + */ +#if GFX_2DACCEL_DYNAMIC +void +gu22_set_source_stride(unsigned short stride) +#else +void +gfx2_set_source_stride(unsigned short stride) +#endif +{ + /* SAVE STRIDE TO BE USED LATER */ + + gu2_src_pitch = (unsigned long)stride; +} + +/*--------------------------------------------------------------------------- + * GFX2_SET_DESTINATION_STRIDE + * + * This routine sets the stride used when rendering to the screen. + *--------------------------------------------------------------------------- + */ +#if GFX_2DACCEL_DYNAMIC +void +gu22_set_destination_stride(unsigned short stride) +#else +void +gfx2_set_destination_stride(unsigned short stride) +#endif +{ + /* SAVE STRIDE TO BE USED LATER */ + + gu2_dst_pitch = (unsigned long)stride; +} + +/*--------------------------------------------------------------------------- + * GFX2_SET_PATTERN_ORIGIN + * + * This routine sets the origin within an 8x8 pattern. It is needed if + * using a monochrome or color pattern (not used for a solid pattern). + *--------------------------------------------------------------------------- + */ +#if GFX_2DACCEL_DYNAMIC +void +gu22_set_pattern_origin(int x, int y) +#else +void +gfx2_set_pattern_origin(int x, int y) +#endif +{ + /* STORE IN FORMAT THAT CAN BE COMBINED WITH THE DESTINATION OFFSET */ + + gu2_pattern_origin = (((unsigned long)(x & 7)) << 26) | + (((unsigned long)(y & 7)) << 29); +} + +/*--------------------------------------------------------------------------- + * GFX2_SET_SOURCE_TRANSPARENCY + * + * This routine sets the source transparency color and mask to be used + * in future rendering operations. If both the color and mask are set + * to zero (normally completely transparent), those values indicate that + * transparency should be disabled. + *--------------------------------------------------------------------------- + */ +#if GFX_2DACCEL_DYNAMIC +void +gu22_set_source_transparency(unsigned long color, unsigned long mask) +#else +void +gfx2_set_source_transparency(unsigned long color, unsigned long mask) +#endif +{ + /* WRITE REGISTERS TO SPECIFY COLOR TRANSPARENCY */ + + GU2_WAIT_PENDING; + WRITE_GP32(MGP_SRC_COLOR_FG, color); + WRITE_GP32(MGP_SRC_COLOR_BG, mask); + + /* SET TRANSPARENCY FLAG */ + + GFXsourceFlags = (color || mask) ? MGP_RM_SRC_TRANS : 0; +} + +/*--------------------------------------------------------------------------- + * GFX2_SET_ALPHA_MODE + * + * This routine sets the alpha blending mode to be used in successive + * rendering operations. + *--------------------------------------------------------------------------- + */ +#if GFX_2DACCEL_DYNAMIC +void +gu22_set_alpha_mode(int mode) +#else +void +gfx2_set_alpha_mode(int mode) +#endif +{ + /* SAVE ALPHA MODE FOR LATER */ + + gu2_alpha_mode = mode; +} + +/*--------------------------------------------------------------------------- + * GFX2_SET_ALPHA_VALUE + * + * This routine sets the alpha value to be used with certain alpha blending + * modes (ALPHA_MODE_BLEND). + *--------------------------------------------------------------------------- + */ +#if GFX_2DACCEL_DYNAMIC +void +gu22_set_alpha_value(unsigned char value) +#else +void +gfx2_set_alpha_value(unsigned char value) +#endif +{ + /* SAVE ALPHA VALUE TO BE USED LATER */ + + gu2_alpha_value = (unsigned long)value; + + /* SET GLOBAL FLAG */ + /* gfx2_* routines will use this flag to program alpha values */ + /* appropriately. Normal gfx_* routines will always write */ + /* the current ROP settings. In this way, the alpha mode */ + /* affects only second generation routines. */ + + gu2_alpha_active = 1; + + switch (gu2_alpha_mode) { + case ALPHA_MODE_BLEND: + + /* GENERATE 32-BIT VERSION OF RASTER MODE REGISTER */ + /* Pattern data is not involved in the operation. */ + + gu2_alpha32 = gu2_alpha_value | gu2_bpp; + + /* HANDLE SPECIAL CASES FOR ENDPOINTS */ + /* The 8-bit hardware alpha value is always */ + /* interpreted as a fraction. Consequently, there */ + /* is no way to use values of 255 or 0 to exclude */ + /* one of the inputs. */ + + switch (gu2_alpha_value) { + /* DESTINATION ONLY */ + /* Operation is alpha * A, where A is destination */ + /* and alpha is 1. */ + + case 0: + + gu2_alpha32 |= MGP_RM_SELECT_ALPHA_1 | + MGP_RM_ALPHA_TIMES_A | + MGP_RM_ALPHA_TO_RGB | MGP_RM_DEST_FROM_CHAN_A; + break; + + /* SOURCE ONLY */ + /* Operation is alpha * A, where A is source and */ + /* alpha is 1. */ + + case 255: + + gu2_alpha32 |= MGP_RM_SELECT_ALPHA_1 | + MGP_RM_ALPHA_TO_RGB | MGP_RM_ALPHA_TIMES_A; + break; + + /* DEFAULT */ + /* Operation is alpha * A + (1 - alpha) * B; */ + /* A is source, B is destination and alpha is the */ + /* programmed 8-bit value. */ + + default: + + gu2_alpha32 |= MGP_RM_SELECT_ALPHA_R | + MGP_RM_ALPHA_TO_RGB | MGP_RM_ALPHA_A_PLUS_BETA_B; + + } + + /* CHECK IF SOURCE INFORMATION SHOULD BE MERGED */ + /* Alpha value of 0 indicates destination only. */ + + if (gu2_alpha_value != 0) + gu2_alpha32 |= GFXsourceFlags; + + /* SET FLAG FOR DESTINATION DATA IF NECESSARY */ + /* Alpha value of 255 indicates no destination */ + + if (gu2_alpha_value != 255) { + gu2_alpha_blt_mode = MGP_BM_DST_REQ; + gu2_alpha_vec_mode = MGP_VM_DST_REQ; + } + + break; + } +} + +/*--------------------------------------------------------------------------- + * GFX2_PATTERN_FILL + * + * This routine is similar to the gfx_pattern_fill routine, but allows the + * use of an arbitrary destination stride. The rendering position is + * also specified as an offset instead of an (x,y) position. + *--------------------------------------------------------------------------- + */ +#if GFX_2DACCEL_DYNAMIC +void +gu22_pattern_fill(unsigned long dstoffset, unsigned short width, + unsigned short height) +#else +void +gfx2_pattern_fill(unsigned long dstoffset, unsigned short width, + unsigned short height) +#endif +{ + unsigned long size; + + size = (((unsigned long)width) << 16) | height; + + /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */ + /* Put off poll for as long as possible (do most calculations first). */ + + GU2_WAIT_PENDING; + WRITE_GP32(MGP_RASTER_MODE, gu2_rop32); + WRITE_GP32(MGP_DST_OFFSET, dstoffset | gu2_pattern_origin); + WRITE_GP32(MGP_WID_HEIGHT, size); + WRITE_GP32(MGP_STRIDE, gu2_dst_pitch); + WRITE_GP32(MGP_BLT_MODE, gu2_blt_mode | gu2_bm_throttle); + gu2_bm_throttle = 0; + gu2_vm_throttle = 0; +} + +/*--------------------------------------------------------------------------- + * GFX2_COLOR_PATTERN_FILL + * + * This routine is used to render a rectangle using the current raster + * operation and the specified color pattern. It allows an 8x8 color + * pattern to be rendered without multiple calls to the gfx_set_color_pattern + * and gfx_pattern_fill routines. + *--------------------------------------------------------------------------- + */ +#if GFX_2DACCEL_DYNAMIC +void +gu22_color_pattern_fill(unsigned long dstoffset, unsigned short width, + unsigned short height, unsigned long *pattern) +#else +void +gfx2_color_pattern_fill(unsigned long dstoffset, unsigned short width, + unsigned short height, unsigned long *pattern) +#endif +{ + int pass; + unsigned long lines, size, patxorigin, patoffset; + + /* ONLY USE HW PATTERN ORIGIN FOR THE X DIRECTION */ + /* Y direction handled by referencing proper location in pattern data. */ + + patxorigin = (gu2_pattern_origin) & 0x1C000000; + + /* OVERRIDE PATTERN FLAGS IN ROP TO FORCE COLOR PATTERN */ + + GU2_WAIT_PENDING; + WRITE_GP32(MGP_RASTER_MODE, + (gu2_rop32 & ~MGP_RM_PAT_FLAGS) | MGP_RM_PAT_COLOR); + + /* ATTEMPT TO OPTIMIZE */ + /* If possible, we can perform the pattern fill in only a few passes */ + /* This is performed by multiplying the pitch by an appropriate amount. */ + /* Consequently, if the multiplied pitch exceeds 16 bits, this */ + /* optimization is impossible. */ + + if ((gu2_dst_pitch << (gu2_xshift + 1)) <= 0xFFFF) { + /* HANDLE VARIOUS COLOR DEPTHS DIFFERENTLY */ + + switch (gu2_xshift) { + case 0: /* 8 BPP */ + + /* TWO PASSES FOR 8 BPP */ + /* Render every other line per pass by doubling the pitch. */ + + patoffset = (gu2_pattern_origin >> 28) & 0x0E; + for (pass = 0; pass < 2; pass++) { + /* CAN WRITE SOME PATTERN REGISTERS WHILE "PENDING" */ + + GU2_WAIT_PENDING; + WRITE_GP32(MGP_DST_OFFSET, dstoffset | patxorigin); + lines = (height + 1 - pass) >> 1; + if (!lines) + break; + size = (((unsigned long)width) << 16) | lines; + WRITE_GP32(MGP_WID_HEIGHT, size); + WRITE_GP32(MGP_STRIDE, gu2_dst_pitch << 1); + WRITE_GP32(MGP_PAT_DATA_1, BYTE_SWIZZLE(pattern[patoffset])); + WRITE_GP32(MGP_PAT_DATA_0, + BYTE_SWIZZLE(pattern[patoffset + 1])); + patoffset = (patoffset + 4) & 0x0E; + WRITE_GP32(MGP_PAT_COLOR_1, BYTE_SWIZZLE(pattern[patoffset])); + WRITE_GP32(MGP_PAT_COLOR_0, + BYTE_SWIZZLE(pattern[patoffset + 1])); + patoffset = (patoffset + 4) & 0x0E; + + /* NEED TO WAIT UNTIL IDLE FOR COLORS 2 THROUGH 5 */ + /* Those registers are not pipelined. */ + + GU2_WAIT_BUSY; + WRITE_GP32(MGP_PAT_COLOR_3, BYTE_SWIZZLE(pattern[patoffset])); + WRITE_GP32(MGP_PAT_COLOR_2, + BYTE_SWIZZLE(pattern[patoffset + 1])); + patoffset = (patoffset + 4) & 0x0E; + WRITE_GP32(MGP_PAT_COLOR_5, BYTE_SWIZZLE(pattern[patoffset])); + WRITE_GP32(MGP_PAT_COLOR_4, + BYTE_SWIZZLE(pattern[patoffset + 1])); + WRITE_GP16(MGP_BLT_MODE, gu2_blt_mode | gu2_bm_throttle); + gu2_bm_throttle = 0; + gu2_vm_throttle = 0; + + /* ADJUST FOR NEXT PASS */ + + dstoffset += gu2_dst_pitch; + patoffset = (patoffset + 6) & 0x0E; + } + break; + + case 1: /* 12, 15, OR 16 BPP */ + + /* FOUR PASSES FOR 16 BPP */ + /* Render every 4th line per pass by quadrupling the pitch. */ + + patoffset = (gu2_pattern_origin >> 27) & 0x1C; + for (pass = 0; pass < 4; pass++) { + /* CAN WRITE SOME PATTERN REGISTERS WHILE "PENDING" */ + + GU2_WAIT_PENDING; + WRITE_GP32(MGP_DST_OFFSET, dstoffset | patxorigin); + lines = (height + 3 - pass) >> 2; + if (!lines) + break; + size = (((unsigned long)width) << 16) | lines; + WRITE_GP32(MGP_WID_HEIGHT, size); + WRITE_GP32(MGP_STRIDE, gu2_dst_pitch << 2); + WRITE_GP32(MGP_PAT_COLOR_1, WORD_SWIZZLE(pattern[patoffset])); + WRITE_GP32(MGP_PAT_COLOR_0, + WORD_SWIZZLE(pattern[patoffset + 1])); + WRITE_GP32(MGP_PAT_DATA_1, + WORD_SWIZZLE(pattern[patoffset + 2])); + WRITE_GP32(MGP_PAT_DATA_0, + WORD_SWIZZLE(pattern[patoffset + 3])); + patoffset = (patoffset + 16) & 0x1C; + + /* NEED TO WAIT UNTIL IDLE FOR COLORS 2 THROUGH 5 */ + /* Those registers are not pipelined. */ + + GU2_WAIT_BUSY; + WRITE_GP32(MGP_PAT_COLOR_5, WORD_SWIZZLE(pattern[patoffset])); + WRITE_GP32(MGP_PAT_COLOR_4, + WORD_SWIZZLE(pattern[patoffset + 1])); + WRITE_GP32(MGP_PAT_COLOR_3, + WORD_SWIZZLE(pattern[patoffset + 2])); + WRITE_GP32(MGP_PAT_COLOR_2, + WORD_SWIZZLE(pattern[patoffset + 3])); + WRITE_GP16(MGP_BLT_MODE, gu2_blt_mode | gu2_bm_throttle); + gu2_bm_throttle = 0; + gu2_vm_throttle = 0; + + /* ADJUST FOR NEXT PASS */ + + dstoffset += gu2_dst_pitch; + patoffset = (patoffset + 20) & 0x1C; + } + break; + + case 2: /* 32 BPP */ + + /* EIGHT PASSES FOR 32 BPP */ + /* Render every 8th line per pass by setting pitch * 8. */ + + patoffset = (gu2_pattern_origin >> 26) & 0x38; + for (pass = 0; pass < 8; pass++) { + /* CAN WRITE SOME PATTERN REGISTERS WHILE "PENDING" */ + + GU2_WAIT_PENDING; + WRITE_GP32(MGP_DST_OFFSET, dstoffset | patxorigin); + lines = (height + 7 - pass) >> 3; + if (!lines) + break; + size = (((unsigned long)width) << 16) | lines; + WRITE_GP32(MGP_WID_HEIGHT, size); + WRITE_GP32(MGP_STRIDE, gu2_dst_pitch << 3); + WRITE_GP32(MGP_PAT_COLOR_1, pattern[patoffset + 4]); + WRITE_GP32(MGP_PAT_COLOR_0, pattern[patoffset + 5]); + WRITE_GP32(MGP_PAT_DATA_1, pattern[patoffset + 6]); + WRITE_GP32(MGP_PAT_DATA_0, pattern[patoffset + 7]); + + /* NEED TO WAIT UNTIL IDLE FOR COLORS 2 THROUGH 5 */ + /* Those registers are not pipelined. */ + + GU2_WAIT_BUSY; + WRITE_GP32(MGP_PAT_COLOR_5, pattern[patoffset]); + WRITE_GP32(MGP_PAT_COLOR_4, pattern[patoffset + 1]); + WRITE_GP32(MGP_PAT_COLOR_3, pattern[patoffset + 2]); + WRITE_GP32(MGP_PAT_COLOR_2, pattern[patoffset + 3]); + WRITE_GP16(MGP_BLT_MODE, gu2_blt_mode | gu2_bm_throttle); + gu2_bm_throttle = 0; + gu2_vm_throttle = 0; + + /* ADJUST FOR NEXT PASS */ + + dstoffset += gu2_dst_pitch; + patoffset = (patoffset + 8) & 0x38; + } + break; + } + } + + else { + WRITE_GP32(MGP_STRIDE, gu2_dst_pitch); + + switch (gu2_xshift) { + case 0: /* 8 BPP - 4 LINES PER PASS */ + + patoffset = (gu2_pattern_origin >> 28) & 0x0E; + while (height) { + lines = height > 4 ? 4 : height; + + /* CAN WRITE SOME REGISTERS WHILE PENDING */ + + WRITE_GP32(MGP_DST_OFFSET, dstoffset | patxorigin); + WRITE_GP32(MGP_WID_HEIGHT, + (((unsigned long)width) << 16) | lines); + WRITE_GP32(MGP_PAT_DATA_1, BYTE_SWIZZLE(pattern[patoffset])); + WRITE_GP32(MGP_PAT_DATA_0, + BYTE_SWIZZLE(pattern[patoffset + 1])); + patoffset = (patoffset + 2) & 0x0E; + WRITE_GP32(MGP_PAT_COLOR_1, BYTE_SWIZZLE(pattern[patoffset])); + WRITE_GP32(MGP_PAT_COLOR_0, + BYTE_SWIZZLE(pattern[patoffset + 1])); + patoffset = (patoffset + 2) & 0x0E; + + /* NEED TO WAIT UNTIL IDLE FOR COLORS 2 THROUGH 5 */ + /* Those registers are not pipelined. */ + + GU2_WAIT_BUSY; + WRITE_GP32(MGP_PAT_COLOR_3, BYTE_SWIZZLE(pattern[patoffset])); + WRITE_GP32(MGP_PAT_COLOR_2, + BYTE_SWIZZLE(pattern[patoffset + 1])); + patoffset = (patoffset + 2) & 0x0E; + WRITE_GP32(MGP_PAT_COLOR_5, BYTE_SWIZZLE(pattern[patoffset])); + WRITE_GP32(MGP_PAT_COLOR_4, + BYTE_SWIZZLE(pattern[patoffset + 1])); + patoffset = (patoffset + 2) & 0x0E; + WRITE_GP16(MGP_BLT_MODE, gu2_blt_mode | gu2_bm_throttle); + + /* ADJUST FOR NEXT PASS */ + + dstoffset += gu2_dst_pitch << 2; + height -= (unsigned short)lines; + } + break; + + case 1: /* 12, 15 AND 16 BPP - 2 LINES PER PASS */ + + patoffset = (gu2_pattern_origin >> 27) & 0x1C; + while (height) { + lines = height > 2 ? 2 : height; + + /* CAN WRITE SOME REGISTERS WHILE PENDING */ + + WRITE_GP32(MGP_DST_OFFSET, dstoffset | patxorigin); + WRITE_GP32(MGP_WID_HEIGHT, + (((unsigned long)width) << 16) | lines); + WRITE_GP32(MGP_PAT_COLOR_1, WORD_SWIZZLE(pattern[patoffset])); + WRITE_GP32(MGP_PAT_COLOR_0, + WORD_SWIZZLE(pattern[patoffset + 1])); + WRITE_GP32(MGP_PAT_DATA_1, + WORD_SWIZZLE(pattern[patoffset + 2])); + WRITE_GP32(MGP_PAT_DATA_0, + WORD_SWIZZLE(pattern[patoffset + 3])); + patoffset = (patoffset + 4) & 0x1C; + + /* NEED TO WAIT UNTIL IDLE FOR COLORS 2 THROUGH 5 */ + /* Those registers are not pipelined. */ + + GU2_WAIT_BUSY; + WRITE_GP32(MGP_PAT_COLOR_5, WORD_SWIZZLE(pattern[patoffset])); + WRITE_GP32(MGP_PAT_COLOR_4, + WORD_SWIZZLE(pattern[patoffset + 1])); + WRITE_GP32(MGP_PAT_COLOR_3, + WORD_SWIZZLE(pattern[patoffset + 2])); + WRITE_GP32(MGP_PAT_COLOR_2, + WORD_SWIZZLE(pattern[patoffset + 3])); + patoffset = (patoffset + 4) & 0x1C; + WRITE_GP16(MGP_BLT_MODE, gu2_blt_mode | gu2_bm_throttle); + + /* ADJUST FOR NEXT PASS */ + + dstoffset += gu2_dst_pitch << 1; + height -= (unsigned short)lines; + } + break; + + case 2: /* 32 BPP - 1 LINE PER PASS */ + + patoffset = (gu2_pattern_origin >> 26) & 0x38; + while (height) { + /* CAN WRITE SOME REGISTERS WHILE PENDING */ + + WRITE_GP32(MGP_DST_OFFSET, dstoffset | patxorigin); + WRITE_GP32(MGP_WID_HEIGHT, + (((unsigned long)width) << 16) | 1l); + WRITE_GP32(MGP_PAT_COLOR_1, pattern[patoffset + 4]); + WRITE_GP32(MGP_PAT_COLOR_0, pattern[patoffset + 5]); + WRITE_GP32(MGP_PAT_DATA_1, pattern[patoffset + 6]); + WRITE_GP32(MGP_PAT_DATA_0, pattern[patoffset + 7]); + + /* NEED TO WAIT UNTIL IDLE FOR COLORS 2 THROUGH 5 */ + /* Those registers are not pipelined. */ + + GU2_WAIT_BUSY; + WRITE_GP32(MGP_PAT_COLOR_5, pattern[patoffset]); + WRITE_GP32(MGP_PAT_COLOR_4, pattern[patoffset + 1]); + WRITE_GP32(MGP_PAT_COLOR_3, pattern[patoffset + 2]); + WRITE_GP32(MGP_PAT_COLOR_2, pattern[patoffset + 3]); + patoffset = (patoffset + 8) & 0x38; + WRITE_GP16(MGP_BLT_MODE, gu2_blt_mode | gu2_bm_throttle); + + /* ADJUST FOR NEXT PASS */ + + dstoffset += gu2_dst_pitch; + height--; + } + break; + } + + } + +} + +/*--------------------------------------------------------------------------- + * GFX2_SCREEN_TO_SCREEN_BLT + * + * This routine is similar to the gfx_screen_to_screen_blt routine but + * allows the use of arbitrary source and destination strides and alpha + * blending. It also allows the use of an arbitrary ROP with transparency. + *--------------------------------------------------------------------------- + */ +#if GFX_2DACCEL_DYNAMIC +void +gu22_screen_to_screen_blt(unsigned long srcoffset, unsigned long dstoffset, + unsigned short width, unsigned short height, int flags) +#else +void +gfx2_screen_to_screen_blt(unsigned long srcoffset, unsigned long dstoffset, + unsigned short width, unsigned short height, int flags) +#endif +{ + unsigned long size, xbytes; + unsigned short blt_mode; + + size = (((unsigned long)width) << 16) | height; + + /* USE ALPHA SETTINGS, IF REQUESTED */ + + if (gu2_alpha_active) + blt_mode = gu2_alpha_blt_mode | MGP_BM_SRC_FB; + + else + blt_mode = (gu2_blt_mode & ~MGP_BM_SRC_TYPE_MASK) | MGP_BM_SRC_FB; + + /* CALCULATE THE DIRECTION OF THE BLT */ + /* Using offsets, so flags from the calling routine are needed. */ + + if (flags & 1) { + xbytes = (width - 1) << gu2_xshift; + srcoffset += xbytes; + dstoffset += xbytes; + blt_mode |= MGP_BM_NEG_XDIR; + } + if (flags & 2) { + srcoffset += (height - 1) * gu2_src_pitch; + dstoffset += (height - 1) * gu2_dst_pitch; + blt_mode |= MGP_BM_NEG_YDIR; + } + + /* TURN INTO BYTE ADDRESS IF NEGATIVE X DIRECTION */ + /* This is a quirk of the hardware. */ + + if (blt_mode & MGP_BM_NEG_XDIR) { + srcoffset += (1 << gu2_xshift) - 1; + dstoffset += (1 << gu2_xshift) - 1; + } + + /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */ + /* Put off poll for as long as possible (do most calculations first). */ + + GU2_WAIT_PENDING; + + if (gu2_alpha_active) { + WRITE_GP32(MGP_RASTER_MODE, gu2_alpha32); + } else { + WRITE_GP32(MGP_RASTER_MODE, gu2_rop32 | GFXsourceFlags); + } + + WRITE_GP32(MGP_SRC_OFFSET, srcoffset); + WRITE_GP32(MGP_DST_OFFSET, dstoffset | gu2_pattern_origin); + WRITE_GP32(MGP_WID_HEIGHT, size); + WRITE_GP32(MGP_STRIDE, gu2_dst_pitch | (gu2_src_pitch << 16)); + WRITE_GP16(MGP_BLT_MODE, blt_mode | gu2_bm_throttle); + gu2_bm_throttle = 0; + gu2_vm_throttle = 0; +} + +/*--------------------------------------------------------------------------- + * GFX2_MONO_EXPAND_BLT + * + * This routine is similar to the gfx2_screen_to_screen_blt routine but + * expands monochrome data stored in graphics memory. + * WARNING: This routine assumes that the regions in graphics memory + * will not overlap, and therefore does not check the BLT direction. + *--------------------------------------------------------------------------- + */ +#if GFX_2DACCEL_DYNAMIC +void +gu22_mono_expand_blt(unsigned long srcbase, unsigned short srcx, + unsigned short srcy, unsigned long dstoffset, unsigned short width, + unsigned short height, int byte_packed) +#else +void +gfx2_mono_expand_blt(unsigned long srcbase, unsigned short srcx, + unsigned short srcy, unsigned long dstoffset, unsigned short width, + unsigned short height, int byte_packed) +#endif +{ + unsigned long size, srcoffset; + unsigned short blt_mode; + + size = (((unsigned long)width) << 16) | height; + + /* CALCULATE SOURCE OFFSET */ + + srcoffset = srcbase + (unsigned long)srcy *gu2_src_pitch; + + srcoffset += srcx >> 3; + srcoffset |= ((unsigned long)srcx & 7) << 26; + + /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */ + /* Put off poll for as long as possible (do most calculations first). */ + + GU2_WAIT_PENDING; + + if (gu2_alpha_active) { + blt_mode = gu2_alpha_blt_mode; + + WRITE_GP32(MGP_RASTER_MODE, gu2_alpha32); + } else { + blt_mode = (gu2_blt_mode & ~MGP_BM_SRC_TYPE_MASK); + + WRITE_GP32(MGP_RASTER_MODE, gu2_rop32 | GFXsourceFlags); + } + + if (byte_packed) + blt_mode |= MGP_BM_SRC_FB | MGP_BM_SRC_BP_MONO | gu2_bm_throttle; + else + blt_mode |= MGP_BM_SRC_FB | MGP_BM_SRC_MONO | gu2_bm_throttle; + + WRITE_GP32(MGP_SRC_OFFSET, srcoffset); + WRITE_GP32(MGP_DST_OFFSET, dstoffset | gu2_pattern_origin); + WRITE_GP32(MGP_WID_HEIGHT, size); + WRITE_GP32(MGP_STRIDE, gu2_dst_pitch | (gu2_src_pitch << 16)); + WRITE_GP16(MGP_BLT_MODE, blt_mode); + gu2_bm_throttle = 0; + gu2_vm_throttle = 0; +} + +/*--------------------------------------------------------------------------- + * GFX2_COLOR_BITMAP_TO_SCREEN_BLT + * + * This routine is similar to the gfx_color_bitmap_to_screen_blt routine + * but allows the use of an arbitrary destination stride and alpha blending. + * It also allows the use of an arbitrary ROP with transparency. + *--------------------------------------------------------------------------- + */ +#if GFX_2DACCEL_DYNAMIC +void +gu22_color_bitmap_to_screen_blt(unsigned short srcx, unsigned short srcy, + unsigned long dstoffset, unsigned short width, + unsigned short height, unsigned char *data, short pitch) +#else +void +gfx2_color_bitmap_to_screen_blt(unsigned short srcx, unsigned short srcy, + unsigned long dstoffset, unsigned short width, + unsigned short height, unsigned char *data, short pitch) +#endif +{ + unsigned long size, bytes; + unsigned long offset, temp_offset; + unsigned long srcoffset, dword_bytes, bytes_extra; + unsigned short blt_mode; + + size = (((unsigned long)width) << 16) | 1; + + /* CALCULATE STARTING OFFSETS */ + + offset = (unsigned long)srcy *pitch + ((unsigned long)srcx << gu2_xshift); + + dstoffset |= gu2_pattern_origin; + + bytes = width << gu2_xshift; + dword_bytes = bytes & ~0x3L; + bytes_extra = bytes & 0x3L; + + /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */ + /* Put off poll for as long as possible (do most calculations first). */ + /* The source offset is always 0 since we allow misaligned dword reads. */ + /* We must wait for BLT busy because the GP may be executing a screen */ + /* to screen BLT from the scratchpad area. */ + + GU2_WAIT_BUSY; + + if (gu2_alpha_active) { + blt_mode = gu2_alpha_blt_mode; + + WRITE_GP32(MGP_RASTER_MODE, gu2_alpha32); + } else { + blt_mode = (gu2_blt_mode & ~MGP_BM_SRC_TYPE_MASK); + + WRITE_GP32(MGP_RASTER_MODE, gu2_rop32 | GFXsourceFlags); + } + blt_mode |= MGP_BM_SRC_FB | gu2_bm_throttle; + gu2_bm_throttle = 0; + gu2_vm_throttle = 0; + + WRITE_GP32(MGP_WID_HEIGHT, size); + + /* WRITE DATA ONE LINE AT A TIME */ + /* For speed reasons, data is written to an offscreen scratch area and + * then BLTed using a screen to screen BLT. This is similar to the GX1 BLT + * buffers, but slightly more efficient in that we can queue up data while + * the GP is rendering a line. + * */ + + while (height--) { + temp_offset = offset; + srcoffset = gfx_gx2_scratch_base; + if (gu2_current_line) + srcoffset += 8192; + + GU2_WAIT_PENDING; + WRITE_GP32(MGP_SRC_OFFSET, srcoffset); + WRITE_GP32(MGP_DST_OFFSET, dstoffset); + dstoffset += gu2_dst_pitch; + dstoffset += 0x20000000; + + WRITE_FRAME_BUFFER_STRING32(srcoffset, dword_bytes, data, + temp_offset); + if (bytes_extra) { + temp_offset += dword_bytes; + srcoffset += dword_bytes; + WRITE_FRAME_BUFFER_STRING8(srcoffset, bytes_extra, data, + temp_offset); + } + WRITE_GP16(MGP_BLT_MODE, blt_mode); + offset += pitch; + gu2_current_line = 1 - gu2_current_line; + } +} + +/*--------------------------------------------------------------------------- + * GFX2_TEXT_BLT + * + * This routine is similar to the gfx2_mono_bitmap_to_screen_blt routine + * but assumes that source data is byte-packed. + *--------------------------------------------------------------------------- + */ +#if GFX_2DACCEL_DYNAMIC +void +gu22_text_blt(unsigned long dstoffset, unsigned short width, + unsigned short height, unsigned char *data) +#else +void +gfx2_text_blt(unsigned long dstoffset, unsigned short width, + unsigned short height, unsigned char *data) +#endif +{ + unsigned long size, bytes; + unsigned long temp1 = 0, temp2 = 0, temp_offset = 0; + unsigned long i, j = 0, fifo_lines, dwords_extra, bytes_extra; + unsigned long shift; + unsigned short blt_mode; + + size = (((unsigned long)width) << 16) | height; + + /* CALCULATE STARTING OFFSETS */ + + bytes = ((width + 7) >> 3) * height; + fifo_lines = bytes >> 5; + dwords_extra = (bytes & 0x0000001Cl) >> 2; + bytes_extra = bytes & 0x00000003l; + + /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */ + + GU2_WAIT_PENDING; + + if (gu2_alpha_active) { + blt_mode = gu2_alpha_blt_mode; + + WRITE_GP32(MGP_RASTER_MODE, gu2_alpha32); + } else { + blt_mode = (gu2_blt_mode & ~MGP_BM_SRC_TYPE_MASK); + + WRITE_GP32(MGP_RASTER_MODE, gu2_rop32 | GFXsourceFlags); + } + + WRITE_GP32(MGP_SRC_OFFSET, 0); + WRITE_GP32(MGP_DST_OFFSET, dstoffset | gu2_pattern_origin); + WRITE_GP32(MGP_WID_HEIGHT, size); + WRITE_GP32(MGP_STRIDE, gu2_dst_pitch); + WRITE_GP16(MGP_BLT_MODE, blt_mode | MGP_BM_SRC_HOST | + MGP_BM_SRC_BP_MONO | gu2_bm_throttle); + gu2_bm_throttle = 0; + gu2_vm_throttle = 0; + + /* WAIT FOR BLT TO BE LATCHED */ + + GU2_WAIT_PENDING; + + /* WRITE ALL FULL FIFO LINES */ + + for (i = 0; i < fifo_lines; i++) { + GU2_WAIT_HALF_EMPTY; + WRITE_GPREG_STRING32(MGP_HST_SOURCE, 8, j, data, temp_offset, temp1); + temp_offset += 32; + } + + /* WRITE ALL FULL DWORDS */ + + if (dwords_extra || bytes_extra) { + GU2_WAIT_HALF_EMPTY; + if (dwords_extra) { + WRITE_GPREG_STRING32(MGP_HST_SOURCE, dwords_extra, i, data, + temp_offset, temp1); + temp_offset += (dwords_extra << 2); + } + if (bytes_extra) { + shift = 0; + WRITE_GPREG_STRING8(MGP_HST_SOURCE, bytes_extra, shift, i, data, + temp_offset, temp1, temp2); + } + } +} + +/*--------------------------------------------------------------------------- + * GFX2_MONO_BITMAP_TO_SCREEN_BLT + * + * This routine is similar to the gfx_mono_bitmap_to_screen_blt routine + * but allows the use of an arbitrary destination stride and alpha blending. + *--------------------------------------------------------------------------- + */ +#if GFX_2DACCEL_DYNAMIC +void +gu22_mono_bitmap_to_screen_blt(unsigned short srcx, unsigned short srcy, + unsigned long dstoffset, unsigned short width, + unsigned short height, unsigned char *data, short pitch) +#else +void +gfx2_mono_bitmap_to_screen_blt(unsigned short srcx, unsigned short srcy, + unsigned long dstoffset, unsigned short width, + unsigned short height, unsigned char *data, short pitch) +#endif +{ + unsigned long size, bytes; + unsigned long offset, temp_offset, temp1 = 0, temp2 = 0; + unsigned long i, j = 0, fifo_lines, dwords_extra, bytes_extra; + unsigned long shift = 0; + unsigned short blt_mode; + + size = (((unsigned long)width) << 16) | height; + + /* CALCULATE STARTING OFFSETS */ + + offset = (unsigned long)srcy *pitch + ((unsigned long)srcx >> 3); + + bytes = ((srcx & 7) + width + 7) >> 3; + fifo_lines = bytes >> 5; + dwords_extra = (bytes & 0x0000001Cl) >> 2; + bytes_extra = bytes & 0x00000003l; + + /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */ + + GU2_WAIT_PENDING; + + if (gu2_alpha_active) { + blt_mode = gu2_alpha_blt_mode; + + WRITE_GP32(MGP_RASTER_MODE, gu2_alpha32); + } else { + blt_mode = (gu2_blt_mode & ~MGP_BM_SRC_TYPE_MASK); + + WRITE_GP32(MGP_RASTER_MODE, gu2_rop32 | GFXsourceFlags); + } + + WRITE_GP32(MGP_SRC_OFFSET, ((unsigned long)srcx & 7) << 26); + WRITE_GP32(MGP_DST_OFFSET, dstoffset | gu2_pattern_origin); + WRITE_GP32(MGP_WID_HEIGHT, size); + WRITE_GP32(MGP_STRIDE, gu2_dst_pitch); + WRITE_GP16(MGP_BLT_MODE, blt_mode | MGP_BM_SRC_HOST | + MGP_BM_SRC_MONO | gu2_bm_throttle); + gu2_bm_throttle = 0; + gu2_vm_throttle = 0; + + /* WAIT FOR BLT TO BE LATCHED */ + + GU2_WAIT_PENDING; + + /* WRITE ALL OF THE DATA TO THE HOST SOURCE REGISTER */ + + while (height--) { + temp_offset = offset; + + /* WRITE ALL FULL FIFO LINES */ + + for (i = 0; i < fifo_lines; i++) { + GU2_WAIT_HALF_EMPTY; + WRITE_GPREG_STRING32(MGP_HST_SOURCE, 8, j, data, temp_offset, + temp1); + temp_offset += 32; + } + + /* WRITE ALL FULL DWORDS */ + + GU2_WAIT_HALF_EMPTY; + if (dwords_extra) + WRITE_GPREG_STRING32(MGP_HST_SOURCE, dwords_extra, i, data, + temp_offset, temp1); + temp_offset += (dwords_extra << 2); + + /* WRITE REMAINING BYTES */ + + shift = 0; + if (bytes_extra) + WRITE_GPREG_STRING8(MGP_HST_SOURCE, bytes_extra, shift, i, data, + temp_offset, temp1, temp2); + + offset += pitch; + } +} + +/*--------------------------------------------------------------------------- + * GFX2_BRESENHAM_LINE + * + * This routine is similar to the gfx_bresenam_line routine but allows + * the use of an arbitrary destination stride. + *--------------------------------------------------------------------------- + */ +#if GFX_2DACCEL_DYNAMIC +void +gu22_bresenham_line(unsigned long dstoffset, + unsigned short length, unsigned short initerr, + unsigned short axialerr, unsigned short diagerr, unsigned short flags) +#else +void +gfx2_bresenham_line(unsigned long dstoffset, + unsigned short length, unsigned short initerr, + unsigned short axialerr, unsigned short diagerr, unsigned short flags) +#endif +{ + unsigned long vector_mode = gu2_vector_mode | flags; + unsigned long data1 = (((unsigned long)axialerr) << 16) | diagerr; + unsigned long data2 = (((unsigned long)length) << 16) | initerr; + + /* CHECK NULL LENGTH */ + + if (!length) + return; + + /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */ + /* Put off poll for as long as possible (do most calculations first). */ + + GU2_WAIT_PENDING; + + if (gu2_alpha_active) { + vector_mode = gu2_alpha_vec_mode | flags; + + WRITE_GP32(MGP_RASTER_MODE, gu2_alpha32); + } else + WRITE_GP32(MGP_RASTER_MODE, gu2_rop32); + + WRITE_GP32(MGP_DST_OFFSET, dstoffset | gu2_pattern_origin); + WRITE_GP32(MGP_VEC_ERR, data1); + WRITE_GP32(MGP_VEC_LEN, data2); + WRITE_GP32(MGP_STRIDE, gu2_dst_pitch); + WRITE_GP32(MGP_VECTOR_MODE, vector_mode | gu2_vm_throttle); + gu2_bm_throttle = 0; + gu2_vm_throttle = 0; +} + +/*--------------------------------------------------------------------------- + * GFX2_SYNC_TO_VBLANK + * + * This routine sets a flag to synchronize the next rendering routine to + * VBLANK. The flag is cleared by the rendering routine. + *--------------------------------------------------------------------------- + */ +#if GFX_2DACCEL_DYNAMIC +void +gu22_sync_to_vblank(void) +#else +void +gfx2_sync_to_vblank(void) +#endif +{ + /* SET FLAGS TO THROTTLE NEXT RENDERING ROUTINE */ + + gu2_bm_throttle = MGP_BM_THROTTLE; + gu2_vm_throttle = MGP_VM_THROTTLE; +} + +/* END OF FILE */ diff --git a/src/gfx/saa7114.c b/src/gfx/saa7114.c new file mode 100644 index 0000000..df516bc --- /dev/null +++ b/src/gfx/saa7114.c @@ -0,0 +1,916 @@ +/* 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 to control the Philips SAA7114 video decoder. + * */ + +/*---------------------------*/ +/* TABLE OF DEFAULT VALUES */ +/*---------------------------*/ + +typedef struct tagGFX_SAA7114_INIT +{ + unsigned char index; + unsigned char value; +} GFX_SAA7114_INIT; + +/* Task A is for VBI raw data and task B is for video */ + +GFX_SAA7114_INIT gfx_saa7114_init_values[] = { + {0x01, 0x08}, {0x02, 0xC0}, {0x03, 0x00}, {0x04, 0x90}, + {0x05, 0x90}, {0x06, 0xEB}, {0x07, 0xE0}, {0x08, 0x88}, + {0x09, 0x40}, {0x0A, 0x80}, {0x0B, 0x44}, {0x0C, 0x40}, + {0x0D, 0x00}, {0x0E, 0x89}, {0x0F, 0x2E}, {0x10, 0x0E}, + {0x11, 0x00}, {0x12, 0x05}, {0x13, 0x00}, {0x14, 0x08}, + {0x15, 0x11}, {0x16, 0xFE}, {0x17, 0x00}, {0x18, 0x40}, + {0x19, 0x80}, {0x30, 0xBC}, {0x31, 0xDF}, {0x32, 0x02}, + {0x34, 0xCD}, {0x35, 0xCC}, {0x36, 0x3A}, {0x38, 0x03}, + {0x39, 0x10}, {0x3A, 0x00}, {0x40, 0x00}, {0x41, 0xFF}, + {0x42, 0xFF}, {0x43, 0xFF}, {0x44, 0xFF}, {0x45, 0xFF}, + {0x46, 0xFF}, {0x47, 0xFF}, {0x48, 0xFF}, {0x49, 0xFF}, + {0x4A, 0xFF}, {0x4B, 0xFF}, {0x4C, 0xFF}, {0x4D, 0xFF}, + {0x4E, 0xFF}, {0x4F, 0xFF}, {0x50, 0xFF}, {0x51, 0xFF}, + {0x52, 0xFF}, {0x53, 0xFF}, {0x54, 0xFF}, {0x55, 0xFF}, + {0x56, 0xFF}, {0x57, 0xFF}, {0x58, 0x00}, {0x59, 0x47}, + {0x5A, 0x06}, {0x5B, 0x43}, {0x5D, 0x3E}, {0x5E, 0x00}, + {0x80, 0x30}, {0x83, 0x00}, {0x84, 0x60}, {0x85, 0x00}, + {0x86, 0xE5}, {0x87, 0x01}, {0x88, 0xF8}, + + /* VBI task */ + + {0x90, 0x01}, {0x91, 0xC8}, {0x92, 0x08}, {0x93, 0x84}, + {0x94, 0x10}, {0x95, 0x00}, {0x96, 0xD0}, {0x97, 0x02}, + {0x98, 0x05}, {0x99, 0x00}, {0x9A, 0x0B}, {0x9B, 0x00}, + {0x9C, 0xA0}, {0x9D, 0x05}, {0x9E, 0x0B}, {0x9F, 0x00}, + {0xA0, 0x01}, {0xA1, 0x00}, {0xA2, 0x00}, {0xA4, 0x80}, + {0xA5, 0x40}, {0xA6, 0x40}, {0xA8, 0x00}, {0xA9, 0x02}, + {0xAA, 0x00}, {0xAC, 0x00}, {0xAD, 0x01}, {0xAE, 0x00}, + {0xB0, 0x00}, {0xB1, 0x04}, {0xB2, 0x00}, {0xB3, 0x04}, + {0xB4, 0x00}, {0xB8, 0x00}, {0xB9, 0x00}, {0xBA, 0x00}, + {0xBB, 0x00}, {0xBC, 0x00}, {0xBD, 0x00}, {0xBE, 0x00}, + {0xBF, 0x00}, + + /* Video task */ + + {0xC0, 0x80}, {0xC1, 0x08}, {0xC2, 0x00}, {0xC3, 0x80}, + {0xC4, 0x10}, {0xC5, 0x00}, {0xC6, 0xD0}, {0xC7, 0x02}, + {0xC8, 0x11}, {0xC9, 0x00}, {0xCA, 0xF1}, {0xCB, 0x00}, + {0xCC, 0xD0}, {0xCD, 0x02}, {0xCE, 0xF1}, {0xCF, 0x00}, + {0xD0, 0x01}, {0xD1, 0x00}, {0xD2, 0x00}, {0xD4, 0x80}, + {0xD5, 0x40}, {0xD6, 0x40}, {0xD8, 0x00}, {0xD9, 0x04}, + {0xDA, 0x00}, {0xDC, 0x00}, {0xDD, 0x02}, {0xDE, 0x00}, + {0xE0, 0x00}, {0xE1, 0x04}, {0xE2, 0x00}, {0xE3, 0x04}, + {0xE4, 0x00}, {0xE8, 0x00}, {0xE9, 0x00}, {0xEA, 0x00}, + {0xEB, 0x00}, {0xEC, 0x00}, {0xED, 0x00}, {0xEE, 0x00}, + {0xEF, 0x00}, +}; + +#define GFX_NUM_SAA7114_INIT_VALUES \ + sizeof(gfx_saa7114_init_values)/sizeof(GFX_SAA7114_INIT) + +/*-----------------------------------------------------*/ +/* TABLE OF FIR PREFILTER RECOMMENDED VALUES */ +/*-----------------------------------------------------*/ + +int optimize_for_aliasing = 0; + +typedef struct tagGFX_SAA7114_FIR_PREFILTER +{ + unsigned char prescaler; + unsigned char acl_low; + unsigned char prefilter_low; + unsigned char acl_high; + unsigned char prefilter_high; +} GFX_SAA7114_FIR_PREFILTER; + +GFX_SAA7114_FIR_PREFILTER gfx_saa7114_fir_values[] = { + {0x01, 0x00, 0x00, 0x00, 0x00}, {0x02, 0x02, 0x5A, 0x01, 0x51}, + {0x03, 0x04, 0xAB, 0x03, 0xA2}, {0x04, 0x07, 0xA3, 0x04, 0xAB}, + {0x05, 0x08, 0xAC, 0x07, 0xA3}, {0x06, 0x08, 0xFC, 0x07, 0xF3}, + {0x07, 0x08, 0xFC, 0x07, 0xF3}, {0x08, 0x0F, 0xF4, 0x08, 0xFC}, + {0x09, 0x0F, 0xF4, 0x08, 0xFC}, {0x0A, 0x10, 0xFD, 0x08, 0xFC}, + {0x0B, 0x10, 0xFD, 0x08, 0xFC}, {0x0C, 0x10, 0xFD, 0x08, 0xFC}, + {0x0D, 0x10, 0xFD, 0x10, 0xFD}, {0x0E, 0x10, 0xFD, 0x10, 0xFD}, + {0x0F, 0x1F, 0xF5, 0x10, 0xFD}, {0x10, 0x20, 0xFE, 0x10, 0xFD}, + {0x11, 0x20, 0xFE, 0x10, 0xFD}, {0x12, 0x20, 0xFE, 0x10, 0xFD}, + {0x13, 0x20, 0xFE, 0x20, 0xFE}, {0x14, 0x20, 0xFE, 0x20, 0xFE}, + {0x15, 0x20, 0xFE, 0x20, 0xFE}, {0x16, 0x20, 0xFE, 0x20, 0xFE}, + {0x17, 0x20, 0xFE, 0x20, 0xFE}, {0x18, 0x20, 0xFE, 0x20, 0xFE}, + {0x19, 0x20, 0xFE, 0x20, 0xFE}, {0x1A, 0x20, 0xFE, 0x20, 0xFE}, + {0x1B, 0x20, 0xFE, 0x20, 0xFE}, {0x1C, 0x20, 0xFE, 0x20, 0xFE}, + {0x1D, 0x20, 0xFE, 0x20, 0xFE}, {0x1E, 0x20, 0xFE, 0x20, 0xFE}, + {0x1F, 0x20, 0xFE, 0x20, 0xFE}, {0x20, 0x3F, 0xFF, 0x20, 0xFE}, + {0x21, 0x3F, 0xFF, 0x20, 0xFE}, {0x22, 0x3F, 0xFF, 0x20, 0xFE}, + {0x23, 0x3F, 0xFF, 0x20, 0xFF} +}; + +int +saa7114_write_reg(unsigned char reg, unsigned char val) +{ + return gfx_i2c_write(2, SAA7114_CHIPADDR, reg, 1, &val); +} + +int +saa7114_read_reg(unsigned char reg, unsigned char *val) +{ + return gfx_i2c_read(2, SAA7114_CHIPADDR, reg, 1, val); +} + +/*---------------------------------------------------------------------------- + * gfx_set_decoder_vbi_upscale + * + * This routine configures the video decoder task A to upscale raw VBI data + * horizontally to match a different system clock. + * The upscale is from 13.5 MHz (SAA7114) to 14.318 MHz (Bt835). + *---------------------------------------------------------------------------- + */ +#if GFX_DECODER_DYNAMIC +int +saa7114_set_decoder_vbi_upscale(void) +#else +int +gfx_set_decoder_vbi_upscale(void) +#endif +{ + /* Set horizontal output length to 1528 (720 * 2 * 14.318 / 13.5) */ + saa7114_write_reg(SAA7114_TASK_A_HORZ_OUTPUT_LO, 0xF8); + saa7114_write_reg(SAA7114_TASK_A_HORZ_OUTPUT_HI, 0x05); + + /* Set horizontal luminance scaling increment to 484 (1024 * 13.5 / + * 28.636) */ + saa7114_write_reg(SAA7114_TASK_A_HSCALE_LUMA_LO, 0xE4); + saa7114_write_reg(SAA7114_TASK_A_HSCALE_LUMA_HI, 0x01); + + /* Set horizontal chrominance scaling increment to 242 */ + saa7114_write_reg(SAA7114_TASK_A_HSCALE_CHROMA_LO, 0xF2); + saa7114_write_reg(SAA7114_TASK_A_HSCALE_CHROMA_HI, 0x00); + + return GFX_STATUS_OK; +} + +/*---------------------------------------------------------------------------- + * gfx_decoder_software_reset + * + * This routine performs a software reset of the decoder. + *---------------------------------------------------------------------------- + */ +#if GFX_DECODER_DYNAMIC +int +saa7114_decoder_software_reset(void) +#else +int +gfx_decoder_software_reset(void) +#endif +{ + saa7114_write_reg(0x88, 0xC0); + /* I2C-bus latency should be sufficient for resetting the internal state + * machine. */ + /* gfx_delay_milliseconds(10); */ + saa7114_write_reg(0x88, 0xF0); + return GFX_STATUS_OK; +} + +/*---------------------------------------------------------------------------- + * gfx_decoder_detect_macrovision + * + * This routine detects if macrovision exists in the input of the video + * decoder. + *---------------------------------------------------------------------------- + */ +#if GFX_DECODER_DYNAMIC +int +saa7114_decoder_detect_macrovision(void) +#else +int +gfx_decoder_detect_macrovision(void) +#endif +{ + unsigned char macrovision = 0xff; + + saa7114_read_reg(SAA7114_STATUS, ¯ovision); + return ((macrovision & 0x02) >> 1); +} + +/*---------------------------------------------------------------------------- + * gfx_decoder_detect_video + * + * This routine detects if video exists in the input of the video decoder. + *---------------------------------------------------------------------------- + */ +#if GFX_DECODER_DYNAMIC +int +saa7114_decoder_detect_video(void) +#else +int +gfx_decoder_detect_video(void) +#endif +{ + unsigned char video = 0xff; + + saa7114_read_reg(SAA7114_STATUS, &video); + return !((video & 0x40) >> 6); +} + +/*---------------------------------------------------------------------------- + * gfx_set_decoder_defaults + * + * This routine is called to set the initial register values of the + * video decoder. + *---------------------------------------------------------------------------- + */ +#if GFX_DECODER_DYNAMIC +int +saa7114_set_decoder_defaults(void) +#else +int +gfx_set_decoder_defaults(void) +#endif +{ + unsigned int i; + + /* LOOP THROUGH INDEX/DATA PAIRS IN THE TABLE */ + + for (i = 0; i < GFX_NUM_SAA7114_INIT_VALUES; i++) { + saa7114_write_reg(gfx_saa7114_init_values[i].index, + gfx_saa7114_init_values[i].value); + } + + gfx_decoder_software_reset(); + return (0); +} + +/*---------------------------------------------------------------------------- + * gfx_set_decoder_analog_input + * + * This routine sets the analog input of the video decoder. + *---------------------------------------------------------------------------- + */ +#if GFX_DECODER_DYNAMIC +int +saa7114_set_decoder_analog_input(unsigned char input) +#else +int +gfx_set_decoder_analog_input(unsigned char input) +#endif +{ + saa7114_write_reg(SAA7114_ANALOG_INPUT_CTRL1, input); + return (0); +} + +/*---------------------------------------------------------------------------- + * gfx_set_decoder_brightness + * + * This routine sets the brightness of the video decoder. + *---------------------------------------------------------------------------- + */ +#if GFX_DECODER_DYNAMIC +int +saa7114_set_decoder_brightness(unsigned char brightness) +#else +int +gfx_set_decoder_brightness(unsigned char brightness) +#endif +{ + saa7114_write_reg(SAA7114_BRIGHTNESS, brightness); + return (0); +} + +/*---------------------------------------------------------------------------- + * gfx_set_decoder_contrast + * + * This routine sets the contrast of the video decoder. + *---------------------------------------------------------------------------- + */ +#if GFX_DECODER_DYNAMIC +int +saa7114_set_decoder_contrast(unsigned char contrast) +#else +int +gfx_set_decoder_contrast(unsigned char contrast) +#endif +{ + saa7114_write_reg(SAA7114_CONTRAST, (unsigned char)(contrast >> 1)); + return (0); +} + +/*---------------------------------------------------------------------------- + * gfx_set_decoder_hue + * + * This routine sets the hue control of the video decoder. + *---------------------------------------------------------------------------- + */ +#if GFX_DECODER_DYNAMIC +int +saa7114_set_decoder_hue(char hue) +#else +int +gfx_set_decoder_hue(char hue) +#endif +{ + saa7114_write_reg(SAA7114_HUE, (unsigned char)hue); + return (0); +} + +/*---------------------------------------------------------------------------- + * gfx_set_decoder_saturation + * + * This routine sets the saturation adjustment of the video decoder. + *---------------------------------------------------------------------------- + */ +#if GFX_DECODER_DYNAMIC +int +saa7114_set_decoder_saturation(unsigned char saturation) +#else +int +gfx_set_decoder_saturation(unsigned char saturation) +#endif +{ + saa7114_write_reg(SAA7114_SATURATION, (unsigned char)(saturation >> 1)); + return (0); +} + +/*---------------------------------------------------------------------------- + * gfx_set_decoder_input_offset + * + * This routine sets the size of the decoder input window. + *---------------------------------------------------------------------------- + */ +#if GFX_DECODER_DYNAMIC +int +saa7114_set_decoder_input_offset(unsigned short x, unsigned short y) +#else +int +gfx_set_decoder_input_offset(unsigned short x, unsigned short y) +#endif +{ + /* SET THE INPUT WINDOW OFFSET */ + + saa7114_write_reg(SAA7114_HORZ_OFFSET_LO, (unsigned char)(x & 0x00FF)); + saa7114_write_reg(SAA7114_HORZ_OFFSET_HI, (unsigned char)(x >> 8)); + saa7114_write_reg(SAA7114_VERT_OFFSET_LO, (unsigned char)(y & 0x00FF)); + saa7114_write_reg(SAA7114_VERT_OFFSET_HI, (unsigned char)(y >> 8)); + + gfx_decoder_software_reset(); + return (0); +} + +/*---------------------------------------------------------------------------- + * gfx_set_decoder_input_size + * + * This routine sets the size of the decoder input window. + *---------------------------------------------------------------------------- + */ +#if GFX_DECODER_DYNAMIC +int +saa7114_set_decoder_input_size(unsigned short width, unsigned short height) +#else +int +gfx_set_decoder_input_size(unsigned short width, unsigned short height) +#endif +{ + /* DIVIDE HEIGHT BY TWO FOR INTERLACING */ + + height = (height + 1) >> 1; + + /* SET THE INPUT WINDOW SIZE */ + + saa7114_write_reg(SAA7114_HORZ_INPUT_LO, (unsigned char)(width & 0x00FF)); + saa7114_write_reg(SAA7114_HORZ_INPUT_HI, (unsigned char)(width >> 8)); + saa7114_write_reg(SAA7114_VERT_INPUT_LO, + (unsigned char)(height & 0x00FF)); + saa7114_write_reg(SAA7114_VERT_INPUT_HI, (unsigned char)(height >> 8)); + + gfx_decoder_software_reset(); + return (0); +} + +/*---------------------------------------------------------------------------- + * gfx_set_decoder_output_size + * + * This routine sets the size of the decoder output window. + *---------------------------------------------------------------------------- + */ +#if GFX_DECODER_DYNAMIC +int +saa7114_set_decoder_output_size(unsigned short width, unsigned short height) +#else +int +gfx_set_decoder_output_size(unsigned short width, unsigned short height) +#endif +{ + /* ROUND WIDTH UP TO EVEN NUMBER TO PREVENT DECODER BECOMING STUCK */ + + width = ((width + 1) >> 1) << 1; + + /* DIVIDE HEIGHT BY TWO FOR INTERLACING */ + + height = (height + 1) >> 1; + + /* SET THE OUTPUT WINDOW SIZE */ + + saa7114_write_reg(SAA7114_HORZ_OUTPUT_LO, + (unsigned char)(width & 0x00FF)); + saa7114_write_reg(SAA7114_HORZ_OUTPUT_HI, (unsigned char)(width >> 8)); + saa7114_write_reg(SAA7114_VERT_OUTPUT_LO, + (unsigned char)(height & 0x00FF)); + saa7114_write_reg(SAA7114_VERT_OUTPUT_HI, (unsigned char)(height >> 8)); + + gfx_decoder_software_reset(); + return (0); +} + +/*---------------------------------------------------------------------------- + * gfx_set_decoder_scale + * + * This routine sets the scaling of the video decoder. + *---------------------------------------------------------------------------- + */ +#if GFX_DECODER_DYNAMIC +int +saa7114_set_decoder_scale(unsigned short srcw, unsigned short srch, + unsigned short dstw, unsigned short dsth) +#else +int +gfx_set_decoder_scale(unsigned short srcw, unsigned short srch, + unsigned short dstw, unsigned short dsth) +#endif +{ + unsigned char prescale = 0; + int scale = 0; + + /* SET THE HORIZONTAL PRESCALE */ + /* Downscale from 1 to 1/63 source size. */ + + if (dstw) + prescale = (unsigned char)(srcw / dstw); + if (!prescale) + prescale = 1; + if (prescale > 63) + return (1); + saa7114_write_reg(SAA7114_HORZ_PRESCALER, prescale); + + /* USE FIR PREFILTER FUNCTIONALITY (OPTIMISATION) */ + + if (prescale < 36) { + if (optimize_for_aliasing) { + saa7114_write_reg(SAA7114_HORZ_ACL, + gfx_saa7114_fir_values[prescale - 1].acl_low); + saa7114_write_reg(SAA7114_HORZ_FIR_PREFILTER, + gfx_saa7114_fir_values[prescale - 1].prefilter_low); + } else { + saa7114_write_reg(SAA7114_HORZ_ACL, + gfx_saa7114_fir_values[prescale - 1].acl_high); + saa7114_write_reg(SAA7114_HORZ_FIR_PREFILTER, + gfx_saa7114_fir_values[prescale - 1].prefilter_high); + } + } else { + /* SAME SETTINGS FOR RATIO 1/35 DOWNTO 1/63 */ + if (optimize_for_aliasing) { + saa7114_write_reg(SAA7114_HORZ_ACL, + gfx_saa7114_fir_values[34].acl_low); + saa7114_write_reg(SAA7114_HORZ_FIR_PREFILTER, + gfx_saa7114_fir_values[34].prefilter_low); + } else { + saa7114_write_reg(SAA7114_HORZ_ACL, + gfx_saa7114_fir_values[34].acl_high); + saa7114_write_reg(SAA7114_HORZ_FIR_PREFILTER, + gfx_saa7114_fir_values[34].prefilter_high); + } + } + + /* SET THE HORIZONTAL SCALING */ + + if (!dstw) + return (1); + scale = ((1024 * srcw * 1000) / (dstw * prescale)) / 1000; + if ((scale > 8191) || (scale < 300)) + return (1); + saa7114_write_reg(SAA7114_HSCALE_LUMA_LO, + (unsigned char)(scale & 0x00FF)); + saa7114_write_reg(SAA7114_HSCALE_LUMA_HI, (unsigned char)(scale >> 8)); + scale >>= 1; + saa7114_write_reg(SAA7114_HSCALE_CHROMA_LO, + (unsigned char)(scale & 0x00FF)); + saa7114_write_reg(SAA7114_HSCALE_CHROMA_HI, (unsigned char)(scale >> 8)); + + /* SET THE VERTICAL SCALING (INTERPOLATION MODE) */ + + if (!dsth) + return (1); + + /* ROUND DESTINATION HEIGHT UP TO EVEN NUMBER TO PREVENT DECODER BECOMING + * STUCK */ + + dsth = ((dsth + 1) >> 1) << 1; + + scale = (int)((1024 * srch) / dsth); + saa7114_write_reg(SAA7114_VSCALE_LUMA_LO, + (unsigned char)(scale & 0x00FF)); + saa7114_write_reg(SAA7114_VSCALE_LUMA_HI, (unsigned char)(scale >> 8)); + saa7114_write_reg(SAA7114_VSCALE_CHROMA_LO, + (unsigned char)(scale & 0x00FF)); + saa7114_write_reg(SAA7114_VSCALE_CHROMA_HI, (unsigned char)(scale >> 8)); + + if (dsth >= (srch >> 1)) { + /* USE INTERPOLATION MODE FOR SCALE FACTOR ABOVE 0.5 */ + + saa7114_write_reg(SAA7114_VSCALE_CONTROL, 0x00); + + /* SET VERTICAL PHASE REGISTER FOR CORRECT SCALED INTERLACED OUTPUT + * (OPTIMISATION) */ + /* THE OPTIMISATION IS BASED ON OFIDC = 0 (REG 90h[6] = 0 ) */ + saa7114_write_reg(SAA7114_VSCALE_CHROMA_OFFS0, SAA7114_VSCALE_PHO); + saa7114_write_reg(SAA7114_VSCALE_CHROMA_OFFS1, SAA7114_VSCALE_PHO); + saa7114_write_reg(SAA7114_VSCALE_CHROMA_OFFS2, + (unsigned char)(SAA7114_VSCALE_PHO + scale / 64 - 16)); + saa7114_write_reg(SAA7114_VSCALE_CHROMA_OFFS3, + (unsigned char)(SAA7114_VSCALE_PHO + scale / 64 - 16)); + + saa7114_write_reg(SAA7114_VSCALE_LUMINA_OFFS0, SAA7114_VSCALE_PHO); + saa7114_write_reg(SAA7114_VSCALE_LUMINA_OFFS1, SAA7114_VSCALE_PHO); + saa7114_write_reg(SAA7114_VSCALE_LUMINA_OFFS2, + (unsigned char)(SAA7114_VSCALE_PHO + scale / 64 - 16)); + saa7114_write_reg(SAA7114_VSCALE_LUMINA_OFFS3, + (unsigned char)(SAA7114_VSCALE_PHO + scale / 64 - 16)); + + /* RESTORE CONTRAST AND SATURATION FOR INTERPOLATION MODE */ + + saa7114_write_reg(SAA7114_FILTER_CONTRAST, (unsigned char)0x40); + saa7114_write_reg(SAA7114_FILTER_SATURATION, (unsigned char)0x40); + } else { + /* USE ACCUMULATION MODE FOR DOWNSCALING BY MORE THAN 2x */ + + saa7114_write_reg(SAA7114_VSCALE_CONTROL, 0x01); + + /* SET VERTICAL PHASE OFFSETS OFF (OPTIMISATION) */ + saa7114_write_reg(SAA7114_VSCALE_CHROMA_OFFS0, 0x00); + saa7114_write_reg(SAA7114_VSCALE_CHROMA_OFFS1, 0x00); + saa7114_write_reg(SAA7114_VSCALE_CHROMA_OFFS2, 0x00); + saa7114_write_reg(SAA7114_VSCALE_CHROMA_OFFS3, 0x00); + + saa7114_write_reg(SAA7114_VSCALE_LUMINA_OFFS0, 0x00); + saa7114_write_reg(SAA7114_VSCALE_LUMINA_OFFS1, 0x00); + saa7114_write_reg(SAA7114_VSCALE_LUMINA_OFFS2, 0x00); + saa7114_write_reg(SAA7114_VSCALE_LUMINA_OFFS3, 0x00); + + /* ADJUST CONTRAST AND SATURATION FOR ACCUMULATION MODE */ + + if (srch) + scale = (64 * dsth) / srch; + saa7114_write_reg(SAA7114_FILTER_CONTRAST, (unsigned char)scale); + saa7114_write_reg(SAA7114_FILTER_SATURATION, (unsigned char)scale); + } + + gfx_decoder_software_reset(); + return (0); +} + +/*---------------------------------------------------------------------------- + * gfx_set_decoder_vbi_format + * + * This routine programs the decoder to produce the specified format of VBI + * data for the specified lines. + *---------------------------------------------------------------------------- + */ +#if GFX_DECODER_DYNAMIC +int +saa7114_set_decoder_vbi_format(int start, int end, int format) +#else +int +gfx_set_decoder_vbi_format(int start, int end, int format) +#endif +{ + int i; + unsigned char data; + + for (i = start; i <= end; i++) { + switch (format) { + case VBI_FORMAT_VIDEO: + data = 0xFF; + break; /* Active video */ + case VBI_FORMAT_RAW: + data = 0x77; + break; /* Raw VBI data */ + case VBI_FORMAT_CC: + data = 0x55; + break; /* US CC */ + case VBI_FORMAT_NABTS: + data = 0xCC; + break; /* US NABTS */ + default: + return GFX_STATUS_BAD_PARAMETER; + } + saa7114_write_reg((unsigned char)(0x3F + i), data); + } + return GFX_STATUS_OK; +} + +/*---------------------------------------------------------------------------- + * gfx_set_decoder_vbi_enable + * + * This routine enables or disables VBI transfer in the decoder. + *---------------------------------------------------------------------------- + */ +#if GFX_DECODER_DYNAMIC +int +saa7114_set_decoder_vbi_enable(int enable) +#else +int +gfx_set_decoder_vbi_enable(int enable) +#endif +{ + unsigned char data; + + saa7114_read_reg(SAA7114_IPORT_CONTROL, &data); + if (enable) + data |= 0x80; + else + data &= ~0x80; + saa7114_write_reg(SAA7114_IPORT_CONTROL, data); + return GFX_STATUS_OK; +} + +/*---------------------------------------------------------------------------- + * gfx_set_decoder_TV_standard + * + * This routine configures the decoder for the required TV standard. + *---------------------------------------------------------------------------- + */ +#if GFX_DECODER_DYNAMIC +int +saa7114_set_decoder_TV_standard(TVStandardType TVStandard) +#else +int +gfx_set_decoder_TV_standard(TVStandardType TVStandard) +#endif +{ + switch (TVStandard) { + case TV_STANDARD_NTSC: + saa7114_write_reg(0x0E, 0x89); + saa7114_write_reg(0x5A, 0x06); + break; + case TV_STANDARD_PAL: + saa7114_write_reg(0x0E, 0x81); + saa7114_write_reg(0x5A, 0x03); + break; + default: + return GFX_STATUS_BAD_PARAMETER; + } + gfx_decoder_software_reset(); + return GFX_STATUS_OK; +} + +/*---------------------------------------------------------------------------- + * gfx_set_decoder_luminance_filter + * + * This routine sets the hue control of the video decoder. + *---------------------------------------------------------------------------- + */ +#if GFX_DECODER_DYNAMIC +int +saa7114_set_decoder_luminance_filter(unsigned char lufi) +#else +int +gfx_set_decoder_luminance_filter(unsigned char lufi) +#endif +{ + unsigned char data; + + saa7114_read_reg(SAA7114_LUMINANCE_CONTROL, &data); + saa7114_write_reg(SAA7114_LUMINANCE_CONTROL, + (unsigned char)((data & ~0x0F) | (lufi & 0x0F))); + return (0); +} + +/*************************************************************/ +/* READ ROUTINES | INCLUDED FOR DIAGNOSTIC PURPOSES ONLY */ +/*************************************************************/ + +#if GFX_READ_ROUTINES + +/*---------------------------------------------------------------------------- + * gfx_get_decoder_brightness + * + * This routine returns the current brightness of the video decoder. + *---------------------------------------------------------------------------- + */ +#if GFX_DECODER_DYNAMIC +unsigned char +saa7114_get_decoder_brightness(void) +#else +unsigned char +gfx_get_decoder_brightness(void) +#endif +{ + unsigned char brightness = 0; + + saa7114_read_reg(SAA7114_BRIGHTNESS, &brightness); + return (brightness); +} + +/*---------------------------------------------------------------------------- + * gfx_get_decoder_contrast + * + * This routine returns the current contrast of the video decoder. + *---------------------------------------------------------------------------- + */ +#if GFX_DECODER_DYNAMIC +unsigned char +saa7114_get_decoder_contrast(void) +#else +unsigned char +gfx_get_decoder_contrast(void) +#endif +{ + unsigned char contrast = 0; + + saa7114_read_reg(SAA7114_CONTRAST, &contrast); + contrast <<= 1; + return (contrast); +} + +/*---------------------------------------------------------------------------- + * gfx_get_decoder_hue + * + * This routine returns the current hue of the video decoder. + *---------------------------------------------------------------------------- + */ +#if GFX_DECODER_DYNAMIC +char +saa7114_get_decoder_hue(void) +#else +char +gfx_get_decoder_hue(void) +#endif +{ + unsigned char hue = 0; + + saa7114_read_reg(SAA7114_HUE, &hue); + return ((char)hue); +} + +/*---------------------------------------------------------------------------- + * gfx_get_decoder_saturation + * + * This routine returns the current saturation of the video decoder. + *---------------------------------------------------------------------------- + */ +#if GFX_DECODER_DYNAMIC +unsigned char +saa7114_get_decoder_saturation(void) +#else +unsigned char +gfx_get_decoder_saturation(void) +#endif +{ + unsigned char saturation = 0; + + saa7114_read_reg(SAA7114_SATURATION, &saturation); + saturation <<= 1; + return (saturation); +} + +/*---------------------------------------------------------------------------- + * gfx_get_decoder_input_offset + * + * This routine returns the offset into the input window. + *---------------------------------------------------------------------------- + */ +#if GFX_DECODER_DYNAMIC +unsigned long +saa7114_get_decoder_input_offset(void) +#else +unsigned long +gfx_get_decoder_input_offset(void) +#endif +{ + unsigned long value = 0; + unsigned char data; + + saa7114_read_reg(SAA7114_HORZ_OFFSET_LO, &data); + value = (unsigned long)data; + saa7114_read_reg(SAA7114_HORZ_OFFSET_HI, &data); + value |= ((unsigned long)data) << 8; + saa7114_read_reg(SAA7114_VERT_OFFSET_LO, &data); + value |= ((unsigned long)data) << 16; + saa7114_read_reg(SAA7114_VERT_OFFSET_HI, &data); + value |= ((unsigned long)data) << 24; + return (value); +} + +/*---------------------------------------------------------------------------- + * gfx_get_decoder_input_size + * + * This routine returns the current size of the input window + *---------------------------------------------------------------------------- + */ +#if GFX_DECODER_DYNAMIC +unsigned long +saa7114_get_decoder_input_size(void) +#else +unsigned long +gfx_get_decoder_input_size(void) +#endif +{ + unsigned long value = 0; + unsigned char data; + + saa7114_read_reg(SAA7114_HORZ_INPUT_LO, &data); + value = (unsigned long)data; + saa7114_read_reg(SAA7114_HORZ_INPUT_HI, &data); + value |= ((unsigned long)data) << 8; + saa7114_read_reg(SAA7114_VERT_INPUT_LO, &data); + value |= ((unsigned long)data) << 17; + saa7114_read_reg(SAA7114_VERT_INPUT_HI, &data); + value |= ((unsigned long)data) << 25; + return (value); +} + +/*---------------------------------------------------------------------------- + * gfx_get_decoder_output_size + * + * This routine returns the current size of the output window. + *---------------------------------------------------------------------------- + */ +#if GFX_DECODER_DYNAMIC +unsigned long +saa7114_get_decoder_output_size(void) +#else +unsigned long +gfx_get_decoder_output_size(void) +#endif +{ + unsigned long value = 0; + unsigned char data; + + saa7114_read_reg(SAA7114_HORZ_OUTPUT_LO, &data); + value = (unsigned long)data; + saa7114_read_reg(SAA7114_HORZ_OUTPUT_HI, &data); + value |= ((unsigned long)data) << 8; + saa7114_read_reg(SAA7114_VERT_OUTPUT_LO, &data); + value |= ((unsigned long)data) << 17; + saa7114_read_reg(SAA7114_VERT_OUTPUT_HI, &data); + value |= ((unsigned long)data) << 25; + return (value); +} + +/*---------------------------------------------------------------------------- + * gfx_get_decoder_vbi_format + * + * This routine returns the current format of VBI data for the specified line. + *---------------------------------------------------------------------------- + */ +#if GFX_DECODER_DYNAMIC +int +saa7114_get_decoder_vbi_format(int line) +#else +int +gfx_get_decoder_vbi_format(int line) +#endif +{ + unsigned char format = 0, data; + + saa7114_read_reg((unsigned char)(0x3F + line), &data); + switch (data) { + case 0xFF: + format = VBI_FORMAT_VIDEO; + break; /* Active video */ + case 0x77: + format = VBI_FORMAT_RAW; + break; /* Raw VBI data */ + case 0x55: + format = VBI_FORMAT_CC; + break; /* US CC */ + case 0xCC: + format = VBI_FORMAT_NABTS; + break; /* US NABTS */ + } + return (format); +} + +#endif /* GFX_READ_ROUTINES */ + +/* END OF FILE */ diff --git a/src/gfx/tv_1200.c b/src/gfx/tv_1200.c new file mode 100644 index 0000000..a75cc32 --- /dev/null +++ b/src/gfx/tv_1200.c @@ -0,0 +1,967 @@ +/* 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 to control the SC1200 TVOUT and TV encoder. + * */ + +/*---------------------------------------------------------------------------- + * gfx_set_tv_format + * + * This routine sets the TV encoder registers to the specified format + * and resolution. + *---------------------------------------------------------------------------- + */ +#if GFX_TV_DYNAMIC +int +sc1200_set_tv_format(TVStandardType format, GfxOnTVType resolution) +#else +int +gfx_set_tv_format(TVStandardType format, GfxOnTVType resolution) +#endif +{ + unsigned long ctrl2, mode; + + /* Save TV output mode */ + ctrl2 = + READ_VID32(SC1200_TVENC_TIM_CTRL_2) & (SC1200_TVENC_OUTPUT_YCBCR | + SC1200_TVENC_CFS_MASK); + /* Save flicker filter setting */ + mode = + READ_VID32(SC1200_TVOUT_HORZ_SCALING) & + SC1200_TVOUT_FLICKER_FILTER_MASK; + + switch (format) { + case TV_STANDARD_NTSC: + /* Horizontal Sync Start is 848 */ + /* Horizontal Sync End is 856 */ + WRITE_VID32(SC1200_TVOUT_HORZ_SYNC, 0x03580350); + /* Vertical Sync Start is 0 */ + /* Vertical Sync End is 1 */ + /* Vertical Display Start Skew is 1 */ + /* Vertical Display End Skew is 1 */ + WRITE_VID32(SC1200_TVOUT_VERT_SYNC, 0x05001000); + /* Disable vertical down scaling, take all lines */ + if (gfx_chip_revision <= SC1200_REV_B3) + WRITE_VID32(SC1200_TVOUT_VERT_DOWNSCALE, 0xffffffff); + /* Enable video timing */ + /* Reset sub carrier every two frames */ + /* Disable BLANK */ + /* Enable color burst */ + /* Add the IRE offset */ + /* NTSC color encoding */ + /* Video generator timing is 525 lines / 60Hz */ + /* Horizontal and Vertical counters are initialized to HPHASE & + * VPHASE */ + /* VPHASE is 2, HPHASE is 0x50 */ + WRITE_VID32(SC1200_TVENC_TIM_CTRL_1, 0xa2a01050); + /* Increase horizontal blanking interval */ + /* Low Water Mark for Y is 0x1F */ + /* Low Water Mark for Cb is 0xF */ + /* HUE is 0 */ + /* SCPHASE is 0xF9 */ + WRITE_VID32(SC1200_TVENC_TIM_CTRL_2, 0x9ff000f9 | ctrl2); + /* Subcarrier Frequency is 3.579545 MHz */ + WRITE_VID32(SC1200_TVENC_SUB_FREQ, 0x21f07c1f); + /* VSTART is 18, HSTART is 113 */ + WRITE_VID32(SC1200_TVENC_DISP_POS, 0x00120071); + /* Display size: HEIGHT is 239, WIDTH is 719 */ + WRITE_VID32(SC1200_TVENC_DISP_SIZE, 0x00ef02cf); + switch (resolution) { + case GFX_ON_TV_SQUARE_PIXELS: + if (gfx_chip_revision <= SC1200_REV_B3) { + /* Horizontal Display start is 116 */ + /* Total number of pixels per line is 857 */ + WRITE_VID32(SC1200_TVOUT_HORZ_TIM, 0x00740359); + /* HSYNC generated in the TV Encoder module */ + /* Interval between resets of TV Encoder is once every odd + * field */ + /* Enable Horizontal interpolation */ + /* Enable Horizontal up scaling 9/8 */ + /* Disable Horizontal downscale */ + WRITE_VID32(SC1200_TVOUT_HORZ_SCALING, 0x10020700 | mode); + /* Horizontal display end is 919, i.e. 720 active pixels */ + /* Total number of display lines per field is 240 */ + WRITE_VID32(SC1200_TVOUT_LINE_END, 0x039700f0); + } else { /* Use new scaler available in Rev. C */ + /* Horizontal Display start is 111 */ + /* Total number of pixels per line is 857 */ + WRITE_VID32(SC1200_TVOUT_HORZ_TIM, 0x006f0359); + /* HSYNC generated in the TV Encoder module */ + /* Interval between resets of TV Encoder is once every odd + * field */ + /* Enable Horizontal interpolation */ + /* Disable Horizontal up scaling 9/8 */ + /* Disable Horizontal downscale */ + WRITE_VID32(SC1200_TVOUT_HORZ_SCALING, 0x10020500 | mode); + /* Set Horizontal upscaling to 64/58 (~ 11/10) */ + WRITE_VID32(SC1200_TVOUT_HORZ_PRE_ENCODER_SCALE, 0x3A000000); + /* Horizontal display end is 900, i.e. 706 active pixels */ + /* Total number of display lines per field is 240 */ + WRITE_VID32(SC1200_TVOUT_LINE_END, 0x038400f0); + } + break; + case GFX_ON_TV_NO_SCALING: + /* Horizontal Display start is 116 */ + /* Total number of pixels per line is 857 */ + WRITE_VID32(SC1200_TVOUT_HORZ_TIM, 0x00740359); + /* HSYNC generated in the TV Encoder module */ + /* Interval between resets of TV Encoder is once every odd field */ + /* Enable Horizontal interpolation */ + /* Disable Horizontal up scaling 9/8 */ + /* Disable Horizontal downscale */ + WRITE_VID32(SC1200_TVOUT_HORZ_SCALING, 0x10020500 | mode); + /* Disable Horizontal scaling (set to 64/64) */ + if (gfx_chip_revision >= SC1200_REV_C1) + WRITE_VID32(SC1200_TVOUT_HORZ_PRE_ENCODER_SCALE, 0x40000000); + /* Horizontal display end is 919, i.e. 720 active pixels */ + /* Total number of display lines per field is 240 */ + WRITE_VID32(SC1200_TVOUT_LINE_END, 0x039700f0); + break; + default: + return (GFX_STATUS_BAD_PARAMETER); + } + break; + case TV_STANDARD_PAL: + /* Horizontal Sync Start is 854 */ + /* Horizontal Sync End is 862 */ + WRITE_VID32(SC1200_TVOUT_HORZ_SYNC, 0x035e0356); + /* Vertical Sync Start is 0 */ + /* Vertical Sync End is 1 */ + /* Vertical Display Start Skew is 1 */ + /* Vertical Display End Skew is 1 */ + WRITE_VID32(SC1200_TVOUT_VERT_SYNC, 0x05001000); + /* Disable vertical down scaling, take all lines */ + if (gfx_chip_revision <= SC1200_REV_B3) + WRITE_VID32(SC1200_TVOUT_VERT_DOWNSCALE, 0xffffffff); + /* Enable video timing */ + /* Never reset sub carrier (should be every 4 frames but doesn't work + * with genlock) */ + /* Disable BLANK */ + /* Enable color burst */ + /* Do not add the IRE offset */ + /* NTSC color encoding */ + /* Video generator timing is 625 lines / 50Hz */ + /* Horizontal and Vertical counters are initialized to HPHASE & VPHASE + * */ + /* VPHASE is 2, HPHASE is 50 */ + WRITE_VID32(SC1200_TVENC_TIM_CTRL_1, 0xB1201050); + /* Increase horizontal blanking interval */ + /* Low Water Mark for Y is 0x1F */ + /* Low Water Mark for Cb is 0xF */ + /* HUE is 0 */ + /* SCPHASE is 0xD9 */ + WRITE_VID32(SC1200_TVENC_TIM_CTRL_2, 0x9ff000d9 | ctrl2); + /* Subcarrier Frequency is 4.43361875 MHz */ + WRITE_VID32(SC1200_TVENC_SUB_FREQ, 0x2a098acb); + /* VSTART is 22, HSTART is 123 */ + WRITE_VID32(SC1200_TVENC_DISP_POS, 0x0016007b); + /* Display size: HEIGHT is 287, WIDTH is 719 */ + WRITE_VID32(SC1200_TVENC_DISP_SIZE, 0x011f02cf); + switch (resolution) { + case GFX_ON_TV_NO_SCALING: + /* Horizontal Display start is 124 */ + /* Total number of pixels per line is 863 */ + WRITE_VID32(SC1200_TVOUT_HORZ_TIM, 0x007c035f); + /* HSYNC generated in the TV Encoder module */ + /* Interval between resets of TV Encoder is once every odd field */ + /* Enable Horizontal interpolation */ + /* Disable Horizontal up scaling 9/8 */ + /* Disable Horizontal downscale */ + WRITE_VID32(SC1200_TVOUT_HORZ_SCALING, 0x10020500 | mode); + /* Disable Horizontal scaling (set to 64/64) */ + if (gfx_chip_revision >= SC1200_REV_C1) + WRITE_VID32(SC1200_TVOUT_HORZ_PRE_ENCODER_SCALE, 0x40000000); + /* Horizontal display end is 924, i.e. 720 active pixels */ + /* Total number of display lines per field is 288 */ + WRITE_VID32(SC1200_TVOUT_LINE_END, 0x039c0120); + break; + case GFX_ON_TV_SQUARE_PIXELS: + /* Horizontal Display start is 122 */ + /* Total number of pixels per line is 863 */ + WRITE_VID32(SC1200_TVOUT_HORZ_TIM, 0x007a035f); + if (gfx_chip_revision <= SC1200_REV_B3) { + /* HSYNC generated in the TV Encoder module */ + /* Interval between resets of TV Encoder is once every odd + * field */ + /* Enable Horizontal interpolation */ + /* Disable Horizontal up scaling 9/8 */ + /* Horizontal downscale m/(m+1), m = 11, (i.e. 11/12 - closest + * possible to 54/59) */ + WRITE_VID32(SC1200_TVOUT_HORZ_SCALING, 0x1002040b | mode); + /* Horizontal display end is 906, i.e. 704 active pixels */ + /* Total number of display lines per field is 288 */ + WRITE_VID32(SC1200_TVOUT_LINE_END, 0x038a0120); + } else { + /* HSYNC generated in the TV Encoder module */ + /* Interval between resets of TV Encoder is once every odd + * field */ + /* Enable Horizontal interpolation */ + /* Disable Horizontal up scaling 9/8 */ + /* Disable Horizontal downscale */ + WRITE_VID32(SC1200_TVOUT_HORZ_SCALING, 0x10020500 | mode); + /* Set Horizontal down scaling to 64/70 (closest possible to + * 54/59) */ + WRITE_VID32(SC1200_TVOUT_HORZ_PRE_ENCODER_SCALE, 0x46000000); + /* Horizontal display end is 904, i.e. 702 active pixels */ + /* Total number of display lines per field is 288 */ + WRITE_VID32(SC1200_TVOUT_LINE_END, 0x03880120); + } + break; + default: + return (GFX_STATUS_BAD_PARAMETER); + } + break; + default: + return (GFX_STATUS_BAD_PARAMETER); + } + return (GFX_STATUS_OK); +} + +/*---------------------------------------------------------------------------- + * gfx_set_tv_output + * + * This routine sets the TV encoder registers to the specified output type. + * Supported output types are : S-VIDEO, Composite, YUV and SCART. + *---------------------------------------------------------------------------- + */ +#if GFX_TV_DYNAMIC +int +sc1200_set_tv_output(int output) +#else +int +gfx_set_tv_output(int output) +#endif +{ + unsigned long ctrl2, ctrl3; + + ctrl2 = READ_VID32(SC1200_TVENC_TIM_CTRL_2); + ctrl3 = READ_VID32(SC1200_TVENC_TIM_CTRL_3); + ctrl2 &= ~(SC1200_TVENC_OUTPUT_YCBCR | SC1200_TVENC_CFS_MASK); + ctrl3 &= + ~(SC1200_TVENC_CM | SC1200_TVENC_SYNCMODE_MASK | SC1200_TVENC_CS); + switch (output) { + case TV_OUTPUT_COMPOSITE: + /* Analog outputs provide Y, C and CVBS */ + /* Chrominance Lowpass filter is 1.3MHz (for composite video output) */ + WRITE_VID32(SC1200_TVENC_TIM_CTRL_2, ctrl2 | SC1200_TVENC_CFS_CVBS); + WRITE_VID32(SC1200_TVENC_TIM_CTRL_3, ctrl3); + break; + case TV_OUTPUT_S_VIDEO: + /* Analog outputs provide Y, C and CVBS */ + /* Chrominance Lowpass filter is 1.8MHz (for S-video output) */ + WRITE_VID32(SC1200_TVENC_TIM_CTRL_2, ctrl2 | SC1200_TVENC_CFS_SVIDEO); + WRITE_VID32(SC1200_TVENC_TIM_CTRL_3, ctrl3); + break; + case TV_OUTPUT_YUV: + /* Analog outputs provide Y, Cb and Cr */ + /* A 7.5 IRE setup is applied to the output */ + WRITE_VID32(SC1200_TVENC_TIM_CTRL_2, + ctrl2 | SC1200_TVENC_OUTPUT_YCBCR | SC1200_TVENC_CFS_BYPASS); + WRITE_VID32(SC1200_TVENC_TIM_CTRL_3, + ctrl3 | SC1200_TVENC_CM | SC1200_TVENC_CS); + break; + case TV_OUTPUT_SCART: + /* Analog outputs provide SCART (RGB and CVBS) */ + /* Sync is added to green signal */ + WRITE_VID32(SC1200_TVENC_TIM_CTRL_2, ctrl2 | SC1200_TVENC_CFS_CVBS); + WRITE_VID32(SC1200_TVENC_TIM_CTRL_3, + ctrl3 | SC1200_TVENC_CM | SC1200_TVENC_SYNC_ON_GREEN); + break; + default: + return (GFX_STATUS_BAD_PARAMETER); + } + + /* Adjusts the internal voltage reference */ + ctrl2 = READ_VID32(SC1200_TVENC_DAC_CONTROL); + ctrl2 &= ~SC1200_TVENC_TRIM_MASK; + + /* Bypass for issue #926 : Inadequate chroma level of S-Video output */ + if ((gfx_chip_revision == SC1200_REV_B3) && (output == TV_OUTPUT_S_VIDEO)) + ctrl2 |= 0x7; + else + ctrl2 |= 0x5; + + WRITE_VID32(SC1200_TVENC_DAC_CONTROL, ctrl2); + + /* Disable 4:2:2 to 4:4:4 converter interpolation */ + WRITE_VID32(SC1200_TVOUT_DEBUG, SC1200_TVOUT_CONVERTER_INTERPOLATION); + + return (GFX_STATUS_OK); +} + +/*---------------------------------------------------------------------------- + * gfx_set_tv_enable + * + * This routine enables or disables the TV output. + *---------------------------------------------------------------------------- + */ +#if GFX_TV_DYNAMIC +int +sc1200_set_tv_enable(int enable) +#else +int +gfx_set_tv_enable(int enable) +#endif +{ + unsigned long value_tim, value_dac; + + value_tim = READ_VID32(SC1200_TVENC_TIM_CTRL_1); + value_dac = READ_VID32(SC1200_TVENC_DAC_CONTROL); + + if (enable) { + value_tim |= SC1200_TVENC_VIDEO_TIMING_ENABLE; + value_dac &= ~SC1200_TVENC_POWER_DOWN; + /* ENABLE GRAPHICS DISPLAY LOGIC IN VIDEO PROCESSOR */ + gfx_set_screen_enable(1); + } else { + value_tim &= ~SC1200_TVENC_VIDEO_TIMING_ENABLE; + value_dac |= SC1200_TVENC_POWER_DOWN; + /* Do not disable the graphics display logic because it might be + * needed for CRT */ + } + + WRITE_VID32(SC1200_TVENC_TIM_CTRL_1, value_tim); + WRITE_VID32(SC1200_TVENC_DAC_CONTROL, value_dac); + + return (GFX_STATUS_OK); +} + +/*---------------------------------------------------------------------------- + * gfx_set_tv_flicker_filter + * + * This routine configures the TV out flicker filter. + *---------------------------------------------------------------------------- + */ +#if GFX_TV_DYNAMIC +int +sc1200_set_tv_flicker_filter(int ff) +#else +int +gfx_set_tv_flicker_filter(int ff) +#endif +{ + unsigned long mode; + + mode = READ_VID32(SC1200_TVOUT_HORZ_SCALING); + mode &= ~SC1200_TVOUT_FLICKER_FILTER_MASK; + switch (ff) { + case TV_FLICKER_FILTER_NONE: + WRITE_VID32(SC1200_TVOUT_HORZ_SCALING, + mode | SC1200_TVOUT_FLICKER_FILTER_DISABLED); + break; + case TV_FLICKER_FILTER_NORMAL: + WRITE_VID32(SC1200_TVOUT_HORZ_SCALING, + mode | SC1200_TVOUT_FLICKER_FILTER_FOURTH_HALF_FOURTH); + break; + case TV_FLICKER_FILTER_INTERLACED: + WRITE_VID32(SC1200_TVOUT_HORZ_SCALING, + mode | SC1200_TVOUT_FLICKER_FILTER_HALF_ONE_HALF); + break; + default: + return GFX_STATUS_BAD_PARAMETER; + } + return (GFX_STATUS_OK); +} + +/*---------------------------------------------------------------------------- + * gfx_set_tv_sub_carrier_reset + * + * This routine configures the TV encoder sub carrier reset interval. + *---------------------------------------------------------------------------- + */ +#if GFX_TV_DYNAMIC +int +sc1200_set_tv_sub_carrier_reset(int screset) +#else +int +gfx_set_tv_sub_carrier_reset(int screset) +#endif +{ + unsigned long mode; + + mode = READ_VID32(SC1200_TVENC_TIM_CTRL_1); + mode &= ~SC1200_TVENC_SUB_CARRIER_RESET_MASK; + switch (screset) { + case TV_SUB_CARRIER_RESET_NEVER: + WRITE_VID32(SC1200_TVENC_TIM_CTRL_1, + mode | SC1200_TVENC_SUB_CARRIER_RESET_NEVER); + break; + case TV_SUB_CARRIER_RESET_EVERY_TWO_LINES: + WRITE_VID32(SC1200_TVENC_TIM_CTRL_1, + mode | SC1200_TVENC_SUB_CARRIER_RESET_EVERY_TWO_LINES); + break; + case TV_SUB_CARRIER_RESET_EVERY_TWO_FRAMES: + WRITE_VID32(SC1200_TVENC_TIM_CTRL_1, + mode | SC1200_TVENC_SUB_CARRIER_RESET_EVERY_TWO_FRAMES); + break; + case TV_SUB_CARRIER_RESET_EVERY_FOUR_FRAMES: + WRITE_VID32(SC1200_TVENC_TIM_CTRL_1, + mode | SC1200_TVENC_SUB_CARRIER_RESET_EVERY_FOUR_FRAMES); + break; + default: + return GFX_STATUS_BAD_PARAMETER; + } + return (GFX_STATUS_OK); +} + +/*---------------------------------------------------------------------------- + * gfx_set_tv_vphase + * + * This routine sets the tv encoder VPHASE value. + *---------------------------------------------------------------------------- + */ +#if GFX_TV_DYNAMIC +int +sc1200_set_tv_vphase(int vphase) +#else +int +gfx_set_tv_vphase(int vphase) +#endif +{ + unsigned long mode = READ_VID32(SC1200_TVENC_TIM_CTRL_1); + + mode &= ~SC1200_TVENC_VPHASE_MASK; + mode |= (vphase << SC1200_TVENC_VPHASE_POS) & SC1200_TVENC_VPHASE_MASK; + WRITE_VID32(SC1200_TVENC_TIM_CTRL_1, mode); + return (GFX_STATUS_OK); +} + +/*---------------------------------------------------------------------------- + * gfx_set_tv_YC_delay + * + * This routine configures the TV out Y/C delay. + *---------------------------------------------------------------------------- + */ +#if GFX_TV_DYNAMIC +int +sc1200_set_tv_YC_delay(int delay) +#else +int +gfx_set_tv_YC_delay(int delay) +#endif +{ + unsigned long mode; + + /* This feature is implemented in Rev C1 */ + if (gfx_chip_revision < SC1200_REV_C1) + return (GFX_STATUS_OK); + + mode = READ_VID32(SC1200_TVOUT_HORZ_PRE_ENCODER_SCALE); + mode &= ~SC1200_TVOUT_YC_DELAY_MASK; + switch (delay) { + case TV_YC_DELAY_NONE: + WRITE_VID32(SC1200_TVOUT_HORZ_PRE_ENCODER_SCALE, + mode | SC1200_TVOUT_YC_DELAY_NONE); + break; + case TV_Y_DELAY_ONE_PIXEL: + WRITE_VID32(SC1200_TVOUT_HORZ_PRE_ENCODER_SCALE, + mode | SC1200_TVOUT_Y_DELAY_ONE_PIXEL); + break; + case TV_C_DELAY_ONE_PIXEL: + WRITE_VID32(SC1200_TVOUT_HORZ_PRE_ENCODER_SCALE, + mode | SC1200_TVOUT_C_DELAY_ONE_PIXEL); + break; + case TV_C_DELAY_TWO_PIXELS: + WRITE_VID32(SC1200_TVOUT_HORZ_PRE_ENCODER_SCALE, + mode | SC1200_TVOUT_C_DELAY_TWO_PIXELS); + break; + default: + return GFX_STATUS_BAD_PARAMETER; + } + return (GFX_STATUS_OK); +} + +/*---------------------------------------------------------------------------- + * gfx_set_tvenc_reset_interval + * + * This routine sets the interval between external resets of the TV encoder + * timing generator by the TV out. + *---------------------------------------------------------------------------- + */ +#if GFX_TV_DYNAMIC +int +sc1200_set_tvenc_reset_interval(int interval) +#else +int +gfx_set_tvenc_reset_interval(int interval) +#endif +{ + unsigned long value; + + value = READ_VID32(SC1200_TVOUT_HORZ_SCALING); + value &= ~SC1200_TVENC_EXTERNAL_RESET_INTERVAL_MASK; + switch (interval) { + case TVENC_RESET_EVERY_ODD_FIELD: + WRITE_VID32(SC1200_TVOUT_HORZ_SCALING, + value | SC1200_TVENC_EXTERNAL_RESET_EVERY_ODD_FIELD); + break; + case TVENC_RESET_EVERY_EVEN_FIELD: + WRITE_VID32(SC1200_TVOUT_HORZ_SCALING, + value | SC1200_TVENC_EXTERNAL_RESET_EVERY_EVEN_FIELD); + break; + case TVENC_RESET_NEXT_ODD_FIELD: + WRITE_VID32(SC1200_TVOUT_HORZ_SCALING, + value | SC1200_TVENC_EXTERNAL_RESET_NEXT_ODD_FIELD); + break; + case TVENC_RESET_NEXT_EVEN_FIELD: + WRITE_VID32(SC1200_TVOUT_HORZ_SCALING, + value | SC1200_TVENC_EXTERNAL_RESET_NEXT_EVEN_FIELD); + break; + case TVENC_RESET_EVERY_FIELD: + WRITE_VID32(SC1200_TVOUT_HORZ_SCALING, + value | SC1200_TVENC_EXTERNAL_RESET_EVERY_FIELD); + break; + case TVENC_RESET_EVERY_X_ODD_FIELDS: + case TVENC_RESET_EVERY_X_EVEN_FIELDS: + return GFX_STATUS_UNSUPPORTED; + default: + return GFX_STATUS_BAD_PARAMETER; + } + return (GFX_STATUS_OK); +} + +/*---------------------------------------------------------------------------- + * gfx_set_tv_cc_enable + * + * This routine enables or disables the use of the hardware CC registers + * in the TV encoder. + *---------------------------------------------------------------------------- + */ +#if GFX_TV_DYNAMIC +int +sc1200_set_tv_cc_enable(int enable) +#else +int +gfx_set_tv_cc_enable(int enable) +#endif +{ + unsigned long value; + + value = READ_VID32(SC1200_TVENC_CC_CONTROL); + value &= ~(0x0005F); + if (enable) + value |= 0x51; + WRITE_VID32(SC1200_TVENC_CC_CONTROL, value); + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_set_tv_display + * + * This routine sets the timings in the display controller to support a + * TV resolution. + *--------------------------------------------------------------------------- + */ +#if GFX_TV_DYNAMIC +int +sc1200_set_tv_display(int width, int height) +#else +int +gfx_set_tv_display(int width, int height) +#endif +{ + DISPLAYMODE *pMode; + unsigned int i; + + for (i = 0; i < NUM_TV_MODES; i++) { + pMode = &TVTimings[i]; + if ((unsigned)width == pMode->hactive + && (unsigned)height == pMode->vactive) + break; + } + + if (i == NUM_TV_MODES) + return 0; + + gfx_set_display_timings(gfx_get_display_bpp(), + (unsigned short)pMode->flags, pMode->hactive, pMode->hblankstart, + pMode->hsyncstart, pMode->hsyncend, pMode->hblankend, pMode->htotal, + pMode->vactive, pMode->vblankstart, pMode->vsyncstart, + pMode->vsyncend, pMode->vblankend, pMode->vtotal, pMode->frequency); + + return 1; +} + +/*---------------------------------------------------------------------------- + * cc_add_parity_bit + * + * This routine adds the (odd) parity bit to the data character. + *---------------------------------------------------------------------------- + */ +unsigned char +cc_add_parity_bit(unsigned char data) +{ + int i, num = 0; + unsigned char d = data; + + for (i = 0; i < 7; i++) { + if (d & 0x1) + num++; + d >>= 1; + } + if (num & 0x1) + return (data & ~0x80); + else + return (data | 0x80); +} + +/*---------------------------------------------------------------------------- + * gfx_set_tv_cc_data + * + * This routine writes the two specified characters to the CC data register + * of the TV encoder. + *---------------------------------------------------------------------------- + */ +#if GFX_TV_DYNAMIC +int +sc1200_set_tv_cc_data(unsigned char data1, unsigned char data2) +#else +int +gfx_set_tv_cc_data(unsigned char data1, unsigned char data2) +#endif +{ + unsigned long value; + + value = cc_add_parity_bit(data1) | (cc_add_parity_bit(data2) << 8); + WRITE_VID32(SC1200_TVENC_CC_DATA, value); + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_test_tvout_odd_field + * + * This routine returns 1 if the current TVout field is odd. Otherwise returns + * 0. + *--------------------------------------------------------------------------- + */ +#if GFX_TV_DYNAMIC +int +sc1200_test_tvout_odd_field(void) +#else +int +gfx_test_tvout_odd_field(void) +#endif +{ + unsigned long debug = READ_VID32(SC1200_TVOUT_DEBUG); + + WRITE_VID32(SC1200_TVOUT_DEBUG, debug | SC1200_TVOUT_FIELD_STATUS_TV); + if (READ_VID32(SC1200_TVOUT_DEBUG) & SC1200_TVOUT_FIELD_STATUS_EVEN) + return (0); + else + return (1); +} + +/*--------------------------------------------------------------------------- + * gfx_test_tvenc_odd_field + * + * This routine returns 1 if the current TV encoder field is odd. Otherwise + * returns 0. + *--------------------------------------------------------------------------- + */ +#if GFX_TV_DYNAMIC +int +sc1200_test_tvenc_odd_field(void) +#else +int +gfx_test_tvenc_odd_field(void) +#endif +{ + unsigned long debug = READ_VID32(SC1200_TVOUT_DEBUG); + + WRITE_VID32(SC1200_TVOUT_DEBUG, debug & ~SC1200_TVOUT_FIELD_STATUS_TV); + if (READ_VID32(SC1200_TVOUT_DEBUG) & SC1200_TVOUT_FIELD_STATUS_EVEN) + return (0); + else + return (1); +} + +/*---------------------------------------------------------------------------- + * gfx_set_tv_field_status_invert + * + * This routines determines whether the tvout/tvencoder field status bit is + * inverted (enable = 1) or not (enable = 0). + *---------------------------------------------------------------------------- + */ +#if GFX_TV_DYNAMIC +int +sc1200_set_tv_field_status_invert(int enable) +#else +int +gfx_set_tv_field_status_invert(int enable) +#endif +{ + unsigned long value; + + value = READ_VID32(SC1200_TVOUT_DEBUG); + + if (enable) { + value |= SC1200_TVOUT_FIELD_STATUS_INVERT; + } else { + value &= ~(SC1200_TVOUT_FIELD_STATUS_INVERT); + } + + WRITE_VID32(SC1200_TVOUT_DEBUG, value); + + return (GFX_STATUS_OK); +} + +/*--------------------------------------------------------------------------- + * gfx_get_tv_vphase + * + * This routine returns the tv encoder vertical phase. + *--------------------------------------------------------------------------- + */ +#if GFX_TV_DYNAMIC +int +sc1200_get_tv_vphase(void) +#else +int +gfx_get_tv_vphase(void) +#endif +{ + unsigned long mode = READ_VID32(SC1200_TVENC_TIM_CTRL_1); + + return (int)((mode & SC1200_TVENC_VPHASE_MASK) >> + SC1200_TVENC_VPHASE_POS); +} + +/*--------------------------------------------------------------------------- + * gfx_get_tv_enable + * + * This routine returns the current tv enable status + *--------------------------------------------------------------------------- + */ +#if GFX_TV_DYNAMIC +int +sc1200_get_tv_enable(unsigned int *p_on) +#else +int +gfx_get_tv_enable(unsigned int *p_on) +#endif +{ + unsigned long control = READ_VID32(SC1200_TVENC_DAC_CONTROL); + + *p_on = (unsigned int)(!(control & SC1200_TVENC_POWER_DOWN)); + + return GFX_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * gfx_get_tv_output + * + * This routine returns the current programmed TV output type. It does not + * detect invalid configurations. + *--------------------------------------------------------------------------- + */ +#if GFX_TV_DYNAMIC +int +sc1200_get_tv_output(void) +#else +int +gfx_get_tv_output(void) +#endif +{ + unsigned long ctrl2, ctrl3; + int format = 0; + + ctrl2 = READ_VID32(SC1200_TVENC_TIM_CTRL_2); + ctrl3 = READ_VID32(SC1200_TVENC_TIM_CTRL_3); + + if ((ctrl2 & SC1200_TVENC_CFS_MASK) == SC1200_TVENC_CFS_SVIDEO) + format = TV_OUTPUT_S_VIDEO; + else if (ctrl2 & SC1200_TVENC_OUTPUT_YCBCR) + format = TV_OUTPUT_YUV; + else if ((ctrl2 & SC1200_TVENC_CFS_MASK) == SC1200_TVENC_CFS_CVBS) { + if (ctrl3 & SC1200_TVENC_CM) + format = TV_OUTPUT_SCART; + else + format = TV_OUTPUT_COMPOSITE; + } + + return format; +} + +/*--------------------------------------------------------------------------- + * gfx_get_tv_mode_count + * + * This routine returns the number of valid TV out resolutions. + *--------------------------------------------------------------------------- + */ +#if GFX_TV_DYNAMIC +int +sc1200_get_tv_mode_count(TVStandardType format) +#else +int +gfx_get_tv_mode_count(TVStandardType format) +#endif +{ + unsigned int mode, count = 0; + unsigned long flag; + + switch (format) { + case TV_STANDARD_NTSC: + flag = GFX_MODE_TV_NTSC; + break; + case TV_STANDARD_PAL: + flag = GFX_MODE_TV_PAL; + break; + default: + return 0; + } + + for (mode = 0; mode < NUM_TV_MODES; mode++) { + if (TVTimings[mode].flags & flag) + count++; + } + + return count; +} + +/*--------------------------------------------------------------------------- + * gfx_get_tv_display_mode + * + * This routine returns the current TV display parameters. + *--------------------------------------------------------------------------- + */ +#if GFX_TV_DYNAMIC +int +sc1200_get_tv_display_mode(int *width, int *height, int *bpp, int *hz) +#else +int +gfx_get_tv_display_mode(int *width, int *height, int *bpp, int *hz) +#endif +{ + unsigned long frequency; + unsigned long mode, flags; + + *width = gfx_get_hactive(); + *height = gfx_get_vactive(); + *bpp = gfx_get_display_bpp(); + frequency = gfx_get_clock_frequency(); + + for (mode = 0; mode < NUM_TV_MODES; mode++) { + if (TVTimings[mode].hactive == (unsigned short)(*width) && + TVTimings[mode].vactive == (unsigned short)(*height) && + TVTimings[mode].frequency == frequency) { + flags = TVTimings[mode].flags; + + if (flags & GFX_MODE_TV_NTSC) + *hz = 60; + else if (flags & GFX_MODE_TV_PAL) + *hz = 50; + else + *hz = 0; + return (1); + } + } + + return -1; +} + +/*--------------------------------------------------------------------------- + * gfx_get_tv_display_mode_frequency + * + * This routine returns the PLL frequency of a given TV mode. + *--------------------------------------------------------------------------- + */ +#if GFX_TV_DYNAMIC +int +sc1200_get_tv_display_mode_frequency(unsigned short width, + unsigned short height, TVStandardType format, int *frequency) +#else +int +gfx_get_tv_display_mode_frequency(unsigned short width, unsigned short height, + TVStandardType format, int *frequency) +#endif +{ + unsigned long mode, flag; + int retval = -1; + + *frequency = 0; + + switch (format) { + case TV_STANDARD_NTSC: + flag = GFX_MODE_TV_NTSC; + break; + case TV_STANDARD_PAL: + flag = GFX_MODE_TV_PAL; + break; + default: + return -1; + } + + for (mode = 0; mode < NUM_TV_MODES; mode++) { + if ((TVTimings[mode].hactive == width) && + (TVTimings[mode].vactive == height) && + (TVTimings[mode].flags & flag)) { + *frequency = TVTimings[mode].frequency; + retval = 1; + } + } + return retval; +} + +/*--------------------------------------------------------------------------- + * gfx_is_tv_display_mode_supported + * + * Returns >= 0 if the mode is available, -1 if the mode could not be found + *--------------------------------------------------------------------------- + */ +#if GFX_TV_DYNAMIC +int +sc1200_is_tv_display_mode_supported(unsigned short width, + unsigned short height, TVStandardType format) +#else +int +gfx_is_tv_display_mode_supported(unsigned short width, unsigned short height, + TVStandardType format) +#endif +{ + unsigned long mode, flag; + + switch (format) { + case TV_STANDARD_NTSC: + flag = GFX_MODE_TV_NTSC; + break; + case TV_STANDARD_PAL: + flag = GFX_MODE_TV_PAL; + break; + default: + return -1; + } + + for (mode = 0; mode < NUM_TV_MODES; mode++) { + if (TVTimings[mode].hactive == width && + TVTimings[mode].vactive == height && + (TVTimings[mode].flags & flag)) { + return ((int)mode); + } + } + + return -1; +} + +/* END OF FILE */ diff --git a/src/gfx/tv_fs450.c b/src/gfx/tv_fs450.c new file mode 100644 index 0000000..942907b --- /dev/null +++ b/src/gfx/tv_fs450.c @@ -0,0 +1,3261 @@ +/* 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. + * */ + +#define FS450_DIRECTREG 0 + +#include "tv_fs450.h" + +/*========================================================================== + * Macros + *========================================================================== + */ +#undef fsmax +#undef fsmin +#define fsmax(a, b) ((a) > (b) ? (a) : (b)) +#define fsmin(a, b) ((a) < (b) ? (a) : (b)) + +#undef range_limit +#define range_limit(val,min_val,max_val) (fsmax((min_val),fsmin((val),(max_val)))) + +/*========================================================================== + * Registers + *========================================================================== + */ + +#define MAX_REGISTERS 32 +#define MAX_BITS 32 + +#define READ 1 +#define WRITE 2 +#define READ_WRITE (READ | WRITE) + +typedef struct +{ + char *name; + unsigned long offset; + unsigned char bit_length; + unsigned char valid_bits; + unsigned char read_write; + char *bitfield_names[MAX_BITS]; +} S_REGISTER_DESCRIP; + +typedef struct +{ + int source; + char *name; + S_REGISTER_DESCRIP registers[MAX_REGISTERS]; +} S_SET_DESCRIP; + +const S_SET_DESCRIP *houston_regs(void); +const S_SET_DESCRIP *encoder_regs(void); +const S_SET_DESCRIP *macrovision_regs(void); +const S_SET_DESCRIP *gcc_regs(void); + +/*========================================================================== + * Houston Register Addresses & Bit Definitions + *========================================================================== + */ +#define HOUSTON_IHO 0x00 /* Input Horizontal Offset */ +#define HOUSTON_IVO 0x02 /* Input Vertical Offset */ +#define HOUSTON_IHA 0x04 /* Input Horizontal Active Width */ +#define HOUSTON_VSC 0x06 /* Vertical Scaling Coeficient */ +#define HOUSTON_HSC 0x08 /* Horizontal Scaling Coeficient */ +#define HOUSTON_BYP 0x0A /* Bypass Register */ +#define HOUSTON_CR 0x0C /* Control Register */ +#define HOUSTON_SP 0x0E /* Status */ +#define HOUSTON_NCONL 0x10 /* NCO numerator low word */ +#define HOUSTON_NCONH 0x12 /* NCO numerator high word */ +#define HOUSTON_NCODL 0x14 /* NCO denominator low word */ +#define HOUSTON_NCODH 0x16 /* NCO denominator high word */ +#define HOUSTON_APO 0x18 +#define HOUSTON_ALO 0x1A +#define HOUSTON_AFO 0x1C +#define HOUSTON_HSOUTWID 0x1E +#define HOUSTON_HSOUTST 0x20 +#define HOUSTON_HSOUTEND 0x22 +#define HOUSTON_SHP 0x24 /* Sharpness */ +#define HOUSTON_FLK 0x26 /* Flicker Filter */ +#define HOUSTON_BCONTL 0x28 +#define HOUSTON_BCONTH 0x2A +#define HOUSTON_BDONE 0x2C +#define HOUSTON_BDIAGL 0x2E +#define HOUSTON_BDIAGH 0x30 +#define HOUSTON_REV 0x32 +#define HOUSTON_MISC 0x34 +#define HOUSTON_FFO 0x36 +#define HOUSTON_FFO_LAT 0x38 +#define HOUSTON_VSOUTWID 0x3A +#define HOUSTON_VSOUTST 0x3C +#define HOUSTON_VSOUTEND 0x3E +/* BYP Register Bits */ +#define BYP_RGB_BYPASS 0x0001 +#define BYP_HDS_BYPASS 0x0002 +#define BYP_HDS_TBYPASS 0x0004 +#define BYP_CAC_BYPASS 0x0008 +#define BYP_R2V_SBYPASS 0x0010 +#define BYP_R2V_BYPASS 0x0020 +#define BYP_VDS_BYPASS 0x0040 +#define BYP_FFT_BYPASS 0x0080 +#define BYP_FIF_BYPASS 0x0100 +#define BYP_FIF_TBYPASS 0x0200 +#define BYP_HUS_BYPASS 0x0400 +#define BYP_HUS_TBYPASS 0x0800 +#define BYP_CCR_BYPASS 0x1000 +#define BYP_PLL_BYPASS 0x2000 +#define BYP_NCO_BYPASS 0x4000 +#define BYP_ENC_BYPASS 0x8000 +/* CR Register Bits */ +#define CR_RESET 0x0001 +#define CR_CLKOFF 0x0002 +#define CR_NCO_EN 0x0004 +#define CR_COMPOFF 0x0008 +#define CR_YCOFF 0x0010 +#define CR_LP_EN 0x0020 +#define CR_CACQ_CLR 0x0040 +#define CR_FFO_CLR 0x0080 +#define CR_656_PAL_NTSC 0x0100 +#define CR_656_STD_VMI 0x0200 +#define CR_OFMT 0x0400 +#define CR_UIM_CLK 0x0800 +#define CR_UIM_DEC 0x1000 +#define CR_BIPGEN_EN1 0x2000 +#define CR_UIM_MOD0 0x4000 +#define CR_UIM_MOD1 0x8000 +/* Status Register Bits */ +#define SP_CACQ_ST 0x0001 +#define SP_FFO_ST 0x0002 +#define SP_REVID_MASK 0x7FFC +#define SP_MV_EN 0x8000 +/* BDONE Register Bits */ +#define BDONE_BIST_DONE_A 0x0001 +#define BDONE_BIST_DONE_B 0x0002 +#define BDONE_BIST_DONE_C 0x0004 +#define BDONE_BIST_DONE_D 0x0008 +#define BDONE_BIST_DONE_E 0x0010 +#define BDONE_BIST_DONE_F 0x0020 +#define BDONE_BIST_DONE_G 0x0040 +/* BDIAGL Register Bits */ +#define BDIAGL_BIST_DIAG_A 0x000F +#define BDIAGL_BIST_DIAG_B 0x00F0 +#define BDIAGL_BIST_DIAG_C 0x0F00 +#define BDIAGL_BIST_DIAG_D 0xF000 +/* BDIAGH Register Bits */ +#define BDIAGH_BIST_DIAG_E 0x000F +#define BDIAGH_BIST_DIAG_F 0x000F +#define BDIAGH_BIST_DIAG_G 0x000F +/* MISC Register Bits */ +#define MISC_TV_SHORT_FLD 0x0001 +#define MISC_ENC_TEST 0x0002 +#define MISC_DAC_TEST 0x0004 +#define MISC_MV_SOFT_EN 0x0008 +#define MISC_NCO_LOAD0 0x0010 +#define MISC_NCO_LOAD1 0x0020 +#define MISC_VGACKDIV 0x0200 +#define MISC_BRIDGE_SYNC 0x0400 +#define MISC_GTLIO_PD 0x8000 +/*========================================================================== + * Encoder Registers & Bit Definitions + *========================================================================== + */ +#define ENC_CHROMA_FREQ 0x40 +#define ENC_CHROMA_PHASE 0x44 +#define ENC_REG05 0x45 +#define ENC_REG06 0x46 +#define ENC_REG07 0x47 +#define ENC_HSYNC_WIDTH 0x48 +#define ENC_BURST_WIDTH 0x49 +#define ENC_BACK_PORCH 0x4A +#define ENC_CB_BURST_LEVEL 0x4B +#define ENC_CR_BURST_LEVEL 0x4C +#define ENC_SLAVE_MODE 0x4D +#define ENC_BLACK_LEVEL 0x4e +#define ENC_BLANK_LEVEL 0x50 +#define ENC_NUM_LINES 0x57 +#define ENC_WHITE_LEVEL 0x5e +#define ENC_CB_GAIN 0x60 +#define ENC_CR_GAIN 0x62 +#define ENC_TINT 0x65 +#define ENC_BREEZE_WAY 0x69 +#define ENC_FRONT_PORCH 0x6C +#define ENC_ACTIVELINE 0x71 +#define ENC_FIRST_LINE 0x73 +#define ENC_REG34 0x74 +#define ENC_SYNC_LEVEL 0x75 +#define ENC_VBI_BLANK_LEVEL 0x7C +#define ENC_RESET 0x7e +#define ENC_NOTCH_FILTER 0x8d +/*========================================================================== + * Macrovision Registers & Bit Definitions + *========================================================================== + */ +#define MV_N0 0x59 +#define MV_N1 0x52 +#define MV_N2 0x7b +#define MV_N3 0x53 +#define MV_N4 0x79 +#define MV_N5 0x5d +#define MV_N6 0x7a +#define MV_N7 0x64 +#define MV_N8 0x54 +#define MV_N9 0x55 +#define MV_N10 0x56 +#define MV_N11 0x6d +#define MV_N12 0x6f +#define MV_N13 0x5a +#define MV_N14 0x5b +#define MV_N15 0x5c +#define MV_N16 0x63 +#define MV_N17 0x66 +#define MV_N18 0x68 +#define MV_N19 0x67 +#define MV_N20 0x61 +#define MV_N21 0x6a +#define MV_N22 0x76 +#define MV_AGC_PULSE_LEVEL 0x77 +#define MV_BP_PULSE_LEVEL 0x78 +/*========================================================================== + * The TRACE macro can be used to display debug information. It can display + * one or more parameters in a formatted string like printf. No code will be + * generated for a release build. Use double parentheses for compatibility + * with C #define statements. Newline characters are not added + * automatically. Usage example: + * + * TRACE(("Number is %d, Name is %s.\n",iNumber,lpszName)) + *========================================================================== + */ +#define TRACE(parameters) {} +/* GCC timing structure */ +typedef struct _S_TIMING_SPECS +{ + int vga_width; + int vga_lines; + int tv_width; + int tv_lines; + int h_total; + int h_sync; + int v_total; + int v_sync; +} S_TIMING_SPECS; + +/* Revision of Houston chip */ +#define HOUSTON_REV_A 0 +#define HOUSTON_REV_B 1 +static int houston_Rev(void); + +/*========================================================================== + * Functions + *========================================================================== + */ +static int houston_init(void); + +static unsigned char PLAL_FS450_i2c_address(void); +static int PLAL_FS450_UIM_mode(void); +static int PLAL_ReadRegister(S_REG_INFO * p_reg); +static int PLAL_WriteRegister(const S_REG_INFO * p_reg); +static int PLAL_IsTVOn(void); +static int PLAL_EnableVga(void); +static int PLAL_PrepForTVout(void); +static int PLAL_SetTVTimingRegisters(const S_TIMING_SPECS * p_specs); +static int PLAL_FinalEnableTVout(unsigned long vga_mode); + +/* Direct Memory Access Functions */ +/* NOTE: Cx5530 is assumed hardcoded at 0x10000 offset from MediaGX base. + * F4Bar is bogus as described in the Cx5530 datasheet (actually points to GX + * frame buffer). */ +static int +DMAL_ReadUInt32(unsigned long phys_addr, unsigned long *p_data) +{ + *p_data = READ_REG32(phys_addr); + return 0; +} + +static int +DMAL_WriteUInt32(unsigned long phys_addr, unsigned long data) +{ + WRITE_REG32(phys_addr, data); + return 0; +} + +/* Houston register access functions. */ +static int +houston_ReadReg(unsigned int reg, unsigned long *p_value, unsigned int bytes) +{ + return gfx_i2c_read(1, PLAL_FS450_i2c_address(), (unsigned char)reg, + (unsigned char)bytes, (unsigned char *)p_value); +} + +static int +houston_WriteReg(unsigned int reg, unsigned long value, unsigned int bytes) +{ + return gfx_i2c_write(1, PLAL_FS450_i2c_address(), (unsigned char)reg, + (unsigned char)bytes, (unsigned char *)&value); +} + +/* TV configuration functions. */ +static int config_init(void); +static const S_TIMING_SPECS *p_specs(void); +static void config_power(int on); +static void config_vga_mode(unsigned long vga_mode); +static void config_tv_std(unsigned long tv_std, unsigned int trigger_bits); +static void conget_tv_std(unsigned long *p_tv_std); +static unsigned long supported_standards(void); +static void config_tvout_mode(unsigned long tvout_mode); +static void conget_tvout_mode(unsigned long *p_tvout_mode); +static void config_overscan_xy(unsigned long tv_std, unsigned long vga_mode, + int overscan_x, int overscan_y, int pos_x, int pos_y); +static void config_nco(unsigned long tv_std, unsigned long vga_mode); +static void config_sharpness(int sharpness); +static void conget_sharpness(int *p_sharpness); +static void config_flicker(int flicker); +static void conget_flicker(int *p_flicker); +static void config_color(int color); +static void conget_color(int *p_color); +static void config_brightness_contrast(unsigned long tv_std, + unsigned int trigger_bits, int brightness, int contrast); +static void conget_brightness_contrast(unsigned long tv_std, + unsigned int trigger_bits, int *p_brightness, int *p_contrast); +static void config_yc_filter(unsigned long tv_std, int luma_filter, + int chroma_filter); +static void conget_yc_filter(int *p_luma_filter, int *p_chroma_filter); +static void config_macrovision(unsigned long tv_std, + unsigned int cp_trigger_bits); +static void conget_macrovision(unsigned long tv_std, + unsigned int *p_cp_trigger_bits); + +/* Device settings. */ +typedef struct _S_DEVICE_SETTINGS +{ + int tv_on; + unsigned long vga_mode; + unsigned long tv_std; + unsigned long tvout_mode; + int overscan_x; + int overscan_y; + int position_x; + int position_y; + int sharpness; + int flicker; + int color; + int brightness; + int contrast; + unsigned char yc_filter; + unsigned int aps_trigger_bits; + int last_overscan_y; +} S_DEVICE_SETTINGS; + +static S_DEVICE_SETTINGS d; + +/*========================================================================== + * TV Setup Parameters + *========================================================================== + * */ + +static const struct +{ + unsigned long chroma_freq[5]; + unsigned short chroma_phase[5]; + unsigned short cphase_rst[5]; + unsigned short color[5]; + unsigned short cr_burst_level[5]; + unsigned short cb_burst_level[5]; + unsigned short sys625_50[5]; + unsigned short vsync5[5]; + unsigned short pal_mode[5]; + unsigned short hsync_width[5]; + unsigned short burst_width[5]; + unsigned short back_porch[5]; + unsigned short front_porch[5]; + unsigned short breeze_way[5]; + unsigned short activeline[5]; + unsigned short blank_level[5]; + unsigned short vbi_blank_level[5]; + unsigned short black_level[5]; + unsigned short white_level[5]; + unsigned short hamp_offset[5]; + unsigned short sync_level[5]; + unsigned short tv_lines[5]; + unsigned short tv_width[5]; + unsigned short tv_active_lines[5]; + unsigned short tv_active_width[5]; + unsigned char notch_filter[5]; + unsigned short houston_cr[5]; + unsigned short houston_ncodl[5]; + unsigned short houston_ncodh[5]; +} tvsetup = { + /* ntsc, pal, ntsc-eij, pal-m, pal-n */ + { + 0x1f7cf021, 0xcb8a092a, 0x1f7cf021, 0xe3efe621, 0xcb8a092a}, + /* chroma_freq */ + { + 0, 0, 0, 0, 0}, + /* chroma_phase */ + { + 2, 0, 2, 0, 0}, + /* cphase_rst */ + { + 54, 43, 54, 43, 43}, + /* color */ + { + 0, 31, 0, 29, 29}, + /* cr_burst_level */ + { + 59, 44, 59, 41, 41}, + /* cb_burst_level */ + { + 0, 1, 0, 0, 1}, + /* sys625_50 */ + { + 0, 1, 0, 0, 0}, + /* vsync5 */ + { + 0, 1, 0, 1, 1}, + /* pal_mode */ + { + 0x7a, 0x7a, 0x7a, 0x7a, 0x7a}, + /* hsync_width */ + { + 0x40, 0x3c, 0x40, 0x40, 0x3c}, + /* burst_width */ + { + 0x80, 0x9a, 0x80, 0x80, 0x9a}, + /* back_porch */ + { + 0x24, 0x1e, 0x24, 0x24, 0x1e}, + /* front_porch */ + { + 0x19, 0x1a, 0x19, 0x12, 0x1a}, + /* breeze_way */ + { + 0xb4, 0xb4, 0xb4, 0xb4, 0xb4}, + /* active_line */ + { + 240, 251, 240, 240, 240}, + /* blank_level */ + { + 240, 251, 240, 240, 240}, + /* vbi_blank_level */ + { + 284, 252, 240, 252, 252}, + /* black_level */ + { + 823, 821, 823, 821, 821}, + /* white_level */ + { + 60, 48, 60, 48, 48}, + /* hamp_offset */ + { + 0x08, 0x08, 0x08, 0x08, 0x08}, + /* sync_level */ + { + 525, 625, 525, 525, 625}, + /* tv_lines */ + { + 858, 864, 858, 858, 864}, + /* tv_width */ + { + 487, 576, 487, 487, 576}, + /* tv_active_lines */ + { + 800, 800, 800, 800, 800}, + /* tv_active_width */ + { + 0x1a, 0x1d, 0x1a, 0x1d, 0x1d}, + /* notch filter enabled */ + { + 0x0000, 0x0100, 0x0000, 0x0000, 0x0100}, + /* houston cr pal */ + { + 0x7e48, 0xf580, 0x7e48, 0x7e48, 0xf580}, + /* houston ncodl */ + { + 0x001b, 0x0020, 0x001b, 0x001b, 0x0020} + /* houston ncodh */ +}; + +/* MediaGX default underscan and centered position setups. */ +#define SCANTABLE_ENTRIES 5 +struct _scantable +{ + unsigned long mode; + unsigned short v_total[5]; + unsigned short v_sync[5]; + unsigned short iha[5]; + signed short iho[5]; + signed short hsc[5]; +}; + +static struct _scantable scantable[SCANTABLE_ENTRIES] = { + { + GFX_VGA_MODE_640X480, + {617, 624, 617, 624, 624}, /* v_total */ + {69, 88, 69, 88, 88}, /* v_sync */ + {720, 720, 720, 720, 720}, /* iha */ + {0, 0, 0, 0, 0}, /* iho */ + {-12, 0, -6, 0, 0} /* hsc */ + }, + { + GFX_VGA_MODE_800X600, + {740, 740, 740, 740, 740}, /* v_total */ + {90, 88, 90, 88, 88}, /* v_sync */ + {720, 720, 508, 720, 720}, /* iha */ + {-8, 11, -8, -8, 11}, /* iho */ + {-27, -27, -27, -27, -27} /* hsc */ + }, + { + GFX_VGA_MODE_720X487, + {525, 720, 525, 720, 720}, /* v_total */ + {23, 230, 23, 230, 230}, /* v_sync */ + {720, 720, 720, 720, 720}, /* iha */ + {0xa2, 0xa2, 0xa2, 0xa2, 0xa2}, /* iho */ + {0, 0, 0, 0, 0} /* hsc */ + }, + { + GFX_VGA_MODE_720X576, + {720, 625, 720, 625, 625}, /* v_total */ + {129, 25, 129, 25, 25}, /* v_sync */ + {720, 720, 720, 720, 720}, /* iha */ + {0xaa, 0xaa, 0xaa, 0xaa, 0xaa}, /* iho */ + {0, 0, 0, 0, 0} /* hsc */ + }, + { + GFX_VGA_MODE_1024X768, + {933, 942, 933, 806, 806}, /* v_total */ + {121, 112, 121, 88, 88}, /* v_sync */ + {600, 600, 600, 600, 600}, /* iha */ + {0x3c, 0x23, 0x3c, 0x65, 0x65}, /* iho */ + {35, 26, 35, 26, 26} /* hsc */ + }, +}; + +/* Houston fifo configuration constants. */ +struct _ffolat +{ + int v_total; + unsigned short ffolat; +}; + +struct _ffolativo +{ + int v_total; + unsigned short ivo; + unsigned short ffolat; +}; + +/* h_total=832, ivo=40, tv_width=858, tv_lines=525, vga_lines=480 */ +#define SIZE6X4NTSC 66 +static struct _ffolat ffo6x4ntsc[SIZE6X4NTSC + 1] = { + {541, 0x40}, {545, 0x40}, {549, 0x40}, {553, 0x40}, + {557, 0x58}, {561, 0x40}, {565, 0x40}, {569, 0x40}, + {573, 0x48}, {577, 0x40}, {581, 0x40}, {585, 0x40}, + {589, 0x40}, {593, 0x48}, {597, 0x40}, {601, 0x40}, + {605, 0x40}, {609, 0x40}, {613, 0x5b}, {617, 0x48}, + {621, 0x60}, {625, 0x48}, {629, 0x48}, {633, 0x40}, + {637, 0x5e}, {641, 0x40}, {645, 0x50}, {649, 0x56}, + {653, 0x58}, {657, 0x6c}, {661, 0x40}, {665, 0x40}, + {669, 0x40}, {673, 0x40}, {677, 0x40}, {681, 0x40}, + {685, 0x40}, {689, 0x40}, {693, 0x40}, {697, 0x40}, + {701, 0x40}, {705, 0x40}, {709, 0x40}, {713, 0x40}, + {717, 0x40}, {721, 0x40}, {725, 0x40}, {729, 0x40}, + {733, 0x40}, {737, 0x40}, {741, 0x40}, {745, 0x40}, + {749, 0x40}, {753, 0x40}, {757, 0x40}, {761, 0x40}, + {765, 0x40}, {769, 0x40}, {773, 0x40}, {777, 0x40}, + {781, 0x40}, {785, 0x40}, {789, 0x40}, {793, 0x40}, + {797, 0x30}, {801, 0x40}, + {-1, 0} +}; + +#define SIZE6X4PAL 45 +static struct _ffolat ffo6x4pal[SIZE6X4PAL + 1] = { + {625, 0x60}, {629, 0x60}, {633, 0x60}, {637, 0x60}, + {641, 0x50}, {645, 0x60}, {649, 0x60}, {653, 0x60}, + {657, 0x60}, {661, 0x60}, {665, 0x60}, {669, 0x60}, + {673, 0x60}, {677, 0x60}, {681, 0x60}, {685, 0x60}, + {689, 0x60}, {693, 0x60}, {697, 0x60}, {701, 0x60}, + {705, 0x60}, {709, 0x60}, {713, 0x60}, {717, 0x60}, + {721, 0x60}, {725, 0x60}, {729, 0x60}, {733, 0x60}, + {737, 0x60}, {741, 0x60}, {745, 0x60}, {749, 0x60}, + {753, 0x60}, {757, 0x60}, {761, 0x60}, {765, 0x60}, + {769, 0x60}, {773, 0x60}, {777, 0x60}, {781, 0x60}, + {785, 0x60}, {789, 0x60}, {793, 0x60}, {797, 0x60}, + {801, 0x60}, + {-1, 0} +}; + +#define SIZE7X4NTSC 40 +static struct _ffolat ffo7x4ntsc[SIZE7X4NTSC + 1] = { + {525, 0x52}, {529, 0x52}, {533, 0x52}, {537, 0x52}, + {541, 0x52}, {545, 0x40}, {549, 0x40}, {553, 0x40}, + {557, 0x58}, {561, 0x40}, {565, 0x58}, {569, 0x40}, + {573, 0x48}, {577, 0x40}, {581, 0x40}, {585, 0x40}, + {589, 0x40}, {593, 0x48}, {597, 0x40}, {601, 0x40}, + {605, 0x40}, {609, 0x40}, {613, 0x5b}, {617, 0x48}, + {621, 0x60}, {625, 0x48}, {629, 0x48}, {633, 0x40}, + {637, 0x5e}, {641, 0x40}, {645, 0x50}, {649, 0x56}, + {653, 0x58}, {657, 0x6c}, {661, 0x40}, {665, 0x40}, + {669, 0x40}, {673, 0x40}, {677, 0x40}, {681, 0x40}, + {-1, 0} +}; + +#define SIZE7X4PAL 24 +static struct _ffolat ffo7x4pal[SIZE7X4PAL + 1] = { + {625, 0x60}, {629, 0x60}, {633, 0x60}, {637, 0x60}, + {641, 0x50}, {645, 0x60}, {649, 0x60}, {653, 0x60}, + {657, 0x60}, {661, 0x60}, {665, 0x60}, {669, 0x60}, + {673, 0x60}, {677, 0x60}, {681, 0x60}, {685, 0x60}, + {689, 0x60}, {693, 0x60}, {697, 0x60}, {701, 0x60}, + {705, 0x60}, {709, 0x60}, {713, 0x60}, {717, 0x60}, + {-1, 0} +}; + +#define SIZE7X5NTSC 54 +static struct _ffolat ffo7x5ntsc[SIZE7X5NTSC + 1] = { + {590, 0x40}, {594, 0x48}, {598, 0x40}, {602, 0x40}, + {606, 0x40}, {610, 0x40}, {614, 0x5b}, {618, 0x48}, + {622, 0x60}, {626, 0x48}, {630, 0x48}, {634, 0x40}, + {638, 0x5e}, {642, 0x40}, {646, 0x50}, {650, 0x56}, + {654, 0x58}, {658, 0x6c}, {662, 0x40}, {666, 0x40}, + {670, 0x40}, {674, 0x40}, {678, 0x40}, {682, 0x40}, + {686, 0x40}, {690, 0x40}, {694, 0x40}, {698, 0x40}, + {702, 0x40}, {706, 0x40}, {710, 0x40}, {714, 0x40}, + {718, 0x40}, {722, 0x40}, {726, 0x40}, {730, 0x40}, + {734, 0x40}, {738, 0x40}, {742, 0x40}, {746, 0x40}, + {750, 0x40}, {754, 0x40}, {758, 0x40}, {762, 0x40}, + {766, 0x40}, {770, 0x40}, {774, 0x40}, {778, 0x40}, + {782, 0x40}, {786, 0x40}, {790, 0x40}, {794, 0x40}, + {798, 0x30}, {802, 0x40}, + {-1, 0} +}; + +#define SIZE7X5PAL 45 +static struct _ffolat ffo7x5pal[SIZE7X5PAL + 1] = { + {625, 0x60}, {629, 0x60}, {633, 0x60}, {637, 0x60}, + {641, 0x50}, {645, 0x60}, {649, 0x60}, {653, 0x60}, + {657, 0x60}, {661, 0x60}, {665, 0x60}, {669, 0x60}, + {673, 0x60}, {677, 0x60}, {681, 0x60}, {685, 0x60}, + {689, 0x60}, {693, 0x60}, {697, 0x60}, {701, 0x60}, + {705, 0x60}, {709, 0x60}, {713, 0x60}, {717, 0x60}, + {721, 0x60}, {725, 0x60}, {729, 0x60}, {733, 0x60}, + {737, 0x60}, {741, 0x60}, {745, 0x60}, {749, 0x60}, + {753, 0x60}, {757, 0x60}, {761, 0x60}, {765, 0x60}, + {769, 0x60}, {773, 0x60}, {777, 0x60}, {781, 0x60}, + {785, 0x60}, {789, 0x60}, {793, 0x60}, {797, 0x60}, + {801, 0x60}, + {-1, 0} +}; + +/* h_total=1056, vga_lines=600 */ +#define SIZE8X6NTSC 37 +static struct _ffolat ffo8x6ntsc[SIZE8X6NTSC + 1] = { + {620, 0x40}, /* v_total_min >= vsync+10 >= vga_lines+10 = 610 */ + {625, 0x58}, {630, 0x40}, {635, 0x40}, {640, 0x40}, + {645, 0x46}, {650, 0x46}, {655, 0x4f}, {660, 0x4c}, + {665, 0x4a}, {670, 0x50}, {675, 0x2f}, {680, 0x48}, + {685, 0x38}, {690, 0x31}, {695, 0x40}, {700, 0x21}, + {705, 0x25}, {710, 0x40}, {715, 0x48}, {720, 0x50}, + {725, 0x30}, {730, 0x50}, {735, 0x50}, {740, 0x50}, + {745, 0x40}, {750, 0x38}, {755, 0x50}, {760, 0x50}, + {765, 0x40}, {770, 0x38}, {775, 0x40}, {780, 0x40}, + {785, 0x40}, {790, 0x38}, {795, 0x50}, {800, 0x50}, + {-1, 0} +}; + +/* h_total=1056, vga_lines=600 */ +#define SIZE8X6PAL 36 +static struct _ffolat ffo8x6pal[SIZE8X6PAL + 1] = { + {625, 0x80}, {630, 0x80}, {635, 0x5a}, {640, 0x55}, + {645, 0x48}, {650, 0x65}, {655, 0x65}, {660, 0x50}, + {665, 0x80}, {670, 0x70}, {675, 0x56}, {680, 0x80}, + {685, 0x58}, {690, 0x31}, {695, 0x80}, {700, 0x60}, + {705, 0x45}, {710, 0x4a}, {715, 0x50}, {720, 0x50}, + {725, 0x50}, {730, 0x45}, {735, 0x50}, {740, 0x50}, + {745, 0x50}, {750, 0x50}, {755, 0x50}, {760, 0x50}, + {765, 0x50}, {770, 0x50}, {775, 0x50}, {780, 0x50}, + {785, 0x50}, {790, 0x50}, {795, 0x50}, {800, 0x50}, + {-1, 0} +}; + +/* h_total=1344, vga_lines=768 */ +#define SIZE10X7NTSC 45 +static struct _ffolativo ffo10x7ntsc[SIZE10X7NTSC] = { + {783, 0x4d, 0x40}, + {789, 0x47, 0x14}, + {795, 0x47, 0x7f}, + {801, 0x47, 0x53}, + {807, 0x47, 0x11}, + {813, 0x47, 0x78}, + {819, 0x47, 0x54}, + {825, 0x47, 0x40}, + {831, 0x47, 0x0f}, + {837, 0x4d, 0x40}, + {843, 0x47, 0x5a}, + {849, 0x4d, 0x40}, + {855, 0x47, 0x4b}, + {861, 0x4d, 0x40}, + {867, 0x47, 0x4b}, + {873, 0x4d, 0x40}, + {879, 0x47, 0x07}, + {885, 0x48, 0x20}, + {891, 0x47, 0x82}, + {897, 0x47, 0x60}, + {903, 0x47, 0x7f}, + {909, 0x4d, 0x40}, + {915, 0x48, 0x40}, + {921, 0x4c, 0x40}, + {927, 0x49, 0x40}, + {933, 0x48, 0x40}, + {939, 0x4a, 0x40}, + {945, 0x46, 0x40}, + {951, 0x4a, 0x40}, + {957, 0x4a, 0x40}, + {963, 0x4b, 0x40}, + {969, 0x4b, 0x40}, + {975, 0x48, 0x40}, + {981, 0x47, 0x40}, + {987, 0x47, 0x40}, + {993, 0x47, 0x40}, + {999, 0x48, 0x40}, + {1005, 0x48, 0x40}, + {1011, 0x47, 0x40}, + {1017, 0x47, 0x40}, + {1023, 0x48, 0x40}, + {1029, 0x48, 0x40}, + {1035, 0x46, 0x40}, + {1041, 0x47, 0x40}, + {1047, 0x47, 0x40} +}; + +/* h_total=1344, vga_lines=768 */ +#define SIZE10X7PAL 46 +static struct _ffolativo ffo10x7pal[SIZE10X7PAL] = { + {781, 0x49, 0x40}, + {787, 0x46, 0x40}, + {793, 0x48, 0x40}, + {799, 0x46, 0x40}, + {805, 0x49, 0x40}, + {811, 0x47, 0x40}, + {817, 0x46, 0x40}, + {823, 0x46, 0x56}, + {829, 0x46, 0x2d}, + {835, 0x46, 0x40}, + {841, 0x46, 0x2d}, + {847, 0x46, 0x3f}, + {853, 0x46, 0x10}, + {859, 0x46, 0x86}, + {865, 0x46, 0xc9}, + {871, 0x46, 0x83}, + {877, 0x46, 0xa8}, + {883, 0x46, 0x81}, + {889, 0x46, 0xa5}, + {895, 0x46, 0xa9}, + {901, 0x46, 0x81}, + {907, 0x46, 0xa4}, + {913, 0x46, 0xa5}, + {919, 0x46, 0x7f}, + {925, 0x46, 0xa2}, + {931, 0x46, 0x9d}, + {937, 0x46, 0xc1}, + {943, 0x46, 0x96}, + {949, 0x46, 0xb7}, + {955, 0x46, 0xb1}, + {961, 0x46, 0x8a}, + {967, 0x46, 0xa9}, + {973, 0x46, 0xa0}, + {979, 0x46, 0x40}, + {985, 0x46, 0x97}, + {991, 0x46, 0xb5}, + {997, 0x46, 0xaa}, + {1003, 0x46, 0x83}, + {1009, 0x46, 0x9f}, + {1015, 0x47, 0x40}, + {1021, 0x46, 0xad}, + {1027, 0x46, 0x87}, + {1033, 0x46, 0xa2}, + {1039, 0x47, 0x40}, + {1045, 0x46, 0xac}, + {1051, 0x46, 0x86} +}; + +/*==========================================================================*/ +/*FS450 API Functions. */ +/*==========================================================================*/ + +/* Initialize device settings */ +static void +initialize_houston_static_registers(void) +{ + houston_WriteReg(HOUSTON_BYP, 0, 2); + houston_WriteReg(HOUSTON_APO, 0, 2); + houston_WriteReg(HOUSTON_ALO, 0, 2); + houston_WriteReg(HOUSTON_AFO, 0, 2); + houston_WriteReg(HOUSTON_BCONTL, 0, 2); + houston_WriteReg(HOUSTON_BCONTH, 0, 2); + houston_WriteReg(HOUSTON_BDONE, 0, 2); + houston_WriteReg(HOUSTON_BDIAGL, 0, 2); + houston_WriteReg(HOUSTON_BDIAGH, 0, 2); + houston_WriteReg(HOUSTON_MISC, 0, 2); +} + +int +FS450_init(void) +{ + int err; + + TRACE(("FS450_Init()\n")) + + err = houston_init(); + if (err) + return err; + + initialize_houston_static_registers(); + + d.tv_on = PLAL_IsTVOn()? 1 : 0; + + /* get the current tv standard */ + conget_tv_std(&d.tv_std); + + d.vga_mode = 0; + + /* default to VP_TVOUT_MODE_CVBS_YC */ + d.tvout_mode = GFX_TVOUT_MODE_CVBS_YC; + + /* default to 1000 out of 1000 */ + d.sharpness = 1000; + config_sharpness(d.sharpness); + + /* default to 800 out of 1000 */ + d.flicker = 800; + config_flicker(d.flicker); + + /* default to zeros */ + d.overscan_x = 0; + d.overscan_y = 0; + d.position_x = 0; + d.position_y = 0; + + d.color = 50; + /* d.color = tvsetup.color[k]; */ + config_color(d.color); + + /* default */ + d.brightness = 50; + d.contrast = 60; + config_brightness_contrast(d.tv_std, d.aps_trigger_bits, d.brightness, + d.contrast); + + /* get the current yc filtering */ + { + int luma_filter, chroma_filter; + + conget_yc_filter(&luma_filter, &chroma_filter); + d.yc_filter = 0; + if (luma_filter) + d.yc_filter |= GFX_LUMA_FILTER; + if (chroma_filter) + d.yc_filter |= GFX_CHROMA_FILTER; + } + + d.aps_trigger_bits = 0; + config_macrovision(d.tv_std, d.aps_trigger_bits); + + d.last_overscan_y = -10000; + + return 0; +} + +void +FS450_cleanup(void) +{ +} + +/*==========================================================================*/ +/* Required configuration calls to write new settings to the device */ +/*==========================================================================*/ + +#define REQ_TV_STANDARD_BIT 0x0002 +#define REQ_VGA_MODE_BIT 0x0004 +#define REQ_TVOUT_MODE_BIT 0x0008 +#define REQ_SHARPNESS_BIT 0x0010 +#define REQ_FLICKER_BIT 0x0020 +#define REQ_OVERSCAN_POSITION_BIT 0x0040 +#define REQ_COLOR_BIT 0x0080 +#define REQ_BRIGHTNESS_CONTRAST_BIT 0x0100 +#define REQ_YC_FILTER_BIT 0x0200 +#define REQ_MACROVISION_BIT 0x0400 +#define REQ_NCO_BIT 0x1000 + +#define REQ_TV_STANDARD (REQ_TV_STANDARD_BIT | REQ_OVERSCAN_POSITION \ + | REQ_BRIGHTNESS_CONTRAST \ + | REQ_MACROVISION_BIT | REQ_YC_FILTER) +#define REQ_VGA_MODE (REQ_VGA_MODE_BIT | REQ_OVERSCAN_POSITION) +#define REQ_TVOUT_MODE (REQ_TVOUT_MODE_BIT) +#define REQ_SHARPNESS (REQ_SHARPNESS_BIT) +#define REQ_FLICKER (REQ_FLICKER_BIT) +#define REQ_OVERSCAN_POSITION (REQ_OVERSCAN_POSITION_BIT | REQ_NCO) +#define REQ_COLOR (REQ_COLOR_BIT) +#define REQ_BRIGHTNESS_CONTRAST (REQ_BRIGHTNESS_CONTRAST_BIT) +#define REQ_YC_FILTER (REQ_YC_FILTER_BIT) +#define REQ_MACROVISION (REQ_TV_STANDARD_BIT | \ + REQ_BRIGHTNESS_CONTRAST_BIT | \ + REQ_MACROVISION_BIT) +#define REQ_NCO (REQ_NCO_BIT) +#define REQ_ENCODER (REQ_TV_STANDARD | REQ_COLOR | \ + REQ_BRIGHTNESS_CONTRAST | REQ_YC_FILTER) + +static int +write_config(int req) +{ + unsigned long reg, reg_encoder_reset = 0; + int reset; + + /*if we're changing the nco, and the vertical scaling has changed... */ + reset = ((REQ_NCO_BIT & req) && (d.overscan_y != d.last_overscan_y)); + if (reset) { + /*put the encoder into reset while making changes */ + houston_ReadReg(ENC_RESET, ®, 1); + houston_WriteReg(ENC_RESET, reg | 0x01, 1); + reg_encoder_reset = reg & 0x01; + } + + if (REQ_TV_STANDARD_BIT & req) + config_tv_std(d.tv_std, d.aps_trigger_bits); + + if (REQ_VGA_MODE_BIT & req) + config_vga_mode(d.vga_mode); + + if (REQ_TVOUT_MODE_BIT & req) + config_tvout_mode(d.tvout_mode); + + if (REQ_OVERSCAN_POSITION_BIT & req) { + config_overscan_xy(d.tv_std, + d.vga_mode, + d.overscan_x, d.overscan_y, d.position_x, d.position_y); + + /*h_timing and v_timing and syncs. */ + if (PLAL_IsTVOn()) + PLAL_SetTVTimingRegisters(p_specs()); + } + + if (REQ_NCO_BIT & req) + config_nco(d.tv_std, d.vga_mode); + + if (REQ_SHARPNESS_BIT & req) + config_sharpness(d.sharpness); + + if (REQ_FLICKER_BIT & req) + config_flicker(d.flicker); + + if (REQ_COLOR_BIT & req) + config_color(d.color); + + if (REQ_BRIGHTNESS_CONTRAST_BIT & req) { + config_brightness_contrast(d.tv_std, + d.aps_trigger_bits, d.brightness, d.contrast); + } + + if (REQ_YC_FILTER_BIT & req) { + config_yc_filter(d.tv_std, + (d.yc_filter & GFX_LUMA_FILTER), + (d.yc_filter & GFX_CHROMA_FILTER)); + } + + if (REQ_MACROVISION_BIT & req) + config_macrovision(d.tv_std, d.aps_trigger_bits); + + /*if we decided to put the encoder into reset, put it back */ + if (reset) { + houston_ReadReg(ENC_RESET, ®, 1); + houston_WriteReg(ENC_RESET, reg_encoder_reset | (reg & ~0x01), 1); + + d.last_overscan_y = d.overscan_y; + } + return 0; +} + +/*==========================================================================*/ +/* TV On */ +/*==========================================================================*/ + +#if GFX_TV_DYNAMIC +int +fs450_get_tv_enable(unsigned int *p_on) +#else +int +gfx_get_tv_enable(unsigned int *p_on) +#endif +{ + if (!p_on) + return ERR_INVALID_PARAMETER; + + *p_on = d.tv_on; + + return 0; +} + +/*//int FS450_set_tv_on(unsigned int on)*/ +#if GFX_TV_DYNAMIC +int +fs450_set_tv_enable(int on) +#else +int +gfx_set_tv_enable(int on) +#endif +{ + unsigned long reg; + + /*if not mode change, just return */ + if ((d.tv_on && on) || (!d.tv_on && !on)) + return 0; + + /*if turning off... */ + if (!on) { + /*reenable vga. */ + PLAL_EnableVga(); + + /*power down houston */ + config_power(0); + + d.tv_on = 0; + + return 0; + } + + /*turning on... */ + + /*power up houston */ + config_power(1); + + /*assert encoder reset. */ + houston_WriteReg(ENC_RESET, 0x01, 1); + + /*initial platform preparation */ + PLAL_PrepForTVout(); + + /*configure encoder and nco. */ + write_config(REQ_VGA_MODE | + REQ_TV_STANDARD | + REQ_TVOUT_MODE | + REQ_OVERSCAN_POSITION | REQ_YC_FILTER | REQ_MACROVISION); + + /*set LP_EN and UIM */ + houston_ReadReg(HOUSTON_CR, ®, 2); + reg |= CR_LP_EN; + reg &= ~(CR_UIM_MOD0 | CR_UIM_MOD1); + reg |= (PLAL_FS450_UIM_mode() << 14); + houston_WriteReg(HOUSTON_CR, reg, 2); + + /*set platform timing registers */ + PLAL_SetTVTimingRegisters(p_specs()); + + PLAL_FinalEnableTVout(d.vga_mode); + + /*sync bridge */ + { + int retry_count = 0; + + /*sync 50 times */ + while (retry_count++ < 50) { + /*sync bridge. */ + houston_ReadReg(HOUSTON_MISC, ®, 2); + reg |= MISC_BRIDGE_SYNC; + houston_WriteReg(HOUSTON_MISC, reg, 2); + reg &= ~MISC_BRIDGE_SYNC; + houston_WriteReg(HOUSTON_MISC, reg, 2); + } + } + + /*deassert encoder reset. */ + houston_WriteReg(ENC_RESET, 0x00, 1); + + d.tv_on = 1; + + return 0; +} + +#if GFX_TV_DYNAMIC +int +fs450_set_tv_defaults(int format) +#else +int +gfx_set_tv_defaults(int format) +#endif +{ + return 0; +} + +/*==========================================================================*/ +/* TV standard */ +/*==========================================================================*/ + +#if GFX_TV_DYNAMIC +int +fs450_get_tv_standard(unsigned long *p_standard) +#else +int +gfx_get_tv_standard(unsigned long *p_standard) +#endif +{ + if (!p_standard) + return ERR_INVALID_PARAMETER; + + *p_standard = d.tv_std; + + return 0; +} + +#if GFX_TV_DYNAMIC +int +fs450_get_available_tv_standards(unsigned long *p_standards) +#else +int +gfx_get_available_tv_standards(unsigned long *p_standards) +#endif +{ + if (!p_standards) + return ERR_INVALID_PARAMETER; + + *p_standards = supported_standards(); + + return 0; +} + +#if GFX_TV_DYNAMIC +int +fs450_set_tv_standard(unsigned long standard) +#else +int +gfx_set_tv_standard(unsigned long standard) +#endif +{ + /* verify supported standard. */ + if (!(standard & supported_standards())) + return ERR_INVALID_PARAMETER; + + /* disallow if tv is on */ + if (d.tv_on) + return ERR_CANNOT_CHANGE_WHILE_TV_ON; + + d.tv_std = standard; + /* d.color = tvsetup.color[k]; */ + + return write_config(REQ_TV_STANDARD); +} + +/*==========================================================================*/ +/* vga mode as known by the driver */ +/*==========================================================================*/ + +#if GFX_TV_DYNAMIC +int +fs450_get_tv_vga_mode(unsigned long *p_vga_mode) +#else +int +gfx_get_tv_vga_mode(unsigned long *p_vga_mode) +#endif +{ + if (!p_vga_mode) + return ERR_INVALID_PARAMETER; + + *p_vga_mode = d.vga_mode; + + return 0; +} + +#if GFX_TV_DYNAMIC +int +fs450_get_available_tv_vga_modes(unsigned long *p_vga_modes) +#else +int +gfx_get_available_tv_vga_modes(unsigned long *p_vga_modes) +#endif +{ + if (!p_vga_modes) + return ERR_INVALID_PARAMETER; + + *p_vga_modes = + GFX_VGA_MODE_640X480 | + GFX_VGA_MODE_720X487 | GFX_VGA_MODE_720X576 | GFX_VGA_MODE_800X600; + if (houston_Rev() >= HOUSTON_REV_B) + *p_vga_modes |= GFX_VGA_MODE_1024X768; + + return 0; +} + +#if GFX_TV_DYNAMIC +int +fs450_set_tv_vga_mode(unsigned long vga_mode) +#else +int +gfx_set_tv_vga_mode(unsigned long vga_mode) +#endif +{ + /*reject if not a single valid VGA mode */ + switch (vga_mode) { + default: + return ERR_INVALID_PARAMETER; + case GFX_VGA_MODE_640X480: + case GFX_VGA_MODE_720X487: + case GFX_VGA_MODE_720X576: + case GFX_VGA_MODE_800X600: + break; + case GFX_VGA_MODE_1024X768: + if (houston_Rev() >= HOUSTON_REV_B) + break; + return ERR_INVALID_PARAMETER; + } + + /*if the mode has changed... */ + if (vga_mode != d.vga_mode) { + d.vga_mode = vga_mode; + + return write_config(REQ_VGA_MODE); + } + + return 0; +} + +/*==========================================================================*/ +/* tvout mode */ +/*==========================================================================*/ + +#if GFX_TV_DYNAMIC +int +fs450_get_tvout_mode(unsigned long *p_tvout_mode) +#else +int +gfx_get_tvout_mode(unsigned long *p_tvout_mode) +#endif +{ + if (!p_tvout_mode) + return ERR_INVALID_PARAMETER; + + *p_tvout_mode = d.tvout_mode; + + return 0; +} + +#if GFX_TV_DYNAMIC +int +fs450_set_tvout_mode(unsigned long tvout_mode) +#else +int +gfx_set_tvout_mode(unsigned long tvout_mode) +#endif +{ + d.tvout_mode = tvout_mode; + + return write_config(REQ_TVOUT_MODE); +} + +/*==========================================================================*/ +/* Sharpness */ +/*==========================================================================*/ + +#if GFX_TV_DYNAMIC +int +fs450_get_sharpness(int *p_sharpness) +#else +int +gfx_get_sharpness(int *p_sharpness) +#endif +{ + if (!p_sharpness) + return ERR_INVALID_PARAMETER; + + *p_sharpness = d.sharpness; + + return 0; +} + +#if GFX_TV_DYNAMIC +int +fs450_set_sharpness(int sharpness) +#else +int +gfx_set_sharpness(int sharpness) +#endif +{ + d.sharpness = range_limit(sharpness, 0, 1000); + + return write_config(REQ_SHARPNESS); +} + +/*==========================================================================*/ +/* flicker filter control. */ +/*==========================================================================*/ + +#if GFX_TV_DYNAMIC +int +fs450_get_flicker_filter(int *p_flicker) +#else +int +gfx_get_flicker_filter(int *p_flicker) +#endif +{ + if (!p_flicker) + return ERR_INVALID_PARAMETER; + + *p_flicker = d.flicker; + + return 0; +} + +#if GFX_TV_DYNAMIC +int +fs450_set_flicker_filter(int flicker) +#else +int +gfx_set_flicker_filter(int flicker) +#endif +{ + d.flicker = range_limit(flicker, 0, 1000); + + return write_config(REQ_FLICKER); +} + +/*==========================================================================*/ +/* Overscan and Position */ +/*==========================================================================*/ + +#if GFX_TV_DYNAMIC +int +fs450_get_overscan(int *p_x, int *p_y) +#else +int +gfx_get_overscan(int *p_x, int *p_y) +#endif +{ + if (!p_x || !p_y) + return ERR_INVALID_PARAMETER; + + *p_x = d.overscan_x; + *p_y = d.overscan_y; + + return 0; +} + +#if GFX_TV_DYNAMIC +int +fs450_set_overscan(int x, int y) +#else +int +gfx_set_overscan(int x, int y) +#endif +{ + d.overscan_x = range_limit(x, -1000, 1000); + d.overscan_y = range_limit(y, -1000, 1000); + + return write_config(REQ_OVERSCAN_POSITION); +} + +#if GFX_TV_DYNAMIC +int +fs450_get_position(int *p_x, int *p_y) +#else +int +gfx_get_position(int *p_x, int *p_y) +#endif +{ + if (!p_x || !p_y) + return ERR_INVALID_PARAMETER; + + *p_x = d.position_x; + *p_y = d.position_y; + + return 0; +} + +#if GFX_TV_DYNAMIC +int +fs450_set_position(int x, int y) +#else +int +gfx_set_position(int x, int y) +#endif +{ + d.position_x = range_limit(x, -1000, 1000); + d.position_y = range_limit(y, -1000, 1000); + + return write_config(REQ_OVERSCAN_POSITION); +} + +/*==========================================================================*/ +/* Color, Brightness, and Contrast */ +/*==========================================================================*/ + +#if GFX_TV_DYNAMIC +int +fs450_get_color(int *p_color) +#else +int +gfx_get_color(int *p_color) +#endif +{ + if (!p_color) + return ERR_INVALID_PARAMETER; + + *p_color = d.color; + + return 0; +} + +#if GFX_TV_DYNAMIC +int +fs450_set_color(int color) +#else +int +gfx_set_color(int color) +#endif +{ + d.color = range_limit(color, 0, 100); + + return write_config(REQ_COLOR); +} + +#if GFX_TV_DYNAMIC +int +fs450_get_brightness(int *p_brightness) +#else +int +gfx_get_brightness(int *p_brightness) +#endif +{ + if (!p_brightness) + return ERR_INVALID_PARAMETER; + + *p_brightness = d.brightness; + + return 0; +} + +#if GFX_TV_DYNAMIC +int +fs450_set_brightness(int brightness) +#else +int +gfx_set_brightness(int brightness) +#endif +{ + d.brightness = range_limit(brightness, 0, 100); + + return write_config(REQ_BRIGHTNESS_CONTRAST); +} + +#if GFX_TV_DYNAMIC +int +fs450_get_contrast(int *p_contrast) +#else +int +gfx_get_contrast(int *p_contrast) +#endif +{ + if (!p_contrast) + return ERR_INVALID_PARAMETER; + + *p_contrast = d.contrast; + + return 0; +} + +#if GFX_TV_DYNAMIC +int +fs450_set_contrast(int constrast) +#else +int +gfx_set_contrast(int constrast) +#endif +{ + d.contrast = range_limit(constrast, 0, 100); + + return write_config(REQ_BRIGHTNESS_CONTRAST); +} + +/*==========================================================================*/ +/* YC filters */ +/*==========================================================================*/ + +#if GFX_TV_DYNAMIC +int +fs450_get_yc_filter(unsigned int *p_yc_filter) +#else +int +gfx_get_yc_filter(unsigned int *p_yc_filter) +#endif +{ + if (!p_yc_filter) + return ERR_INVALID_PARAMETER; + + if (houston_Rev() < HOUSTON_REV_B) + return ERR_NOT_SUPPORTED; + + *p_yc_filter = d.yc_filter; + + return 0; +} + +#if GFX_TV_DYNAMIC +int +fs450_set_yc_filter(unsigned int yc_filter) +#else +int +gfx_set_yc_filter(unsigned int yc_filter) +#endif +{ + if (houston_Rev() < HOUSTON_REV_B) + return ERR_NOT_SUPPORTED; + + /*luma filter. */ + if (yc_filter & GFX_LUMA_FILTER) + d.yc_filter |= GFX_LUMA_FILTER; + else + d.yc_filter &= ~GFX_LUMA_FILTER; + + /*chroma filter. */ + if (yc_filter & GFX_CHROMA_FILTER) + d.yc_filter |= GFX_CHROMA_FILTER; + else + d.yc_filter &= ~GFX_CHROMA_FILTER; + + return write_config(REQ_YC_FILTER); +} + +#if GFX_TV_DYNAMIC +int +fs450_get_aps_trigger_bits(unsigned int *p_trigger_bits) +#else +int +gfx_get_aps_trigger_bits(unsigned int *p_trigger_bits) +#endif +{ + if (!p_trigger_bits) + return ERR_INVALID_PARAMETER; + + *p_trigger_bits = d.aps_trigger_bits; + + return 0; +} + +#if GFX_TV_DYNAMIC +int +fs450_set_aps_trigger_bits(unsigned int trigger_bits) +#else +int +gfx_set_aps_trigger_bits(unsigned int trigger_bits) +#endif +{ + d.aps_trigger_bits = trigger_bits; + + return write_config(REQ_MACROVISION); +} + +/*---------------------------------------------------------------------------- + * gfx_set_tv_format + * + * This routine sets the TV encoder registers to the specified format + * and resolution. + * Currently only NTSC 640x480 is supported. + *---------------------------------------------------------------------------- + */ +#if GFX_TV_DYNAMIC +int +fs450_set_tv_format(TVStandardType format, GfxOnTVType resolution) +#else +int +gfx_set_tv_format(TVStandardType format, GfxOnTVType resolution) +#endif +{ + /* ### ADD ### IMPLEMENTATION */ + return (0); +} + +/*---------------------------------------------------------------------------- + * gfx_set_tv_output + * + * This routine sets the TV encoder registers to the specified output type. + * Supported output types are : S-VIDEO and Composite. + *---------------------------------------------------------------------------- + */ +#if GFX_TV_DYNAMIC +int +fs450_set_tv_output(int output) +#else +int +gfx_set_tv_output(int output) +#endif +{ + /* ### ADD ### IMPLEMENTATION */ + return (0); +} + +/*---------------------------------------------------------------------------- + * gfx_set_tv_cc_enable + * + * This routine enables or disables the use of the hardware CC registers + * in the TV encoder. + *---------------------------------------------------------------------------- + */ +#if GFX_TV_DYNAMIC +int +fs450_set_tv_cc_enable(int enable) +#else +int +gfx_set_tv_cc_enable(int enable) +#endif +{ + /* ### ADD ### IMPLEMENTATION */ + return (0); +} + +/*---------------------------------------------------------------------------- + * gfx_set_tv_cc_data + * + * This routine writes the two specified characters to the CC data register + * of the TV encoder. + *---------------------------------------------------------------------------- + */ +#if GFX_TV_DYNAMIC +int +fs450_set_tv_cc_data(unsigned char data1, unsigned char data2) +#else +int +gfx_set_tv_cc_data(unsigned char data1, unsigned char data2) +#endif +{ + /* ### ADD ### IMPLEMENTATION */ + return (0); +} + +#ifdef FS450_DIRECTREG + +/*==========================================================================*/ +/* Direct Read and Write registers */ +/*==========================================================================*/ + +int +FS450_ReadRegister(S_REG_INFO * p_reg) +{ + unsigned long tmp; + + if (PLAL_ReadRegister(p_reg)) + return 0; + + if (SOURCE_HOUSTON == p_reg->source) { + switch (p_reg->size) { + case 1: + case 2: + { + houston_ReadReg((int)p_reg->offset, &tmp, (int)p_reg->size); + p_reg->value = tmp; + } + return 0; + + case 4: + { + houston_ReadReg((unsigned int)p_reg->offset, &tmp, 2); + p_reg->value = (tmp << 16); + houston_ReadReg((unsigned int)(p_reg->offset + 2), &tmp, 2); + p_reg->value |= tmp; + } + return 0; + } + } + + return ERR_INVALID_PARAMETER; +} + +int +FS450_WriteRegister(S_REG_INFO * p_reg) +{ + if (PLAL_WriteRegister(p_reg)) + return 0; + + if (SOURCE_HOUSTON == p_reg->source) { + houston_WriteReg((unsigned int)p_reg->offset, p_reg->value, + p_reg->size); + + return 0; + } + + return ERR_INVALID_PARAMETER; +} + +#endif + +/* Houston initialization function. */ +static int g_houston_rev = -1; + +static int +houston_init(void) +{ + /*//int errc; */ + unsigned long write, read; + + TRACE(("houston_init()\n")) + + /*Before we begin, we must enable power to the TFT */ + read = READ_VID32(CS5530_DISPLAY_CONFIG); + read |= CS5530_DCFG_FP_PWR_EN | CS5530_DCFG_FP_DATA_EN; + WRITE_VID32(CS5530_DISPLAY_CONFIG, read); + + /*simple w/r test. */ + write = 0x0055; + read = 0; + + houston_WriteReg(HOUSTON_IHO, write, 2); + houston_ReadReg(HOUSTON_IHO, &read, 2); + if (read != write) { + houston_WriteReg(HOUSTON_IHO, write, 2); + houston_ReadReg(HOUSTON_IHO, &read, 2); + if (read != write) { + /*chip is not there, do something appropriate? */ + TRACE(("wrote HOUSTON_IHO=0x0055, read 0x%04x\n", read)) + return ERR_DEVICE_NOT_FOUND; + } + } + + /*read chip revision. */ + houston_ReadReg(HOUSTON_REV, &read, 2); + g_houston_rev = (int)read; + + /*ok. */ + return 0; +} + +static int +houston_Rev(void) +{ + return g_houston_rev; +} + +static S_TIMING_SPECS g_specs; + +static const S_TIMING_SPECS * +p_specs(void) +{ + return &g_specs; +} + +/*==========================================================================*/ +/* FS450 configuration functions. */ +/*==========================================================================*/ +static int +config_init(void) +{ + int err; + + TRACE(("config_init()\n")) + + err = houston_init(); + if (err) + return err; + + return 0; +} + +/*==========================================================================*/ +/* convert word to encoder 10 bit value. */ +/*==========================================================================*/ + +static unsigned short +w10bit2z(unsigned short w) +{ + return (w >> 2) | ((w & 0x03) << 8); +} + +static unsigned short +z2w10bit(unsigned short z) +{ + return (0x03 & (z >> 8)) | ((0xFF & z) << 2); +} + +/*==========================================================================*/ +/* TV Standards */ +/*==========================================================================*/ + +static const struct +{ + unsigned long standard; + int tvsetup_index; +} g_tv_standards[] = { + { + GFX_TV_STANDARD_NTSC_M, 0}, { + GFX_TV_STANDARD_NTSC_M_J, 2}, { + GFX_TV_STANDARD_PAL_B, 1}, { + GFX_TV_STANDARD_PAL_D, 1}, { + GFX_TV_STANDARD_PAL_H, 1}, { + GFX_TV_STANDARD_PAL_I, 1}, { + GFX_TV_STANDARD_PAL_M, 3}, { + GFX_TV_STANDARD_PAL_N, 4}, { +GFX_TV_STANDARD_PAL_G, 1},}; + +static int +map_tvstd_to_index(unsigned long tv_std) +{ + unsigned int i; + + for (i = 0; i < sizeof(g_tv_standards) / sizeof(*g_tv_standards); i++) { + if (tv_std == g_tv_standards[i].standard) + return g_tv_standards[i].tvsetup_index; + } + + return -1; +} + +static unsigned long +supported_standards(void) +{ + unsigned long standards = 0; + unsigned int i; + + for (i = 0; i < sizeof(g_tv_standards) / sizeof(*g_tv_standards); i++) { + if (g_tv_standards[i].tvsetup_index >= 0) + standards |= g_tv_standards[i].standard; + } + + return standards; +} + +/*==========================================================================*/ + +static void +config_power(int on) +{ + unsigned long reg; + + if (houston_Rev() < HOUSTON_REV_B) { + /* no power down supported, but still turn of clock in off mode */ + if (on) { + houston_ReadReg(HOUSTON_CR, ®, 2); + reg &= ~(CR_CLKOFF | CR_RESET); + houston_WriteReg(HOUSTON_CR, reg, 2); + reg |= CR_RESET; + houston_WriteReg(HOUSTON_CR, reg, 2); + reg &= ~CR_RESET; + houston_WriteReg(HOUSTON_CR, reg, 2); + } else { + houston_ReadReg(HOUSTON_CR, ®, 2); + reg |= CR_CLKOFF; + houston_WriteReg(HOUSTON_CR, reg, 2); + } + + return; + } + + if (on) { + /* !CLKOFF, !COMPOFF, !YCOFF */ + /* and reset Houston */ + houston_ReadReg(HOUSTON_CR, ®, 2); + reg &= ~(CR_CLKOFF | CR_RESET | CR_COMPOFF | CR_YCOFF); + houston_WriteReg(HOUSTON_CR, reg, 2); + reg |= CR_RESET; + houston_WriteReg(HOUSTON_CR, reg, 2); + reg &= ~CR_RESET; + houston_WriteReg(HOUSTON_CR, reg, 2); + + /* !GTLIO_PD */ + houston_ReadReg(HOUSTON_MISC, ®, 2); + reg &= ~MISC_GTLIO_PD; + houston_WriteReg(HOUSTON_MISC, reg, 2); + } else { + /* CLKOFF, COMPOFF, YCOFF */ + houston_ReadReg(HOUSTON_CR, ®, 2); + reg |= (CR_CLKOFF | CR_COMPOFF | CR_YCOFF); + houston_WriteReg(HOUSTON_CR, reg, 2); + + /* GTLIO_PD */ + houston_ReadReg(HOUSTON_MISC, ®, 2); + reg |= MISC_GTLIO_PD; + houston_WriteReg(HOUSTON_MISC, reg, 2); + } +} + +/*==========================================================================*/ +/* VGA mode */ +/*==========================================================================*/ + +static void +config_vga_mode(unsigned long vga_mode) +{ + /*h_total must be evenly divisible by 32? */ + + static struct + { + unsigned long mode; + int width; + int lines; + int h_total; + } vgaparams[] = { + { + GFX_VGA_MODE_640X480, 640, 480, 1056}, { + GFX_VGA_MODE_720X487, 720, 487, 1056}, { + GFX_VGA_MODE_720X576, 720, 576, 1056}, { + GFX_VGA_MODE_800X600, 800, 600, 1056}, { + GFX_VGA_MODE_1024X768, 1024, 768, 1344},}; + + unsigned long cr, misc, byp; + unsigned int i; + + g_specs.vga_width = 0; + g_specs.vga_lines = 0; + g_specs.h_total = 0; + + for (i = 0; i < sizeof(vgaparams) / sizeof(*vgaparams); i++) { + if (vga_mode == vgaparams[i].mode) { + g_specs.vga_width = vgaparams[i].width; + g_specs.vga_lines = vgaparams[i].lines; + g_specs.h_total = vgaparams[i].h_total; + break; + } + } + if (!g_specs.h_total) + return; + + /*clock mux decimator and vga dual. */ + houston_ReadReg(HOUSTON_CR, &cr, 2); + houston_ReadReg(HOUSTON_MISC, &misc, 2); + houston_ReadReg(HOUSTON_BYP, &byp, 2); + + if (vga_mode == GFX_VGA_MODE_1024X768) { + /*XGA*/ cr |= CR_UIM_DEC; + misc |= MISC_VGACKDIV; + byp |= (BYP_HDS_BYPASS | BYP_CAC_BYPASS); + } else { + /*VGA,SVGA */ + cr &= ~CR_UIM_DEC; + misc &= ~MISC_VGACKDIV; + byp &= ~(BYP_HDS_BYPASS | BYP_CAC_BYPASS); + } + + houston_WriteReg(HOUSTON_CR, cr, 2); + houston_WriteReg(HOUSTON_MISC, misc, 2); + houston_WriteReg(HOUSTON_BYP, byp, 2); +} + +/*==========================================================================*/ +/* Write settings for TV standard to device */ +/*==========================================================================*/ + +static void +config_tv_std(unsigned long tv_std, unsigned int trigger_bits) +{ + int k; + unsigned short reg34; + unsigned long cr, w; + unsigned long l; + + /*verify supported standard. */ + k = map_tvstd_to_index(tv_std); + if (k < 0) + return; + + /*store tv width and lines */ + g_specs.tv_width = tvsetup.tv_width[k]; + g_specs.tv_lines = tvsetup.tv_lines[k]; + + /*houston CR register. */ + houston_ReadReg(HOUSTON_CR, &cr, 2); + cr &= ~CR_656_PAL_NTSC; + cr |= tvsetup.houston_cr[k]; + houston_WriteReg(HOUSTON_CR, cr, 2); + + /*setup the encoder. */ + l = tvsetup.chroma_freq[k]; + houston_WriteReg(ENC_CHROMA_FREQ, (int)(l & 0x00ff), 1); + houston_WriteReg(ENC_CHROMA_FREQ + 1, (int)((l >> 8) & 0x00ff), 1); + houston_WriteReg(ENC_CHROMA_FREQ + 2, (int)((l >> 16) & 0x00ff), 1); + houston_WriteReg(ENC_CHROMA_FREQ + 3, (int)((l >> 24) & 0x00ff), 1); + + houston_WriteReg(ENC_CHROMA_PHASE, tvsetup.chroma_phase[k], 1); + houston_WriteReg(ENC_REG05, 0x00, 1); /*reg 0x05 */ + houston_WriteReg(ENC_REG06, 0x89, 1); /*reg 0x06 */ + houston_WriteReg(ENC_REG07, 0x00, 1); /*reg 0x07 */ + houston_WriteReg(ENC_HSYNC_WIDTH, tvsetup.hsync_width[k], 1); + houston_WriteReg(ENC_BURST_WIDTH, tvsetup.burst_width[k], 1); + houston_WriteReg(ENC_BACK_PORCH, tvsetup.back_porch[k], 1); + houston_WriteReg(ENC_CB_BURST_LEVEL, tvsetup.cb_burst_level[k], 1); + houston_WriteReg(ENC_CR_BURST_LEVEL, tvsetup.cr_burst_level[k], 1); + houston_WriteReg(ENC_SLAVE_MODE, 0x01, 1); /*slave mode */ + if (trigger_bits == 0) + w = w10bit2z(tvsetup.blank_level[k]); /*blank level */ + else + w = w10bit2z((unsigned short)(tvsetup.blank_level[k] - + tvsetup.hamp_offset[k])); + houston_WriteReg(ENC_BLANK_LEVEL, w & 0x00ff, 1); + houston_WriteReg(ENC_BLANK_LEVEL + 1, w >> 8, 1); + w = w10bit2z(tvsetup.tv_lines[k]); /*num_lines */ + houston_WriteReg(ENC_NUM_LINES, w & 0x00ff, 1); + houston_WriteReg(ENC_NUM_LINES + 1, w >> 8, 1); + + houston_WriteReg(ENC_TINT, 0x00, 1); /*tint */ + houston_WriteReg(ENC_BREEZE_WAY, tvsetup.breeze_way[k], 1); + houston_WriteReg(ENC_FRONT_PORCH, tvsetup.front_porch[k], 1); + houston_WriteReg(ENC_ACTIVELINE, tvsetup.activeline[k], 1); + houston_WriteReg(ENC_FIRST_LINE, 0x15, 1); /*firstvideoline */ + reg34 = + 0x80 | + (tvsetup.pal_mode[k] << 6) | + (tvsetup.sys625_50[k] << 3) | + (tvsetup.cphase_rst[k] << 1) | (tvsetup.vsync5[k]); + houston_WriteReg(ENC_REG34, reg34, 1); /*reg 0x34 */ + houston_WriteReg(ENC_SYNC_LEVEL, tvsetup.sync_level[k], 1); + if (trigger_bits == 0) + w = w10bit2z(tvsetup.vbi_blank_level[k]); /*blank level */ + else + w = w10bit2z((unsigned short)(tvsetup.vbi_blank_level[k] - 1)); + houston_WriteReg(ENC_VBI_BLANK_LEVEL, w & 0x00ff, 1); + houston_WriteReg(ENC_VBI_BLANK_LEVEL + 1, w >> 8, 1); +} + +static void +conget_tv_std(unsigned long *p_tv_standard) +{ + unsigned long cr; + + if (!p_tv_standard) + return; + + /*just pick between NTSC and PAL */ + houston_ReadReg(HOUSTON_CR, &cr, 2); + if (CR_656_PAL_NTSC & cr) + *p_tv_standard = GFX_TV_STANDARD_PAL_B; + else + *p_tv_standard = GFX_TV_STANDARD_NTSC_M; +} + +/*==========================================================================*/ +/* TVout mode */ +/*==========================================================================*/ + +static void +config_tvout_mode(unsigned long tvout_mode) +{ + unsigned long cr; + + houston_ReadReg(HOUSTON_CR, &cr, 2); + + /*all dacs off */ + cr |= (CR_COMPOFF | CR_YCOFF); + /*not rgb */ + cr &= ~CR_OFMT; + + /*turn on requested output */ + if (GFX_TVOUT_MODE_CVBS & tvout_mode) + cr &= ~CR_COMPOFF; + if (GFX_TVOUT_MODE_YC & tvout_mode) + cr &= ~CR_YCOFF; + if (GFX_TVOUT_MODE_RGB & tvout_mode) { + cr &= ~(CR_COMPOFF | CR_YCOFF); + cr |= CR_OFMT; + } + + houston_WriteReg(HOUSTON_CR, cr, 2); +} + +static void +conget_tvout_mode(unsigned long *p_tvout_mode) +{ + unsigned long cr; + + if (!p_tvout_mode) + return; + + houston_ReadReg(HOUSTON_CR, &cr, 2); + + if (CR_OFMT & cr) + *p_tvout_mode = GFX_TVOUT_MODE_RGB; + else { + *p_tvout_mode = 0; + if (!(CR_YCOFF & cr)) + *p_tvout_mode |= GFX_TVOUT_MODE_YC; + if (!(CR_COMPOFF & cr)) + *p_tvout_mode |= GFX_TVOUT_MODE_CVBS; + } +} + +/*==========================================================================*/ +/* Size & Position */ +/*==========================================================================*/ + +#define IS_NTSC(tv_std) \ + (tv_std & ( \ + GFX_TV_STANDARD_NTSC_M | \ + GFX_TV_STANDARD_NTSC_M_J | \ + GFX_TV_STANDARD_PAL_M)) +#define IS_PAL(tv_std) \ + (tv_std & ( \ + GFX_TV_STANDARD_PAL_B | \ + GFX_TV_STANDARD_PAL_D | \ + GFX_TV_STANDARD_PAL_H | \ + GFX_TV_STANDARD_PAL_I | \ + GFX_TV_STANDARD_PAL_N | \ + GFX_TV_STANDARD_PAL_G)) + +/*return fifo delay setting for mode, std, and total lines.*/ + +static void +get_ffolat_ivo(unsigned long vga_mode, + unsigned long tv_std, long i, unsigned short *ffolat, unsigned short *ivo) +{ + switch (vga_mode) { + case GFX_VGA_MODE_640X480: + if (IS_NTSC(tv_std)) { + if (i > SIZE6X4NTSC - 1) + i = SIZE6X4NTSC - 1; + *ffolat = ffo6x4ntsc[i].ffolat; + *ivo = 0x20; + } else { + if (i > SIZE6X4PAL - 1) + i = SIZE6X4PAL - 1; + *ffolat = ffo6x4pal[i].ffolat; + *ivo = 0x28; + } + break; + + case GFX_VGA_MODE_800X600: + if (IS_NTSC(tv_std)) { + if (i > SIZE8X6NTSC - 1) + i = SIZE8X6NTSC - 1; + *ffolat = ffo8x6ntsc[i].ffolat; + *ivo = 0x3a; + } else { + if (i > SIZE8X6PAL - 1) + i = SIZE8X6PAL - 1; + *ffolat = ffo8x6pal[i].ffolat; + *ivo = 0x39; + } + break; + + case GFX_VGA_MODE_720X487: + *ffolat = 0x40; /*FFO7x4; */ + *ivo = 0x1a; + break; + + case GFX_VGA_MODE_720X576: + *ffolat = 0x40; /*FFO7x5; */ + *ivo = 0x1a; + break; + + case GFX_VGA_MODE_1024X768: + default: + if (IS_NTSC(tv_std)) { + if (i > SIZE10X7NTSC - 1) + i = SIZE10X7NTSC - 1; + *ffolat = ffo10x7ntsc[i].ffolat; + *ivo = ffo10x7ntsc[i].ivo; + } else { + if (i > SIZE10X7PAL - 1) + i = SIZE10X7PAL - 1; + *ffolat = ffo10x7pal[i].ffolat; + *ivo = ffo10x7pal[i].ivo; + } + break; + } +} + +/*get vertical line min and max for mode and std.*/ + +static void +get_vtotal_min_max(unsigned long vga_mode, + unsigned long tv_std, int *v_total_min, int *v_total_max, int *v_step) +{ + int k = map_tvstd_to_index(tv_std); + + switch (vga_mode) { + case GFX_VGA_MODE_640X480: + if (IS_NTSC(tv_std)) { + *v_total_min = ffo6x4ntsc[0].v_total; + *v_total_max = ffo6x4ntsc[SIZE6X4NTSC - 1].v_total; + } else { + *v_total_min = ffo6x4pal[0].v_total; + *v_total_max = ffo6x4pal[SIZE6X4PAL - 1].v_total; + } + *v_step = 4; + break; + + case GFX_VGA_MODE_800X600: + if (IS_NTSC(tv_std)) { + *v_total_min = ffo8x6ntsc[0].v_total; + *v_total_max = ffo8x6ntsc[SIZE8X6NTSC - 1].v_total; + } else { + *v_total_min = ffo8x6pal[0].v_total; + *v_total_max = ffo8x6pal[SIZE8X6PAL - 1].v_total; + } + *v_step = 5; + break; + + case GFX_VGA_MODE_720X487: + case GFX_VGA_MODE_720X576: + *v_total_min = tvsetup.tv_lines[k]; + *v_total_max = tvsetup.tv_lines[k]; + *v_step = 4; + break; + + case GFX_VGA_MODE_1024X768: + if (IS_NTSC(tv_std)) { + *v_total_min = ffo10x7ntsc[0].v_total; + *v_total_max = ffo10x7ntsc[SIZE10X7NTSC - 1].v_total; + } else { + *v_total_min = ffo10x7pal[0].v_total; + *v_total_max = ffo10x7pal[SIZE10X7PAL - 1].v_total; + } + *v_step = 6; + break; + } +} + +static void +config_overscan_xy(unsigned long tv_std, + unsigned long vga_mode, + int overscan_x, int overscan_y, int pos_x, int pos_y) +{ + unsigned int vga_index; + unsigned long reg; + double vsc; + int k; + unsigned short ffolat, ivo; + int base_v_total, range, v_offset; + int v_total_min, v_total_max, v_step; + float r, f; + int vga_pixels, pre_pixels; + float hscale, hscale_min, hscale_max; + int hsc; + int iho, iho_max, ihw; + + /*tv_std is valid. */ + k = map_tvstd_to_index(tv_std); + + /*store tv width and lines */ + g_specs.tv_width = tvsetup.tv_width[k]; + g_specs.tv_lines = tvsetup.tv_lines[k]; + + /*determine vga mode index */ + for (vga_index = 0; vga_index < SCANTABLE_ENTRIES; vga_index++) { + if (scantable[vga_index].mode == vga_mode) + break; + } + if (vga_index >= SCANTABLE_ENTRIES) + return; + + /*vertical scaling (v_total setup). */ + /*calculate vertical range. */ + get_vtotal_min_max(vga_mode, tv_std, &v_total_min, &v_total_max, &v_step); + TRACE(("v_total min=%d, max=%d\n", v_total_min, v_total_max)) + base_v_total = scantable[vga_index].v_total[k]; + range = fsmax(base_v_total - v_total_min, v_total_max - base_v_total); + TRACE(("v_total range = %d\n", range)) + + /*map +/-1000 overscan y into +/-range. */ + v_offset = (int)((((float)overscan_y * range) / 1000.f) + .5f); + TRACE(("v_offset = %d\n", v_offset)) + + /*range limit v_total. */ + g_specs.v_total = + range_limit(base_v_total + v_offset, v_total_min, v_total_max); + + /*round to calibrated value. */ + v_offset = (g_specs.v_total - v_total_min + (v_step / 2)) / v_step; + g_specs.v_total = v_total_min + v_offset * v_step; + TRACE(("desired v_total=%d\n", g_specs.v_total)) + + /*vertical positioning (vsync setup). */ + get_ffolat_ivo(vga_mode, tv_std, v_offset, &ffolat, &ivo); + houston_WriteReg(HOUSTON_IVO, ivo, 2); + + /*scale base sync offset by scaling ratio. */ + r = (float)g_specs.v_total / (float)base_v_total; + v_offset = (int)(r * (float)scantable[vga_index].v_sync[k]); + + /*scale ivo. */ + f = (float)ivo; + v_offset -= (int)(f - f / r); + + /*compensate for center screen. */ + f = (float)tvsetup.tv_active_lines[k] / 2.f; + v_offset += (int)(f * r - f); + + /*calculate vsync. */ + g_specs.v_sync = g_specs.v_total - v_offset + pos_y; + TRACE(("desired v_total=%d, desired v_sync=%d\n", g_specs.v_total, + g_specs.v_sync)) + if (g_specs.v_sync < g_specs.vga_lines + 10) { + TRACE(("vsync too low\n")) + /*d.v_total += d.vga_lines+10-d.v_sync; */ + g_specs.v_sync = g_specs.vga_lines + 10; + } else if (g_specs.v_sync > g_specs.v_total - 10) { + TRACE(("vsync too high\n")) + g_specs.v_sync = g_specs.v_total - 10; + } + TRACE(("v_total=%d v_sync=%d\n", g_specs.v_total, g_specs.v_sync)) + + /* FFOLAT. */ + houston_WriteReg(HOUSTON_FFO_LAT, ffolat, 2); + + /* VSC. */ + vsc = + (65536.0f * (1.0f - + (double)g_specs.tv_lines / (double)g_specs.v_total)) + 0.5f; + reg = ((unsigned long)-vsc) & 0xffff; + TRACE(("vsc=%04x, tv_lines=%d, v_total=%d\n", reg, g_specs.tv_lines, + g_specs.v_total)) + houston_WriteReg(HOUSTON_VSC, (int)reg, 2); + + /* horizontal scaling. */ + + /* vga pixels is vga width, except in 1024x768, where it's half that. */ + vga_pixels = g_specs.vga_width; + if (1024 == vga_pixels) + vga_pixels /= 2; + + /* maximum scaling coefficient is tv_width / vga_pixels */ + /* minimum is about 1/2, but that is quite small. arbitrarily set + * minimum at 75% maximum. */ + hscale_max = (720.0f / vga_pixels); + hscale_min = fsmax((0.75f * hscale_max), (1.0f - (63.0f / 128.0f))); + TRACE(("hscale_min = %u.%u, hscale_max = %u.%u\n", + (int)hscale_min, + (int)((hscale_min - (int)hscale_min) * 1000), + (int)hscale_max, (int)((hscale_max - (int)hscale_max) * 1000))) + + /* map overscan_x into min to max. */ + hscale = + hscale_min + ((overscan_x + 1000.0f) / 2000.0f) * (hscale_max - + hscale_min); + TRACE(("hscale = %u.%u\n", (int)hscale, + (int)((hscale - (int)hscale) * 1000))) + + /* determine hsc where hscale = (1 + hsc/128) */ + if (hscale >= 1.0f) + hsc = (int)(128.f * (hscale - 1.0f) + .5f); + else + hsc = (int)(128.f * (hscale - 1.0f) - .5f); + + TRACE(("hsc = %d\n", hsc)) + if (hsc >= 0) + houston_WriteReg(HOUSTON_HSC, hsc << 8, 2); + else + houston_WriteReg(HOUSTON_HSC, hsc & 0xFF, 2); + + /* recalculate hscale for future formulas */ + hscale = 1.0f + (hsc / 128.0f); + TRACE(("recalculated hscale = %u.%u\n", (int)hscale, + (int)((hscale - (int)hscale) * 1000))) + + /* horizontal offset. */ + /* place hsync 40 before halfway from vga_width to htotal */ + /* but not less than vga_width + 10 */ + g_specs.h_sync = + fsmax((g_specs.h_total + g_specs.vga_width) / 2 - 40, + g_specs.vga_width + 10); + /* also, make it even */ + g_specs.h_sync &= ~1; + TRACE(("hsync = %u\n", g_specs.h_sync)) + + /* iho range is 0 to iho_max. */ + /* iho_max is 2 * iho_center. */ + /* iho_center is pre_pixels - (tvwidth / hscale - vga pixels) / 2. */ + /* pre_pixels = (htotal - hsync) * (vga_pixels / vga_width) */ + /* note that the range is inverted also, because it specifies the number + * of pixels */ + /* to skip, or subtract. iho=0 maps to farthest right. */ + /* map -pos_x = +/-1000 into (0 to iho_max) */ + pre_pixels = + (int)((long)(g_specs.h_total - + g_specs.h_sync) * vga_pixels / g_specs.vga_width); + iho_max = (2 * pre_pixels) - ((int)(720.0f / hscale + 0.5f) - vga_pixels); + TRACE(("iho_max = %u\n", iho_max)) + iho = + (int)range_limit(((long)(1000 - pos_x) * iho_max / 2000) + + scantable[vga_index].iho[k], 0, iho_max); + TRACE(("iho = %u\n", iho)) + houston_WriteReg(HOUSTON_IHO, iho, 2); + + /* input horizontal width. */ + + /* input horizontal width is vga pixels + pre_pixels - iho */ + /* additionally, ihw cannot exceed tv width / hscale */ + /* and if hsc is negative, (ihw)(-hsc/128) cannot exceed ~250. */ + /* and ihw should be even. */ + ihw = fsmin(vga_pixels + pre_pixels - iho, (int)(720.0f / hscale)); + if (hsc < 0) + ihw = (int)fsmin(ihw, 253L * 128 / (-hsc)); + ihw &= ~1; + TRACE(("ihw = %u\n", ihw)) + houston_WriteReg(HOUSTON_IHA, ihw, 2); + + f = (((float)g_specs.h_total * g_specs.v_total) * 27.f) / + ((float)g_specs.tv_width * g_specs.tv_lines); + + TRACE(("freq=%u.%uMHz\n", (int)f, (int)((f - (int)f) * 1000))) +} + +/*==========================================================================*/ +/* configure houston nco. */ +/*==========================================================================*/ + +static void +config_nco(unsigned long tv_std, unsigned long vga_mode) +{ + unsigned long cr, misc; + unsigned long reg; + int k = map_tvstd_to_index(tv_std); + + /*read and store CR. */ + houston_ReadReg(HOUSTON_CR, &cr, 2); + + /*make sure NCO_EN (enable latch) bit is clear */ + cr &= ~CR_NCO_EN; + houston_WriteReg(HOUSTON_CR, cr, 2); + + /*clear NCO_LOADX. */ + houston_ReadReg(HOUSTON_MISC, &misc, 2); + misc &= ~(MISC_NCO_LOAD1 + MISC_NCO_LOAD0); + houston_WriteReg(HOUSTON_MISC, misc, 2); + + if (vga_mode == GFX_VGA_MODE_1024X768) { + /*setup for M and N load (Nco_load=1). */ + misc |= (MISC_NCO_LOAD0); + houston_WriteReg(HOUSTON_MISC, misc, 2); + + /*M and N. */ + houston_WriteReg(HOUSTON_NCONL, 1024 - 2, 2); + houston_WriteReg(HOUSTON_NCODL, 128 - 1, 2); + + /*latch M/N in. */ + cr |= CR_NCO_EN; + houston_WriteReg(HOUSTON_CR, cr, 2); + cr &= ~CR_NCO_EN; + houston_WriteReg(HOUSTON_CR, cr, 2); + + /*setup ncon and ncod load (Nco_load=0). */ + misc &= ~(MISC_NCO_LOAD1 + MISC_NCO_LOAD0); + houston_WriteReg(HOUSTON_MISC, misc, 2); + + /*NCON. */ + reg = ((unsigned long)g_specs.v_total * g_specs.h_total) / 2; + houston_WriteReg(HOUSTON_NCONH, reg >> 16, 2); + houston_WriteReg(HOUSTON_NCONL, reg & 0xffff, 2); + + /*NCOD. */ + houston_WriteReg(HOUSTON_NCODL, tvsetup.houston_ncodl[k], 2); + houston_WriteReg(HOUSTON_NCODH, tvsetup.houston_ncodh[k], 2); + } else { + /*setup for M and N load (Nco_load=2). */ + misc |= (MISC_NCO_LOAD1); + houston_WriteReg(HOUSTON_MISC, misc, 2); + + /*NCON. */ + reg = (unsigned long)g_specs.v_total * g_specs.h_total; + houston_WriteReg(HOUSTON_NCONH, reg >> 16, 2); + houston_WriteReg(HOUSTON_NCONL, reg & 0xffff, 2); + + /*NCOD. */ + houston_WriteReg(HOUSTON_NCODL, tvsetup.houston_ncodl[k], 2); + houston_WriteReg(HOUSTON_NCODH, tvsetup.houston_ncodh[k], 2); + + TRACE(("NCON = %lu (0x%08lx), NCOD = %lu (0x%08lx)\n", + reg, + reg, + ((unsigned long)tvsetup.houston_ncodh[k] << 16) + + tvsetup.houston_ncodl[k], + ((unsigned long)tvsetup.houston_ncodh[k] << 16) + + tvsetup.houston_ncodl[k])) + } + + /*latch M/N and NCON/NCOD in. */ + cr |= CR_NCO_EN; + houston_WriteReg(HOUSTON_CR, cr, 2); + cr &= ~CR_NCO_EN; + houston_WriteReg(HOUSTON_CR, cr, 2); +} + +/*==========================================================================*/ +/* Write sharpness settings to device */ +/*==========================================================================*/ + +static void +config_sharpness(int sharpness) +{ + unsigned int shp; + + /*map 0-1000 to 0-20. */ + shp = (unsigned int)(0.5f + ((float)sharpness * 20.0f / 1000.0f)); + shp = range_limit(shp, 0, 20); + + houston_WriteReg(HOUSTON_SHP, shp, 2); +} + +static void +conget_sharpness(int *p_sharpness) +{ + unsigned long shp; + + if (!p_sharpness) + return; + + houston_ReadReg(HOUSTON_SHP, &shp, 2); + + /*map 0-20 to 0-1000. */ + *p_sharpness = (int)(0.5f + ((float)shp * 1000.0f / 20.0f)); +} + +/*==========================================================================*/ +/* Write flicker settings to device */ +/*==========================================================================*/ + +static void +config_flicker(int flicker) +{ + unsigned int flk; + + /*map 0-1000 to 0-16. */ + flk = (unsigned int)(0.5f + ((float)flicker * 16.0f / 1000.0f)); + flk = range_limit(flk, 0, 16); + + houston_WriteReg(HOUSTON_FLK, flk, 2); +} + +static void +conget_flicker(int *p_flicker) +{ + unsigned long flk; + + if (!p_flicker) + return; + + houston_ReadReg(HOUSTON_FLK, &flk, 2); + + /*map 0-16 to 0-1000. */ + *p_flicker = (int)(0.5f + ((float)flk * 1000.0f / 16.0f)); +} + +/*==========================================================================*/ +/* Write color settings to device */ +/*==========================================================================*/ + +static void +config_color(int color) +{ + unsigned long clr; + + /*map 0-100 to 0-255. */ + /*montreal production test needs 169 to be mappable, so */ + /*use .8 rounding factor, 169=(int)(66.*2.55+.8). */ + clr = (unsigned long)(0.8f + ((float)color * 255.0f / 100.0f)); + clr = range_limit(clr, 0, 255); + + houston_WriteReg(ENC_CR_GAIN, clr, 1); + houston_WriteReg(ENC_CB_GAIN, clr, 1); +} + +static void +conget_color(int *p_color) +{ + unsigned long cr_gain; + + if (!p_color) + return; + + /*just get CR GAIN, CB GAIN should match. */ + houston_ReadReg(ENC_CR_GAIN, &cr_gain, 1); + + /*map 0-255 to 0-100. */ + *p_color = (int)(0.5f + ((float)cr_gain * 100.0f / 255.0f)); +} + +/*==========================================================================*/ +/* Write brightness and contrast settings to device */ +/*==========================================================================*/ + +#define NTSC_BLANK_LEVEL 240 + +static const int min_black_level = NTSC_BLANK_LEVEL + 1; +static const int max_white_level = 1023; + +static void +config_brightness_contrast(unsigned long tv_std, unsigned int trigger_bits, + int brightness, int contrast) +{ + int brightness_off; + float contrast_mult; + int black, white; + unsigned short w; + int k = map_tvstd_to_index(tv_std); + + /*0-100 maps to +/-220. */ + brightness_off = + (int)(0.5f + ((float)brightness * 440.0f / 100.0f)) - 220; + + /*0-100 maps to .75-1.25. */ + contrast_mult = ((float)contrast * 0.5f / 100.0f) + 0.75f; + + black = tvsetup.black_level[k]; + if (trigger_bits != 0) + black -= tvsetup.hamp_offset[k]; + + white = tvsetup.white_level[k]; + if (trigger_bits != 0) + white -= tvsetup.hamp_offset[k]; + + black = (int)((float)(black + brightness_off) * contrast_mult); + white = (int)((float)(white + brightness_off) * contrast_mult); + if (black < min_black_level) + black = min_black_level; + if (white > max_white_level) + white = max_white_level; + + w = w10bit2z((unsigned short)black); + houston_WriteReg(ENC_BLACK_LEVEL, w & 0x00ff, 1); + houston_WriteReg(ENC_BLACK_LEVEL + 1, w >> 8, 1); + w = w10bit2z((unsigned short)white); + houston_WriteReg(ENC_WHITE_LEVEL, w & 0x00ff, 1); + houston_WriteReg(ENC_WHITE_LEVEL + 1, w >> 8, 1); +} + +static void +conget_brightness_contrast(unsigned long tv_std, unsigned int trigger_bits, + int *p_brightness, int *p_contrast) +{ + int brightness_off; + float contrast_mult; + unsigned short black, white; + unsigned long zh, zl; + int k; + + if (!p_brightness || !p_contrast) + return; + + k = map_tvstd_to_index(tv_std); + + houston_ReadReg(ENC_BLACK_LEVEL, &zl, 1); + houston_ReadReg(ENC_BLACK_LEVEL + 1, &zh, 1); + black = z2w10bit((unsigned short)(zl + (zh << 8))); + if (trigger_bits != 0) + black += tvsetup.hamp_offset[k]; + houston_ReadReg(ENC_WHITE_LEVEL, &zl, 1); + houston_ReadReg(ENC_WHITE_LEVEL + 1, &zh, 1); + white = z2w10bit((unsigned short)(zl + (zh << 8))); + if (trigger_bits != 0) + white += tvsetup.hamp_offset[k]; + + /*this reverse computation does not account for clipping, but should */ + /*provide somewhat reasonable numbers */ + contrast_mult = + ((float)white - (float)black) / ((float)tvsetup.white_level[k] - + (float)tvsetup.black_level[k]); + brightness_off = + (int)(((float)black / contrast_mult) - tvsetup.black_level[k]); + + /*+/-220 maps to 0-100. */ + *p_brightness = + range_limit((int)(0.5f + ((float)(brightness_off + + 220) * 100.0f / 440.0f)), 0, 100); + + /*.75-1.25 maps to 0-100. */ + *p_contrast = + range_limit((int)(0.5f + ((float)(contrast_mult - + 0.75f) * 100.0f / 0.5f)), 0, 100); +} + +/*==========================================================================*/ +/* configure luma/chroma filters. */ +/*==========================================================================*/ + +static void +config_yc_filter(unsigned long tv_std, int luma_filter, int chroma_filter) +{ + unsigned long reg, reg07, reg34; + + if (houston_Rev() < HOUSTON_REV_B) + return; + + /*luma filter. */ + if (luma_filter) + reg = tvsetup.notch_filter[map_tvstd_to_index(tv_std)]; + else + reg = 0; + houston_WriteReg(ENC_NOTCH_FILTER, reg, 1); + + /*chroma filter. */ + houston_ReadReg(ENC_REG07, ®07, 1); + houston_ReadReg(ENC_REG34, ®34, 1); + if (chroma_filter) { + reg07 &= ~0x08; + reg34 &= ~0x20; + } else { + reg07 |= 0x08; + reg34 |= 0x20; + } + houston_WriteReg(ENC_REG07, reg07, 1); + houston_WriteReg(ENC_REG34, reg34, 1); +} + +static void +conget_yc_filter(int *p_luma_filter, int *p_chroma_filter) +{ + unsigned long reg, reg07, reg34; + + if (!p_luma_filter || !p_chroma_filter) + return; + + if (houston_Rev() < HOUSTON_REV_B) { + *p_luma_filter = 0; + *p_chroma_filter = 0; + return; + } + + /*luma filter. */ + houston_ReadReg(ENC_NOTCH_FILTER, ®, 1); + *p_luma_filter = (reg ? 1 : 0); + + /*chroma filter. */ + houston_ReadReg(ENC_REG07, ®07, 1); + houston_ReadReg(ENC_REG34, ®34, 1); + *p_chroma_filter = !((0x08 & reg07) || (0x20 & reg34)); +} + +/*==========================================================================*/ +/* Macrovision */ +/*==========================================================================*/ + +static void +config_macrovision(unsigned long tv_std, unsigned int trigger_bits) +{ +/*Constants to index into mvsetup columns.*/ +#define nNTSC_APS00 0 /*ntsc mv off. */ +#define nNTSC_APS01 1 /*ntsc AGC only. */ +#define nNTSC_APS10 2 /*ntsc AGC + 2-line CS. */ +#define nNTSC_APS11 3 /*ntsc AGC + 4-line CS. */ +#define nPAL_APS00 4 /*pal mv off. */ +#define nPAL_APSXX 5 /*pal mv on. */ +#define nMVModes 6 + + /*Macrovision setup table. */ + static const struct mvparms + { + unsigned short n0[nMVModes]; + unsigned short n1[nMVModes]; + unsigned short n2[nMVModes]; + unsigned short n3[nMVModes]; + unsigned short n4[nMVModes]; + unsigned short n5[nMVModes]; + unsigned short n6[nMVModes]; + unsigned short n7[nMVModes]; + unsigned short n8[nMVModes]; + unsigned short n9[nMVModes]; + unsigned short n10[nMVModes]; + unsigned short n11[nMVModes]; + unsigned short n12[nMVModes]; + unsigned short n13[nMVModes]; + unsigned short n14[nMVModes]; + unsigned short n15[nMVModes]; + unsigned short n16[nMVModes]; + unsigned short n17[nMVModes]; + unsigned short n18[nMVModes]; + unsigned short n19[nMVModes]; + unsigned short n20[nMVModes]; + unsigned short n21[nMVModes]; + unsigned short n22[nMVModes]; + unsigned short agc_pulse_level[nMVModes]; + unsigned short bp_pulse_level[nMVModes]; + } + + mvsetup = { + /* ntsc ntsc ntsc ntsc pal pal */ + /* MV AGC AGC + AGC + MV MV */ + /* off. only 2-line 4-line off. on. */ + /* CS. CS. */ + { + 0x00, 0x36, 0x3e, 0x3e, 0x00, 0x3e}, /*n0 */ + { + 0x1d, 0x1d, 0x1d, 0x17, 0x1a, 0x1a}, /*n1 */ + { + 0x11, 0x11, 0x11, 0x15, 0x22, 0x22}, /*n2 */ + { + 0x25, 0x25, 0x25, 0x21, 0x2a, 0x2a}, /*n3 */ + { + 0x11, 0x11, 0x11, 0x15, 0x22, 0x22}, /*n4 */ + { + 0x01, 0x01, 0x01, 0x05, 0x05, 0x05}, /*n5 */ + { + 0x07, 0x07, 0x07, 0x05, 0x02, 0x02}, /*n6 */ + { + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00}, /*n7 */ + { + 0x1b, 0x1b, 0x1b, 0x1b, 0x1c, 0x1c}, /*n8 */ + { + 0x1b, 0x1b, 0x1b, 0x1b, 0x3d, 0x3d}, /*n9 */ + { + 0x24, 0x24, 0x24, 0x24, 0x14, 0x14}, /*n10 */ + { + 0x780f, 0x780f, 0x780f, 0x780f, 0x7e07, 0x7e07}, /*n11 */ + { + 0x0000, 0x0000, 0x0000, 0x0000, 0x5402, 0x5402}, /*n12 */ + { + 0x0f, 0x0f, 0x0f, 0x0f, 0xfe, 0xfe}, /*n13 */ + { + 0x0f, 0x0f, 0x0f, 0x0f, 0x7e, 0x7e}, /*n14 */ + { + 0x60, 0x60, 0x60, 0x60, 0x60, 0x60}, /*n15 */ + { + 0x01, 0x01, 0x01, 0x01, 0x00, 0x00}, /*n16 */ + { + 0x0a, 0x0a, 0x0a, 0x0a, 0x08, 0x08}, /*n17 */ + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*n18 */ + { + 0x05, 0x05, 0x05, 0x05, 0x04, 0x04}, /*n19 */ + { + 0x04, 0x04, 0x04, 0x04, 0x07, 0x07}, /*n20 */ + { + 0x03ff, 0x03ff, 0x03ff, 0x03ff, 0x0155, 0x0155}, /*n21 */ + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*n22 */ + { + 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3}, /*agc_pulse_level */ + { + 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8}, /*bp_pulse_level */ + }; + + int nMode; + unsigned long misc; + unsigned short n0; + + trigger_bits &= 0x3; + + /*Determine the OEM Macrovision Program Mode and Register 0 Data. */ + if (IS_NTSC(tv_std)) { + /*NTSC TV Standard. */ + if (trigger_bits == 0) { + /*turn Macrovision OFF. */ + nMode = nNTSC_APS00; + } else if (trigger_bits == 1) { + /*AGC Only. */ + nMode = nNTSC_APS01; + } else if (trigger_bits == 2) { + /*AGC + 2-line CS. */ + nMode = nNTSC_APS10; + } else { + /*AGC + 4-line CS. */ + nMode = nNTSC_APS11; + } + } else { + /*PAL TV Standard. */ + if (trigger_bits == 0) { + /*turn Macrovision OFF. */ + nMode = nPAL_APS00; + } else { + /*APS 01, 10, or 11. */ + nMode = nPAL_APSXX; + } + } + + /*Retrieve the Macrovision Program Mode Data */ + if (tv_std != GFX_TV_STANDARD_PAL_M) + n0 = mvsetup.n0[nMode]; + else { + /*PAL-M sets up like NTSC except for n0. */ + if ((trigger_bits & 0x03) == 0) + n0 = mvsetup.n0[nPAL_APS00]; + else + n0 = mvsetup.n0[nPAL_APSXX]; + } + + /*download settings now. */ + houston_WriteReg(MV_N0, n0, 1); + houston_WriteReg(MV_N1, mvsetup.n1[nMode], 1); + houston_WriteReg(MV_N2, mvsetup.n2[nMode], 1); + houston_WriteReg(MV_N3, mvsetup.n3[nMode], 1); + houston_WriteReg(MV_N4, mvsetup.n4[nMode], 1); + houston_WriteReg(MV_N5, mvsetup.n5[nMode], 1); + houston_WriteReg(MV_N6, mvsetup.n6[nMode], 1); + houston_WriteReg(MV_N7, mvsetup.n7[nMode], 1); + houston_WriteReg(MV_N8, mvsetup.n8[nMode], 1); + houston_WriteReg(MV_N9, mvsetup.n9[nMode], 1); + houston_WriteReg(MV_N10, mvsetup.n10[nMode], 1); + houston_WriteReg(MV_N11, mvsetup.n11[nMode] & 0xff, 1); + houston_WriteReg(MV_N11 + 1, mvsetup.n11[nMode] >> 8, 1); + houston_WriteReg(MV_N12, mvsetup.n12[nMode] & 0xff, 1); + houston_WriteReg(MV_N12 + 1, mvsetup.n12[nMode] >> 8, 1); + houston_WriteReg(MV_N13, mvsetup.n13[nMode], 1); + houston_WriteReg(MV_N14, mvsetup.n14[nMode], 1); + houston_WriteReg(MV_N15, mvsetup.n15[nMode], 1); + houston_WriteReg(MV_N16, mvsetup.n16[nMode], 1); + houston_WriteReg(MV_N17, mvsetup.n17[nMode], 1); + houston_WriteReg(MV_N18, mvsetup.n18[nMode], 1); + houston_WriteReg(MV_N19, mvsetup.n19[nMode], 1); + houston_WriteReg(MV_N20, mvsetup.n20[nMode], 1); + houston_WriteReg(MV_N21, mvsetup.n21[nMode] & 0xff, 1); + houston_WriteReg(MV_N21 + 1, mvsetup.n21[nMode] >> 8, 1); + houston_WriteReg(MV_N22, mvsetup.n22[nMode], 1); + houston_WriteReg(MV_AGC_PULSE_LEVEL, mvsetup.agc_pulse_level[nMode], 1); + houston_WriteReg(MV_BP_PULSE_LEVEL, mvsetup.bp_pulse_level[nMode], 1); + + houston_ReadReg(HOUSTON_MISC, &misc, 2); + if (trigger_bits == 0) + misc &= ~MISC_MV_SOFT_EN; + else + misc |= MISC_MV_SOFT_EN; + houston_WriteReg(HOUSTON_MISC, misc, 2); +} + +static void +conget_macrovision(unsigned long tv_std, unsigned int *p_cp_trigger_bits) +{ + unsigned long n0, n1; + + if (!p_cp_trigger_bits) + return; + + houston_ReadReg(MV_N0, &n0, 1); + houston_ReadReg(MV_N1, &n1, 1); + + *p_cp_trigger_bits = 0; + + if (IS_NTSC(tv_std)) { + switch (n0) { + case 0: + *p_cp_trigger_bits = 0; + break; + + case 0x36: + *p_cp_trigger_bits = 1; + break; + + case 0x3E: + { + if (0x1D == n1) + *p_cp_trigger_bits = 2; + else + *p_cp_trigger_bits = 3; + } + break; + } + } else if (IS_PAL(tv_std)) { + if (0 == n0) + *p_cp_trigger_bits = 0; + else { + /*don't know here what the non-zero trigger bits were */ + *p_cp_trigger_bits = 1; + } + } +} + +/* PLAL_MediaGX.cpp */ +/*==========================================================================*/ +/* These functions provides implementation of platform-specific functions */ +/* MediaGX platform. */ +/*==========================================================================*/ + +/*MediaGX control registers.*/ +#define CCR3 0xC3 +#define GCR 0xb8 + +/*Media GX general config register.*/ +#define GX_DCLK_MUL 0x00c0 +#define GX_DCLKx1 0x0040 +#define GX_DCLKx2 0x0080 +#define GX_DCLKx4 0x00c0 + +/*Media GX timing config register.*/ +#define GX_TGEN 0x0020 + +/*Cx5530 register offsets (from GX_BASE).*/ +#define CX_DISPLAY_CONFIG 0x10004 +#define CX_DOT_CLK 0x10024 +#define CX_TV_CONFIG 0x10028 + +/*Cx5530 display configuration register.*/ +#define CX_FPVSYNC_POL 0x0800 +#define CX_FPHSYNC_POL 0x0400 +#define CX_FPDATA_ENB 0x0080 +#define CX_FPPOWER_ENB 0x0040 +#define CX_CRTVSYNC_POL 0x0200 +#define CX_CRTHSYNC_POL 0x0100 + +/*Cx5530 dot clock configuration register.*/ +#define CX_TVCLK_SELECT 0x0400 + +/*Cx5530 tv configuration register*/ +#define CX_INVERT_FPCLK (1 << 6) + +/*========================================================================== + * FS450 I2C Address + * There are two possible 7-bit addresses, 0x4A and 0x6A. + * The address if selectable via pins on the FS450. + * There are also two possible 10-bit addresses, 0x224 and 0x276, but this + * source is not designed to use them. + *==========================================================================*/ + +#define FS450_I2C_ADDRESS (0x4A) + +static unsigned char +PLAL_FS450_i2c_address(void) +{ + return FS450_I2C_ADDRESS; +} + +/*========================================================================== + * FS450 UIM mode + * This mode is programmed in the FS450 command register when enabling TV + * out. + *========================================================================== + */ +static int +PLAL_FS450_UIM_mode(void) +{ + return 3; +} + +/*==========================================================================*/ +/* Read and Write MediaGX registers */ +/*==========================================================================*/ +static unsigned long +ReadGx(unsigned long inRegAddr) +{ + unsigned long data; + + DMAL_ReadUInt32(inRegAddr, &data); + + return data; +} + +static void +WriteGx(unsigned long inRegAddr, unsigned long inData) +{ + int is_timing_register; + unsigned long reg_timing_cfg; + + /*because the unlock register for the MediaGx video registers may not */ + /*persist, we will write the unlock code before every write. */ + DMAL_WriteUInt32(DC_UNLOCK, 0x4758); + + /*see if register is a timing register */ + is_timing_register = + (DC_H_TIMING_1 == inRegAddr) || + (DC_H_TIMING_2 == inRegAddr) || + (DC_H_TIMING_3 == inRegAddr) || + (DC_FP_H_TIMING == inRegAddr) || + (DC_V_TIMING_1 == inRegAddr) || + (DC_V_TIMING_2 == inRegAddr) || + (DC_V_TIMING_3 == inRegAddr) || (DC_FP_V_TIMING == inRegAddr); + + /*if the register is a timing register, clear the TGEN bit to allow + * modification */ + if (is_timing_register) { + DMAL_ReadUInt32(DC_TIMING_CFG, ®_timing_cfg); + DMAL_WriteUInt32(DC_TIMING_CFG, reg_timing_cfg & ~GX_TGEN); + } + + /*write the requested register */ + DMAL_WriteUInt32(inRegAddr, inData); + + /*reset the TGEN bit to previous state */ + if (is_timing_register) { + DMAL_WriteUInt32(DC_TIMING_CFG, reg_timing_cfg); + } +} + +#ifdef FS450_DIRECTREG + +/*==========================================================================*/ +/* Platform-specific processing for a Read or Write Register calls. */ +/* The functions should return true if the specified register belongs to */ +/* this platform. */ +/*==========================================================================*/ + +static int +PLAL_ReadRegister(S_REG_INFO * p_reg) +{ + if (!p_reg) + return 0; + + if (SOURCE_GCC == p_reg->source) { + p_reg->value = ReadGx(p_reg->offset); + + return 1; + } + + return 0; +} + +static int +PLAL_WriteRegister(const S_REG_INFO * p_reg) +{ + if (!p_reg) + return 0; + + if (SOURCE_GCC == p_reg->source) { + WriteGx(p_reg->offset, p_reg->value); + + return 1; + } + + return 0; +} + +#endif + +/*========================================================================== + * Determine if TV is on + *==========================================================================*/ +static int +PLAL_IsTVOn(void) +{ + unsigned long reg; + + /*check Cx5530 dot clock */ + reg = ReadGx(CX_DOT_CLK); + return (reg & CX_TVCLK_SELECT) ? 1 : 0; +} + +/*========================================================================== + * Platform-specific actions to reset to VGA mode + *==========================================================================*/ + +static int +PLAL_EnableVga(void) +{ + unsigned long reg; + + /*2 x dclk */ + reg = ReadGx(DC_GENERAL_CFG); + reg &= ~GX_DCLK_MUL; + reg |= GX_DCLKx2; + WriteGx(DC_GENERAL_CFG, reg); + + /*select pll dot clock. */ + reg = ReadGx(CX_DOT_CLK); + reg &= ~CX_TVCLK_SELECT; + WriteGx(CX_DOT_CLK, reg); + + /*timing config, reset everything on dclk. */ + reg = ReadGx(DC_TIMING_CFG); + reg &= ~GX_TGEN; + WriteGx(DC_TIMING_CFG, reg); + reg |= GX_TGEN; + WriteGx(DC_TIMING_CFG, reg); + + /*un-invert FP clock */ + reg = ReadGx(CX_TV_CONFIG); + reg &= ~CX_INVERT_FPCLK; + WriteGx(CX_TV_CONFIG, reg); + + return 0; +} + +/*==========================================================================*/ +/*Platform-specific actions to enter TVout mode */ +/*==========================================================================*/ + +static int +PLAL_PrepForTVout(void) +{ + unsigned int reg; + + /*Cx5530 tv config. */ + reg = 0; + WriteGx(CX_TV_CONFIG, reg); + + /*invert FP clock */ + reg = (int)ReadGx(CX_TV_CONFIG); + reg |= CX_INVERT_FPCLK; + WriteGx(CX_TV_CONFIG, reg); + + return 0; +} + +static int +PLAL_SetTVTimingRegisters(const S_TIMING_SPECS * p_specs) +{ + unsigned long reg; + + /*timing config, reset everything on dclk. */ + reg = ReadGx(DC_TIMING_CFG); + reg &= ~GX_TGEN; + WriteGx(DC_TIMING_CFG, reg); + + /*htotal and hactive. */ + reg = ((p_specs->h_total - 1) << 16) | (p_specs->vga_width - 1); + WriteGx(DC_H_TIMING_1, reg); + + /*hblank. */ + reg = ((p_specs->h_total - 1) << 16) | (p_specs->vga_width - 1); + WriteGx(DC_H_TIMING_2, reg); + + /*hsync. */ + reg = ((p_specs->h_sync + 63) << 16) | p_specs->h_sync; + WriteGx(DC_H_TIMING_3, reg); + + /*fp hsync. */ + WriteGx(DC_FP_H_TIMING, reg); + + /*vtotal and vactive. */ + reg = ((p_specs->v_total - 1) << 16) | (p_specs->vga_lines - 1); + WriteGx(DC_V_TIMING_1, reg); + + /*vblank. */ + reg = ((p_specs->v_total - 1) << 16) | (p_specs->vga_lines - 1); + WriteGx(DC_V_TIMING_2, reg); + + /*vsync. */ + reg = ((p_specs->v_sync) << 16) | (p_specs->v_sync - 1); + WriteGx(DC_V_TIMING_3, reg); + + /*fp vsync. */ + reg = ((p_specs->v_sync - 1) << 16) | (p_specs->v_sync - 2); + WriteGx(DC_FP_V_TIMING, reg); + + /*timing config, reenable all dclk stuff. */ + reg = ReadGx(DC_TIMING_CFG); + reg |= GX_TGEN; + WriteGx(DC_TIMING_CFG, reg); + + return 0; +} + +static int +PLAL_FinalEnableTVout(unsigned long vga_mode) +{ + unsigned int reg; + + /*Cx5530 select tv dot clock. */ + reg = (int)ReadGx(CX_DOT_CLK); + reg |= CX_TVCLK_SELECT; + WriteGx(CX_DOT_CLK, reg); + + /*2 x dclk (actually 1x) */ + reg = (int)ReadGx(DC_GENERAL_CFG); + reg &= ~GX_DCLK_MUL; + WriteGx(DC_GENERAL_CFG, reg); + + reg |= GX_DCLKx2; + WriteGx(DC_GENERAL_CFG, reg); + + /*Cx5530 display configuration register. */ + reg = (int)ReadGx(CX_DISPLAY_CONFIG); + reg |= (CX_FPVSYNC_POL | CX_FPHSYNC_POL | CX_FPDATA_ENB | CX_FPPOWER_ENB); + WriteGx(CX_DISPLAY_CONFIG, reg); + + return 0; +} diff --git a/src/gfx/tv_fs450.h b/src/gfx/tv_fs450.h new file mode 100644 index 0000000..7e917c0 --- /dev/null +++ b/src/gfx/tv_fs450.h @@ -0,0 +1,206 @@ +/* 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 defines the common FS450 API. + * */ + +#ifndef __FS450_H__ +#define __FS450_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*==========================================================================*/ +/* Init and cleanup functions*/ + + int FS450_init(void); + void FS450_cleanup(void); + /* call FS450_init at startup to probe for and initialize FS450. */ + /* returns 0 if successful. */ + +/*==========================================================================*/ +/* TV output on or off*/ + + int FS450_get_tv_enable(unsigned int *p_on); + int FS450_set_tv_enable(unsigned int on); + /* on is 1 for TV on, 0 for off */ + +/*==========================================================================*/ +/* TV standard*/ + + int FS450_get_tv_standard(unsigned long *p_standard); + int FS450_get_available_tv_standards(unsigned long *p_standards); + int FS450_set_tv_standard(unsigned long standard); + /* standard is one of the FS450_TV_STANDARD constants */ + /* standards is a bitmask of zero or more FS450_TV_STANDARD constants */ + +/* FS450 TV Standard flags*/ +#define FS450_TV_STANDARD_NTSC_M 0x0001 +#define FS450_TV_STANDARD_NTSC_M_J 0x0002 +#define FS450_TV_STANDARD_PAL_B 0x0004 +#define FS450_TV_STANDARD_PAL_D 0x0008 +#define FS450_TV_STANDARD_PAL_H 0x0010 +#define FS450_TV_STANDARD_PAL_I 0x0020 +#define FS450_TV_STANDARD_PAL_M 0x0040 +#define FS450_TV_STANDARD_PAL_N 0x0080 +#define FS450_TV_STANDARD_PAL_G 0x0100 + +/*==========================================================================*/ +/* VGA mode assumed by FS450*/ + + int FS450_get_vga_mode(unsigned long *p_vga_mode); + int FS450_get_available_vga_modes(unsigned long *p_vga_modes); + int FS450_set_vga_mode(unsigned long vga_mode); + /* vga_mode is one of the FS450_VGA_MODE constants */ + /* vga_modes is a bitmask of zero or more FS450_VGA_MODE constants */ + +/* FS450 VGA Mode flags*/ +#define FS450_VGA_MODE_UNKNOWN 0 +#define FS450_VGA_MODE_640X480 0x0001 +#define FS450_VGA_MODE_720X487 0x0002 +#define FS450_VGA_MODE_720X576 0x0004 +#define FS450_VGA_MODE_800X600 0x0008 +#define FS450_VGA_MODE_1024X768 0x0010 + +/*==========================================================================*/ +/* TVout mode*/ + + int FS450_get_tvout_mode(unsigned long *p_tvout_mode); + int FS450_set_tvout_mode(unsigned long tvout_mode); + /* tvout_mode is a bitmask of FS450_TVOUT_MODE constants */ + +/* FS450 TVout mode flags*/ +#define FS450_TVOUT_MODE_CVBS 0x0001 +#define FS450_TVOUT_MODE_YC 0x0002 +#define FS450_TVOUT_MODE_RGB 0x0004 +#define FS450_TVOUT_MODE_CVBS_YC (FS450_TVOUT_MODE_CVBS | FS450_TVOUT_MODE_YC) + +/*==========================================================================*/ +/* Flicker control*/ + + int FS450_get_sharpness(int *p_sharpness); + int FS450_set_sharpness(int sharpness); + /* sharpness is a percentage in tenths of a percent, 0 to 1000 */ + + int FS450_get_flicker_filter(int *p_flicker); + int FS450_set_flicker_filter(int flicker); + /* flicker_filter is a percentage in tenths of a percent, 0 to 1000 */ + +/*==========================================================================*/ +/* Size and Position*/ + + int FS450_get_overscan(int *p_x, int *p_y); + int FS450_set_overscan(int x, int y); + int FS450_get_position(int *p_x, int *p_y); + int FS450_set_position(int x, int y); + /* x and y are horizontal and vertical adjustments, -1000 to +1000 */ + +/*==========================================================================*/ +/* Visual adjustments*/ + + int FS450_get_color(int *p_color); + int FS450_set_color(int color); + /* color is a percentage, 0 to 100 */ + + int FS450_get_brightness(int *p_brightness); + int FS450_set_brightness(int brightness); + /* brightness is a percentage, 0 to 100 */ + + int FS450_get_contrast(int *p_contrast); + int FS450_set_contrast(int constrast); + /* contrast is a percentage, 0 to 100 */ + +/*==========================================================================*/ +/* Luma and Chroma filter*/ + + int FS450_get_yc_filter(unsigned int *p_yc_filter); + int FS450_set_yc_filter(unsigned int yc_filter); + /* yc_filter is a bitmask of FS450_LUMA_FILTER and/or FS450_CHROMA_FILTER */ + +/* FS450 Luma and Chroma Filters*/ +#define FS450_LUMA_FILTER 0x0001 +#define FS450_CHROMA_FILTER 0x0002 + +/*==========================================================================*/ +/* Macrovision*/ + + int FS450_get_aps_trigger_bits(unsigned int *p_trigger_bits); + int FS450_set_aps_trigger_bits(unsigned int trigger_bits); + /* trigger_bits is one of the FS450_APS_TRIGGER constants */ + +/* APS Trigger Bits*/ +#define FS450_APS_TRIGGER_OFF 0 +#define FS450_APS_TRIGGER_AGC_ONLY 1 +#define FS450_APS_TRIGGER_AGC_2_LINE 2 +#define FS450_APS_TRIGGER_AGC_4_LINE 3 + +/*==========================================================================*/ +/* direct access to Houston and platform registers (debug builds only) + * The two functions FS450_ReadRegister and FS450_WriteRegister allow access + * to device registers. These functions are intended for debugging purposes + * only and should not be included in a shipping product. + * */ + +#ifdef FS450_DIRECTREG + +#define SOURCE_HOUSTON 0 +#define SOURCE_GCC 1 + + typedef struct _S_REG_INFO + { + int source; + unsigned int size; + unsigned long offset; + unsigned long value; + } S_REG_INFO; + + int FS450_ReadRegister(S_REG_INFO * p_reg); + int FS450_WriteRegister(S_REG_INFO * p_reg); + +#endif + +/*==========================================================================*/ +/* Error Codes*/ + +#define ERR_INVALID_PARAMETER 0x1000 +#define ERR_NOT_SUPPORTED 0x1001 +#define ERR_CANNOT_CHANGE_WHILE_TV_ON 0x1002 + +#define ERR_DRIVER_NOT_FOUND 0x1100 +#define ERR_DRIVER_ERROR 0x1101 +#define ERR_DEVICE_NOT_FOUND 0x1120 + +#define ERR_I2C_MISSING_DEVICE 0x1200 +#define ERR_I2C_WRITE_FAILED 0x1201 +#define ERR_I2C_READ_FAILED 0x1202 + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/gfx/vga_gu1.c b/src/gfx/vga_gu1.c new file mode 100644 index 0000000..20cf232 --- /dev/null +++ b/src/gfx/vga_gu1.c @@ -0,0 +1,680 @@ +/* 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 to set modes using the VGA registers. + * Since this file is for the first generation graphics unit, it interfaces + * to SoftVGA registers. It works for both VSA1 and VSA2. + * */ + +/* SoftVGA Extended CRTC register indices and bit definitions */ + +#define CRTC_EXTENDED_REGISTER_LOCK 0x30 +#define CRTC_MODE_SWITCH_CONTROL 0x3F + +/* BIT DEFINITIONS */ + +#define CRTC_BIT_16BPP 0x01 +#define CRTC_BIT_555 0x02 + +/* LOCAL ROUTINE DEFINITIONS */ + +int gu1_detect_vsa2(void); + +/*---------------------------------*/ +/* MODE TABLES FOR VGA REGISTERS */ +/*---------------------------------*/ + +/* FOR SoftVGA, the CRTC_EXTENDED_ADDRESS_CONTROL (0x43) is always equal to + * 0x03 for a packed linear frame buffer organization. The + * CRTC_EXTENDED_DAC_CONTROL (0x4B) is always equal to 0x03 to work with + * older versions of VSA1 (that needed to specify 8 or 16 bit bus to an + * external RAMDAC. This is not used in VSA2. The clock frequency is + * specified in register 0x4D if clock control (0x4C) is set to 0x80. + * Higher resolutions (1280x1024) use the CRTC_EXTENDED_VERTICAL_TIMING + * register (index 0x41). + */ + +gfx_vga_struct gfx_vga_modes[] = { +/*--------------------------------------------------------------------------*/ + { + 640, 480, 60, /* 640x480 */ + 25, /* 25 MHz clock = 60 Hz refresh rate */ + 0xE3, /* miscOutput register */ + { + 0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0x0B, 0x3E, + /* standard CRTC */ + 0x80, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xEA, 0x0C, 0xDF, 0x50, 0x00, 0xE7, 0x04, 0xE3, 0xFF}, + { + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, + /* extended CRTC */ + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00} + }, +/*--------------------------------------------------------------------------*/ + { + 640, 480, 72, /* 640x480 */ + 29, /* 29 MHz clock = 72 Hz refresh rate */ + 0xE3, /* miscOutput register */ + { + 0x63, 0x4f, 0x50, 0x86, 0x55, 0x99, 0x06, 0x3e, + /* standard CRTC */ + 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xe9, 0x0c, 0xdf, 0x00, 0x00, 0xe7, 0x00, 0xe3, 0xff}, + { + 0x6D, 0x00, 0x00, 0x03, 0x00, 0x01, 0x01, 0x00, + /* extended CRTC */ + 0x00, 0x00, 0x01, 0x08, 0x80, 0x1F, 0x00, 0x4B} + }, +/*--------------------------------------------------------------------------*/ + { + 640, 480, 75, /* 640x480 */ + 31, + /* 31.5 MHz clock = 75 Hz refresh rate */ + 0xE3, /* miscOutput register */ + { + 0x64, 0x4F, 0x4F, 0x88, 0x54, 0x9B, 0xF2, 0x1F, + /* standard CRTC */ + 0x80, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xE1, 0x04, 0xDF, 0x50, 0x00, 0xDF, 0xF3, 0xE3, 0xFF}, + { + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, + /* extended CRTC */ + 0x00, 0x00, 0x00, 0x03, 0x80, 0x1F, 0x00, 0x00} + }, +/*--------------------------------------------------------------------------*/ + { + 800, 600, 60, /* 800x600 */ + 40, /* 40 MHz clock = 60 Hz refresh rate */ + 0x23, /* miscOutput register */ + { + 0x7F, 0x63, 0x64, 0x82, 0x6B, 0x1B, 0x72, 0xF0, + /* standard CRTC */ + 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x59, 0x0D, 0x57, 0x64, 0x00, 0x57, 0x73, 0xE3, 0xFF}, + { + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, + /* extended CRTC */ + 0x00, 0x00, 0x00, 0x03, 0x80, 0x28, 0x00, 0x00} + }, +/*--------------------------------------------------------------------------*/ + { + 800, 600, 72, /* 800x600 */ + 47, /* 47 MHz clock = 72 Hz refresh rate */ + 0x2B, /* miscOutput register */ + { + 0x7D, 0x63, 0x63, 0x81, 0x6D, 0x1B, 0x98, 0xF0, + /* standard CRTC */ + 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7D, 0x03, 0x57, 0x00, 0x00, 0x57, 0x9A, 0xE3, 0xFF}, + { + 0x6F, 0x00, 0x00, 0x03, 0x00, 0x01, 0x01, 0x00, + /* extended CRTC */ + 0x00, 0x00, 0x01, 0x08, 0x80, 0x32, 0x00, 0x4B} + }, +/*--------------------------------------------------------------------------*/ + { + 800, 600, 75, /* 800x600 */ + 49, + /* 49.5 MHz clock = 75 Hz refresh rate */ + 0x23, /* miscOutput register */ + { + 0x7F, 0x63, 0x63, 0x83, 0x68, 0x11, 0x6F, 0xF0, + /* standard CRTC */ + 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x59, 0x1C, 0x57, 0x64, 0x00, 0x57, 0x70, 0xE3, 0xFF}, + { + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, + /* extended CRTC */ + 0x00, 0x00, 0x00, 0x03, 0x80, 0x31, 0x00, 0x00} + }, +/*--------------------------------------------------------------------------*/ + { + 1024, 768, 60, /* 1024x768 */ + 65, /* 65 MHz clock = 60 Hz refresh rate */ + 0xE3, /* miscOutput register */ + { + 0xA3, 0x7F, 0x80, 0x86, 0x85, 0x96, 0x24, 0xF5, + /* standard CRTC */ + 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x0A, 0xFF, 0x80, 0x00, 0xFF, 0x25, 0xE3, 0xFF}, + { + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, + /* extended CRTC */ + 0x00, 0x00, 0x00, 0x03, 0x80, 0x41, 0x00, 0x00} + }, +/*--------------------------------------------------------------------------*/ + { + 1024, 768, 70, /* 1024x768 */ + 76, /* 76 MHz clock = 70 Hz refresh rate */ + 0x2B, /* miscOutput register */ + { + 0xA1, 0x7F, 0x7F, 0x85, 0x85, 0x95, 0x24, 0xF5, + /* standard CRTC */ + 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x09, 0xFF, 0x00, 0x00, 0xFF, 0x26, 0xE3, 0xFF}, + { + 0x62, 0x00, 0x00, 0x03, 0x00, 0x01, 0x01, 0x00, + /* extended CRTC */ + 0x00, 0x00, 0x01, 0x02, 0x80, 0x4B, 0x00, 0x4B} + }, +/*--------------------------------------------------------------------------*/ + { + 1024, 768, 75, /* 1024x768 */ + 79, /* 79 MHz clock = 75 Hz refresh rate */ + 0xE3, /* miscOutput register */ + { + 0x9F, 0x7F, 0x7F, 0x83, 0x84, 0x8F, 0x1E, 0xF5, + /* standard CRTC */ + 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x04, 0xFF, 0x80, 0x00, 0xFF, 0x1F, 0xE3, 0xFF}, + { + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, + /* extended CRTC */ + 0x00, 0x00, 0x00, 0x03, 0x80, 0x4F, 0x00, 0x00} + }, +/*--------------------------------------------------------------------------*/ + { + 1280, 1024, 60, /* 1280x1024 */ + 108, + /* 108 MHz clock = 60 Hz refresh rate */ + 0x23, /* miscOutput register */ + { + 0xCF, 0x9F, 0xA0, 0x92, 0xAA, 0x19, 0x28, 0x52, + /* standard CRTC */ + 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x04, 0xFF, 0xA0, 0x00, 0x00, 0x29, 0xE3, 0xFF}, + { + 0x00, 0x51, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, + /* extended CRTC */ + 0x00, 0x00, 0x00, 0x03, 0x80, 0x6C, 0x00, 0x00} + }, +/*--------------------------------------------------------------------------*/ + { + 1280, 1024, 75, /* 1280x1024 */ + 135, + /* 135 MHz clock = 75 Hz refresh rate */ + 0x23, /* miscOutput register */ + { + 0xCE, 0x9F, 0x9F, 0x92, 0xA4, 0x15, 0x28, 0x52, + /* standard CRTC */ + 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x04, 0xFF, 0xA0, 0x00, 0x00, 0x29, 0xE3, 0xFF}, + { + 0x00, 0x51, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, + /* extended CRTC */ + 0x00, 0x00, 0x00, 0x03, 0x80, 0x87, 0x00, 0x00} + }, +/*--------------------------------------------------------------------------*/ + { + 1280, 1024, 85, /* 1280x1024 */ + 159, + /* 159 MHz clock = 85 Hz refresh rate */ + 0x2B, /* miscOutput register */ + { + 0xD3, 0x9F, 0xA0, 0x98, 0xA8, 0x9C, 0x2E, 0x5A, + /* standard CRTC */ + 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x04, 0xFF, 0x00, 0x00, 0xFF, 0x30, 0xE3, 0xFF}, + { + 0x6B, 0x41, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, + /* extended CRTC */ + 0x00, 0x00, 0x01, 0x00, 0x80, 0x9D, 0x00, 0x4B} + }, +/*--------------------------------------------------------------------------*/ +}; + +#define GFX_VGA_MODES sizeof(gfx_vga_modes)/sizeof(gfx_vga_struct) + +/*---------------------------------------------------------------------------- + * gfx_get_softvga_active + * + * This returns the active status of SoftVGA + *---------------------------------------------------------------------------- + */ +int +gfx_get_softvga_active(void) +{ + unsigned short crtcindex, crtcdata; + + if (gu1_detect_vsa2()) + return (gfx_get_vsa2_softvga_enable()); + + crtcindex = (INB(0x3CC) & 0x01) ? 0x3D4 : 0x3B4; + crtcdata = crtcindex + 1; + + OUTB(crtcindex, CRTC_MODE_SWITCH_CONTROL); + return (INB(crtcdata) & 0x1); +} + +/*---------------------------------------------------------------------------- + * gfx_vga_test_pci + * + * This routine looks for the VGA PCI header. It checks to see that bit 1 + * of the command register is writable to know that SoftVGA is trapping + * the PCI config cuscles. If SoftVGA is not emulating the header, the + * hardware will still respond with the proper device ID, etc. + * + * We need to know that SoftVGA is really there so that we can set the + * command register and have the proper effect (enable trapping of VGA). + * Otherwise, if we enable VGA via the PCI header, trapping really won't be + * enabled and the VGA register writes will go out to the external card. + *---------------------------------------------------------------------------- + */ +int +gfx_vga_test_pci(void) +{ + int softvga = 1; + unsigned long value; + + value = gfx_pci_config_read(0x80009400); + if ((value & 0x0000FFFF) != 0x1078) + softvga = 0; + else { + value = gfx_pci_config_read(0x80009404); + gfx_pci_config_write(0x80009404, value | 0x02); + if (!(gfx_pci_config_read(0x80009404) & 0x02)) + softvga = 0; + gfx_pci_config_write(0x80009404, value); + } + return (softvga); +} + +/*---------------------------------------------------------------------------- + * gfx_vga_get_pci_command + * + * This routine returns the value of the PCI command register. + *---------------------------------------------------------------------------- + */ +unsigned char +gfx_vga_get_pci_command(void) +{ + unsigned long value; + + value = gfx_pci_config_read(0x80009404); + return ((unsigned char)value); +} + +/*---------------------------------------------------------------------------- + * gfx_vga_set_pci_command + * + * This routine writes the value of the PCI command register. It is used + * to enable or disable SoftVGA. + * + * Bit 0: Enable VGA IO + * Bit 1: Enable VGA memory + *---------------------------------------------------------------------------- + */ +int +gfx_vga_set_pci_command(unsigned char command) +{ + unsigned long value; + + value = gfx_pci_config_read(0x80009404) & 0xFFFFFF00; + value |= (unsigned long)command; + gfx_pci_config_write(0x80009404, value); + return (GFX_STATUS_OK); +} + +/*---------------------------------------------------------------------------- + * gfx_vga_seq_reset + * + * This routine enables or disables SoftVGA. It is used to make SoftVGA + * "be quiet" and not interfere with any of the direct hardware access from + * Durango. For VSA1, the sequencer is reset to stop text redraws. VSA2 may + * provide a better way to have SoftVGA sit in the background. + *---------------------------------------------------------------------------- + */ +int +gfx_vga_seq_reset(int reset) +{ + OUTB(0x3C4, 0); + OUTB(0x3C5, (unsigned char)(reset ? 0x00 : 0x03)); + return (GFX_STATUS_OK); +} + +/*---------------------------------------------------------------------------- + * gfx_vga_set_graphics_bits + * + * This routine sets the standard VGA sequencer, graphics controller, and + * attribute registers to appropriate values for a graphics mode (packed, + * 8 BPP or greater). This is also known as "VESA" modes. The timings for + * a particular mode are handled by the CRTC registers, which are set by + * the "gfx_vga_restore" routine. Most OSs that use VGA to set modes save + * and restore the standard VGA registers themselves, which is why these + * registers are not part of the save/restore paradigm. + *---------------------------------------------------------------------------- + */ +int +gfx_vga_set_graphics_bits(void) +{ + /* SET GRAPHICS BIT IN GRAPHICS CONTROLLER REG 0x06 */ + + OUTB(0x3CE, 0x06); + OUTB(0x3CF, 0x01); + + /* SET GRAPHICS BIT IN ATTRIBUTE CONTROLLER REG 0x10 */ + + INB(0x3BA); /* Reset flip-flop */ + INB(0x3DA); + OUTB(0x3C0, 0x10); + OUTB(0x3C0, 0x01); + return (GFX_STATUS_OK); +} + +/*---------------------------------------------------------------------------- + * gfx_vga_mode + * + * This routine searches the VGA mode table for a match of the specified + * mode and then fills in the VGA structure with the associated VGA register + * values. The "gfx_vga_restore" routine can then be called to actually + * set the mode. + *---------------------------------------------------------------------------- + */ +int +gfx_vga_mode(gfx_vga_struct * vga, int xres, int yres, int bpp, int hz) +{ + unsigned int i; + unsigned short pitch; + + for (i = 0; i < GFX_VGA_MODES; i++) { + if ((gfx_vga_modes[i].xsize == xres) && + (gfx_vga_modes[i].ysize == yres) && (gfx_vga_modes[i].hz == hz)) { + /* COPY ENTIRE STRUCTURE FROM THE TABLE */ + + *vga = gfx_vga_modes[i]; + + /* SET PITCH TO 1K OR 2K */ + /* CRTC_EXTENDED_OFFSET index is 0x45, so offset = 0x05 */ + + pitch = (unsigned short)xres; + if (bpp > 8) + pitch <<= 1; + if (pitch <= 1024) + pitch = 1024 >> 3; + else + pitch = 2048 >> 3; + vga->stdCRTCregs[0x13] = (unsigned char)pitch; + vga->extCRTCregs[0x05] = (unsigned char)((pitch >> 8) & 0x03); + + /* SET PROPER COLOR DEPTH VALUE */ + /* CRTC_EXTENDED_COLOR_CONTROL index is 0x46, so offset = 0x06 */ + + switch (bpp) { + case 15: + vga->extCRTCregs[0x06] = CRTC_BIT_16BPP | CRTC_BIT_555; + break; + case 16: + vga->extCRTCregs[0x06] = CRTC_BIT_16BPP; + break; + default: + vga->extCRTCregs[0x06] = 0; + break; + } + return (GFX_STATUS_OK); + } + } + return (GFX_STATUS_UNSUPPORTED); +} + +/*---------------------------------------------------------------------------- + * gfx_vga_pitch + * + * This routine updates the VGA regisers in the specified VGA structure for + * the specified pitch. It does not program the hardware. + *---------------------------------------------------------------------------- + */ +int +gfx_vga_pitch(gfx_vga_struct * vga, unsigned short pitch) +{ + pitch >>= 3; + vga->stdCRTCregs[0x13] = (unsigned char)pitch; + vga->extCRTCregs[0x05] = (unsigned char)((pitch >> 8) & 0x03); + return (0); +} + +/*---------------------------------------------------------------------------- + * gfx_vga_save + * + * This routine saves the state of the VGA registers into the specified + * structure. Flags indicate what portions of the register state need to + * be saved. + *---------------------------------------------------------------------------- + */ +int +gfx_vga_save(gfx_vga_struct * vga, int flags) +{ + int i; + unsigned short crtcindex, crtcdata; + + crtcindex = (INB(0x3CC) & 0x01) ? 0x3D4 : 0x3B4; + crtcdata = crtcindex + 1; + + /* CHECK MISCELLANEOUS OUTPUT FLAG */ + + if (flags & GFX_VGA_FLAG_MISC_OUTPUT) { + /* SAVE MISCCELLANEOUS OUTPUT REGISTER */ + + vga->miscOutput = INB(0x3CC); + } + + /* CHECK STANDARD CRTC FLAG */ + + if (flags & GFX_VGA_FLAG_STD_CRTC) { + /* SAVE STANDARD CRTC REGISTERS */ + + for (i = 0; i < GFX_STD_CRTC_REGS; i++) { + OUTB(crtcindex, (unsigned char)i); + vga->stdCRTCregs[i] = INB(crtcdata); + } + } + + /* CHECK EXTENDED CRTC FLAG */ + + if (flags & GFX_VGA_FLAG_EXT_CRTC) { + /* SAVE EXTENDED CRTC REGISTERS */ + + for (i = 0; i < GFX_EXT_CRTC_REGS; i++) { + OUTB(crtcindex, (unsigned char)(0x40 + i)); + vga->extCRTCregs[i] = INB(crtcdata); + } + } + return (0); +} + +/*---------------------------------------------------------------------------- + * gfx_vga_clear_extended + * + * This routine clears the extended SoftVGA register values to have SoftVGA + * behave like standard VGA. + *---------------------------------------------------------------------------- + */ +void +gfx_vga_clear_extended(void) +{ + int i; + unsigned short crtcindex, crtcdata; + + crtcindex = (INB(0x3CC) & 0x01) ? 0x3D4 : 0x3B4; + crtcdata = crtcindex + 1; + + OUTB(crtcindex, 0x30); + OUTB(crtcdata, 0x57); + OUTB(crtcdata, 0x4C); + for (i = 0x40; i <= 0x4F; i++) { + OUTB(crtcindex, (unsigned char)i); + OUTB(crtcdata, 0); + } + OUTB(crtcindex, 0x30); + OUTB(crtcdata, 0x00); +} + +/*---------------------------------------------------------------------------- + * gfx_vga_restore + * + * This routine restores the state of the VGA registers from the specified + * structure. Flags indicate what portions of the register state need to + * be saved. + *---------------------------------------------------------------------------- + */ +int +gfx_vga_restore(gfx_vga_struct * vga, int flags) +{ + int i; + unsigned short crtcindex, crtcdata; + + crtcindex = (INB(0x3CC) & 0x01) ? 0x3D4 : 0x3B4; + crtcdata = crtcindex + 1; + + /* CHECK MISCELLANEOUS OUTPUT FLAG */ + + if (flags & GFX_VGA_FLAG_MISC_OUTPUT) { + /* RESTORE MISCELLANEOUS OUTPUT REGISTER VALUE */ + + OUTB(0x3C2, vga->miscOutput); + } + + /* CHECK STANDARD CRTC FLAG */ + + if (flags & GFX_VGA_FLAG_STD_CRTC) { + /* UNLOCK STANDARD CRTC REGISTERS */ + + OUTB(crtcindex, 0x11); + OUTB(crtcdata, 0); + + /* RESTORE STANDARD CRTC REGISTERS */ + + for (i = 0; i < GFX_STD_CRTC_REGS; i++) { + OUTB(crtcindex, (unsigned char)i); + OUTB(crtcdata, vga->stdCRTCregs[i]); + } + } + + /* CHECK EXTENDED CRTC FLAG */ + + if (flags & GFX_VGA_FLAG_EXT_CRTC) { + /* UNLOCK EXTENDED CRTC REGISTERS */ + + OUTB(crtcindex, 0x30); + OUTB(crtcdata, 0x57); + OUTB(crtcdata, 0x4C); + + /* RESTORE EXTENDED CRTC REGISTERS */ + + for (i = 0; i < GFX_EXT_CRTC_REGS; i++) { + OUTB(crtcindex, (unsigned char)(0x40 + i)); + OUTB(crtcdata, vga->extCRTCregs[i]); + } + + /* LOCK EXTENDED CRTC REGISTERS */ + + OUTB(crtcindex, 0x30); + OUTB(crtcdata, 0x00); + + /* CHECK IF DIRECT FRAME BUFFER MODE (VESA MODE) */ + + if (vga->extCRTCregs[0x03] & 1) { + /* SET BORDER COLOR TO BLACK */ + /* This really should be another thing saved/restored, but */ + /* Durango currently doesn't do the attr controller registers. */ + + INB(0x3BA); /* Reset flip-flop */ + INB(0x3DA); + OUTB(0x3C0, 0x11); + OUTB(0x3C0, 0x00); + } + } + return (0); +} + +/*---------------------------------------------------------------------------- + * gfx_vga_mode_switch + * + * This routine programs the SoftVGA register to indicate that a mode switch + * is in progress. This results in a cleaner mode switch since SoftVGA will + * not validate the hardware with intermediate values. + *---------------------------------------------------------------------------- + */ +int +gfx_vga_mode_switch(int active) +{ + unsigned short crtcindex, crtcdata; + + crtcindex = (INB(0x3CC) & 0x01) ? 0x3D4 : 0x3B4; + crtcdata = crtcindex + 1; + + /* UNLOCK EXTENDED CRTC REGISTERS */ + + OUTB(crtcindex, CRTC_EXTENDED_REGISTER_LOCK); + OUTB(crtcdata, 0x57); + OUTB(crtcdata, 0x4C); + + /* SIGNAL THE BEGINNING OR END OF THE MODE SWITCH */ + /* SoftVGA will hold off validating the back end hardware. */ + + OUTB(crtcindex, CRTC_MODE_SWITCH_CONTROL); + active = active ? 1 : 0; + OUTB(crtcdata, (unsigned char)active); + + /* WAIT UNTIL SOFTVGA HAS VALIDATED MODE IF ENDING MODE SWITCH */ + /* This is for VSA1 only, where SoftVGA waits until the next */ + /* vertical blank to validate the hardware state. */ + + if ((!active) && (!(gu1_detect_vsa2()))) { + OUTB(crtcindex, 0x33); + while (INB(crtcdata) & 0x80) ; + } + + /* LOCK EXTENDED CRTC REGISTERS */ + + OUTB(crtcindex, CRTC_EXTENDED_REGISTER_LOCK); + OUTB(crtcdata, 0x00); + return (0); +} + +/*---------------------------------------------------------------------------- + * gu1_detect_vsa2 + * + * This routine detects if VSA2 is present. The interface to SoftVGA + * changed slightly. + *---------------------------------------------------------------------------- + */ +int +gu1_detect_vsa2(void) +{ + unsigned short crtcindex, crtcdata; + + crtcindex = (INB(0x3CC) & 0x01) ? 0x3D4 : 0x3B4; + crtcdata = crtcindex + 1; + OUTB(crtcindex, 0x35); + if (INB(crtcdata) != 'C') + return (0); + OUTB(crtcindex, 0x36); + if (INB(crtcdata) != 'X') + return (0); + return (1); +} + +/* END OF FILE */ diff --git a/src/gfx/vid_1200.c b/src/gfx/vid_1200.c new file mode 100644 index 0000000..5eb5793 --- /dev/null +++ b/src/gfx/vid_1200.c @@ -0,0 +1,2849 @@ +/* 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 to control the SC1200 video overlay hardware. + * */ + +/*---------------------------------------------------------------------------- + * SC1200 GAMMA RAM TABLE + *---------------------------------------------------------------------------- + */ + +unsigned long gfx_gamma_ram_1200[] = { + 0x00000000, 0x00040003, 0x00050104, 0x00060205, 0x00070306, 0x00080407, + 0x00090508, 0x000A0609, 0x000B070A, 0x000C080B, 0x000D090C, 0x000E0A0D, + 0x000F0B0E, 0x00100C0F, 0x00110D10, 0x00110E11, 0x00120F12, 0x00141013, + 0x00151114, 0x00161215, 0x00171316, 0x00181417, 0x00191518, 0x001A1619, + 0x001B171A, 0x001C181B, 0x001D191C, 0x001D1A1D, 0x001E1B1E, 0x00201C1F, + 0x00201D20, 0x00221E21, 0x00231F22, 0x00242023, 0x00252124, 0x00262225, + 0x00262326, 0x00282427, 0x00292528, 0x00292629, 0x002B272A, 0x002C282B, + 0x002D292C, 0x002E2A2D, 0x002F2B2E, 0x00302C2F, 0x00312D30, 0x00322E31, + 0x00332F32, 0x00343033, 0x00353134, 0x00363235, 0x00373336, 0x00383437, + 0x00393538, 0x003A3639, 0x003B373A, 0x003C383B, 0x003D393C, 0x003E3A3D, + 0x003F3B3E, 0x00403C3F, 0x00413D40, 0x00423E41, 0x00433F42, 0x00444043, + 0x00444144, 0x00454245, 0x00474346, 0x00484447, 0x00494548, 0x004A4649, + 0x004B474A, 0x004C484B, 0x004D494C, 0x004E4A4D, 0x004F4B4E, 0x00504C4F, + 0x00514D50, 0x00524E51, 0x00534F52, 0x00545053, 0x00555154, 0x00565255, + 0x00575356, 0x00585457, 0x00595558, 0x005A5659, 0x005B575A, 0x005C585B, + 0x005D595C, 0x005E5A5D, 0x005F5B5E, 0x00605C5F, 0x00615D60, 0x00625E61, + 0x00635F62, 0x00646063, 0x00656164, 0x00666265, 0x00676366, 0x00686467, + 0x00696568, 0x006A6669, 0x006B676A, 0x006C686B, 0x006D696C, 0x006E6A6D, + 0x006F6B6E, 0x00706C6F, 0x00716D70, 0x00726E71, 0x00736F72, 0x00747073, + 0x00757174, 0x00767275, 0x00777376, 0x00787477, 0x00797578, 0x007A7679, + 0x007B777A, 0x007C787B, 0x007D797C, 0x007E7A7D, 0x007F7B7E, 0x00807C7F, + 0x00817D80, 0x00827E81, 0x00837F82, 0x00848083, 0x00858184, 0x00868285, + 0x00878386, 0x00888487, 0x00898588, 0x008A8689, 0x008B878A, 0x008C888B, + 0x008D898C, 0x008E8A8D, 0x008F8B8E, 0x00908C8F, 0x00918D90, 0x00928E91, + 0x00938F92, 0x00949093, 0x00959194, 0x00969295, 0x00979396, 0x00989497, + 0x00999598, 0x009A9699, 0x009B979A, 0x009C989B, 0x009D999C, 0x009E9A9D, + 0x009F9B9E, 0x00A09C9F, 0x00A19DA0, 0x00A29EA1, 0x00A39FA2, 0x00A4A0A3, + 0x00A5A1A4, 0x00A6A2A5, 0x00A7A3A6, 0x00A8A4A7, 0x00A9A5A8, 0x00AAA6A9, + 0x00ABA7AA, 0x00ACA8AB, 0x00ADA9AC, 0x00AEAAAD, 0x00AFABAE, 0x00B0ACAF, + 0x00B1ADB0, 0x00B2AEB1, 0x00B3AFB2, 0x00B4B0B3, 0x00B5B1B4, 0x00B6B2B5, + 0x00B7B3B6, 0x00B8B4B7, 0x00B9B5B8, 0x00BAB6B9, 0x00BBB7BA, 0x00BCB8BB, + 0x00BDB9BC, 0x00BEBABD, 0x00BFBBBE, 0x00C0BCBF, 0x00C1BDC0, 0x00C2BEC1, + 0x00C3BFC2, 0x00C4C0C3, 0x00C5C1C4, 0x00C6C2C5, 0x00C7C3C6, 0x00C8C4C7, + 0x00C9C5C8, 0x00CAC6C9, 0x00CBC7CA, 0x00CCC8CB, 0x00CDC9CC, 0x00CECACD, + 0x00CFCBCE, 0x00D0CCCF, 0x00D1CDD0, 0x00D2CED1, 0x00D3CFD2, 0x00D4D0D3, + 0x00D5D1D4, 0x00D6D2D5, 0x00D7D3D6, 0x00D8D4D7, 0x00D9D5D8, 0x00DAD6D9, + 0x00DBD7DA, 0x00DCD8DB, 0x00DDD9DC, 0x00DEDADD, 0x00DFDBDE, 0x00E0DCDF, + 0x00E1DDE0, 0x00E2DEE1, 0x00E3DFE2, 0x00E4E0E3, 0x00E5E1E4, 0x00E6E2E5, + 0x00E7E3E6, 0x00E8E4E7, 0x00E9E5E8, 0x00EAE6E9, 0x00EBE7EA, 0x00ECE8EB, + 0x00EDE9EC, 0x00EEEAED, 0x00EFEBEE, 0x00F0ECEF, 0x00F1EDF0, 0x00F2EEF1, + 0x00F3EFF2, 0x00F4F0F3, 0x00F5F1F4, 0x00F6F2F5, 0x00F7F3F6, 0x00F8F4F7, + 0x00F9F5F8, 0x00FAF6F9, 0x00FBF7FA, 0x00FCF8FB, 0x00FDF9FC, 0x00FEFAFD, + 0x00FFFBFE, 0x00FFFCFE, 0x00FFFDFE, 0x00FFFFFF +}; + +/*---------------------------------------------------------------------------- + * SC1200 PLL TABLE + *---------------------------------------------------------------------------- + */ + +typedef struct tagSC1200PLL +{ + long frequency; /* 16.16 fixed point frequency */ + unsigned long clock_select; /* clock select register (0x2C) */ +} SC1200PLL; + +SC1200PLL gfx_sc1200_clock_table[] = { + {(25L << 16) | ((1750L * 65536L) / 10000L), 0x0070E00C}, /* 25.1750 + * (sc=24.9231) */ + {(27L << 16) | ((0000L * 65536L) / 10000L), 0x00300100}, /* 27.0000 */ + {(28L << 16) | ((3220L * 65536L) / 10000L), 0x0070EC0C}, /* 28.3220 + * (SC=27.000) */ + {(31L << 16) | ((5000L * 65536L) / 10000L), 0x00500D02}, /* 31.5000 */ + {(36L << 16) | ((0000L * 65536L) / 10000L), 0x00500F02}, /* 36.0000 */ + {(37L << 16) | ((5000L * 65536L) / 10000L), 0x0050B108}, /* 37.5000 */ + {(40L << 16) | ((0000L * 65536L) / 10000L), 0x0050D20D}, /* 40.0000 */ + {(44L << 16) | ((9000L * 65536L) / 10000L), 0x0050DC0D}, /* 44.9000 */ + {(49L << 16) | ((5000L * 65536L) / 10000L), 0x00501502}, /* 49.5000 */ + {(50L << 16) | ((0000L * 65536L) / 10000L), 0x0050A404}, /* 50.0000 */ + {(50L << 16) | ((3500L * 65536L) / 10000L), 0x0050E00C}, /* 50.3500 */ + {(54L << 16) | ((0000L * 65536L) / 10000L), 0x00300300}, /* 54.0000 */ + {(56L << 16) | ((3916L * 65536L) / 10000L), 0x0050F40D}, /* 56.3916 */ + {(56L << 16) | ((6440L * 65536L) / 10000L), 0x0050EC0C}, /* 56.6440 */ + {(59L << 16) | ((0000L * 65536L) / 10000L), 0x0030A207}, /* 59.0000 */ + {(63L << 16) | ((0000L * 65536L) / 10000L), 0x00300D02}, /* 63.0000 */ + {(65L << 16) | ((0000L * 65536L) / 10000L), 0x0030CC0F}, /* 65.0000 */ + {(67L << 16) | ((5000L * 65536L) / 10000L), 0x00300400}, /* 67.5000 */ + {(70L << 16) | ((8000L * 65536L) / 10000L), 0x00301403}, /* 70.8000 */ + {(72L << 16) | ((0000L * 65536L) / 10000L), 0x00300F02}, /* 72.0000 */ + {(75L << 16) | ((0000L * 65536L) / 10000L), 0x0030B108}, /* 75.0000 */ + {(78L << 16) | ((7500L * 65536L) / 10000L), 0x0030A205}, /* 78.7500 */ + {(80L << 16) | ((0000L * 65536L) / 10000L), 0x0030D20D}, /* 80.0000 */ + {(87L << 16) | ((2728L * 65536L) / 10000L), 0x0030E00E}, /* 87.2728 */ + {(89L << 16) | ((8000L * 65536L) / 10000L), 0x0030DC0D}, /* 89.8000 */ + {(94L << 16) | ((5000L * 65536L) / 10000L), 0x00300600}, /* 99.0000 */ + {(99L << 16) | ((0000L * 65536L) / 10000L), 0x00301502}, /* 99.0000 */ + {(100L << 16) | ((0000L * 65536L) / 10000L), 0x0030A404}, /* 100.00 */ + {(108L << 16) | ((0000L * 65536L) / 10000L), 0x00100300}, /* 108.00 */ + {(112L << 16) | ((5000L * 65536L) / 10000L), 0x00301802}, /* 108.00 */ + {(130L << 16) | ((0000L * 65536L) / 10000L), 0x0010CC0F}, /* 130.00 */ + {(135L << 16) | ((0000L * 65536L) / 10000L), 0x00100400}, /* 135.00 */ + {(157L << 16) | ((5000L * 65536L) / 10000L), 0x0010A205}, /* 157.50 */ + {(162L << 16) | ((0000L * 65536L) / 10000L), 0x00100500}, /* 162.00 */ + {(175L << 16) | ((0000L * 65536L) / 10000L), 0x0010E00E}, /* 175.50 */ + {(189L << 16) | ((0000L * 65536L) / 10000L), 0x00100600}, /* 189.00 */ + {(202L << 16) | ((0000L * 65536L) / 10000L), 0x0010EF0E}, /* 202.50 */ + {(232L << 16) | ((0000L * 65536L) / 10000L), 0x0010AA04}, /* 232.50 */ + + /* Precomputed inidces in the hardware */ + {0x0018EC4D, 0x000F0000}, /* 24.923052 */ + {0x00192CCC, 0x00000000}, /* 25.1750 */ + {0x001B0000, 0x00300100}, /* 27.0000 */ + {0x001F8000, 0x00010000}, /* 31.5000 */ + {0x00240000, 0x00020000}, /* 36.0000 */ + {0x00280000, 0x00030000}, /* 40.0000 */ + {0x00318000, 0x00050000}, /* 49.5000 */ + {0x00320000, 0x00040000}, /* 50.0000 */ + {0x00384000, 0x00060000}, /* 56.2500 */ + {0x00410000, 0x00080000}, /* 65.0000 */ + {0x004E8000, 0x000A0000}, /* 78.5000 */ + {0x005E8000, 0x000B0000}, /* 94.5000 */ + {0x006C0000, 0x000C0000}, /* 108.0000 */ + {0x00870000, 0x000D0000}, /* 135.0000 */ +}; + +#define NUM_SC1200_FREQUENCIES \ + sizeof(gfx_sc1200_clock_table)/sizeof(SC1200PLL) + +/*--------------------------------------------------------------------------- + * gfx_reset_video (PRIVATE ROUTINE: NOT PART OF DURANGO API) + * + * This routine is used to disable all components of video overlay before + * performing a mode switch. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +void +sc1200_reset_video(void) +#else +void +gfx_reset_video(void) +#endif +{ + int i; + + gfx_set_video_enable(0); + + /* SET WINDOW 0 AFTER RESET */ + + for (i = 2; i >= 0; i--) { + gfx_select_alpha_region(i); + gfx_set_alpha_enable(0); + gfx_set_alpha_color_enable(0); + } + + /* CLEAR THE DISPLAY BUFFER SIZE TO ZERO */ + /* During a modeset,if FIFO load is enabled with a large buffer size, */ + /* the FIFO can hang. To prevent this, we set the buffer size to zero */ + /* and wait for this new size to be latched */ + + gfx_set_display_video_size(0, 0); + + if (gfx_test_timing_active()) { + while (!gfx_test_vertical_active()) ; + while (gfx_test_vertical_active()) ; + while (!gfx_test_vertical_active()) ; + while (gfx_test_vertical_active()) ; + } +} + +/*----------------------------------------------------------------------------- + * gfx_set_display_control (PRIVATE ROUTINE: NOT PART OF DURANGO API) + * + * This routine configures the display output. + * + * "sync_polarities" is used to set the polarities of the sync pulses + * according to the following mask: + * + * Bit 0: If set to 1, negative horizontal polarity is programmed, + * otherwise positive horizontal polarity is programmed. + * Bit 1: If set to 1, negative vertical polarity is programmed, + * otherwise positive vertical polarity is programmed. + * + *----------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +sc1200_set_display_control(int sync_polarities) +#else +int +gfx_set_display_control(int sync_polarities) +#endif +{ + unsigned long dcfg; + + /* CONFIGURE DISPLAY OUTPUT FROM VIDEO PROCESSOR */ + + dcfg = READ_VID32(SC1200_DISPLAY_CONFIG); + dcfg &= ~(SC1200_DCFG_CRT_SYNC_SKW_MASK | SC1200_DCFG_PWR_SEQ_DLY_MASK | + SC1200_DCFG_CRT_HSYNC_POL | SC1200_DCFG_CRT_VSYNC_POL | + SC1200_DCFG_FP_PWR_EN | SC1200_DCFG_FP_DATA_EN); + + dcfg |= (SC1200_DCFG_CRT_SYNC_SKW_INIT | + SC1200_DCFG_PWR_SEQ_DLY_INIT | SC1200_DCFG_GV_PAL_BYP); + + if (PanelEnable) + dcfg |= SC1200_DCFG_FP_PWR_EN; + + /* SET APPROPRIATE SYNC POLARITIES */ + + if (sync_polarities & 0x1) + dcfg |= SC1200_DCFG_CRT_HSYNC_POL; + if (sync_polarities & 0x2) + dcfg |= SC1200_DCFG_CRT_VSYNC_POL; + + WRITE_VID32(SC1200_DISPLAY_CONFIG, dcfg); + + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_set_clock_frequency + * + * This routine sets the clock frequency, specified as a 16.16 fixed point + * value (0x00318000 = 49.5 MHz). It will set the closest frequency found + * in the lookup table. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +void +sc1200_set_clock_frequency(unsigned long frequency) +#else +void +gfx_set_clock_frequency(unsigned long frequency) +#endif +{ + unsigned int index; + unsigned long value, pll; + long min, diff; + + /* FIND THE REGISTER VALUES FOR THE DESIRED FREQUENCY */ + /* Search the table for the closest frequency (16.16 format). */ + + value = gfx_sc1200_clock_table[0].clock_select; + min = (long)gfx_sc1200_clock_table[0].frequency - frequency; + if (min < 0L) + min = -min; + for (index = 1; index < NUM_SC1200_FREQUENCIES; index++) { + diff = (long)gfx_sc1200_clock_table[index].frequency - frequency; + if (diff < 0L) + diff = -diff; + if (diff < min) { + min = diff; + value = gfx_sc1200_clock_table[index].clock_select; + } + } + + /* SET THE DOT CLOCK REGISTER */ + + pll = READ_VID32(SC1200_VID_MISC); + WRITE_VID32(SC1200_VID_MISC, pll | SC1200_PLL_POWER_NORMAL); + WRITE_VID32(SC1200_VID_CLOCK_SELECT, value); + return; +} + +/*--------------------------------------------------------------------------- + * gfx_set_screen_enable (PRIVATE ROUTINE - NOT PART OF API) + * + * This routine enables or disables the graphics display logic of the video + * processor. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +sc1200_set_screen_enable(int enable) +#else +int +gfx_set_screen_enable(int enable) +#endif +{ + unsigned long config; + + config = READ_VID32(SC1200_DISPLAY_CONFIG); + if (enable) + WRITE_VID32(SC1200_DISPLAY_CONFIG, config | SC1200_DCFG_DIS_EN); + else + WRITE_VID32(SC1200_DISPLAY_CONFIG, config & ~SC1200_DCFG_DIS_EN); + return (GFX_STATUS_OK); +} + +/*--------------------------------------------------------------------------- + * gfx_set_crt_enable + * + * This routine enables or disables the CRT output from the video processor. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +sc1200_set_crt_enable(int enable) +#else +int +gfx_set_crt_enable(int enable) +#endif +{ + unsigned long config, misc; + + config = READ_VID32(SC1200_DISPLAY_CONFIG); + misc = READ_VID32(SC1200_VID_MISC); + + /* + * IMPORTANT: For all modes do NOT disable the graphics display logic + * because it might be needed for TV + */ + + switch (enable) { + case CRT_DISABLE: /* HSync:Off VSync:Off */ + WRITE_VID32(SC1200_DISPLAY_CONFIG, config & ~(SC1200_DCFG_HSYNC_EN + | SC1200_DCFG_VSYNC_EN | SC1200_DCFG_DAC_BL_EN)); + WRITE_VID32(SC1200_VID_MISC, misc | SC1200_DAC_POWER_DOWN); + break; + case CRT_ENABLE: /* Enable CRT display, including + * display logic */ + WRITE_VID32(SC1200_DISPLAY_CONFIG, config | SC1200_DCFG_HSYNC_EN + | SC1200_DCFG_VSYNC_EN | SC1200_DCFG_DAC_BL_EN); + WRITE_VID32(SC1200_VID_MISC, misc & ~SC1200_DAC_POWER_DOWN); + + /* ENABLE GRAPHICS DISPLAY LOGIC */ + gfx_set_screen_enable(1); + break; + case CRT_STANDBY: /* HSync:Off VSync:On */ + WRITE_VID32(SC1200_DISPLAY_CONFIG, (config & ~(SC1200_DCFG_HSYNC_EN + | SC1200_DCFG_DAC_BL_EN)) + | SC1200_DCFG_VSYNC_EN); + WRITE_VID32(SC1200_VID_MISC, misc | SC1200_DAC_POWER_DOWN); + break; + case CRT_SUSPEND: /* HSync:On VSync:Off */ + WRITE_VID32(SC1200_DISPLAY_CONFIG, (config & ~(SC1200_DCFG_VSYNC_EN + | SC1200_DCFG_DAC_BL_EN)) + | SC1200_DCFG_HSYNC_EN); + WRITE_VID32(SC1200_VID_MISC, misc | SC1200_DAC_POWER_DOWN); + break; + default: + return GFX_STATUS_BAD_PARAMETER; + } + return (GFX_STATUS_OK); +} + +/*---------------------------------------------------------------------------- + * gfx_set_video_enable + * + * This routine enables or disables the video overlay functionality. + *---------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +sc1200_set_video_enable(int enable) +#else +int +gfx_set_video_enable(int enable) +#endif +{ + unsigned long vcfg; + + /* WAIT FOR VERTICAL BLANK TO START */ + /* Otherwise a glitch can be observed. */ + + if (gfx_test_timing_active()) { + if (!gfx_test_vertical_active()) { + while (!gfx_test_vertical_active()) ; + } + while (gfx_test_vertical_active()) ; + } + + vcfg = READ_VID32(SC1200_VIDEO_CONFIG); + if (enable) { + /* ENABLE SC1200 VIDEO OVERLAY */ + + vcfg |= SC1200_VCFG_VID_EN; + WRITE_VID32(SC1200_VIDEO_CONFIG, vcfg); + } else { + /* DISABLE SC1200 VIDEO OVERLAY */ + + vcfg &= ~SC1200_VCFG_VID_EN; + WRITE_VID32(SC1200_VIDEO_CONFIG, vcfg); + } + return (0); +} + +/*---------------------------------------------------------------------------- + * gfx_set_video_format + * + * Sets input video format type, to one of the YUV formats or to RGB. + *---------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +sc1200_set_video_format(unsigned long format) +#else +int +gfx_set_video_format(unsigned long format) +#endif +{ + unsigned long ctrl, vcfg = 0; + + /* SET THE SC1200 VIDEO INPUT FORMAT */ + + vcfg = READ_VID32(SC1200_VIDEO_CONFIG); + ctrl = READ_VID32(SC1200_VID_ALPHA_CONTROL); + ctrl &= ~(SC1200_VIDEO_INPUT_IS_RGB); + vcfg &= ~(SC1200_VCFG_VID_INP_FORMAT | SC1200_VCFG_4_2_0_MODE); + switch (format) { + case VIDEO_FORMAT_UYVY: + vcfg |= SC1200_VCFG_UYVY_FORMAT; + break; + case VIDEO_FORMAT_YUYV: + vcfg |= SC1200_VCFG_YUYV_FORMAT; + break; + case VIDEO_FORMAT_Y2YU: + vcfg |= SC1200_VCFG_Y2YU_FORMAT; + break; + case VIDEO_FORMAT_YVYU: + vcfg |= SC1200_VCFG_YVYU_FORMAT; + break; + case VIDEO_FORMAT_Y0Y1Y2Y3: + vcfg |= SC1200_VCFG_UYVY_FORMAT; + vcfg |= SC1200_VCFG_4_2_0_MODE; + break; + case VIDEO_FORMAT_Y3Y2Y1Y0: + vcfg |= SC1200_VCFG_Y2YU_FORMAT; + vcfg |= SC1200_VCFG_4_2_0_MODE; + break; + case VIDEO_FORMAT_Y1Y0Y3Y2: + vcfg |= SC1200_VCFG_YUYV_FORMAT; + vcfg |= SC1200_VCFG_4_2_0_MODE; + break; + case VIDEO_FORMAT_Y1Y2Y3Y0: + vcfg |= SC1200_VCFG_YVYU_FORMAT; + vcfg |= SC1200_VCFG_4_2_0_MODE; + break; + case VIDEO_FORMAT_RGB: + ctrl |= SC1200_VIDEO_INPUT_IS_RGB; + vcfg |= SC1200_VCFG_UYVY_FORMAT; + break; + case VIDEO_FORMAT_P2M_P2L_P1M_P1L: + ctrl |= SC1200_VIDEO_INPUT_IS_RGB; + vcfg |= SC1200_VCFG_Y2YU_FORMAT; + break; + case VIDEO_FORMAT_P1M_P1L_P2M_P2L: + ctrl |= SC1200_VIDEO_INPUT_IS_RGB; + vcfg |= SC1200_VCFG_YUYV_FORMAT; + break; + case VIDEO_FORMAT_P1M_P2L_P2M_P1L: + ctrl |= SC1200_VIDEO_INPUT_IS_RGB; + vcfg |= SC1200_VCFG_YVYU_FORMAT; + break; + default: + return GFX_STATUS_BAD_PARAMETER; + } + + /* ALWAYS DISABLE GRAPHICS CSC */ + /* This is enabled in the function gfx_set_color_space_YUV for */ + /* YUV blending on TV. */ + + ctrl &= ~SC1200_CSC_GFX_RGB_TO_YUV; + + if (ctrl & SC1200_VIDEO_INPUT_IS_RGB) + ctrl &= ~SC1200_CSC_VIDEO_YUV_TO_RGB; + else + ctrl |= SC1200_CSC_VIDEO_YUV_TO_RGB; + + WRITE_VID32(SC1200_VIDEO_CONFIG, vcfg); + WRITE_VID32(SC1200_VID_ALPHA_CONTROL, ctrl); + + return (0); +} + +/*---------------------------------------------------------------------------- + * gfx_set_video_size + * + * This routine specifies the size of the source data. It is used only + * to determine how much data to transfer per frame, and is not used to + * calculate the scaling value (that is handled by a separate routine). + *---------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +sc1200_set_video_size(unsigned short width, unsigned short height) +#else +int +gfx_set_video_size(unsigned short width, unsigned short height) +#endif +{ + unsigned long size, vcfg; + + /* SET THE SC1200 VIDEO LINE SIZE */ + + vcfg = READ_VID32(SC1200_VIDEO_CONFIG); + vcfg &= ~(SC1200_VCFG_LINE_SIZE_LOWER_MASK | SC1200_VCFG_LINE_SIZE_UPPER); + size = (width >> 1); + vcfg |= (size & 0x00FF) << 8; + if (size & 0x0100) + vcfg |= SC1200_VCFG_LINE_SIZE_UPPER; + WRITE_VID32(SC1200_VIDEO_CONFIG, vcfg); + + /* SET TOTAL VIDEO BUFFER SIZE IN DISPLAY CONTROLLER */ + /* Use private routine to abstract the display controller. */ + + /* Add 1 line to bypass issue #803 */ + gfx_set_display_video_size(width, (unsigned short)(height + 2)); + return (0); +} + +/*---------------------------------------------------------------------------- + * gfx_set_video_offset + * + * This routine sets the starting offset for the video buffer when only + * one offset needs to be specified. + *---------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +sc1200_set_video_offset(unsigned long offset) +#else +int +gfx_set_video_offset(unsigned long offset) +#endif +{ + /* SAVE VALUE FOR FUTURE CLIPPING OF THE TOP OF THE VIDEO WINDOW */ + + gfx_vid_offset = offset; + + /* SET VIDEO BUFFER OFFSET IN DISPLAY CONTROLLER */ + /* Use private routine to abstract the display controller. */ + + gfx_set_display_video_offset(offset); + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_set_video_upscale + * + * This routine sets the scale factor for the video overlay window. The + * size of the source and destination regions are specified in pixels. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +sc1200_set_video_upscale(unsigned short srcw, unsigned short srch, + unsigned short dstw, unsigned short dsth) +#else +int +gfx_set_video_upscale(unsigned short srcw, unsigned short srch, + unsigned short dstw, unsigned short dsth) +#endif +{ + unsigned long xscale, yscale; + + /* SAVE PARAMETERS (unless don't-care zero destination arguments are used) + * */ + /* These are needed for clipping the video window later. */ + + if (dstw != 0) { + gfx_vid_srcw = srcw; + gfx_vid_dstw = dstw; + } + if (dsth != 0) { + gfx_vid_srch = srch; + gfx_vid_dsth = dsth; + } + + /* CALCULATE SC1200 SCALE FACTORS */ + + if (dstw == 0) + xscale = READ_VID32(SC1200_VIDEO_UPSCALE) & 0xffff; + /* keep previous if don't-care argument */ + else if (dstw <= srcw) + xscale = 0x2000l; + /* horizontal downscaling is currently done in a separate function */ + else if ((srcw == 1) || (dstw == 1)) + return GFX_STATUS_BAD_PARAMETER; + else + xscale = (0x2000l * (srcw - 1l)) / (dstw - 1l); + + if (dsth == 0) + yscale = (READ_VID32(SC1200_VIDEO_UPSCALE) & 0xffff0000) >> 16; + /* keep previous if don't-care argument */ + else if (dsth <= srch) + yscale = 0x2000l; + /* No vertical downscaling in SC1200 so force to 1x if attempted */ + else if ((srch == 1) || (dsth == 1)) + return GFX_STATUS_BAD_PARAMETER; + else + yscale = (0x2000l * (srch - 1l)) / (dsth - 1l); + + WRITE_VID32(SC1200_VIDEO_UPSCALE, (yscale << 16) | xscale); + + /* CALL ROUTINE TO UPDATE WINDOW POSITION */ + /* This is required because the scale values effect the number of */ + /* source data pixels that need to be clipped, as well as the */ + /* amount of data that needs to be transferred. */ + + gfx_set_video_window(gfx_vid_xpos, gfx_vid_ypos, gfx_vid_width, + gfx_vid_height); + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_set_video_scale + * + * This routine sets the scale factor for the video overlay window. The + * size of the source and destination regions are specified in pixels. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +sc1200_set_video_scale(unsigned short srcw, unsigned short srch, + unsigned short dstw, unsigned short dsth) +#else +int +gfx_set_video_scale(unsigned short srcw, unsigned short srch, + unsigned short dstw, unsigned short dsth) +#endif +{ + return gfx_set_video_upscale(srcw, srch, dstw, dsth); +} + +/*--------------------------------------------------------------------------- + * gfx_set_video_downscale_config + * + * This routine sets the downscale type and factor for the video overlay + * window. + * Note: No downscaling support for RGB565 and YUV420 video formats. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +sc1200_set_video_downscale_config(unsigned short type, unsigned short m) +#else +int +gfx_set_video_downscale_config(unsigned short type, unsigned short m) +#endif +{ + unsigned long downscale; + + if ((m < 1) || (m > 16)) + return GFX_STATUS_BAD_PARAMETER; + + downscale = READ_VID32(SC1200_VIDEO_DOWNSCALER_CONTROL); + downscale &= + ~(SC1200_VIDEO_DOWNSCALE_FACTOR_MASK | + SC1200_VIDEO_DOWNSCALE_TYPE_MASK); + downscale |= ((m - 1l) << SC1200_VIDEO_DOWNSCALE_FACTOR_POS); + switch (type) { + case VIDEO_DOWNSCALE_KEEP_1_OF: + downscale |= SC1200_VIDEO_DOWNSCALE_TYPE_A; + break; + case VIDEO_DOWNSCALE_DROP_1_OF: + downscale |= SC1200_VIDEO_DOWNSCALE_TYPE_B; + break; + default: + return GFX_STATUS_BAD_PARAMETER; + } + WRITE_VID32(SC1200_VIDEO_DOWNSCALER_CONTROL, downscale); + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_set_video_downscale_coefficients + * + * This routine sets the downscale filter coefficients. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +sc1200_set_video_downscale_coefficients(unsigned short coef1, + unsigned short coef2, unsigned short coef3, unsigned short coef4) +#else +int +gfx_set_video_downscale_coefficients(unsigned short coef1, + unsigned short coef2, unsigned short coef3, unsigned short coef4) +#endif +{ + if ((coef1 + coef2 + coef3 + coef4) != 16) + return GFX_STATUS_BAD_PARAMETER; + + WRITE_VID32(SC1200_VIDEO_DOWNSCALER_COEFFICIENTS, + ((unsigned long)coef1 << SC1200_VIDEO_DOWNSCALER_COEF1_POS) | + ((unsigned long)coef2 << SC1200_VIDEO_DOWNSCALER_COEF2_POS) | + ((unsigned long)coef3 << SC1200_VIDEO_DOWNSCALER_COEF3_POS) | + ((unsigned long)coef4 << SC1200_VIDEO_DOWNSCALER_COEF4_POS)); + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_set_video_downscale_enable + * + * This routine enables or disables downscaling for the video overlay window. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +sc1200_set_video_downscale_enable(int enable) +#else +int +gfx_set_video_downscale_enable(int enable) +#endif +{ + unsigned long downscale; + + downscale = READ_VID32(SC1200_VIDEO_DOWNSCALER_CONTROL); + downscale &= ~SC1200_VIDEO_DOWNSCALE_ENABLE; + if (enable) + downscale |= SC1200_VIDEO_DOWNSCALE_ENABLE; + WRITE_VID32(SC1200_VIDEO_DOWNSCALER_CONTROL, downscale); + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_set_video_window + * + * This routine sets the position and size of the video overlay window. The + * y position is specified in screen relative coordinates, and may be negative. + * The size of destination region is specified in pixels. The line size + * indicates the number of bytes of source data per scanline. + * For the effect of negative x values, call the function + * gfx_set_video_left_crop(). + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +sc1200_set_video_window(short x, short y, unsigned short w, unsigned short h) +#else +int +gfx_set_video_window(short x, short y, unsigned short w, unsigned short h) +#endif +{ + unsigned long control; + unsigned long hadjust, vadjust; + unsigned long xstart, ystart, xend, yend; + + /* For left cropping call the function gfx_set_video_left_crop() */ + + if (x < 0) + return GFX_STATUS_BAD_PARAMETER; + + /* SAVE PARAMETERS */ + /* These are needed to call this routine if the scale value changes. */ + /* In the case of SC1200 they are also needed for restoring when video + * is re-enabled */ + + gfx_vid_xpos = x; + gfx_vid_ypos = y; + gfx_vid_width = w; + gfx_vid_height = h; + + /* GET ADJUSTMENT VALUES */ + /* Use routines to abstract version of display controller. */ + + hadjust = gfx_get_htotal() - gfx_get_hsync_end() - 14l; + vadjust = gfx_get_vtotal() - gfx_get_vsync_end() + 1l; + + /* HORIZONTAL START */ + + xstart = (unsigned long)x + hadjust; + + /* HORIZONTAL END */ + /* End positions in register are non-inclusive (one more than the actual + * end) */ + + if ((x + w) < gfx_get_hactive()) + xend = (unsigned long)x + (unsigned long)w + hadjust; + else /* right clipping needed */ + xend = (unsigned long)gfx_get_hactive() + hadjust; + + /* VERTICAL START */ + + ystart = (unsigned long)y + vadjust; + + /* VERTICAL END */ + + if ((y + h) < gfx_get_vactive()) + yend = (unsigned long)y + (unsigned long)h + vadjust; + else /* bottom clipping needed */ + yend = (unsigned long)gfx_get_vactive() + vadjust; + + /* SET VIDEO LINE INVERT BIT */ + + control = READ_VID32(SC1200_VID_ALPHA_CONTROL); + if (y & 0x1) + WRITE_VID32(SC1200_VID_ALPHA_CONTROL, + control | SC1200_VIDEO_LINE_OFFSET_ODD); + else + WRITE_VID32(SC1200_VID_ALPHA_CONTROL, + control & ~SC1200_VIDEO_LINE_OFFSET_ODD); + + /* SET VIDEO POSITION */ + + WRITE_VID32(SC1200_VIDEO_X_POS, (xend << 16) | xstart); + WRITE_VID32(SC1200_VIDEO_Y_POS, (yend << 16) | ystart); + + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_set_video_left_crop + * + * This routine sets the number of pixels which will be cropped from the + * beginning of each video line. The video window will begin to display only + * from the pixel following the cropped pixels, and the cropped pixels + * will be ignored. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +sc1200_set_video_left_crop(unsigned short x) +#else +int +gfx_set_video_left_crop(unsigned short x) +#endif +{ + unsigned long vcfg, initread; + + /* CLIPPING ON LEFT */ + /* Adjust initial read for scale, checking for divide by zero */ + + if (gfx_vid_dstw) + initread = (unsigned long)x *gfx_vid_srcw / gfx_vid_dstw; + + else + initread = 0l; + + /* SET INITIAL READ ADDRESS */ + + vcfg = READ_VID32(SC1200_VIDEO_CONFIG); + vcfg &= ~SC1200_VCFG_INIT_READ_MASK; + vcfg |= (initread << 15) & SC1200_VCFG_INIT_READ_MASK; + WRITE_VID32(SC1200_VIDEO_CONFIG, vcfg); + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_set_video_color_key + * + * This routine specifies the color key value and mask for the video overlay + * hardware. To disable color key, the color and mask should both be set to + * zero. The hardware uses the color key in the following equation: + * + * ((source data) & (color key mask)) == ((color key) & (color key mask)) + * + * If "graphics" is set to TRUE, the source data is graphics, and color key + * is an RGB value. If "graphics" is set to FALSE, the source data is the + * video, and color key is a YUV value. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +sc1200_set_video_color_key(unsigned long key, unsigned long mask, + int graphics) +#else +int +gfx_set_video_color_key(unsigned long key, unsigned long mask, int graphics) +#endif +{ + unsigned long dcfg = 0; + + /* SET SC1200 COLOR KEY VALUE */ + + WRITE_VID32(SC1200_VIDEO_COLOR_KEY, key); + WRITE_VID32(SC1200_VIDEO_COLOR_MASK, mask); + + /* SELECT GRAPHICS OR VIDEO DATA TO COMPARE TO THE COLOR KEY */ + + dcfg = READ_VID32(SC1200_DISPLAY_CONFIG); + if (graphics & 0x01) + dcfg &= ~SC1200_DCFG_VG_CK; + else + dcfg |= SC1200_DCFG_VG_CK; + WRITE_VID32(SC1200_DISPLAY_CONFIG, dcfg); + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_set_video_filter + * + * This routine enables or disables the video overlay filters. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +sc1200_set_video_filter(int xfilter, int yfilter) +#else +int +gfx_set_video_filter(int xfilter, int yfilter) +#endif +{ + unsigned long vcfg = 0; + + /* ENABLE OR DISABLE SC1200 VIDEO OVERLAY FILTERS */ + + vcfg = READ_VID32(SC1200_VIDEO_CONFIG); + vcfg &= ~(SC1200_VCFG_X_FILTER_EN | SC1200_VCFG_Y_FILTER_EN); + if (xfilter) + vcfg |= SC1200_VCFG_X_FILTER_EN; + if (yfilter) + vcfg |= SC1200_VCFG_Y_FILTER_EN; + WRITE_VID32(SC1200_VIDEO_CONFIG, vcfg); + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_set_video_palette + * + * This routine loads the video hardware palette. If a NULL pointer is + * specified, the palette is bypassed (for SC1200, this means loading the + * palette with identity values). + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +sc1200_set_video_palette(unsigned long *palette) +#else +int +gfx_set_video_palette(unsigned long *palette) +#endif +{ + unsigned long i, entry; + unsigned long dcfg, misc; + + /* WAIT FOR VERTICAL BLANK TO END */ + /* Otherwise palette will not be written properly. */ + + if (gfx_test_timing_active()) { + if (gfx_test_vertical_active()) { + while (gfx_test_vertical_active()) ; + } + while (!gfx_test_vertical_active()) ; + } + + /* LOAD SC1200 VIDEO PALETTE */ + + WRITE_VID32(SC1200_PALETTE_ADDRESS, 0); + for (i = 0; i < 256; i++) { + if (palette) + entry = palette[i]; + else + entry = gfx_gamma_ram_1200[i] << 8; + WRITE_VID32(SC1200_PALETTE_DATA, entry); + } + + /* ENABLE THE VIDEO PALETTE */ + /* Ensure that the video palette has an effect by routing video data */ + /* through the palette RAM and clearing the 'Bypass Both' bit. */ + + dcfg = READ_VID32(SC1200_DISPLAY_CONFIG); + misc = READ_VID32(SC1200_VID_MISC); + + dcfg |= SC1200_DCFG_GV_PAL_BYP; + misc &= ~SC1200_GAMMA_BYPASS_BOTH; + + WRITE_VID32(SC1200_DISPLAY_CONFIG, dcfg); + WRITE_VID32(SC1200_VID_MISC, misc); + + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_set_video_palette_entry + * + * This routine loads a single entry of the video hardware palette. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +sc1200_set_video_palette_entry(unsigned long index, unsigned long palette) +#else +int +gfx_set_video_palette_entry(unsigned long index, unsigned long palette) +#endif +{ + unsigned long dcfg, misc; + + if (index > 0xFF) + return GFX_STATUS_BAD_PARAMETER; + + /* WAIT FOR VERTICAL BLANK TO END */ + /* Otherwise palette will not be written properly. */ + + if (gfx_test_timing_active()) { + if (gfx_test_vertical_active()) { + while (gfx_test_vertical_active()) ; + } + while (!gfx_test_vertical_active()) ; + } + + /* SET A SINGLE ENTRY */ + + WRITE_VID32(SC1200_PALETTE_ADDRESS, index); + WRITE_VID32(SC1200_PALETTE_DATA, palette); + + /* ENABLE THE VIDEO PALETTE */ + /* Ensure that the video palette has an effect by routing video data */ + /* through the palette RAM and clearing the 'Bypass Both' bit. */ + + dcfg = READ_VID32(SC1200_DISPLAY_CONFIG); + misc = READ_VID32(SC1200_VID_MISC); + + dcfg |= SC1200_DCFG_GV_PAL_BYP; + misc &= ~SC1200_GAMMA_BYPASS_BOTH; + + WRITE_VID32(SC1200_DISPLAY_CONFIG, dcfg); + WRITE_VID32(SC1200_VID_MISC, misc); + + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_set_video_palette_bypass + * + * This routine enables/disables the pallete RAM bypass. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +sc1200_set_video_palette_bypass(int enable) +#else +int +gfx_set_video_palette_bypass(int enable) +#endif +{ + unsigned long misc; + + misc = READ_VID32(SC1200_VID_MISC); + + if (enable) + misc |= SC1200_GAMMA_BYPASS_BOTH; + else + misc &= ~SC1200_GAMMA_BYPASS_BOTH; + + WRITE_VID32(SC1200_VID_MISC, misc); + + return 0; +} + +/*--------------------------------------------------------------------------- + * gfx_set_video_request() + * + * This routine sets the horizontal (pixel) and vertical (line) video request + * values. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +sc1200_set_video_request(short x, short y) +#else +int +gfx_set_video_request(short x, short y) +#endif +{ + /* SET SC1200 VIDEO REQUEST */ + + x += gfx_get_htotal() - gfx_get_hsync_end() - 2; + y += gfx_get_vtotal() - gfx_get_vsync_end() + 1; + + if ((x < 0) || (x > SC1200_VIDEO_REQUEST_MASK) || + (y < 0) || (y > SC1200_VIDEO_REQUEST_MASK)) + return GFX_STATUS_BAD_PARAMETER; + + WRITE_VID32(SC1200_VIDEO_REQUEST, + ((unsigned long)x << SC1200_VIDEO_X_REQUEST_POS) | ((unsigned long)y + << SC1200_VIDEO_Y_REQUEST_POS)); + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_set_video_source() + * + * This routine sets the video source to either memory or Direct VIP. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +sc1200_set_video_source(VideoSourceType source) +#else +int +gfx_set_video_source(VideoSourceType source) +#endif +{ + unsigned long display_mode; + + display_mode = READ_VID32(SC1200_VIDEO_DISPLAY_MODE); + + /* SET SC1200 VIDEO SOURCE */ + switch (source) { + case VIDEO_SOURCE_MEMORY: + WRITE_VID32(SC1200_VIDEO_DISPLAY_MODE, + (display_mode & ~SC1200_VIDEO_SOURCE_MASK) | + SC1200_VIDEO_SOURCE_GX1); + break; + case VIDEO_SOURCE_DVIP: + WRITE_VID32(SC1200_VIDEO_DISPLAY_MODE, + (display_mode & ~SC1200_VIDEO_SOURCE_MASK) | + SC1200_VIDEO_SOURCE_DVIP); + break; + default: + return GFX_STATUS_BAD_PARAMETER; + } + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_set_vbi_source() + * + * This routine sets the vbi source to either memory or Direct VIP. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +sc1200_set_vbi_source(VbiSourceType source) +#else +int +gfx_set_vbi_source(VbiSourceType source) +#endif +{ + unsigned long display_mode; + + display_mode = READ_VID32(SC1200_VIDEO_DISPLAY_MODE); + + /* SET SC1200 VBI SOURCE */ + switch (source) { + case VBI_SOURCE_MEMORY: + WRITE_VID32(SC1200_VIDEO_DISPLAY_MODE, + (display_mode & ~SC1200_VBI_SOURCE_MASK) | SC1200_VBI_SOURCE_GX1); + break; + case VBI_SOURCE_DVIP: + WRITE_VID32(SC1200_VIDEO_DISPLAY_MODE, + (display_mode & ~SC1200_VBI_SOURCE_MASK) | + SC1200_VBI_SOURCE_DVIP); + break; + default: + return GFX_STATUS_BAD_PARAMETER; + } + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_set_vbi_lines() + * + * This routine sets the VBI lines to pass to the TV encoder. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +sc1200_set_vbi_lines(unsigned long even, unsigned long odd) +#else +int +gfx_set_vbi_lines(unsigned long even, unsigned long odd) +#endif +{ + /* SET SC1200 VBI LINES */ + WRITE_VID32(SC1200_VIDEO_EVEN_VBI_LINE_ENABLE, + even & SC1200_VIDEO_VBI_LINE_ENABLE_MASK); + WRITE_VID32(SC1200_VIDEO_ODD_VBI_LINE_ENABLE, + odd & SC1200_VIDEO_VBI_LINE_ENABLE_MASK); + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_set_vbi_total() + * + * This routine sets the total number of VBI bytes for each field. + * The total is needed when both VBI and active video are received from memory + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +sc1200_set_vbi_total(unsigned long even, unsigned long odd) +#else +int +gfx_set_vbi_total(unsigned long even, unsigned long odd) +#endif +{ + /* SET SC1200 VBI TOTAL */ + WRITE_VID32(SC1200_VIDEO_EVEN_VBI_TOTAL_COUNT, + even & SC1200_VIDEO_VBI_TOTAL_COUNT_MASK); + WRITE_VID32(SC1200_VIDEO_ODD_VBI_TOTAL_COUNT, + odd & SC1200_VIDEO_VBI_TOTAL_COUNT_MASK); + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_set_video_interlaced() + * + * This routine configures the video processor video overlay mode to be + * interlaced YUV. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +sc1200_set_video_interlaced(int enable) +#else +int +gfx_set_video_interlaced(int enable) +#endif +{ + unsigned long control; + + control = READ_VID32(SC1200_VID_ALPHA_CONTROL); + /* SET INTERLACED VIDEO */ + if (enable) + WRITE_VID32(SC1200_VID_ALPHA_CONTROL, + control | SC1200_VIDEO_IS_INTERLACED); + else + WRITE_VID32(SC1200_VID_ALPHA_CONTROL, + control & ~SC1200_VIDEO_IS_INTERLACED); + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_set_color_space_YUV() + * + * This routine configures the video processor to process graphics and video + * in either YUV or RGB color space. The mode should be set to tune image + * quality. + * Setting "enable" to TRUE improves image quality on TV, + * but in this mode colors on CRT will not be correct. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +sc1200_set_color_space_YUV(int enable) +#else +int +gfx_set_color_space_YUV(int enable) +#endif +{ + unsigned long control; + + control = READ_VID32(SC1200_VID_ALPHA_CONTROL); + + /* SET SC1200 VIDEO COLOR SPACE TO YUV OR RGB */ + + if (enable) { + /* ENABLE YUV BLENDING */ + /* YUV blending cannot be enabled in RGB video formats */ + + control |= SC1200_CSC_GFX_RGB_TO_YUV; /* Convert graphics to YUV */ + control &= ~SC1200_CSC_VIDEO_YUV_TO_RGB; /* Leave video in YUV */ + + if (control & SC1200_VIDEO_INPUT_IS_RGB) + return (GFX_STATUS_UNSUPPORTED); /* Can't convert video from + * RGB to YUV */ + } else { + /* RGB BLENDING */ + + control &= ~SC1200_CSC_GFX_RGB_TO_YUV; /* Leave graphics in RGB */ + if (control & SC1200_VIDEO_INPUT_IS_RGB) + control &= ~SC1200_CSC_VIDEO_YUV_TO_RGB; /* Leave video in RGB */ + else + control |= SC1200_CSC_VIDEO_YUV_TO_RGB; /* Convert video to RGB */ + } + WRITE_VID32(SC1200_VID_ALPHA_CONTROL, control); + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_set_vertical_scaler_offset() + * + * This routine sets the value by which the odd frame is shifted with respect + * to the even frame. This is useful for de-interlacing in Bob method, by + * setting the shift value to be one line. + * If offset is 0, no shifting occurs. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +sc1200_set_vertical_scaler_offset(char offset) +#else +int +gfx_set_vertical_scaler_offset(char offset) +#endif +{ + unsigned long control; + + control = READ_VID32(SC1200_VID_ALPHA_CONTROL); + if (offset == 1) { + control &= ~SC1200_VERTICAL_SCALER_SHIFT_MASK; + /* Clear shifting value */ + control |= SC1200_VERTICAL_SCALER_SHIFT_INIT; + /* Set shifting value */ + control |= SC1200_VERTICAL_SCALER_SHIFT_EN; + /* Enable odd frame shifting */ + } else if (offset == 0) { + control &= ~SC1200_VERTICAL_SCALER_SHIFT_EN; + /* No shifting occurs */ + control &= ~SC1200_VERTICAL_SCALER_SHIFT_MASK; + /* Clear shifting value */ + } else + return (GFX_STATUS_BAD_PARAMETER); + /* TODO: how to program other values ? */ + WRITE_VID32(SC1200_VID_ALPHA_CONTROL, control); + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_set_top_line_in_odd() + * + * This routine sets the field in which the top line of input video resides. + * If enable is "0", this is the even field (default). [not to be confused + * with the odd field being the top field on TV]. + * If enable is "1", this is the odd field. + * Use enable "1" for input devices whose field indication is reversed from + * normal, i.e. an indication of "odd" field is given for even field data, + * and vice versa. + * This setting affects the video processor only when it is in either + * interlaced or Bob (scaler offset active) modes. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +sc1200_set_top_line_in_odd(int enable) +#else +int +gfx_set_top_line_in_odd(int enable) +#endif +{ + unsigned long control; + + control = READ_VID32(SC1200_VID_ALPHA_CONTROL); + if (enable) + control |= SC1200_TOP_LINE_IN_ODD; /* Set shifting value */ + else + control &= ~SC1200_TOP_LINE_IN_ODD; /* No shifting occurs */ + WRITE_VID32(SC1200_VID_ALPHA_CONTROL, control); + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_set_genlock_delay() + * + * This routine sets the delay between VIP VSYNC and display controller VSYNC. + * The delay is in 27 MHz clocks. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +sc1200_set_genlock_delay(unsigned long delay) +#else +int +gfx_set_genlock_delay(unsigned long delay) +#endif +{ + /* SET SC1200 GENLOCK DELAY */ + WRITE_VID32(SC1200_GENLOCK_DELAY, delay & SC1200_GENLOCK_DELAY_MASK); + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_set_genlock_enable() + * + * This routine sets and configures the genlock according to the flags + * parameter. + * Flags value of 0 disables genlock and resets its configuration. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +sc1200_set_genlock_enable(int flags) +#else +int +gfx_set_genlock_enable(int flags) +#endif +{ + unsigned long genlock = 0; + + if (flags) { + /* SET SC1200 GENLOCK CONFIGURATION */ + if (flags & GENLOCK_SINGLE) + genlock |= SC1200_GENLOCK_SINGLE_ENABLE; + if (flags & GENLOCK_FIELD_SYNC) + genlock |= SC1200_GENLOCK_FIELD_SYNC_ENABLE; + if (flags & GENLOCK_CONTINUOUS) + genlock |= SC1200_GENLOCK_CONTINUOUS_ENABLE; + if (flags & GENLOCK_SYNCED_EDGE_FALLING) + genlock |= SC1200_GENLOCK_GX_VSYNC_FALLING_EDGE; + if (flags & GENLOCK_SYNCING_EDGE_FALLING) + genlock |= SC1200_GENLOCK_VIP_VSYNC_FALLING_EDGE; + if (flags & GENLOCK_TIMEOUT) + genlock |= SC1200_GENLOCK_TIMEOUT_ENABLE; + if (flags & GENLOCK_TVENC_RESET_EVEN_FIELD) + genlock |= SC1200_GENLOCK_TVENC_RESET_EVEN_FIELD; + if (flags & GENLOCK_TVENC_RESET_BEFORE_DELAY) + genlock |= SC1200_GENLOCK_TVENC_RESET_BEFORE_DELAY; + if (flags & GENLOCK_TVENC_RESET) + genlock |= SC1200_GENLOCK_TVENC_RESET_ENABLE; + if (flags & GENLOCK_SYNC_TO_TVENC) + genlock |= SC1200_GENLOCK_SYNC_TO_TVENC; + } + WRITE_VID32(SC1200_GENLOCK, genlock); + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_set_video_cursor() + * + * This routine configures the video hardware cursor. + * If the "mask"ed bits in the graphics pixel match "key", then either + * "color1" or "color2" will be used for this pixel, according to the value of + * bit number "select_color2" of the graphics pixel. + * + * key - 24 bit RGB value + * mask - 24 bit mask + * color1, color2 - RGB or YUV, depending on the current color space + * conversion select_color2 - value between 0 to 23 + * + * To disable match, a "mask" and "key" value of 0xffffff should be set, + * because the graphics pixels incoming to the video processor have maximum 16 + * bits set (0xF8FCF8). + * + * This feature is useful for disabling alpha blending of the cursor. + * Otherwise cursor image would be blurred (or completely invisible if video + * alpha is maximum value). + * Note: the cursor pixel replacements take place both inside and outside the + * video overlay window. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +sc1200_set_video_cursor(unsigned long key, unsigned long mask, + unsigned short select_color2, unsigned long color1, unsigned long color2) +#else +int +gfx_set_video_cursor(unsigned long key, unsigned long mask, + unsigned short select_color2, unsigned long color1, unsigned long color2) +#endif +{ + if (select_color2 > SC1200_CURSOR_COLOR_BITS) + return GFX_STATUS_BAD_PARAMETER; + key = + (key & SC1200_COLOR_MASK) | ((unsigned long)select_color2 << + SC1200_CURSOR_COLOR_KEY_OFFSET_POS); + WRITE_VID32(SC1200_CURSOR_COLOR_KEY, key); + WRITE_VID32(SC1200_CURSOR_COLOR_MASK, mask); + WRITE_VID32(SC1200_CURSOR_COLOR_1, color1); + WRITE_VID32(SC1200_CURSOR_COLOR_2, color2); + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_set_alpha_enable + * + * This routine enables or disables the currently selected alpha region. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +sc1200_set_alpha_enable(int enable) +#else +int +gfx_set_alpha_enable(int enable) +#endif +{ + unsigned long address = 0, value = 0; + + if (gfx_alpha_select > 2) + return (GFX_STATUS_UNSUPPORTED); + address = SC1200_ALPHA_CONTROL_1 + ((unsigned long)gfx_alpha_select << 4); + value = READ_VID32(address); + if (enable) + value |= (SC1200_ACTRL_WIN_ENABLE | SC1200_ACTRL_LOAD_ALPHA); + else + value &= ~(SC1200_ACTRL_WIN_ENABLE); + WRITE_VID32(address, value); + return (GFX_STATUS_OK); +} + +/*--------------------------------------------------------------------------- + * gfx_set_alpha_window + * + * This routine sets the size of the currently selected alpha region. + * Note: "x" and "y" are signed to enable using negative values needed for + * implementing workarounds of hardware issues. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +sc1200_set_alpha_window(short x, short y, + unsigned short width, unsigned short height) +#else +int +gfx_set_alpha_window(short x, short y, + unsigned short width, unsigned short height) +#endif +{ + unsigned long address = 0; + + /* CHECK FOR CLIPPING */ + + if ((x + width) > gfx_get_hactive()) + width = gfx_get_hactive() - x; + if ((y + height) > gfx_get_vactive()) + height = gfx_get_vactive() - y; + + /* ADJUST POSITIONS */ + + x += gfx_get_htotal() - gfx_get_hsync_end() - 2; + y += gfx_get_vtotal() - gfx_get_vsync_end() + 1; + + if (gfx_alpha_select > 2) + return (GFX_STATUS_UNSUPPORTED); + address = SC1200_ALPHA_XPOS_1 + ((unsigned long)gfx_alpha_select << 4); + + /* End positions in register are non-inclusive (one more than the actual + * end) */ + + WRITE_VID32(address, (unsigned long)x | + ((unsigned long)(x + width) << 16)); + WRITE_VID32(address + 4l, (unsigned long)y | + ((unsigned long)(y + height) << 16)); + return (GFX_STATUS_OK); +} + +/*--------------------------------------------------------------------------- + * gfx_set_alpha_value + * + * This routine sets the alpha value for the currently selected alpha + * region. It also specifies an increment/decrement value for fading. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +sc1200_set_alpha_value(unsigned char alpha, char delta) +#else +int +gfx_set_alpha_value(unsigned char alpha, char delta) +#endif +{ + unsigned long address = 0, value = 0; + unsigned char new_value = 0; + int loop = 1; + + if (gfx_alpha_select > 2) + return (GFX_STATUS_UNSUPPORTED); + address = SC1200_ALPHA_CONTROL_1 + ((unsigned long)gfx_alpha_select << 4); + value = READ_VID32(address); + value &= SC1200_ACTRL_WIN_ENABLE; /* keep only enable bit */ + value |= (unsigned long)alpha; + value |= (((unsigned long)delta) & 0xff) << 8; + value |= SC1200_ACTRL_LOAD_ALPHA; + WRITE_VID32(address, value); + + /* WORKAROUND FOR ISSUE #1187 */ + /* Need to verify that the alpha operation succeeded */ + + while (1) { + /* WAIT FOR VERTICAL BLANK TO END */ + if (gfx_test_timing_active()) { + if (gfx_test_vertical_active()) + while (gfx_test_vertical_active()) ; + while (!gfx_test_vertical_active()) ; + } + new_value = + (unsigned char)((READ_VID32(SC1200_ALPHA_WATCH) >> + (gfx_alpha_select << 3)) & 0xff); + if (new_value == alpha) + return GFX_STATUS_OK; + if (++loop > 10) + return GFX_STATUS_ERROR; + WRITE_VID32(address, value); + } +} + +/*--------------------------------------------------------------------------- + * gfx_set_alpha_priority + * + * This routine sets the priority of the currently selected alpha region. + * A higher value indicates a higher priority. + * Note: Priority of enabled alpha windows must be different. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +sc1200_set_alpha_priority(int priority) +#else +int +gfx_set_alpha_priority(int priority) +#endif +{ + unsigned long pos = 0, value = 0; + + if (priority > 3) + return (GFX_STATUS_BAD_PARAMETER); + if (gfx_alpha_select > 2) + return (GFX_STATUS_UNSUPPORTED); + value = READ_VID32(SC1200_VID_ALPHA_CONTROL); + pos = 16 + (gfx_alpha_select << 1); + value &= ~(0x03l << pos); + value |= (unsigned long)priority << pos; + WRITE_VID32(SC1200_VID_ALPHA_CONTROL, value); + return (GFX_STATUS_OK); +} + +/*--------------------------------------------------------------------------- + * gfx_set_alpha_color + * + * This routine sets the color to be displayed inside the currently selected + * alpha window when there is a color key match (when the alpha color + * mechanism is enabled). + * "color" is a 24 bit RGB value (for RGB blending) or YUV value (for YUV + * blending). + * In Interlaced YUV blending mode, Y/2 value should be used. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +sc1200_set_alpha_color(unsigned long color) +#else +int +gfx_set_alpha_color(unsigned long color) +#endif +{ + unsigned long address = 0; + + if (gfx_alpha_select > 2) + return (GFX_STATUS_UNSUPPORTED); + address = SC1200_ALPHA_COLOR_1 + ((unsigned long)gfx_alpha_select << 4); + + /* ONLY 24 VALID BITS */ + color &= 0xffffffl; + + /* KEEP UPPER BYTE UNCHANGED */ + WRITE_VID32(address, (color | (READ_VID32(address) & ~0xffffffl))); + return (GFX_STATUS_OK); +} + +/*--------------------------------------------------------------------------- + * gfx_set_alpha_color_enable + * + * Enable or disable the color mechanism in the alpha window. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +sc1200_set_alpha_color_enable(int enable) +#else +int +gfx_set_alpha_color_enable(int enable) +#endif +{ + unsigned long color; + unsigned long address = 0; + + if (gfx_alpha_select > 2) + return (GFX_STATUS_UNSUPPORTED); + address = SC1200_ALPHA_COLOR_1 + ((unsigned long)gfx_alpha_select << 4); + color = READ_VID32(address); + if (enable) + color |= SC1200_ALPHA_COLOR_ENABLE; + else + color &= ~SC1200_ALPHA_COLOR_ENABLE; + WRITE_VID32(address, color); + return (GFX_STATUS_OK); +} + +/*--------------------------------------------------------------------------- + * gfx_set_no_ck_outside_alpha + * + * This function affects where inside the video window color key or chroma + * key comparison is done: + * If enable is TRUE, color/chroma key comparison is performed only inside + * the enabled alpha windows. Outside the (enabled) alpha windows, only video + * is displayed if color key is used, and only graphics is displayed if chroma + * key is used. + * If enable is FALSE, color/chroma key comparison is performed in all the + * video window area. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +sc1200_set_no_ck_outside_alpha(int enable) +#else +int +gfx_set_no_ck_outside_alpha(int enable) +#endif +{ + unsigned long value; + + value = READ_VID32(SC1200_VID_ALPHA_CONTROL); + if (enable) + WRITE_VID32(SC1200_VID_ALPHA_CONTROL, + value | SC1200_NO_CK_OUTSIDE_ALPHA); + else + WRITE_VID32(SC1200_VID_ALPHA_CONTROL, + value & ~SC1200_NO_CK_OUTSIDE_ALPHA); + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_set_macrovision_enable + * + * This routine enables or disables macrovision on the tv encoder output. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +sc1200_set_macrovision_enable(int enable) +#else +int +gfx_set_macrovision_enable(int enable) +#endif +{ + if (enable) + WRITE_VID32(SC1200_TVENC_MV_CONTROL, SC1200_TVENC_MV_ENABLE); + else + WRITE_VID32(SC1200_TVENC_MV_CONTROL, 0); + return (GFX_STATUS_OK); +} + +#define SC1200_VIDEO_PCI_44 0x80009444 + +/*--------------------------------------------------------------------------- + * gfx_disable_softvga + * + * Disables SoftVga. This function is only valid with VSA2, Returns 1 if + * SoftVga can be disabled; 0 if not. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +sc1200_disable_softvga(void) +#else +int +gfx_disable_softvga(void) +#endif +{ + unsigned long reg_val; + + /* get the current value */ + reg_val = gfx_pci_config_read(SC1200_VIDEO_PCI_44); + /* setting video PCI register 44 bit 0 to 1 disables SoftVga */ + reg_val |= 0x1; + gfx_pci_config_write(SC1200_VIDEO_PCI_44, reg_val); + + /* see if we set the bit and return the appropriate value */ + reg_val = gfx_pci_config_read(SC1200_VIDEO_PCI_44); + if ((reg_val & 0x1) == 0x1) + return (1); + else + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_enable_softvga + * + * Enables SoftVga. This function is only valid with VSA2, Returns 1 if + * SoftVga can be enbled; 0 if not. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +sc1200_enable_softvga(void) +#else +int +gfx_enable_softvga(void) +#endif +{ + unsigned long reg_val; + + /* get the current value */ + reg_val = gfx_pci_config_read(SC1200_VIDEO_PCI_44); + /* clearing video PCI register 44 bit 0 enables SoftVga */ + gfx_pci_config_write(SC1200_VIDEO_PCI_44, reg_val & 0xfffffffel); + + /* see if we cleared the bit and return the appropriate value */ + reg_val = gfx_pci_config_read(SC1200_VIDEO_PCI_44); + if ((reg_val & 0x1) == 0) + return (1); + else + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_get_clock_frequency + * + * This routine returns the current clock frequency in 16.16 format. + * It reads the current register value and finds the match in the table. + * If no match is found, this routine returns 0. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +unsigned long +sc1200_get_clock_frequency(void) +#else +unsigned long +gfx_get_clock_frequency(void) +#endif +{ + unsigned int index; + unsigned long value, mask; + + mask = 0x007FFF0F; + value = READ_VID32(SC1200_VID_CLOCK_SELECT) & mask; + for (index = 0; index < NUM_SC1200_FREQUENCIES; index++) { + if ((gfx_sc1200_clock_table[index].clock_select & mask) == value) + return (gfx_sc1200_clock_table[index].frequency); + } + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_get_max_video_width + * + * This routine returns the maximum theoretical video width for the current + * display mode. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +unsigned long +sc1200_get_max_video_width(void) +#else +unsigned long +gfx_get_max_video_width(void) +#endif +{ + /* RETURN MPEG2 MAXIMUM */ + + return 720; +} + +/*************************************************************/ +/* READ ROUTINES | INCLUDED FOR DIAGNOSTIC PURPOSES ONLY */ +/*************************************************************/ + +#if GFX_READ_ROUTINES + +/*--------------------------------------------------------------------------- + * gfx_get_vsa2_softvga_enable + * + * This function returns the enable status of SoftVGA. It is valid + * only if VSAII is present. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +sc1200_get_vsa2_softvga_enable(void) +#else +int +gfx_get_vsa2_softvga_enable(void) +#endif +{ + unsigned long reg_val; + + reg_val = gfx_pci_config_read(SC1200_VIDEO_PCI_44); + if ((reg_val & 0x1) == 0) + return (1); + else + return (0); + +} + +/*--------------------------------------------------------------------------- + * gfx_get_sync_polarities + * + * This routine returns the polarities of the sync pulses: + * Bit 0: Set if negative horizontal polarity. + * Bit 1: Set if negative vertical polarity. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +sc1200_get_sync_polarities(void) +#else +int +gfx_get_sync_polarities(void) +#endif +{ + int polarities = 0; + + if (READ_VID32(SC1200_DISPLAY_CONFIG) & SC1200_DCFG_CRT_HSYNC_POL) + polarities |= 1; + if (READ_VID32(SC1200_DISPLAY_CONFIG) & SC1200_DCFG_CRT_VSYNC_POL) + polarities |= 2; + return (polarities); +} + +/*--------------------------------------------------------------------------- + * gfx_get_video_palette_entry + * + * This routine returns a single palette entry. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +sc1200_get_video_palette_entry(unsigned long index, unsigned long *palette) +#else +int +gfx_get_video_palette_entry(unsigned long index, unsigned long *palette) +#endif +{ + if (index > 0xFF) + return GFX_STATUS_BAD_PARAMETER; + + /* READ A SINGLE ENTRY */ + + WRITE_VID32(SC1200_PALETTE_ADDRESS, index); + *palette = READ_VID32(SC1200_PALETTE_DATA); + + return (GFX_STATUS_OK); +} + +/*----------------------------------------------------------------------------- + * gfx_get_video_enable + * + * This routine returns the value "one" if video overlay is currently enabled, + * otherwise it returns the value "zero". + *----------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +sc1200_get_video_enable(void) +#else +int +gfx_get_video_enable(void) +#endif +{ + if (READ_VID32(SC1200_VIDEO_CONFIG) & SC1200_VCFG_VID_EN) + return (1); + return (0); +} + +/*----------------------------------------------------------------------------- + * gfx_get_video_format + * + * This routine returns the current video overlay format. + *----------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +sc1200_get_video_format(void) +#else +int +gfx_get_video_format(void) +#endif +{ + unsigned long ctrl, vcfg; + + ctrl = READ_VID32(SC1200_VID_ALPHA_CONTROL); + vcfg = READ_VID32(SC1200_VIDEO_CONFIG); + + if (ctrl & SC1200_VIDEO_INPUT_IS_RGB) { + switch (vcfg & SC1200_VCFG_VID_INP_FORMAT) { + case SC1200_VCFG_UYVY_FORMAT: + return VIDEO_FORMAT_RGB; + case SC1200_VCFG_Y2YU_FORMAT: + return VIDEO_FORMAT_P2M_P2L_P1M_P1L; + case SC1200_VCFG_YUYV_FORMAT: + return VIDEO_FORMAT_P1M_P1L_P2M_P2L; + case SC1200_VCFG_YVYU_FORMAT: + return VIDEO_FORMAT_P1M_P2L_P2M_P1L; + } + } + + if (vcfg & SC1200_VCFG_4_2_0_MODE) { + switch (vcfg & SC1200_VCFG_VID_INP_FORMAT) { + case SC1200_VCFG_UYVY_FORMAT: + return VIDEO_FORMAT_Y0Y1Y2Y3; + case SC1200_VCFG_Y2YU_FORMAT: + return VIDEO_FORMAT_Y3Y2Y1Y0; + case SC1200_VCFG_YUYV_FORMAT: + return VIDEO_FORMAT_Y1Y0Y3Y2; + case SC1200_VCFG_YVYU_FORMAT: + return VIDEO_FORMAT_Y1Y2Y3Y0; + } + } else { + switch (vcfg & SC1200_VCFG_VID_INP_FORMAT) { + case SC1200_VCFG_UYVY_FORMAT: + return VIDEO_FORMAT_UYVY; + case SC1200_VCFG_Y2YU_FORMAT: + return VIDEO_FORMAT_Y2YU; + case SC1200_VCFG_YUYV_FORMAT: + return VIDEO_FORMAT_YUYV; + case SC1200_VCFG_YVYU_FORMAT: + return VIDEO_FORMAT_YVYU; + } + } + return (GFX_STATUS_ERROR); +} + +/*---------------------------------------------------------------------------- + * gfx_get_video_src_size + * + * This routine returns the size of the source video overlay buffer. The + * return value is (height << 16) | width. + *---------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +unsigned long +sc1200_get_video_src_size(void) +#else +unsigned long +gfx_get_video_src_size(void) +#endif +{ + unsigned long width = 0, height = 0; + + /* DETERMINE SOURCE WIDTH FROM THE SC1200 VIDEO LINE SIZE */ + + width = (READ_VID32(SC1200_VIDEO_CONFIG) >> 7) & 0x000001FE; + if (READ_VID32(SC1200_VIDEO_CONFIG) & SC1200_VCFG_LINE_SIZE_UPPER) + width += 512l; + + if (width) { + /* DETERMINE HEIGHT BY DIVIDING TOTAL SIZE BY WIDTH */ + /* Get total size from display controller - abtracted. */ + + height = gfx_get_display_video_size() / (width << 1); + } + return ((height << 16) | width); +} + +/*---------------------------------------------------------------------------- + * gfx_get_video_line_size + * + * This routine returns the line size of the source video overlay buffer, in + * pixels. + *---------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +unsigned long +sc1200_get_video_line_size(void) +#else +unsigned long +gfx_get_video_line_size(void) +#endif +{ + unsigned long width = 0; + + /* DETERMINE SOURCE WIDTH FROM THE SC1200 VIDEO LINE SIZE */ + + width = (READ_VID32(SC1200_VIDEO_CONFIG) >> 7) & 0x000001FE; + if (READ_VID32(SC1200_VIDEO_CONFIG) & SC1200_VCFG_LINE_SIZE_UPPER) + width += 512l; + return (width); +} + +/*---------------------------------------------------------------------------- + * gfx_get_video_xclip + * + * This routine returns the number of bytes clipped on the left side of a + * video overlay line (skipped at beginning). + *---------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +unsigned long +sc1200_get_video_xclip(void) +#else +unsigned long +gfx_get_video_xclip(void) +#endif +{ + unsigned long clip = 0; + + /* DETERMINE SOURCE WIDTH FROM THE SC1200 VIDEO LINE SIZE */ + + clip = (READ_VID32(SC1200_VIDEO_CONFIG) >> 14) & 0x000007FC; + return (clip); +} + +/*---------------------------------------------------------------------------- + * gfx_get_video_offset + * + * This routine returns the current offset for the video overlay buffer. + *---------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +unsigned long +sc1200_get_video_offset(void) +#else +unsigned long +gfx_get_video_offset(void) +#endif +{ + return (gfx_get_display_video_offset()); +} + +/*--------------------------------------------------------------------------- + * gfx_get_video_upscale + * + * This routine returns the scale factor for the video overlay window. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +unsigned long +sc1200_get_video_upscale(void) +#else +unsigned long +gfx_get_video_upscale(void) +#endif +{ + return (READ_VID32(SC1200_VIDEO_UPSCALE)); +} + +/*--------------------------------------------------------------------------- + * gfx_get_video_scale + * + * This routine returns the scale factor for the video overlay window. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +unsigned long +sc1200_get_video_scale(void) +#else +unsigned long +gfx_get_video_scale(void) +#endif +{ + return gfx_get_video_upscale(); +} + +/*--------------------------------------------------------------------------- + * gfx_get_video_downscale_config + * + * This routine returns the current type and value of video downscaling. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +sc1200_get_video_downscale_config(unsigned short *type, unsigned short *m) +#else +int +gfx_get_video_downscale_config(unsigned short *type, unsigned short *m) +#endif +{ + unsigned long downscale; + + downscale = READ_VID32(SC1200_VIDEO_DOWNSCALER_CONTROL); + *m = (unsigned short)((downscale & SC1200_VIDEO_DOWNSCALE_FACTOR_MASK) >> + SC1200_VIDEO_DOWNSCALE_FACTOR_POS) + 1; + + switch (downscale & SC1200_VIDEO_DOWNSCALE_TYPE_MASK) { + case SC1200_VIDEO_DOWNSCALE_TYPE_A: + *type = VIDEO_DOWNSCALE_KEEP_1_OF; + break; + case SC1200_VIDEO_DOWNSCALE_TYPE_B: + *type = VIDEO_DOWNSCALE_DROP_1_OF; + break; + default: + return GFX_STATUS_ERROR; + break; + } + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_get_video_downscale_coefficients + * + * This routine returns the current video downscaling coefficients. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +void +sc1200_get_video_downscale_coefficients(unsigned short *coef1, + unsigned short *coef2, unsigned short *coef3, unsigned short *coef4) +#else +void +gfx_get_video_downscale_coefficients(unsigned short *coef1, + unsigned short *coef2, unsigned short *coef3, unsigned short *coef4) +#endif +{ + unsigned long coef; + + coef = READ_VID32(SC1200_VIDEO_DOWNSCALER_COEFFICIENTS); + *coef1 = + (unsigned short)((coef >> SC1200_VIDEO_DOWNSCALER_COEF1_POS) & + SC1200_VIDEO_DOWNSCALER_COEF_MASK); + *coef2 = + (unsigned short)((coef >> SC1200_VIDEO_DOWNSCALER_COEF2_POS) & + SC1200_VIDEO_DOWNSCALER_COEF_MASK); + *coef3 = + (unsigned short)((coef >> SC1200_VIDEO_DOWNSCALER_COEF3_POS) & + SC1200_VIDEO_DOWNSCALER_COEF_MASK); + *coef4 = + (unsigned short)((coef >> SC1200_VIDEO_DOWNSCALER_COEF4_POS) & + SC1200_VIDEO_DOWNSCALER_COEF_MASK); + return; +} + +/*--------------------------------------------------------------------------- + * gfx_get_video_downscale_enable + * + * This routine returns 1 if video downscaling is currently enabled, + * or 0 if it is currently disabled. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +void +sc1200_get_video_downscale_enable(int *enable) +#else +void +gfx_get_video_downscale_enable(int *enable) +#endif +{ + if (READ_VID32(SC1200_VIDEO_DOWNSCALER_CONTROL) & + SC1200_VIDEO_DOWNSCALE_ENABLE) + *enable = 1; + else + *enable = 0; + return; +} + +/*--------------------------------------------------------------------------- + * gfx_get_video_dst_size + * + * This routine returns the size of the displayed video overlay window. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +unsigned long +sc1200_get_video_dst_size(void) +#else +unsigned long +gfx_get_video_dst_size(void) +#endif +{ + unsigned long xsize, ysize; + + xsize = READ_VID32(SC1200_VIDEO_X_POS); + xsize = ((xsize >> 16) & 0x7FF) - (xsize & 0x7FF); + ysize = READ_VID32(SC1200_VIDEO_Y_POS); + ysize = ((ysize >> 16) & 0x7FF) - (ysize & 0x7FF); + return ((ysize << 16) | xsize); +} + +/*--------------------------------------------------------------------------- + * gfx_get_video_position + * + * This routine returns the position of the video overlay window. The + * return value is (ypos << 16) | xpos. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +unsigned long +sc1200_get_video_position(void) +#else +unsigned long +gfx_get_video_position(void) +#endif +{ + unsigned long hadjust, vadjust; + unsigned long xpos, ypos; + + /* READ HARDWARE POSITION */ + + xpos = READ_VID32(SC1200_VIDEO_X_POS) & 0x000007FF; + ypos = READ_VID32(SC1200_VIDEO_Y_POS) & 0x000007FF; + + /* GET ADJUSTMENT VALUES */ + /* Use routines to abstract version of display controller. */ + + hadjust = + (unsigned long)gfx_get_htotal() - (unsigned long)gfx_get_hsync_end() - + 14l; + vadjust = + (unsigned long)gfx_get_vtotal() - (unsigned long)gfx_get_vsync_end() + + 1l; + xpos -= hadjust; + ypos -= vadjust; + return ((ypos << 16) | (xpos & 0x0000FFFF)); +} + +/*--------------------------------------------------------------------------- + * gfx_get_video_color_key + * + * This routine returns the current video color key value. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +unsigned long +sc1200_get_video_color_key(void) +#else +unsigned long +gfx_get_video_color_key(void) +#endif +{ + return (READ_VID32(SC1200_VIDEO_COLOR_KEY)); +} + +/*--------------------------------------------------------------------------- + * gfx_get_video_color_key_mask + * + * This routine returns the current video color mask value. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +unsigned long +sc1200_get_video_color_key_mask(void) +#else +unsigned long +gfx_get_video_color_key_mask(void) +#endif +{ + return (READ_VID32(SC1200_VIDEO_COLOR_MASK)); +} + +/*--------------------------------------------------------------------------- + * gfx_get_video_color_key_src + * + * This routine returns 0 for video data compare, 1 for graphics data. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +sc1200_get_video_color_key_src(void) +#else +int +gfx_get_video_color_key_src(void) +#endif +{ + if (READ_VID32(SC1200_DISPLAY_CONFIG) & SC1200_DCFG_VG_CK) + return (0); + return (1); +} + +/*--------------------------------------------------------------------------- + * gfx_get_video_filter + * + * This routine returns if the filters are currently enabled. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +sc1200_get_video_filter(void) +#else +int +gfx_get_video_filter(void) +#endif +{ + int retval = 0; + + if (READ_VID32(SC1200_VIDEO_CONFIG) & SC1200_VCFG_X_FILTER_EN) + retval |= 1; + if (READ_VID32(SC1200_VIDEO_CONFIG) & SC1200_VCFG_Y_FILTER_EN) + retval |= 2; + return (retval); +} + +/*--------------------------------------------------------------------------- + * gfx_get_video_request + * + * This routine returns the horizontal (pixel) and vertical (lines) video + * request values. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +sc1200_get_video_request(short *x, short *y) +#else +int +gfx_get_video_request(short *x, short *y) +#endif +{ + int request = 0; + + request = (int)(READ_VID32(SC1200_VIDEO_REQUEST)); + *x = (request >> SC1200_VIDEO_X_REQUEST_POS) & SC1200_VIDEO_REQUEST_MASK; + *y = (request >> SC1200_VIDEO_Y_REQUEST_POS) & SC1200_VIDEO_REQUEST_MASK; + + *x -= gfx_get_htotal() - gfx_get_hsync_end() - 2; + *y -= gfx_get_vtotal() - gfx_get_vsync_end() + 1; + + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_get_video_source + * + * This routine returns the current video source. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +sc1200_get_video_source(VideoSourceType * source) +#else +int +gfx_get_video_source(VideoSourceType * source) +#endif +{ + switch (READ_VID32(SC1200_VIDEO_DISPLAY_MODE) & SC1200_VIDEO_SOURCE_MASK) { + case SC1200_VIDEO_SOURCE_GX1: + *source = VIDEO_SOURCE_MEMORY; + break; + case SC1200_VIDEO_SOURCE_DVIP: + *source = VIDEO_SOURCE_DVIP; + break; + default: + return GFX_STATUS_ERROR; + } + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_get_vbi_source + * + * This routine returns the current vbi source. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +sc1200_get_vbi_source(VbiSourceType * source) +#else +int +gfx_get_vbi_source(VbiSourceType * source) +#endif +{ + switch (READ_VID32(SC1200_VIDEO_DISPLAY_MODE) & SC1200_VBI_SOURCE_MASK) { + case SC1200_VBI_SOURCE_GX1: + *source = VBI_SOURCE_MEMORY; + break; + case SC1200_VBI_SOURCE_DVIP: + *source = VBI_SOURCE_DVIP; + break; + default: + return GFX_STATUS_ERROR; + } + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_get_vbi_lines + * + * This routine returns the VBI lines which are sent to the TV encoder. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +unsigned long +sc1200_get_vbi_lines(int odd) +#else +unsigned long +gfx_get_vbi_lines(int odd) +#endif +{ + if (odd) + return (READ_VID32(SC1200_VIDEO_ODD_VBI_LINE_ENABLE) & + SC1200_VIDEO_VBI_LINE_ENABLE_MASK); + return (READ_VID32(SC1200_VIDEO_EVEN_VBI_LINE_ENABLE) & + SC1200_VIDEO_VBI_LINE_ENABLE_MASK); +} + +/*--------------------------------------------------------------------------- + * gfx_get_vbi_total + * + * This routine returns the total number of VBI bytes in the field. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +unsigned long +sc1200_get_vbi_total(int odd) +#else +unsigned long +gfx_get_vbi_total(int odd) +#endif +{ + if (odd) + return (READ_VID32(SC1200_VIDEO_ODD_VBI_TOTAL_COUNT) & + SC1200_VIDEO_VBI_TOTAL_COUNT_MASK); + return (READ_VID32(SC1200_VIDEO_EVEN_VBI_TOTAL_COUNT) & + SC1200_VIDEO_VBI_TOTAL_COUNT_MASK); +} + +/*--------------------------------------------------------------------------- + * gfx_get_video_interlaced() + * + * This routine returns "1" if input video is currently in interlaced mode. + * "0" otherwise. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +sc1200_get_video_interlaced(void) +#else +int +gfx_get_video_interlaced(void) +#endif +{ + if (READ_VID32(SC1200_VID_ALPHA_CONTROL) & SC1200_VIDEO_IS_INTERLACED) + return (1); + else + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_get_color_space_YUV() + * + * This routine returns "1" if video processor color space mode is currently + * YUV. "0" otherwise. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +sc1200_get_color_space_YUV(void) +#else +int +gfx_get_color_space_YUV(void) +#endif +{ + unsigned long control; + + control = READ_VID32(SC1200_VID_ALPHA_CONTROL); + + /* IS SC1200 VIDEO COLOR SPACE RGB OR CONVERTED TO RGB */ + if ((control & SC1200_VIDEO_INPUT_IS_RGB) + || (control & SC1200_CSC_VIDEO_YUV_TO_RGB)) + return (0); + else + return (1); +} + +/*--------------------------------------------------------------------------- + * gfx_get_vertical_scaler_offset() + * + * This routine sets "offset" to the value by which odd frames are shifted, + * if insert is enabled, and to 0 if no shifting occurs. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +sc1200_get_vertical_scaler_offset(char *offset) +#else +int +gfx_get_vertical_scaler_offset(char *offset) +#endif +{ + unsigned long control; + + control = READ_VID32(SC1200_VID_ALPHA_CONTROL); + if (control & SC1200_VERTICAL_SCALER_SHIFT_EN) { + if ((control & SC1200_VERTICAL_SCALER_SHIFT_MASK) == + SC1200_VERTICAL_SCALER_SHIFT_INIT) + *offset = 1; + else + return GFX_STATUS_ERROR; + /* TODO: find the interpretation of other values */ + } else + *offset = 0; + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_get_genlock_delay + * + * This routine returns the genlock delay in 27 MHz clocks. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +unsigned long +sc1200_get_genlock_delay(void) +#else +unsigned long +gfx_get_genlock_delay(void) +#endif +{ + return (READ_VID32(SC1200_GENLOCK_DELAY) & SC1200_GENLOCK_DELAY_MASK); +} + +/*--------------------------------------------------------------------------- + * gfx_get_genlock_enable + * + * This routine returns "1" if genlock is currently enabled, "0" otherwise. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +sc1200_get_genlock_enable(void) +#else +int +gfx_get_genlock_enable(void) +#endif +{ + if (READ_VID32(SC1200_GENLOCK) & + (SC1200_GENLOCK_SINGLE_ENABLE | SC1200_GENLOCK_CONTINUOUS_ENABLE)) + return (1); + else + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_get_video_cursor() + * + * This routine configures the video hardware cursor. + * If the "mask"ed bits in the graphics pixel match "key", then either + * "color1" or "color2" will be used for this pixel, according to the value of + * the bit in offset "select_color2". + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +sc1200_get_video_cursor(unsigned long *key, unsigned long *mask, + unsigned short *select_color2, unsigned long *color1, + unsigned short *color2) +#else +int +gfx_get_video_cursor(unsigned long *key, unsigned long *mask, + unsigned short *select_color2, unsigned long *color1, + unsigned short *color2) +#endif +{ + *select_color2 = + (unsigned short)(READ_VID32(SC1200_CURSOR_COLOR_KEY) >> + SC1200_CURSOR_COLOR_KEY_OFFSET_POS); + *key = READ_VID32(SC1200_CURSOR_COLOR_KEY) & SC1200_COLOR_MASK; + *mask = READ_VID32(SC1200_CURSOR_COLOR_MASK) & SC1200_COLOR_MASK; + *color1 = READ_VID32(SC1200_CURSOR_COLOR_1) & SC1200_COLOR_MASK; + *color2 = + (unsigned short)(READ_VID32(SC1200_CURSOR_COLOR_2) & + SC1200_COLOR_MASK); + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_read_crc + * + * This routine returns the hardware CRC value, which is used for automated + * testing. The value is like a checksum, but will change if pixels move + * locations. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +unsigned long +sc1200_read_crc(void) +#else +unsigned long +gfx_read_crc(void) +#endif +{ + unsigned long crc = 0xFFFFFFFF; + + if (gfx_test_timing_active()) { + /* WAIT UNTIL ACTIVE DISPLAY */ + + while (!gfx_test_vertical_active()) ; + + /* RESET CRC DURING ACTIVE DISPLAY */ + + WRITE_VID32(SC1200_VID_CRC, 0); + WRITE_VID32(SC1200_VID_CRC, 1); + + /* WAIT UNTIL NOT ACTIVE, THEN ACTIVE, NOT ACTIVE, THEN ACTIVE */ + + while (gfx_test_vertical_active()) ; + while (!gfx_test_vertical_active()) ; + while (gfx_test_vertical_active()) ; + while (!gfx_test_vertical_active()) ; + crc = READ_VID32(SC1200_VID_CRC) >> 8; + } + return (crc); +} + +/*---------------------------------------------------------------------------- + * gfx_get_macrovision_enable + * + * This routine returns the value "one" if macrovision currently enabled in + * the TV encoder, otherwise it returns the value "zero". + *---------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +sc1200_get_macrovision_enable(void) +#else +int +gfx_get_macrovision_enable(void) +#endif +{ + if (READ_VID32(SC1200_TVENC_MV_CONTROL) == SC1200_TVENC_MV_ENABLE) + return (1); + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_get_alpha_enable + * + * This routine returns 1 if the selected alpha window is currently + * enabled, or 0 if it is currently disabled. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +void +sc1200_get_alpha_enable(int *enable) +#else +void +gfx_get_alpha_enable(int *enable) +#endif +{ + unsigned long value = 0; + + *enable = 0; + if (gfx_alpha_select <= 2) { + value = + READ_VID32(SC1200_ALPHA_CONTROL_1 + + ((unsigned long)gfx_alpha_select << 4)); + if (value & SC1200_ACTRL_WIN_ENABLE) + *enable = 1; + } + return; +} + +/*--------------------------------------------------------------------------- + * gfx_get_alpha_size + * + * This routine returns the size of the currently selected alpha region. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +void +sc1200_get_alpha_size(unsigned short *x, unsigned short *y, + unsigned short *width, unsigned short *height) +#else +void +gfx_get_alpha_size(unsigned short *x, unsigned short *y, + unsigned short *width, unsigned short *height) +#endif +{ + unsigned long value = 0; + + *x = 0; + *y = 0; + *width = 0; + *height = 0; + if (gfx_alpha_select <= 2) { + value = + READ_VID32(SC1200_ALPHA_XPOS_1 + + ((unsigned long)gfx_alpha_select << 4)); + *x = (unsigned short)(value & 0x000007FF); + *width = (unsigned short)((value >> 16) & 0x000007FF) - *x; + value = + READ_VID32(SC1200_ALPHA_YPOS_1 + + ((unsigned long)gfx_alpha_select << 4)); + *y = (unsigned short)(value & 0x000007FF); + *height = (unsigned short)((value >> 16) & 0x000007FF) - *y; + } + *x -= gfx_get_htotal() - gfx_get_hsync_end() - 2; + *y -= gfx_get_vtotal() - gfx_get_vsync_end() + 1; + return; +} + +/*--------------------------------------------------------------------------- + * gfx_get_alpha_value + * + * This routine returns the alpha value and increment/decrement value of + * the currently selected alpha region. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +void +sc1200_get_alpha_value(unsigned char *alpha, char *delta) +#else +void +gfx_get_alpha_value(unsigned char *alpha, char *delta) +#endif +{ + unsigned long value = 0; + + *alpha = 0; + *delta = 0; + if (gfx_alpha_select <= 2) { + value = + READ_VID32(SC1200_ALPHA_CONTROL_1 + + ((unsigned long)gfx_alpha_select << 4)); + *alpha = (unsigned char)(value & 0x00FF); + *delta = (char)((value >> 8) & 0x00FF); + } + return; +} + +/*--------------------------------------------------------------------------- + * gfx_get_alpha_priority + * + * This routine returns the priority of the currently selected alpha region. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +void +sc1200_get_alpha_priority(int *priority) +#else +void +gfx_get_alpha_priority(int *priority) +#endif +{ + unsigned long pos = 0, value = 0; + + *priority = 0; + if (gfx_alpha_select <= 2) { + value = READ_VID32(SC1200_VID_ALPHA_CONTROL); + pos = 16 + (gfx_alpha_select << 1); + *priority = (int)((value >> pos) & 3); + } + return; +} + +/*--------------------------------------------------------------------------- + * gfx_get_alpha_color + * + * This routine returns the color register value for the currently selected + * alpha region. Bit 24 is set if the color register is enabled. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +void +sc1200_get_alpha_color(unsigned long *color) +#else +void +gfx_get_alpha_color(unsigned long *color) +#endif +{ + *color = 0; + if (gfx_alpha_select <= 2) { + *color = + READ_VID32(SC1200_ALPHA_COLOR_1 + + ((unsigned long)gfx_alpha_select << 4)); + } + return; +} + +#endif /* GFX_READ_ROUTINES */ + +/* END OF FILE */ diff --git a/src/gfx/vid_5530.c b/src/gfx/vid_5530.c new file mode 100644 index 0000000..40e3ffc --- /dev/null +++ b/src/gfx/vid_5530.c @@ -0,0 +1,1354 @@ +/* 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 to control the CS5530 video overlay hardware. + */ + +/*---------------------------------------------------------------------------- + * CS5530 PLL TABLE + *---------------------------------------------------------------------------- + */ +typedef struct tagCS5530PLLENTRY +{ + long frequency; /* 16.16 fixed point frequency */ + unsigned long pll_value; /* associated register value */ +} CS5530PLLENTRY; + +CS5530PLLENTRY CS5530_PLLtable[] = { + {0x00192CCC, 0x31C45801,}, /* 25.1750 */ + {0x001C526E, 0x20E36802,}, /* 28.3220 */ + {0x001F8000, 0x33915801,}, /* 31.5000 */ + {0x00240000, 0x31EC4801,}, /* 36.0000 */ + {0x00258000, 0x21E22801,}, /* 37.5000 */ + {0x00280000, 0x33088801,}, /* 40.0000 */ + {0x002CE666, 0x33E22801,}, /* 44.9000 */ + {0x00318000, 0x336C4801,}, /* 49.5000 */ + {0x00320000, 0x23088801,}, /* 50.0000 */ + {0x00325999, 0x23088801,}, /* 50.3500 */ + {0x00360000, 0x3708A801,}, /* 54.0000 */ + {0x00384000, 0x23E36802,}, /* 56.2500 */ + {0x0038643F, 0x23E36802,}, /* 56.3916 */ + {0x0038A4DD, 0x23E36802,}, /* 56.6444 */ + {0x003B0000, 0x37C45801,}, /* 59.0000 */ + {0x003F0000, 0x23EC4801,}, /* 63.0000 */ + {0x00410000, 0x37911801,}, /* 65.0000 */ + {0x00438000, 0x37963803,}, /* 67.5000 */ + {0x0046CCCC, 0x37058803,}, /* 70.8000 */ + {0x00480000, 0x3710C805,}, /* 72.0000 */ + {0x004B0000, 0x37E22801,}, /* 75.0000 */ + {0x004EC000, 0x27915801,}, /* 78.7500 */ + {0x00500000, 0x37D8D802,}, /* 80.0000 */ + {0x0059CCCC, 0x27588802,}, /* 89.8000 */ + {0x005E8000, 0x27EC4802,}, /* 94.5000 */ + {0x00630000, 0x27AC6803,}, /* 99.0000 */ + {0x00640000, 0x27088801,}, /* 100.0000 */ + {0x006C0000, 0x2710C805,}, /* 108.0000 */ + {0x00708000, 0x27E36802,}, /* 112.5000 */ + {0x00820000, 0x27C58803,}, /* 130.0000 */ + {0x00870000, 0x27316803,}, /* 135.0000 */ + {0x009D8000, 0x2F915801,}, /* 157.5000 */ + {0x00A20000, 0x2F08A801,}, /* 162.0000 */ + {0x00AF0000, 0x2FB11802,}, /* 175.0000 */ + {0x00BD0000, 0x2FEC4802,}, /* 189.0000 */ + {0x00CA0000, 0x2F963803,}, /* 202.0000 */ + {0x00E80000, 0x2FB1B802,}, /* 232.0000 */ +}; + +#define NUM_CS5530_FREQUENCIES sizeof(CS5530_PLLtable)/sizeof(CS5530PLLENTRY) + +/*--------------------------------------------------------------------------- + * gfx_set_crt_enable + * + * This routine enables or disables the CRT output from the video processor. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +cs5530_set_crt_enable(int enable) +#else +int +gfx_set_crt_enable(int enable) +#endif +{ + unsigned long config; + + config = READ_VID32(CS5530_DISPLAY_CONFIG); + + switch (enable) { + case CRT_DISABLE: /* Disable everything */ + + WRITE_VID32(CS5530_DISPLAY_CONFIG, + config & ~(CS5530_DCFG_DIS_EN | CS5530_DCFG_HSYNC_EN | + CS5530_DCFG_VSYNC_EN | CS5530_DCFG_DAC_BL_EN | + CS5530_DCFG_DAC_PWDNX)); + break; + + case CRT_ENABLE: /* Enable CRT display, including display logic */ + + WRITE_VID32(CS5530_DISPLAY_CONFIG, + config | CS5530_DCFG_DIS_EN | CS5530_DCFG_HSYNC_EN | + CS5530_DCFG_VSYNC_EN | CS5530_DCFG_DAC_BL_EN | + CS5530_DCFG_DAC_PWDNX); + break; + + case CRT_STANDBY: /* HSync:Off VSync:On */ + + WRITE_VID32(CS5530_DISPLAY_CONFIG, + (config & ~(CS5530_DCFG_DIS_EN | CS5530_DCFG_HSYNC_EN | + CS5530_DCFG_DAC_BL_EN | CS5530_DCFG_DAC_PWDNX)) + | CS5530_DCFG_VSYNC_EN); + break; + + case CRT_SUSPEND: /* HSync:On VSync:Off */ + + WRITE_VID32(CS5530_DISPLAY_CONFIG, + (config & ~(CS5530_DCFG_DIS_EN | CS5530_DCFG_VSYNC_EN | + CS5530_DCFG_DAC_BL_EN | CS5530_DCFG_DAC_PWDNX)) + | CS5530_DCFG_HSYNC_EN); + break; + + default: + return (GFX_STATUS_BAD_PARAMETER); + } + return (GFX_STATUS_OK); +} + +/*--------------------------------------------------------------------------- + * gfx_reset_video (PRIVATE ROUTINE: NOT PART OF DURANGO API) + * + * This routine is used to disable all components of video overlay before + * performing a mode switch. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +void +cs5530_reset_video(void) +#else +void +gfx_reset_video(void) +#endif +{ + gfx_set_video_enable(0); + + /* CLEAR THE DISPLAY BUFFER SIZE TO ZERO */ + /* During a modeset,if FIFO load is enabled with a large buffer size, */ + /* the FIFO can hang. To prevent this, we set the buffer size to zero */ + /* and wait for this new size to be latched */ + + gfx_set_display_video_size(0, 0); + + if (gfx_test_timing_active()) { + while (!gfx_test_vertical_active()) ; + while (gfx_test_vertical_active()) ; + while (!gfx_test_vertical_active()) ; + while (gfx_test_vertical_active()) ; + } +} + +/*---------------------------------------------------------------------------- + * gfx_set_display_control (PRIVATE ROUTINE: NOT PART OF DURANGO API) + * + * This routine configures the display output. + * + * "sync_polarities" is used to set the polarities of the sync pulses + * according to the following mask: + * + * Bit 0: If set to 1, negative horizontal polarity is programmed, + * otherwise positive horizontal polarity is programmed. + * Bit 1: If set to 1, negative vertical polarity is programmed, + * otherwise positive vertical polarity is programmed. + * + *---------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +cs5530_set_display_control(int sync_polarities) +#else +int +gfx_set_display_control(int sync_polarities) +#endif +{ + unsigned long dcfg; + + /* ENABLE DISPLAY OUTPUT FROM CX5530 */ + + dcfg = READ_VID32(CS5530_DISPLAY_CONFIG); + + /* CLEAR RELEVANT FIELDS */ + + dcfg &= ~(CS5530_DCFG_CRT_SYNC_SKW_MASK | CS5530_DCFG_PWR_SEQ_DLY_MASK | + CS5530_DCFG_CRT_HSYNC_POL | CS5530_DCFG_CRT_VSYNC_POL | + CS5530_DCFG_FP_PWR_EN | CS5530_DCFG_FP_DATA_EN); + + /* INITIALIZATION */ + + dcfg |= (CS5530_DCFG_CRT_SYNC_SKW_INIT | + CS5530_DCFG_PWR_SEQ_DLY_INIT | CS5530_DCFG_GV_PAL_BYP); + + if (PanelEnable) { + dcfg |= CS5530_DCFG_FP_PWR_EN; + dcfg |= CS5530_DCFG_FP_DATA_EN; + } + + /* SET APPROPRIATE SYNC POLARITIES */ + + if (sync_polarities & 1) + dcfg |= CS5530_DCFG_CRT_HSYNC_POL; + if (sync_polarities & 2) + dcfg |= CS5530_DCFG_CRT_VSYNC_POL; + + WRITE_VID32(CS5530_DISPLAY_CONFIG, dcfg); + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_set_clock_frequency + * + * This routine sets the clock frequency, specified as a 16.16 fixed point + * value (0x00318000 = 49.5 MHz). It will set the closest frequency found + * in the lookup table. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +void +cs5530_set_clock_frequency(unsigned long frequency) +#else +void +gfx_set_clock_frequency(unsigned long frequency) +#endif +{ + unsigned int index; + unsigned long value; + long min, diff; + + /* FIND THE REGISTER VALUES FOR THE DESIRED FREQUENCY */ + /* Search the table for the closest frequency (16.16 format). */ + + value = CS5530_PLLtable[0].pll_value; + min = (long)CS5530_PLLtable[0].frequency - frequency; + if (min < 0L) + min = -min; + for (index = 1; index < NUM_CS5530_FREQUENCIES; index++) { + diff = (long)CS5530_PLLtable[index].frequency - frequency; + if (diff < 0L) + diff = -diff; + if (diff < min) { + min = diff; + value = CS5530_PLLtable[index].pll_value; + } + } + + /* SET THE DOT CLOCK REGISTER */ + + WRITE_VID32(CS5530_DOT_CLK_CONFIG, value); + WRITE_VID32(CS5530_DOT_CLK_CONFIG, value | 0x80000100); + /* set reset/bypass */ + gfx_delay_milliseconds(1); /* wait for PLL to settle */ + WRITE_VID32(CS5530_DOT_CLK_CONFIG, value & 0x7FFFFFFF); + /* clear reset */ + WRITE_VID32(CS5530_DOT_CLK_CONFIG, value & 0x7FFFFEFF); + /* clear bypass */ + return; +} + +/*---------------------------------------------------------------------------- + * gfx_set_video_enable + * + * This routine enables or disables the video overlay functionality. + *---------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +cs5530_set_video_enable(int enable) +#else +int +gfx_set_video_enable(int enable) +#endif +{ + unsigned long vcfg; + + /* WAIT FOR VERTICAL BLANK TO START */ + /* Otherwise a glitch can be observed. */ + + if (gfx_test_timing_active()) { + if (!gfx_test_vertical_active()) { + while (!gfx_test_vertical_active()) ; + } + while (gfx_test_vertical_active()) ; + } + vcfg = READ_VID32(CS5530_VIDEO_CONFIG); + if (enable) { + /* SET CS5530 BUS CONTROL PARAMETERS */ + /* Currently always high speed, 8-bit interface. */ + + vcfg |= CS5530_VCFG_HIGH_SPD_INT; + vcfg &= ~(CS5530_VCFG_EARLY_VID_RDY | CS5530_VCFG_16_BIT_EN); + + /* ENABLE CS5530 VIDEO OVERLAY */ + + vcfg |= CS5530_VCFG_VID_EN; + WRITE_VID32(CS5530_VIDEO_CONFIG, vcfg); + } else { + /* DISABLE CS5530 VIDEO OVERLAY */ + + vcfg &= ~CS5530_VCFG_VID_EN; + WRITE_VID32(CS5530_VIDEO_CONFIG, vcfg); + } + return (0); +} + +/*---------------------------------------------------------------------------- + * gfx_set_video_format + * + * Currently only sets 4:2:0 format, Y1 V Y0 U. + *---------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +cs5530_set_video_format(unsigned long format) +#else +int +gfx_set_video_format(unsigned long format) +#endif +{ + unsigned long vcfg = 0; + + /* SET THE CS5530 VIDEO INPUT FORMAT */ + + vcfg = READ_VID32(CS5530_VIDEO_CONFIG); + vcfg &= ~(CS5530_VCFG_VID_INP_FORMAT | CS5530_VCFG_4_2_0_MODE); + vcfg &= ~(CS5530_VCFG_CSC_BYPASS); + vcfg &= ~(CS5530_VCFG_GV_SEL); + + if (format < 4) + vcfg |= (format << 2); + else { + if (format == VIDEO_FORMAT_Y0Y1Y2Y3) { + vcfg |= CS5530_VCFG_4_2_0_MODE; + vcfg |= 1 << 2; + } + if (format == VIDEO_FORMAT_RGB) { + vcfg |= CS5530_VCFG_CSC_BYPASS; + vcfg |= CS5530_VCFG_GV_SEL; + } + } + + WRITE_VID32(CS5530_VIDEO_CONFIG, vcfg); + return (0); +} + +/*---------------------------------------------------------------------------- + * gfx_set_video_size + * + * This routine specifies the size of the source data. It is used only + * to determine how much data to transfer per frame, and is not used to + * calculate the scaling value (that is handled by a separate routine). + *---------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +cs5530_set_video_size(unsigned short width, unsigned short height) +#else +int +gfx_set_video_size(unsigned short width, unsigned short height) +#endif +{ + unsigned long size, vcfg; + + /* SET THE CS5530 VIDEO LINE SIZE */ + + vcfg = READ_VID32(CS5530_VIDEO_CONFIG); + vcfg &= ~(CS5530_VCFG_LINE_SIZE_LOWER_MASK | CS5530_VCFG_LINE_SIZE_UPPER); + size = (width >> 1); + vcfg |= (size & 0x00FF) << 8; + if (size & 0x0100) + vcfg |= CS5530_VCFG_LINE_SIZE_UPPER; + WRITE_VID32(CS5530_VIDEO_CONFIG, vcfg); + + /* SET TOTAL VIDEO BUFFER SIZE IN DISPLAY CONTROLLER */ + /* Use private routine to abstract the display controller. */ + + gfx_set_display_video_size(width, height); + return (0); +} + +/*---------------------------------------------------------------------------- + * gfx_set_video_offset + * + * This routine sets the starting offset for the video buffer when only + * one offset needs to be specified. + *---------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +cs5530_set_video_offset(unsigned long offset) +#else +int +gfx_set_video_offset(unsigned long offset) +#endif +{ + /* SAVE VALUE FOR FUTURE CLIPPING OF THE TOP OF THE VIDEO WINDOW */ + + gfx_vid_offset = offset; + + /* SET VIDEO BUFFER OFFSET IN DISPLAY CONTROLLER */ + /* Use private routine to abstract the display controller. */ + + gfx_set_display_video_offset(offset); + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_set_video_scale + * + * This routine sets the scale factor for the video overlay window. The + * size of the source and destination regions are specified in pixels. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +cs5530_set_video_scale(unsigned short srcw, unsigned short srch, + unsigned short dstw, unsigned short dsth) +#else +int +gfx_set_video_scale(unsigned short srcw, unsigned short srch, + unsigned short dstw, unsigned short dsth) +#endif +{ + unsigned long xscale, yscale; + + /* SAVE PARAMETERS */ + /* These are needed for clipping the video window later. */ + + gfx_vid_srcw = srcw; + gfx_vid_srch = srch; + gfx_vid_dstw = dstw; + gfx_vid_dsth = dsth; + + /* CALCULATE CS5530 SCALE FACTORS */ + /* No downscaling in CS5530 so force to 1x if attempted. */ + + if (dstw <= srcw) + xscale = 0x1FFF; + else if (dstw == 1 || srcw == 1) + return GFX_STATUS_BAD_PARAMETER; + else + xscale = (0x2000l * (srcw - 1l)) / (dstw - 1l); + if (dsth <= srch) + yscale = 0x1FFF; + else if (dsth == 1 || srch == 1) + return GFX_STATUS_BAD_PARAMETER; + else + yscale = (0x2000l * (srch - 1l)) / (dsth - 1l); + WRITE_VID32(CS5530_VIDEO_SCALE, (yscale << 16) | xscale); + + /* CALL ROUTINE TO UPDATE WINDOW POSITION */ + /* This is required because the scale values effect the number of */ + /* source data pixels that need to be clipped, as well as the */ + /* amount of data that needs to be transferred. */ + + gfx_set_video_window(gfx_vid_xpos, gfx_vid_ypos, gfx_vid_width, + gfx_vid_height); + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_set_video_window + * + * This routine sets the position and size of the video overlay window. The + * position is specified in screen relative coordinates, and may be negative. + * The size of destination region is specified in pixels. The line size + * indicates the number of bytes of source data per scanline. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +cs5530_set_video_window(short x, short y, unsigned short w, unsigned short h) +#else +int +gfx_set_video_window(short x, short y, unsigned short w, unsigned short h) +#endif +{ + unsigned long vcfg = 0; + unsigned long hadjust, vadjust; + unsigned long xstart, ystart, xend, yend; + unsigned long offset, line_size; + + /* SAVE PARAMETERS */ + /* These are needed to call this routine if the scale value changes. */ + + gfx_vid_xpos = x; + gfx_vid_ypos = y; + gfx_vid_width = w; + gfx_vid_height = h; + + /* GET ADJUSTMENT VALUES */ + /* Use routines to abstract version of display controller. */ + + hadjust = gfx_get_htotal() - gfx_get_hsync_end() - 13l; + vadjust = gfx_get_vtotal() - gfx_get_vsync_end() + 1l; + + /* LEFT CLIPPING */ + + if (x < 0) { + gfx_set_video_left_crop((unsigned short)(-x)); + xstart = hadjust; + } else { + gfx_set_video_left_crop(0); + xstart = (unsigned long)x + hadjust; + } + + /* CLIPPING ON RIGHT */ + + xend = x + w; + if (xend > gfx_get_hactive()) + xend = gfx_get_hactive(); + xend += hadjust; + + /* CLIPPING ON TOP */ + + offset = gfx_vid_offset; + if (y >= 0) { + ystart = y + vadjust; + } else { + ystart = vadjust; + line_size = (READ_VID32(CS5530_VIDEO_CONFIG) >> 7) & 0x000001FE; + if (READ_VID32(CS5530_VIDEO_CONFIG) & CS5530_VCFG_LINE_SIZE_UPPER) + line_size += 512l; + if (gfx_vid_dsth) + offset = gfx_vid_offset + (line_size << 1) * + (((-y) * gfx_vid_srch) / gfx_vid_dsth); + } + + /* CLIPPING ON BOTTOM */ + + yend = y + h; + if (yend >= gfx_get_vactive()) + yend = gfx_get_vactive(); + yend += vadjust; + + /* SET VIDEO BUFFER OFFSET IN DISPLAY CONTROLLER */ + /* Use private routine to abstract the display controller. */ + + gfx_set_display_video_offset(offset); + + /* DISABLE REGISTER UPDATES */ + + vcfg = READ_VID32(CS5530_VIDEO_CONFIG); + vcfg &= ~CS5530_VCFG_VID_REG_UPDATE; + WRITE_VID32(CS5530_VIDEO_CONFIG, vcfg); + + /* SET VIDEO POSITION */ + + WRITE_VID32(CS5530_VIDEO_X_POS, (xend << 16) | xstart); + WRITE_VID32(CS5530_VIDEO_Y_POS, (yend << 16) | ystart); + + vcfg |= CS5530_VCFG_VID_REG_UPDATE; + WRITE_VID32(CS5530_VIDEO_CONFIG, vcfg); + + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_set_video_left_crop + * + * This routine sets the number of pixels which will be cropped from the + * beginning of each video line. The video window will begin to display only + * from the pixel following the cropped pixels, and the cropped pixels + * will be ignored. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +cs5530_set_video_left_crop(unsigned short x) +#else +int +gfx_set_video_left_crop(unsigned short x) +#endif +{ + unsigned long vcfg, initread; + + /* CLIPPING ON LEFT */ + /* Adjust initial read for scale, checking for divide by zero */ + + if (gfx_vid_dstw) + initread = (unsigned long)x *gfx_vid_srcw / gfx_vid_dstw; + + else + initread = 0; + + /* SET INITIAL READ ADDRESS AND ENABLE REGISTER UPDATES */ + + vcfg = READ_VID32(CS5530_VIDEO_CONFIG); + vcfg &= ~CS5530_VCFG_INIT_READ_MASK; + vcfg |= (initread << 15) & CS5530_VCFG_INIT_READ_MASK; + vcfg |= CS5530_VCFG_VID_REG_UPDATE; + WRITE_VID32(CS5530_VIDEO_CONFIG, vcfg); + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_set_video_color_key + * + * This routine specifies the color key value and mask for the video overlay + * hardware. To disable color key, the color and mask should both be set to + * zero. The hardware uses the color key in the following equation: + * + * ((source data) & (color key mask)) == ((color key) & (color key mask)) + * + * The source data can be either graphics data or video data. The bluescreen + * parameter is set to have the hardware compare video data and clear to + * comapare graphics data. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +cs5530_set_video_color_key(unsigned long key, unsigned long mask, + int graphics) +#else +int +gfx_set_video_color_key(unsigned long key, unsigned long mask, int graphics) +#endif +{ + unsigned long dcfg = 0; + + /* SET CS5530 COLOR KEY VALUE */ + + WRITE_VID32(CS5530_VIDEO_COLOR_KEY, key); + WRITE_VID32(CS5530_VIDEO_COLOR_MASK, mask); + + /* SELECT GRAPHICS OR VIDEO DATA TO COMPARE TO THE COLOR KEY */ + + dcfg = READ_VID32(CS5530_DISPLAY_CONFIG); + if (graphics & 0x01) + dcfg &= ~CS5530_DCFG_VG_CK; + else + dcfg |= CS5530_DCFG_VG_CK; + WRITE_VID32(CS5530_DISPLAY_CONFIG, dcfg); + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_set_video_filter + * + * This routine enables or disables the video overlay filters. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +cs5530_set_video_filter(int xfilter, int yfilter) +#else +int +gfx_set_video_filter(int xfilter, int yfilter) +#endif +{ + unsigned long vcfg = 0; + + /* ENABLE OR DISABLE CS5530 VIDEO OVERLAY FILTERS */ + + vcfg = READ_VID32(CS5530_VIDEO_CONFIG); + vcfg &= ~(CS5530_VCFG_X_FILTER_EN | CS5530_VCFG_Y_FILTER_EN); + if (xfilter) + vcfg |= CS5530_VCFG_X_FILTER_EN; + if (yfilter) + vcfg |= CS5530_VCFG_Y_FILTER_EN; + WRITE_VID32(CS5530_VIDEO_CONFIG, vcfg); + + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_set_video_palette + * + * This routine loads the video hardware palette. If a NULL pointer is + * specified, the palette is bypassed (for CS5530, this means loading the + * palette with identity values). + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +cs5530_set_video_palette(unsigned long *palette) +#else +int +gfx_set_video_palette(unsigned long *palette) +#endif +{ + unsigned long i, entry; + + /* LOAD CS5530 VIDEO PALETTE */ + + WRITE_VID32(CS5530_PALETTE_ADDRESS, 0); + for (i = 0; i < 256; i++) { + if (palette) + entry = palette[i]; + else + entry = i | (i << 8) | (i << 16); + WRITE_VID32(CS5530_PALETTE_DATA, entry); + } + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_set_video_palette_entry + * + * This routine loads a single entry of the video hardware palette. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +cs5530_set_video_palette_entry(unsigned long index, unsigned long palette) +#else +int +gfx_set_video_palette_entry(unsigned long index, unsigned long palette) +#endif +{ + if (index > 0xFF) + return GFX_STATUS_BAD_PARAMETER; + + /* SET A SINGLE ENTRY */ + + WRITE_VID32(CS5530_PALETTE_ADDRESS, index); + WRITE_VID32(CS5530_PALETTE_DATA, palette); + + return (0); +} + +#define CX55xx_VIDEO_PCI_44 0x80009444 + +/*--------------------------------------------------------------------------- + * gfx_disable_softvga + * + * Disables SoftVga. This function is only valid with VSA2, Returns 1 if + * SoftVga can be disabled; 0 if not. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +cs5530_disable_softvga(void) +#else +int +gfx_disable_softvga(void) +#endif +{ + unsigned long reg_val; + + /* get the current value */ + reg_val = gfx_pci_config_read(CX55xx_VIDEO_PCI_44); + /* setting video PCI register 44 bit 0 to 1 disables SoftVga */ + reg_val |= 0x1; + gfx_pci_config_write(CX55xx_VIDEO_PCI_44, reg_val); + + /* see if we set the bit and return the appropriate value */ + reg_val = gfx_pci_config_read(CX55xx_VIDEO_PCI_44); + if ((reg_val & 0x1) == 0x1) + return (1); + else + return (0); + +} + +/*--------------------------------------------------------------------------- + * gfx_enable_softvga + * + * Enables SoftVga. This function is only valid with VSA2, Returns 1 if + * SoftVga can be enbled; 0 if not. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +cs5530_enable_softvga(void) +#else +int +gfx_enable_softvga(void) +#endif +{ + unsigned long reg_val; + + /* get the current value */ + reg_val = gfx_pci_config_read(CX55xx_VIDEO_PCI_44); + /* clearing video PCI register 44 bit 0 enables SoftVga */ + gfx_pci_config_write(CX55xx_VIDEO_PCI_44, reg_val & 0xfffffffe); + + /* see if we cleared the bit and return the appropriate value */ + reg_val = gfx_pci_config_read(CX55xx_VIDEO_PCI_44); + if ((reg_val & 0x1) == 0) + return (1); + else + return (0); + +} + +/*--------------------------------------------------------------------------- + * gfx_get_clock_frequency + * + * This routine returns the current clock frequency in 16.16 format. + * It reads the current register value and finds the match in the table. + * If no match is found, this routine returns 0. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +unsigned long +cs5530_get_clock_frequency(void) +#else +unsigned long +gfx_get_clock_frequency(void) +#endif +{ + unsigned int index; + unsigned long value, mask; + + mask = 0x7FFFFEDC; + value = READ_VID32(CS5530_DOT_CLK_CONFIG) & mask; + for (index = 0; index < NUM_CS5530_FREQUENCIES; index++) { + if ((CS5530_PLLtable[index].pll_value & mask) == value) + return (CS5530_PLLtable[index].frequency); + } + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_get_max_video_width + * + * This routine returns the maximum theoretical video width for the current + * display mode. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +unsigned long +cs5530_get_max_video_width(void) +#else +unsigned long +gfx_get_max_video_width(void) +#endif +{ + unsigned long htotal, vidclk, dotpll; + unsigned long low, high, sublow, subhigh; + unsigned long width, value; + unsigned long temp0, temp1; + unsigned long highshift; + unsigned long divisor, dividend; + + htotal = gfx_get_htotal(); + + vidclk = gfx_cpu_frequency << 15; + if (READ_REG32(DC_GENERAL_CFG) & DC_GCFG_VCLK_DIV) + vidclk >>= 1; + + dotpll = gfx_get_clock_frequency(); + + /* CHECK FOR UNKNOWN DOT CLOCK */ + + if (!dotpll) + return 0; + + /* DERIVE THEORETICAL MAXIMUM */ + /* The GX/CS5530 video interface transfers 8 bytes for every 9 video */ + /* clocks. This implies that 4 video pixels are transferred for every */ + /* 9 clocks. The time allowed to fill a line buffer is an entire */ + /* display line, or (HTotal * DotPll). The time needed to fill the */ + /* line buffer is thus ((4/9) * VidClk * VidWidth). Solving for */ + /* equality yields the theoretical maximum: */ + /* */ + /* 4 * VidClk * HTotal */ + /* VidWidth = ----------------------- */ + /* 9 * DotPLL */ + + /* CALCULATE TOP OF EQUATION */ + /* The equation as it stands will overflow 32-bit integer math. We must */ + /* therefore use tricks to perform a 64-bit equation to calculate the */ + /* correct value. We assume in this equation that the upper 16 bits of */ + /* htotal are 0, i.e. that htotal is never greater than 65535. */ + + vidclk <<= 2; + + low = (vidclk & 0xFFFF) * (htotal & 0xFFFF); + temp0 = (vidclk >> 16) * (htotal & 0xFFFF); + temp1 = temp0 << 16; + + high = temp0 >> 16; + if ((0xFFFFFFFF - temp1) < low) + high++; + low += temp1; + + /* DIVIDE BY BOTTOM OF EQUATION */ + /* Use an iterative divide to avoid floating point or inline assembly */ + /* Costly, but so is the price of OS independence. */ + + divisor = 9 * dotpll; + highshift = 0; + width = 0; + while (highshift <= 32) { + if (highshift == 0) + dividend = high; + else if (highshift == 32) + dividend = low; + else + dividend = (high << highshift) | (low >> (32 - highshift)); + + value = dividend / divisor; + + width = (width << 4) + value; + + value *= divisor; + + subhigh = value >> highshift; + sublow = value << (32 - highshift); + + if (low < sublow) + high = high - subhigh - 1; + else + high = high - subhigh; + + low -= sublow; + + highshift += 4; + } + + /* ALIGN TO 8 PIXEL BOUNDARY */ + + width &= 0xFFFC; + + return width; +} + +/*************************************************************/ +/* READ ROUTINES | INCLUDED FOR DIAGNOSTIC PURPOSES ONLY */ +/*************************************************************/ + +#if GFX_READ_ROUTINES + +/*--------------------------------------------------------------------------- + * gfx_get_vsa2_softvga_enable + * + * This function returns the enable status of SoftVGA. It is valid + * only if VSAII is present. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +cs5530_get_vsa2_softvga_enable(void) +#else +int +gfx_get_vsa2_softvga_enable(void) +#endif +{ + unsigned long reg_val; + + reg_val = gfx_pci_config_read(CX55xx_VIDEO_PCI_44); + if ((reg_val & 0x1) == 0) + return (1); + else + return (0); + +} + +/*--------------------------------------------------------------------------- + * gfx_get_sync_polarities + * + * This routine returns the polarities of the sync pulses: + * Bit 0: Set if negative horizontal polarity. + * Bit 1: Set if negative vertical polarity. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +cs5530_get_sync_polarities(void) +#else +int +gfx_get_sync_polarities(void) +#endif +{ + int polarities = 0; + + if (READ_VID32(CS5530_DISPLAY_CONFIG) & 0x00000100) + polarities |= 1; + if (READ_VID32(CS5530_DISPLAY_CONFIG) & 0x00000200) + polarities |= 2; + return (polarities); +} + +/*--------------------------------------------------------------------------- + * gfx_get_video_palette_entry + * + * This routine returns a single palette entry. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +cs5530_get_video_palette_entry(unsigned long index, unsigned long *palette) +#else +int +gfx_get_video_palette_entry(unsigned long index, unsigned long *palette) +#endif +{ + if (index > 0xFF) + return GFX_STATUS_BAD_PARAMETER; + + /* READ A SINGLE ENTRY */ + + WRITE_VID32(CS5530_PALETTE_ADDRESS, index); + *palette = READ_VID32(CS5530_PALETTE_DATA); + + return (GFX_STATUS_OK); +} + +/*---------------------------------------------------------------------------- + * gfx_get_video_enable + * + * This routine returns the value "one" if video overlay is currently enabled, + * otherwise it returns the value "zero". + *---------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +cs5530_get_video_enable(void) +#else +int +gfx_get_video_enable(void) +#endif +{ + if (READ_VID32(CS5530_VIDEO_CONFIG) & CS5530_VCFG_VID_EN) + return (1); + return (0); +} + +/*---------------------------------------------------------------------------- + * gfx_get_video_format + * + * This routine returns the current video overlay format. + *---------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +cs5530_get_video_format(void) +#else +int +gfx_get_video_format(void) +#endif +{ + unsigned long vcfg; + + vcfg = READ_VID32(CS5530_VIDEO_CONFIG); + if (vcfg & CS5530_VCFG_CSC_BYPASS) + return (VIDEO_FORMAT_RGB); + if (vcfg & CS5530_VCFG_4_2_0_MODE) + return (VIDEO_FORMAT_Y0Y1Y2Y3); + + return ((int)((vcfg >> 2) & 3)); +} + +/*---------------------------------------------------------------------------- + * gfx_get_video_src_size + * + * This routine returns the size of the source video overlay buffer. The + * return value is (height << 16) | width. + *---------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +unsigned long +cs5530_get_video_src_size(void) +#else +unsigned long +gfx_get_video_src_size(void) +#endif +{ + unsigned long width = 0, height = 0; + + /* DETERMINE SOURCE WIDTH FROM THE CS5530 VIDEO LINE SIZE */ + + width = (READ_VID32(CS5530_VIDEO_CONFIG) >> 7) & 0x000001FE; + if (READ_VID32(CS5530_VIDEO_CONFIG) & CS5530_VCFG_LINE_SIZE_UPPER) + width += 512l; + + if (width) { + /* DETERMINE HEIGHT BY DIVIDING TOTAL SIZE BY WIDTH */ + /* Get total size from display controller - abtracted. */ + + height = gfx_get_display_video_size() / (width << 1); + } + return ((height << 16) | width); +} + +/*---------------------------------------------------------------------------- + * gfx_get_video_line_size + * + * This routine returns the line size of the source video overlay buffer, in + * pixels. + *---------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +unsigned long +cs5530_get_video_line_size(void) +#else +unsigned long +gfx_get_video_line_size(void) +#endif +{ + unsigned long width = 0; + + /* DETERMINE SOURCE WIDTH FROM THE CS5530 VIDEO LINE SIZE */ + + width = (READ_VID32(CS5530_VIDEO_CONFIG) >> 7) & 0x000001FE; + if (READ_VID32(CS5530_VIDEO_CONFIG) & CS5530_VCFG_LINE_SIZE_UPPER) + width += 512l; + return (width); +} + +/*---------------------------------------------------------------------------- + * gfx_get_video_xclip + * + * This routine returns the number of bytes clipped on the left side of a + * video overlay line (skipped at beginning). + *---------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +unsigned long +cs5530_get_video_xclip(void) +#else +unsigned long +gfx_get_video_xclip(void) +#endif +{ + unsigned long clip = 0; + + /* DETERMINE SOURCE WIDTH FROM THE CS5530 VIDEO LINE SIZE */ + + clip = (READ_VID32(CS5530_VIDEO_CONFIG) >> 14) & 0x000007FC; + return (clip); +} + +/*---------------------------------------------------------------------------- + * gfx_get_video_offset + * + * This routine returns the current offset for the video overlay buffer. + *---------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +unsigned long +cs5530_get_video_offset(void) +#else +unsigned long +gfx_get_video_offset(void) +#endif +{ + return (gfx_get_display_video_offset()); +} + +/*--------------------------------------------------------------------------- + * gfx_get_video_scale + * + * This routine returns the scale factor for the video overlay window. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +unsigned long +cs5530_get_video_scale(void) +#else +unsigned long +gfx_get_video_scale(void) +#endif +{ + return (READ_VID32(CS5530_VIDEO_SCALE)); +} + +/*--------------------------------------------------------------------------- + * gfx_get_video_dst_size + * + * This routine returns the size of the displayed video overlay window. + * NOTE: This is the displayed window size, which may be different from + * the real window size if clipped. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +unsigned long +cs5530_get_video_dst_size(void) +#else +unsigned long +gfx_get_video_dst_size(void) +#endif +{ + unsigned long xsize, ysize; + + xsize = READ_VID32(CS5530_VIDEO_X_POS); + xsize = ((xsize >> 16) & 0x7FF) - (xsize & 0x07FF); + ysize = READ_VID32(CS5530_VIDEO_Y_POS); + ysize = ((ysize >> 16) & 0x7FF) - (ysize & 0x07FF); + return ((ysize << 16) | xsize); +} + +/*--------------------------------------------------------------------------- + * gfx_get_video_position + * + * This routine returns the position of the video overlay window. The + * return value is (ypos << 16) | xpos. + * NOTE: This is the displayed window position, which may be different from + * the real window position if clipped. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +unsigned long +cs5530_get_video_position(void) +#else +unsigned long +gfx_get_video_position(void) +#endif +{ + unsigned long hadjust, vadjust; + unsigned long xpos, ypos; + + /* READ HARDWARE POSITION */ + + xpos = READ_VID32(CS5530_VIDEO_X_POS) & 0x000007FF; + ypos = READ_VID32(CS5530_VIDEO_Y_POS) & 0x000007FF; + + /* GET ADJUSTMENT VALUES */ + /* Use routines to abstract version of display controller. */ + + hadjust = gfx_get_htotal() - gfx_get_hsync_end() - 13l; + vadjust = gfx_get_vtotal() - gfx_get_vsync_end() + 1l; + xpos -= hadjust; + ypos -= vadjust; + return ((ypos << 16) | (xpos & 0x0000FFFF)); +} + +/*--------------------------------------------------------------------------- + * gfx_get_video_color_key + * + * This routine returns the current video color key value. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +unsigned long +cs5530_get_video_color_key(void) +#else +unsigned long +gfx_get_video_color_key(void) +#endif +{ + return (READ_VID32(CS5530_VIDEO_COLOR_KEY)); +} + +/*--------------------------------------------------------------------------- + * gfx_get_video_color_key_mask + * + * This routine returns the current video color mask value. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +unsigned long +cs5530_get_video_color_key_mask(void) +#else +unsigned long +gfx_get_video_color_key_mask(void) +#endif +{ + return (READ_VID32(CS5530_VIDEO_COLOR_MASK)); +} + +/*--------------------------------------------------------------------------- + * gfx_get_video_color_key_src + * + * This routine returns 0 for video data compare, 1 for graphics data. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +cs5530_get_video_color_key_src(void) +#else +int +gfx_get_video_color_key_src(void) +#endif +{ + if (READ_VID32(CS5530_DISPLAY_CONFIG) & CS5530_DCFG_VG_CK) + return (0); + return (1); +} + +/*--------------------------------------------------------------------------- + * gfx_get_video_filter + * + * This routine returns if the filters are currently enabled. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +cs5530_get_video_filter(void) +#else +int +gfx_get_video_filter(void) +#endif +{ + int retval = 0; + + if (READ_VID32(CS5530_VIDEO_CONFIG) & CS5530_VCFG_X_FILTER_EN) + retval |= 1; + if (READ_VID32(CS5530_VIDEO_CONFIG) & CS5530_VCFG_Y_FILTER_EN) + retval |= 2; + return (retval); +} + +/*--------------------------------------------------------------------------- + * gfx_read_crc + * + * This routine returns the hardware CRC value, which is used for automated + * testing. The value is like a checksum, but will change if pixels move + * locations. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +unsigned long +cs5530_read_crc(void) +#else +unsigned long +gfx_read_crc(void) +#endif +{ + unsigned long crc = 0xFFFFFFFF; + + if (gfx_test_timing_active()) { + /* WAIT UNTIL ACTIVE DISPLAY */ + + while (!gfx_test_vertical_active()) ; + + /* RESET CRC DURING ACTIVE DISPLAY */ + + WRITE_VID32(CS5530_CRCSIG_TFT_TV, 0); + WRITE_VID32(CS5530_CRCSIG_TFT_TV, 1); + + /* WAIT UNTIL NOT ACTIVE, THEN ACTIVE, NOT ACTIVE, THEN ACTIVE */ + + while (gfx_test_vertical_active()) ; + while (!gfx_test_vertical_active()) ; + while (gfx_test_vertical_active()) ; + while (!gfx_test_vertical_active()) ; + crc = READ_VID32(CS5530_CRCSIG_TFT_TV) >> 8; + } + return (crc); +} + +#endif /* GFX_READ_ROUTINES */ + +/* END OF FILE */ diff --git a/src/gfx/vid_cstl.c b/src/gfx/vid_cstl.c new file mode 100644 index 0000000..5b642cc --- /dev/null +++ b/src/gfx/vid_cstl.c @@ -0,0 +1,2571 @@ +/* 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. + * */ + +/* DEFAULT FILTER COEFFICIENTS */ + +long DurangoVideoFilter[][2] = { + {0x10000000, 0x00000000}, /* 0, 4096, 0, 0 */ + {0x10008008, 0x00000008}, /* -8, 4096, 8, 0 */ + {0x10008010, 0x80010011}, /* -16, 4096, 17, -1 */ + {0x10008019, 0x8001001A}, /* -25, 4096, 26, -1 */ + {0x10008021, 0x80020023}, /* -33, 4096, 35, -2 */ + {0x0FFF8029, 0x8003002D}, /* -41, 4095, 45, -3 */ + {0x0FFE8031, 0x80030036}, /* -49, 4094, 54, -3 */ + {0x0FFC8038, 0x80040040}, /* -56, 4092, 64, -4 */ + {0x0FFB8040, 0x8005004A}, /* -64, 4091, 74, -5 */ + {0x0FF88047, 0x80050054}, /* -71, 4088, 84, -5 */ + {0x0FF6804E, 0x8006005E}, /* -78, 4086, 94, -6 */ + {0x0FF48055, 0x80070068}, /* -85, 4084, 104, -7 */ + {0x0FF0805C, 0x80070073}, /* -92, 4080, 115, -7 */ + {0x0FEE8063, 0x8008007D}, /* -99, 4078, 125, -8 */ + {0x0FEA8069, 0x80090088}, /* -105, 4074, 136, -9 */ + {0x0FE78070, 0x800A0093}, /* -112, 4071, 147, -10 */ + {0x0FE28076, 0x800A009E}, /* -118, 4066, 158, -10 */ + {0x0FDD807C, 0x800B00AA}, /* -124, 4061, 170, -11 */ + {0x0FD98082, 0x800C00B5}, /* -130, 4057, 181, -12 */ + {0x0FD48088, 0x800D00C1}, /* -136, 4052, 193, -13 */ + {0x0FCE808E, 0x800D00CD}, /* -142, 4046, 205, -13 */ + {0x0FC88093, 0x800E00D9}, /* -147, 4040, 217, -14 */ + {0x0FC38099, 0x800F00E5}, /* -153, 4035, 229, -15 */ + {0x0FBD809E, 0x801000F1}, /* -158, 4029, 241, -16 */ + {0x0FB680A3, 0x801000FD}, /* -163, 4022, 253, -16 */ + {0x0FAF80A8, 0x8011010A}, /* -168, 4015, 266, -17 */ + {0x0FA880AD, 0x80120117}, /* -173, 4008, 279, -18 */ + {0x0FA180B2, 0x80130124}, /* -178, 4001, 292, -19 */ + {0x0F9980B6, 0x80140131}, /* -182, 3993, 305, -20 */ + {0x0F9280BB, 0x8015013E}, /* -187, 3986, 318, -21 */ + {0x0F8880BF, 0x8015014C}, /* -191, 3976, 332, -21 */ + {0x0F8080C3, 0x80160159}, /* -195, 3968, 345, -22 */ + {0x0F7880C8, 0x80170167}, /* -200, 3960, 359, -23 */ + {0x0F6E80CB, 0x80180175}, /* -203, 3950, 373, -24 */ + {0x0F6580CF, 0x80190183}, /* -207, 3941, 387, -25 */ + {0x0F5C80D3, 0x801A0191}, /* -211, 3932, 401, -26 */ + {0x0F5280D7, 0x801B01A0}, /* -215, 3922, 416, -27 */ + {0x0F4880DA, 0x801C01AE}, /* -218, 3912, 430, -28 */ + {0x0F3D80DD, 0x801D01BD}, /* -221, 3901, 445, -29 */ + {0x0F3280E0, 0x801E01CC}, /* -224, 3890, 460, -30 */ + {0x0F2880E4, 0x801F01DB}, /* -228, 3880, 475, -31 */ + {0x0F1C80E6, 0x802001EA}, /* -230, 3868, 490, -32 */ + {0x0F1180E9, 0x802101F9}, /* -233, 3857, 505, -33 */ + {0x0F0480EB, 0x80210208}, /* -235, 3844, 520, -33 */ + {0x0EFA80EF, 0x80230218}, /* -239, 3834, 536, -35 */ + {0x0EEC80F0, 0x80230227}, /* -240, 3820, 551, -35 */ + {0x0EE080F3, 0x80240237}, /* -243, 3808, 567, -36 */ + {0x0ED380F5, 0x80250247}, /* -245, 3795, 583, -37 */ + {0x0EC780F7, 0x80270257}, /* -247, 3783, 599, -39 */ + {0x0EB980F9, 0x80280268}, /* -249, 3769, 616, -40 */ + {0x0EAC80FB, 0x80290278}, /* -251, 3756, 632, -41 */ + {0x0E9E80FD, 0x802A0289}, /* -253, 3742, 649, -42 */ + {0x0E9080FE, 0x802B0299}, /* -254, 3728, 665, -43 */ + {0x0E838100, 0x802D02AA}, /* -256, 3715, 682, -45 */ + {0x0E758102, 0x802E02BB}, /* -258, 3701, 699, -46 */ + {0x0E668103, 0x802F02CC}, /* -259, 3686, 716, -47 */ + {0x0E568104, 0x803002DE}, /* -260, 3670, 734, -48 */ + {0x0E498106, 0x803202EF}, /* -262, 3657, 751, -50 */ + {0x0E398107, 0x80330301}, /* -263, 3641, 769, -51 */ + {0x0E298108, 0x80340313}, /* -264, 3625, 787, -52 */ + {0x0E1A8109, 0x80360325}, /* -265, 3610, 805, -54 */ + {0x0E0B810A, 0x80370336}, /* -266, 3595, 822, -55 */ + {0x0DFA810A, 0x80380348}, /* -266, 3578, 840, -56 */ + {0x0DEA810B, 0x803A035B}, /* -267, 3562, 859, -58 */ + {0x0DDA810C, 0x803B036D}, /* -268, 3546, 877, -59 */ + {0x0DCA810C, 0x803D037F}, /* -268, 3530, 895, -61 */ + {0x0DB7810B, 0x803E0392}, /* -267, 3511, 914, -62 */ + {0x0DA7810C, 0x804003A5}, /* -268, 3495, 933, -64 */ + {0x0D95810C, 0x804103B8}, /* -268, 3477, 952, -65 */ + {0x0D85810C, 0x804303CA}, /* -268, 3461, 970, -67 */ + {0x0D73810C, 0x804403DD}, /* -268, 3443, 989, -68 */ + {0x0D61810C, 0x804603F1}, /* -268, 3425, 1009, -70 */ + {0x0D50810C, 0x80480404}, /* -268, 3408, 1028, -72 */ + {0x0D3E810C, 0x80490417}, /* -268, 3390, 1047, -73 */ + {0x0D2C810C, 0x804B042B}, /* -268, 3372, 1067, -75 */ + {0x0D1B810C, 0x804D043E}, /* -268, 3355, 1086, -77 */ + {0x0D07810B, 0x804E0452}, /* -267, 3335, 1106, -78 */ + {0x0CF5810B, 0x80500466}, /* -267, 3317, 1126, -80 */ + {0x0CE2810A, 0x8052047A}, /* -266, 3298, 1146, -82 */ + {0x0CCF810A, 0x8053048E}, /* -266, 3279, 1166, -83 */ + {0x0CBC8109, 0x805504A2}, /* -265, 3260, 1186, -85 */ + {0x0CA98108, 0x805704B6}, /* -264, 3241, 1206, -87 */ + {0x0C968108, 0x805904CB}, /* -264, 3222, 1227, -89 */ + {0x0C838107, 0x805B04DF}, /* -263, 3203, 1247, -91 */ + {0x0C6F8106, 0x805C04F3}, /* -262, 3183, 1267, -92 */ + {0x0C5B8105, 0x805E0508}, /* -261, 3163, 1288, -94 */ + {0x0C478104, 0x8060051D}, /* -260, 3143, 1309, -96 */ + {0x0C348103, 0x80620531}, /* -259, 3124, 1329, -98 */ + {0x0C1F8102, 0x80640547}, /* -258, 3103, 1351, -100 */ + {0x0C0C8101, 0x8066055B}, /* -257, 3084, 1371, -102 */ + {0x0BF88100, 0x80680570}, /* -256, 3064, 1392, -104 */ + {0x0BE380FE, 0x806A0585}, /* -254, 3043, 1413, -106 */ + {0x0BCF80FD, 0x806C059A}, /* -253, 3023, 1434, -108 */ + {0x0BBA80FC, 0x806E05B0}, /* -252, 3002, 1456, -110 */ + {0x0BA480F9, 0x807005C5}, /* -249, 2980, 1477, -112 */ + {0x0B8F80F8, 0x807205DB}, /* -248, 2959, 1499, -114 */ + {0x0B7A80F6, 0x807405F0}, /* -246, 2938, 1520, -116 */ + {0x0B6580F5, 0x80760606}, /* -245, 2917, 1542, -118 */ + {0x0B4F80F3, 0x8077061B}, /* -243, 2895, 1563, -119 */ + {0x0B3A80F2, 0x80790631}, /* -242, 2874, 1585, -121 */ + {0x0B2480F0, 0x807B0647}, /* -240, 2852, 1607, -123 */ + {0x0B0F80EE, 0x807D065C}, /* -238, 2831, 1628, -125 */ + {0x0AF980ED, 0x807F0673}, /* -237, 2809, 1651, -127 */ + {0x0AE480EB, 0x80810688}, /* -235, 2788, 1672, -129 */ + {0x0ACE80E9, 0x8084069F}, /* -233, 2766, 1695, -132 */ + {0x0AB980E7, 0x808606B4}, /* -231, 2745, 1716, -134 */ + {0x0AA380E6, 0x808806CB}, /* -230, 2723, 1739, -136 */ + {0x0A8D80E4, 0x808A06E1}, /* -228, 2701, 1761, -138 */ + {0x0A7780E2, 0x808C06F7}, /* -226, 2679, 1783, -140 */ + {0x0A6180E0, 0x808E070D}, /* -224, 2657, 1805, -142 */ + {0x0A4B80DE, 0x80910724}, /* -222, 2635, 1828, -145 */ + {0x0A3580DC, 0x8093073A}, /* -220, 2613, 1850, -147 */ + {0x0A1F80DA, 0x80950750}, /* -218, 2591, 1872, -149 */ + {0x0A0880D8, 0x80970767}, /* -216, 2568, 1895, -151 */ + {0x09F280D6, 0x8099077D}, /* -214, 2546, 1917, -153 */ + {0x09DD80D4, 0x809C0793}, /* -212, 2525, 1939, -156 */ + {0x09C680D2, 0x809E07AA}, /* -210, 2502, 1962, -158 */ + {0x09B080D0, 0x80A007C0}, /* -208, 2480, 1984, -160 */ + {0x099980CE, 0x80A207D7}, /* -206, 2457, 2007, -162 */ + {0x098380CB, 0x80A507ED}, /* -203, 2435, 2029, -165 */ + {0x096C80C9, 0x80A70804}, /* -201, 2412, 2052, -167 */ + {0x095680C7, 0x80A9081A}, /* -199, 2390, 2074, -169 */ + {0x094080C5, 0x80AB0830}, /* -197, 2368, 2096, -171 */ + {0x092980C3, 0x80AE0848}, /* -195, 2345, 2120, -174 */ + {0x091380C1, 0x80B0085E}, /* -193, 2323, 2142, -176 */ + {0x08FC80BE, 0x80B20874}, /* -190, 2300, 2164, -178 */ + {0x08E580BC, 0x80B4088B}, /* -188, 2277, 2187, -180 */ + {0x08D080BB, 0x80B708A2}, /* -187, 2256, 2210, -183 */ + {0x08B980B9, 0x80B908B9}, /* -185, 2233, 2233, -185 */ + {0x08A380B7, 0x80BB08CF}, /* -183, 2211, 2255, -187 */ + {0x088B80B4, 0x80BC08E5}, /* -180, 2187, 2277, -188 */ + {0x087480B2, 0x80BE08FC}, /* -178, 2164, 2300, -190 */ + {0x085E80B0, 0x80C10913}, /* -176, 2142, 2323, -193 */ + {0x084880AE, 0x80C30929}, /* -174, 2120, 2345, -195 */ + {0x083080AB, 0x80C50940}, /* -171, 2096, 2368, -197 */ + {0x081A80A9, 0x80C70956}, /* -169, 2074, 2390, -199 */ + {0x080480A7, 0x80C9096C}, /* -167, 2052, 2412, -201 */ + {0x07ED80A5, 0x80CB0983}, /* -165, 2029, 2435, -203 */ + {0x07D780A2, 0x80CE0999}, /* -162, 2007, 2457, -206 */ + {0x07C080A0, 0x80D009B0}, /* -160, 1984, 2480, -208 */ + {0x07AA809E, 0x80D209C6}, /* -158, 1962, 2502, -210 */ + {0x0793809C, 0x80D409DD}, /* -156, 1939, 2525, -212 */ + {0x077D8099, 0x80D609F2}, /* -153, 1917, 2546, -214 */ + {0x07668097, 0x80D80A09}, /* -151, 1894, 2569, -216 */ + {0x074F8095, 0x80DA0A20}, /* -149, 1871, 2592, -218 */ + {0x073A8093, 0x80DC0A35}, /* -147, 1850, 2613, -220 */ + {0x07238091, 0x80DE0A4C}, /* -145, 1827, 2636, -222 */ + {0x070C808E, 0x80E00A62}, /* -142, 1804, 2658, -224 */ + {0x06F7808C, 0x80E20A77}, /* -140, 1783, 2679, -226 */ + {0x06E0808A, 0x80E40A8E}, /* -138, 1760, 2702, -228 */ + {0x06CA8088, 0x80E60AA4}, /* -136, 1738, 2724, -230 */ + {0x06B48086, 0x80E70AB9}, /* -134, 1716, 2745, -231 */ + {0x069E8084, 0x80E90ACF}, /* -132, 1694, 2767, -233 */ + {0x06878081, 0x80EB0AE5}, /* -129, 1671, 2789, -235 */ + {0x0672807F, 0x80ED0AFA}, /* -127, 1650, 2810, -237 */ + {0x065C807D, 0x80EE0B0F}, /* -125, 1628, 2831, -238 */ + {0x0646807B, 0x80F00B25}, /* -123, 1606, 2853, -240 */ + {0x06308079, 0x80F20B3B}, /* -121, 1584, 2875, -242 */ + {0x061A8077, 0x80F30B50}, /* -119, 1562, 2896, -243 */ + {0x06068076, 0x80F50B65}, /* -118, 1542, 2917, -245 */ + {0x05F08074, 0x80F60B7A}, /* -116, 1520, 2938, -246 */ + {0x05DB8072, 0x80F80B8F}, /* -114, 1499, 2959, -248 */ + {0x05C58070, 0x80F90BA4}, /* -112, 1477, 2980, -249 */ + {0x05B1806E, 0x80FC0BB9}, /* -110, 1457, 3001, -252 */ + {0x059B806C, 0x80FD0BCE}, /* -108, 1435, 3022, -253 */ + {0x0586806A, 0x80FE0BE2}, /* -106, 1414, 3042, -254 */ + {0x05718068, 0x81000BF7}, /* -104, 1393, 3063, -256 */ + {0x055C8066, 0x81010C0B}, /* -102, 1372, 3083, -257 */ + {0x05478064, 0x81020C1F}, /* -100, 1351, 3103, -258 */ + {0x05328062, 0x81030C33}, /* -98, 1330, 3123, -259 */ + {0x051D8060, 0x81040C47}, /* -96, 1309, 3143, -260 */ + {0x0508805E, 0x81050C5B}, /* -94, 1288, 3163, -261 */ + {0x04F3805C, 0x81060C6F}, /* -92, 1267, 3183, -262 */ + {0x04E0805B, 0x81070C82}, /* -91, 1248, 3202, -263 */ + {0x04CB8059, 0x81080C96}, /* -89, 1227, 3222, -264 */ + {0x04B68057, 0x81080CA9}, /* -87, 1206, 3241, -264 */ + {0x04A28055, 0x81090CBC}, /* -85, 1186, 3260, -265 */ + {0x048E8053, 0x810A0CCF}, /* -83, 1166, 3279, -266 */ + {0x047A8052, 0x810A0CE2}, /* -82, 1146, 3298, -266 */ + {0x04668050, 0x810B0CF5}, /* -80, 1126, 3317, -267 */ + {0x0451804E, 0x810B0D08}, /* -78, 1105, 3336, -267 */ + {0x043E804D, 0x810C0D1B}, /* -77, 1086, 3355, -268 */ + {0x042B804B, 0x810C0D2C}, /* -75, 1067, 3372, -268 */ + {0x04178049, 0x810C0D3E}, /* -73, 1047, 3390, -268 */ + {0x04038048, 0x810C0D51}, /* -72, 1027, 3409, -268 */ + {0x03F08046, 0x810C0D62}, /* -70, 1008, 3426, -268 */ + {0x03DD8044, 0x810C0D73}, /* -68, 989, 3443, -268 */ + {0x03CA8043, 0x810C0D85}, /* -67, 970, 3461, -268 */ + {0x03B78041, 0x810C0D96}, /* -65, 951, 3478, -268 */ + {0x03A48040, 0x810C0DA8}, /* -64, 932, 3496, -268 */ + {0x0391803E, 0x810B0DB8}, /* -62, 913, 3512, -267 */ + {0x0380803D, 0x810C0DC9}, /* -61, 896, 3529, -268 */ + {0x036D803B, 0x810C0DDA}, /* -59, 877, 3546, -268 */ + {0x035B803A, 0x810B0DEA}, /* -58, 859, 3562, -267 */ + {0x03488038, 0x810A0DFA}, /* -56, 840, 3578, -266 */ + {0x03368037, 0x810A0E0B}, /* -55, 822, 3595, -266 */ + {0x03248036, 0x81090E1B}, /* -54, 804, 3611, -265 */ + {0x03128034, 0x81080E2A}, /* -52, 786, 3626, -264 */ + {0x03018033, 0x81070E39}, /* -51, 769, 3641, -263 */ + {0x02EF8032, 0x81060E49}, /* -50, 751, 3657, -262 */ + {0x02DE8030, 0x81040E56}, /* -48, 734, 3670, -260 */ + {0x02CC802F, 0x81030E66}, /* -47, 716, 3686, -259 */ + {0x02BB802E, 0x81020E75}, /* -46, 699, 3701, -258 */ + {0x02AA802D, 0x81000E83}, /* -45, 682, 3715, -256 */ + {0x0299802B, 0x80FE0E90}, /* -43, 665, 3728, -254 */ + {0x0288802A, 0x80FD0E9F}, /* -42, 648, 3743, -253 */ + {0x02778029, 0x80FB0EAD}, /* -41, 631, 3757, -251 */ + {0x02678028, 0x80F90EBA}, /* -40, 615, 3770, -249 */ + {0x02568027, 0x80F70EC8}, /* -39, 598, 3784, -247 */ + {0x02468025, 0x80F50ED4}, /* -37, 582, 3796, -245 */ + {0x02368024, 0x80F30EE1}, /* -36, 566, 3809, -243 */ + {0x02268023, 0x80F00EED}, /* -35, 550, 3821, -240 */ + {0x02188023, 0x80EF0EFA}, /* -35, 536, 3834, -239 */ + {0x02078021, 0x80EB0F05}, /* -33, 519, 3845, -235 */ + {0x01F98021, 0x80E90F11}, /* -33, 505, 3857, -233 */ + {0x01EA8020, 0x80E60F1C}, /* -32, 490, 3868, -230 */ + {0x01DC801F, 0x80E40F27}, /* -31, 476, 3879, -228 */ + {0x01CD801E, 0x80E00F31}, /* -30, 461, 3889, -224 */ + {0x01BE801D, 0x80DD0F3C}, /* -29, 446, 3900, -221 */ + {0x01AF801C, 0x80DA0F47}, /* -28, 431, 3911, -218 */ + {0x01A1801B, 0x80D70F51}, /* -27, 417, 3921, -215 */ + {0x0192801A, 0x80D30F5B}, /* -26, 402, 3931, -211 */ + {0x01848019, 0x80CF0F64}, /* -25, 388, 3940, -207 */ + {0x01768018, 0x80CB0F6D}, /* -24, 374, 3949, -203 */ + {0x01688017, 0x80C80F77}, /* -23, 360, 3959, -200 */ + {0x015A8016, 0x80C30F7F}, /* -22, 346, 3967, -195 */ + {0x014D8015, 0x80BF0F87}, /* -21, 333, 3975, -191 */ + {0x013F8015, 0x80BB0F91}, /* -21, 319, 3985, -187 */ + {0x01328014, 0x80B60F98}, /* -20, 306, 3992, -182 */ + {0x01258013, 0x80B20FA0}, /* -19, 293, 4000, -178 */ + {0x01188012, 0x80AD0FA7}, /* -18, 280, 4007, -173 */ + {0x010B8011, 0x80A80FAE}, /* -17, 267, 4014, -168 */ + {0x00FE8010, 0x80A30FB5}, /* -16, 254, 4021, -163 */ + {0x00F28010, 0x809E0FBC}, /* -16, 242, 4028, -158 */ + {0x00E6800F, 0x80990FC2}, /* -15, 230, 4034, -153 */ + {0x00DA800E, 0x80930FC7}, /* -14, 218, 4039, -147 */ + {0x00CE800D, 0x808E0FCD}, /* -13, 206, 4045, -142 */ + {0x00C2800D, 0x80880FD3}, /* -13, 194, 4051, -136 */ + {0x00B6800C, 0x80820FD8}, /* -12, 182, 4056, -130 */ + {0x00AB800B, 0x807C0FDC}, /* -11, 171, 4060, -124 */ + {0x009F800A, 0x80760FE1}, /* -10, 159, 4065, -118 */ + {0x0094800A, 0x80700FE6}, /* -10, 148, 4070, -112 */ + {0x00898009, 0x80690FE9}, /* -9, 137, 4073, -105 */ + {0x007E8008, 0x80630FED}, /* -8, 126, 4077, -99 */ + {0x00748007, 0x805C0FEF}, /* -7, 116, 4079, -92 */ + {0x00698007, 0x80550FF3}, /* -7, 105, 4083, -85 */ + {0x005F8006, 0x804E0FF5}, /* -6, 95, 4085, -78 */ + {0x00558005, 0x80470FF7}, /* -5, 85, 4087, -71 */ + {0x004B8005, 0x80400FFA}, /* -5, 75, 4090, -64 */ + {0x00418004, 0x80380FFB}, /* -4, 65, 4091, -56 */ + {0x00378003, 0x80310FFD}, /* -3, 55, 4093, -49 */ + {0x002E8003, 0x80290FFE}, /* -3, 46, 4094, -41 */ + {0x00238002, 0x80211000}, /* -2, 35, 4096, -33 */ + {0x001A8001, 0x80191000}, /* -1, 26, 4096, -25 */ + {0x00118001, 0x80101000}, /* -1, 17, 4096, -16 */ + {0x00080000, 0x80081000}, /* 0, 8, 4096, -8 */ +}; + +/* CASTLE PLL TABLE */ + +typedef struct tagCASTLEPLL +{ + long frequency; /* 16.16 fixed point frequency */ + unsigned long pll_value; /* MCP DotPLL Register Upper 32(0x0015) */ +} CASTLEPLLENTRY; + +CASTLEPLLENTRY CASTLE_PLLtable[] = { + {0x00192CCC, 0x0000215D}, /* 25.1750 */ + {0x001C526E, 0x0000216C}, /* 28.3220 */ + {0x001C8F5C, 0x0000218D}, /* 28.5600 */ + {0x001F8000, 0x00003147}, /* 31.5000 */ + {0x00240000, 0x00000057}, /* 36.0000 */ + {0x0025E395, 0x0000219A}, /* 37.8890 */ + {0x00280000, 0x00000045}, /* 40.0000 */ + {0x002B29BA, 0x00000089}, /* 43.1630 */ + {0x002CE666, 0x000010E7}, /* 44.9000 */ + {0x002DB851, 0x00002136}, /* 45.7200 */ + {0x00318000, 0x00003207}, /* 49.5000 */ + {0x00320000, 0x00002187}, /* 50.0000 */ + {0x00384000, 0x00004286}, /* 56.2500 */ + {0x003C10A3, 0x000010E5}, /* 60.0650 */ + {0x00410000, 0x00004214}, /* 65.0000 */ + {0x00442DD2, 0x00001105}, /* 68.1790 */ + {0x004B0000, 0x00003183}, /* 75.0000 */ + {0x004EC000, 0x00004284}, /* 78.7500 */ + {0x00519999, 0x00001104}, /* 81.6000 */ + {0x005E8000, 0x00006363}, /* 94.5000 */ + {0x00618560, 0x00005303}, /* 97.5200 */ + {0x00630000, 0x00002523}, /* 99.0000 */ + {0x00640000, 0x000000D1}, /* 100.0000 */ + {0x00642FDF, 0x00002183}, /* 100.1870 */ + {0x00656B85, 0x00002122}, /* 101.4200 */ + {0x006C0000, 0x00001081}, /* 108.0000 */ + {0x00708000, 0x000013E3}, /* 112.5000 */ + {0x00714F1A, 0x00006201}, /* 113.3090 */ + {0x0077A666, 0x00000041}, /* 119.6500 */ + {0x00806666, 0x00000072}, /* 128.4000 */ + {0x00821999, 0x00006382}, /* 130.1000 */ + {0x00858000, 0x00002182}, /* 133.5000 */ + {0x00870000, 0x000041B1}, /* 135.0000 */ + {0x00906147, 0x00000051}, /* 144.3800 */ + {0x009D8000, 0x000062D1}, /* 157.5000 */ + {0x00A20000, 0x000031A1}, /* 162.0000 */ + {0x00A933F7, 0x00000061}, /* 169.2030 */ + {0x00AF8000, 0x00002151}, /* 175.5000 */ + {0x00BD0000, 0x000052E1}, /* 189.0000 */ + {0x00BEF5C2, 0x00000071}, /* 190.9600 */ + {0x00C60000, 0x00003201}, /* 198.0000 */ + {0x00CA8000, 0x00004291}, /* 202.5000 */ + {0x00E58000, 0x00004170}, /* 229.5000 */ +}; + +#define NUM_CASTLE_FREQUENCIES sizeof(CASTLE_PLLtable)/sizeof(CASTLEPLLENTRY) + +/*--------------------------------------------------------------------------- + * gfx_reset_video (PRIVATE ROUTINE: NOT PART OF DURANGO API) + * + * This routine is used to disable all components of video overlay before + * performing a mode switch. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +void +castle_reset_video(void) +#else +void +gfx_reset_video(void) +#endif +{ + gfx_set_video_enable(0); + gfx_select_alpha_region(1); + gfx_set_alpha_enable(0); + gfx_select_alpha_region(2); + gfx_set_alpha_enable(0); + + /* SET REGION 0 AFTER RESET */ + + gfx_select_alpha_region(0); + gfx_set_alpha_enable(0); +} + +/*---------------------------------------------------------------------------- + * gfx_set_display_control (PRIVATE ROUTINE: NOT PART OF DURANGO API) + * + * This routine configures the display output. + * + * "sync_polarities" is used to set the polarities of the sync pulses + * according to the following mask: + * + * Bit 0: If set to 1, negative horizontal polarity is programmed, + * otherwise positive horizontal polarity is programmed. + * Bit 1: If set to 1, negative vertical polarity is programmed, + * otherwise positive vertical polarity is programmed. + * + *---------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +castle_set_display_control(int sync_polarities) +#else +int +gfx_set_display_control(int sync_polarities) +#endif +{ + unsigned long power; + unsigned long dcfg; + + /* CONFIGURE DISPLAY OUTPUT FROM VIDEO PROCESSOR */ + + dcfg = READ_VID32(CASTLE_DISPLAY_CONFIG); + dcfg &= ~(CASTLE_DCFG_CRT_SYNC_SKW_MASK | CASTLE_DCFG_PWR_SEQ_DLY_MASK | + CASTLE_DCFG_CRT_HSYNC_POL | CASTLE_DCFG_CRT_VSYNC_POL); + + dcfg |= (CASTLE_DCFG_CRT_SYNC_SKW_INIT | + CASTLE_DCFG_PWR_SEQ_DLY_INIT | CASTLE_DCFG_GV_PAL_BYP); + + if (PanelEnable) { + power = READ_VID32(CASTLE_POWER_MANAGEMENT); + power |= CASTLE_PM_PANEL_POWER_ON; + WRITE_VID32(CASTLE_POWER_MANAGEMENT, power); + } + + /* SET APPROPRIATE SYNC POLARITIES */ + + if (sync_polarities & 0x1) + dcfg |= CASTLE_DCFG_CRT_HSYNC_POL; + if (sync_polarities & 0x2) + dcfg |= CASTLE_DCFG_CRT_VSYNC_POL; + + WRITE_VID32(CASTLE_DISPLAY_CONFIG, dcfg); + + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_set_clock_frequency + * + * This routine sets the clock frequency, specified as a 16.16 fixed point + * value (0x00318000 = 49.5 MHz). It will set the closest frequency found + * in the lookup table. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +void +castle_set_clock_frequency(unsigned long frequency) +#else +void +gfx_set_clock_frequency(unsigned long frequency) +#endif +{ + Q_WORD msr_value; + unsigned int i, index = 0; + unsigned long value; + unsigned long unlock; + long timeout; + long min, diff; + + /* FIND THE REGISTER VALUES FOR THE DESIRED FREQUENCY */ + /* Search the table for the closest frequency (16.16 format). */ + + value = CASTLE_PLLtable[0].pll_value; + min = (long)CASTLE_PLLtable[0].frequency - frequency; + if (min < 0L) + min = -min; + for (i = 1; i < NUM_CASTLE_FREQUENCIES; i++) { + diff = (long)CASTLE_PLLtable[i].frequency - frequency; + if (diff < 0L) + diff = -diff; + if (diff < min) { + min = diff; + index = i; + } + } + + /* VERIFY THAT WE ARE NOT WRITING WHAT IS ALREADY IN THE REGISTERS */ + /* The Dot PLL reset bit is tied to VDD for flat panels. This can */ + /* cause a brief drop in flat panel power, which can cause serious */ + /* glitches on some panels. */ + + gfx_msr_read(RC_ID_MCP, MCP_DOTPLL, &msr_value); + + if ((msr_value.low & MCP_DOTPLL_LOCK) && + ((msr_value.low & MCP_DOTPLL_HALFPIX) == 0) && + (msr_value.high == CASTLE_PLLtable[index].pll_value)) { + return; + } + + /* PROGRAM THE SETTINGS WITH THE RESET BIT SET */ + /* Clear the bypass bit to ensure that the programmed */ + /* M, N and P values are being used. */ + + msr_value.high = CASTLE_PLLtable[index].pll_value; + msr_value.low |= 0x00000001; + msr_value.low &= ~MCP_DOTPLL_BYPASS; + gfx_msr_write(RC_ID_MCP, MCP_DOTPLL, &msr_value); + + /* WAIT FOR THE LOCK BIT */ + /* The official word from LEDA is that the PLL may take up to 100 */ + /* us to lock and the lock bit is unreliable. We thus add a long */ + /* delay followed by a timed-out poll */ + + unlock = READ_REG32(DC3_UNLOCK); + for (timeout = 0; timeout < 1280; timeout++) + WRITE_REG32(DC3_UNLOCK, unlock); + + for (timeout = 0; timeout < 1000; timeout++) { + gfx_msr_read(RC_ID_MCP, MCP_DOTPLL, &msr_value); + if (msr_value.low & MCP_DOTPLL_LOCK) + break; + } + + /* CLEAR THE RESET BIT */ + + msr_value.low &= 0xFFFFFFFE; + gfx_msr_write(RC_ID_MCP, MCP_DOTPLL, &msr_value); +} + +/*--------------------------------------------------------------------------- + * gfx_set_crt_enable + * + * This routine enables or disables the CRT output from the video processor. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +castle_set_crt_enable(int enable) +#else +int +gfx_set_crt_enable(int enable) +#endif +{ + unsigned long config, misc; + + config = READ_VID32(CASTLE_DISPLAY_CONFIG); + misc = READ_VID32(CASTLE_VID_MISC); + + switch (enable) { + case CRT_DISABLE: /* DISABLE EVERYTHING */ + + WRITE_VID32(CASTLE_DISPLAY_CONFIG, + config & ~(CASTLE_DCFG_DIS_EN | CASTLE_DCFG_HSYNC_EN | + CASTLE_DCFG_VSYNC_EN | CASTLE_DCFG_DAC_BL_EN)); + WRITE_VID32(CASTLE_VID_MISC, misc | CASTLE_DAC_POWER_DOWN); + break; + + case CRT_ENABLE: /* ENABLE CRT DISPLAY, INCLUDING DISPLAY LOGIC */ + + WRITE_VID32(CASTLE_DISPLAY_CONFIG, + config | CASTLE_DCFG_DIS_EN | CASTLE_DCFG_HSYNC_EN | + CASTLE_DCFG_VSYNC_EN | CASTLE_DCFG_DAC_BL_EN); + WRITE_VID32(CASTLE_VID_MISC, + misc & ~CASTLE_DAC_POWER_DOWN & ~CASTLE_ANALOG_POWER_DOWN); + break; + + case CRT_STANDBY: /* HSYNC:OFF VSYNC:ON */ + + WRITE_VID32(CASTLE_DISPLAY_CONFIG, + (config & ~(CASTLE_DCFG_DIS_EN | CASTLE_DCFG_HSYNC_EN | + CASTLE_DCFG_DAC_BL_EN)) | CASTLE_DCFG_VSYNC_EN); + WRITE_VID32(CASTLE_VID_MISC, misc | CASTLE_DAC_POWER_DOWN); + break; + + case CRT_SUSPEND: /* HSYNC:ON VSYNC:OFF */ + + WRITE_VID32(CASTLE_DISPLAY_CONFIG, + (config & ~(CASTLE_DCFG_DIS_EN | CASTLE_DCFG_VSYNC_EN | + CASTLE_DCFG_DAC_BL_EN)) | CASTLE_DCFG_HSYNC_EN); + WRITE_VID32(CASTLE_VID_MISC, misc | CASTLE_DAC_POWER_DOWN); + break; + + default: + return (GFX_STATUS_BAD_PARAMETER); + } + return (GFX_STATUS_OK); +} + +/*---------------------------------------------------------------------------- + * gfx_set_video_enable + * + * This routine enables or disables the video overlay functionality. + *---------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +castle_set_video_enable(int enable) +#else +int +gfx_set_video_enable(int enable) +#endif +{ + unsigned long vcfg; + + /* WAIT FOR VERTICAL BLANK TO START */ + /* Otherwise a glitch can be observed. */ + + if (gfx_test_timing_active()) { + if (!gfx_test_vertical_active()) { + while (!gfx_test_vertical_active()) ; + } + while (gfx_test_vertical_active()) ; + } + + vcfg = READ_VID32(CASTLE_VIDEO_CONFIG); + if (enable) { + /* ENABLE VIDEO OVERLAY FROM DISPLAY CONTROLLER */ + /* Use private routine to abstract the display controller. */ + + gfx_set_display_video_enable(1); + + /* ENABLE DISPLAY FILTER VIDEO OVERLAY */ + + vcfg |= CASTLE_VCFG_VID_EN; + WRITE_VID32(CASTLE_VIDEO_CONFIG, vcfg); + } else { + /* DISABLE DISPLAY FILTER VIDEO OVERLAY */ + + vcfg &= ~CASTLE_VCFG_VID_EN; + WRITE_VID32(CASTLE_VIDEO_CONFIG, vcfg); + + /* DISABLE VIDEO OVERLAY FROM DISPLAY CONTROLLER */ + /* Use private routine to abstract the display controller. */ + + gfx_set_display_video_enable(0); + } + return (0); +} + +/*---------------------------------------------------------------------------- + * gfx_set_video_format + * + * Sets input video format type, to one of the YUV formats or to RGB. + *---------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +castle_set_video_format(unsigned long format) +#else +int +gfx_set_video_format(unsigned long format) +#endif +{ + unsigned long ctrl, vcfg = 0; + + /* SET THE DISPLAY FILTER VIDEO INPUT FORMAT */ + + vcfg = READ_VID32(CASTLE_VIDEO_CONFIG); + ctrl = READ_VID32(CASTLE_VID_ALPHA_CONTROL); + ctrl &= + ~(CASTLE_VIDEO_INPUT_IS_RGB | CASTLE_CSC_VIDEO_YUV_TO_RGB | + CASTLE_CSC_GRAPHICS_RGB_TO_YUV); + vcfg &= ~(CASTLE_VCFG_VID_INP_FORMAT | CASTLE_VCFG_4_2_0_MODE); + switch (format) { + case VIDEO_FORMAT_UYVY: + vcfg |= CASTLE_VCFG_UYVY_FORMAT; + ctrl |= CASTLE_CSC_VIDEO_YUV_TO_RGB; + break; + case VIDEO_FORMAT_YUYV: + vcfg |= CASTLE_VCFG_YUYV_FORMAT; + ctrl |= CASTLE_CSC_VIDEO_YUV_TO_RGB; + break; + case VIDEO_FORMAT_Y2YU: + vcfg |= CASTLE_VCFG_Y2YU_FORMAT; + ctrl |= CASTLE_CSC_VIDEO_YUV_TO_RGB; + break; + case VIDEO_FORMAT_YVYU: + vcfg |= CASTLE_VCFG_YVYU_FORMAT; + ctrl |= CASTLE_CSC_VIDEO_YUV_TO_RGB; + break; + case VIDEO_FORMAT_Y0Y1Y2Y3: + vcfg |= CASTLE_VCFG_UYVY_FORMAT; + ctrl |= CASTLE_CSC_VIDEO_YUV_TO_RGB; + vcfg |= CASTLE_VCFG_4_2_0_MODE; + break; + case VIDEO_FORMAT_Y3Y2Y1Y0: + vcfg |= CASTLE_VCFG_Y2YU_FORMAT; + ctrl |= CASTLE_CSC_VIDEO_YUV_TO_RGB; + vcfg |= CASTLE_VCFG_4_2_0_MODE; + break; + case VIDEO_FORMAT_Y1Y0Y3Y2: + vcfg |= CASTLE_VCFG_YUYV_FORMAT; + ctrl |= CASTLE_CSC_VIDEO_YUV_TO_RGB; + vcfg |= CASTLE_VCFG_4_2_0_MODE; + break; + case VIDEO_FORMAT_Y1Y2Y3Y0: + vcfg |= CASTLE_VCFG_YVYU_FORMAT; + ctrl |= CASTLE_CSC_VIDEO_YUV_TO_RGB; + vcfg |= CASTLE_VCFG_4_2_0_MODE; + break; + case VIDEO_FORMAT_RGB: + ctrl |= CASTLE_VIDEO_INPUT_IS_RGB; + vcfg |= CASTLE_VCFG_UYVY_FORMAT; + break; + case VIDEO_FORMAT_P2M_P2L_P1M_P1L: + ctrl |= CASTLE_VIDEO_INPUT_IS_RGB; + vcfg |= CASTLE_VCFG_Y2YU_FORMAT; + break; + case VIDEO_FORMAT_P1M_P1L_P2M_P2L: + ctrl |= CASTLE_VIDEO_INPUT_IS_RGB; + vcfg |= CASTLE_VCFG_YUYV_FORMAT; + break; + case VIDEO_FORMAT_P1M_P2L_P2M_P1L: + ctrl |= CASTLE_VIDEO_INPUT_IS_RGB; + vcfg |= CASTLE_VCFG_YVYU_FORMAT; + break; + default: + return GFX_STATUS_BAD_PARAMETER; + } + WRITE_VID32(CASTLE_VIDEO_CONFIG, vcfg); + WRITE_VID32(CASTLE_VID_ALPHA_CONTROL, ctrl); + + /* SET THE VIDEO FORMAT IN THE DISPLAY CONTROLLER */ + /* Use private routine to abstract display controller. */ + + gfx_set_display_video_format(format); + return (0); +} + +/*---------------------------------------------------------------------------- + * gfx_set_video_size + * + * This routine specifies the size of the source data. It is used only + * to determine how much data to transfer per frame, and is not used to + * calculate the scaling value (that is handled by a separate routine). + *---------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +castle_set_video_size(unsigned short width, unsigned short height) +#else +int +gfx_set_video_size(unsigned short width, unsigned short height) +#endif +{ + unsigned long size, vcfg, vid_420, pitch, scale; + + /* SET THE DISPLAY FILTER VIDEO LINE SIZE */ + /* Match the DC hardware alignment requirement. The line size must */ + /* always be 32-byte aligned. However, we can manage smaller */ + /* alignments by decreasing the pitch and clipping the video window. */ + /* The VG will fetch extra data for each line, but the decreased */ + /* pitch will ensure that it always begins fetching at the start of */ + /* the video line. */ + + vcfg = READ_VID32(CASTLE_VIDEO_CONFIG); + + vid_420 = vcfg & CASTLE_VCFG_4_2_0_MODE; + + vcfg &= + ~(CASTLE_VCFG_LINE_SIZE_LOWER_MASK | CASTLE_VCFG_LINE_SIZE_UPPER | + CASTLE_VCFG_LINE_SIZE_BIT9); + + size = ((width >> 1) + 7) & 0xFFF8; + pitch = ((width << 1) + 7) & 0xFFF8; + + vcfg |= (size & 0x00FF) << 8; + if (size & 0x0100) + vcfg |= CASTLE_VCFG_LINE_SIZE_UPPER; + if (size & 0x0200) + vcfg |= CASTLE_VCFG_LINE_SIZE_BIT9; + WRITE_VID32(CASTLE_VIDEO_CONFIG, vcfg); + + /* WRITE THE VIDEO HEIGHT */ + + scale = READ_VID32(CASTLE_VIDEO_SCALER); + scale = (scale & ~0x7FF) | height; + WRITE_VID32(CASTLE_VIDEO_SCALER, scale); + + /* SET VIDEO BUFFER LINE SIZE IN DISPLAY CONTROLLER */ + /* Use private routine to abstract the display controller. */ + + gfx_set_display_video_size(width, height); + + /* SET VIDEO PITCH */ + /* We are only maintaining legacy for 4:2:2 video formats. */ + /* 4:2:0 video in previous chips was inadequate for most */ + /* common video formats. */ + + if (!vid_420) + gfx_set_video_yuv_pitch(pitch, pitch << 1); + + return (0); +} + +/*---------------------------------------------------------------------------- + * gfx_set_video_offset + * + * This routine sets the starting offset for the video buffer when only + * one offset needs to be specified. + *---------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +castle_set_video_offset(unsigned long offset) +#else +int +gfx_set_video_offset(unsigned long offset) +#endif +{ + /* SAVE VALUE FOR FUTURE CLIPPING OF THE TOP OF THE VIDEO WINDOW */ + + gfx_vid_offset = offset; + + /* SET VIDEO BUFFER OFFSET IN DISPLAY CONTROLLER */ + /* Use private routine to abstract the display controller. */ + + gfx_set_display_video_offset(offset); + return (0); +} + +/*---------------------------------------------------------------------------- + * gfx_set_video_yuv_offsets + * + * This routine sets the starting offset for the video buffer when displaying + * 4:2:0 video. + *---------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +castle_set_video_yuv_offsets(unsigned long yoffset, unsigned long uoffset, + unsigned long voffset) +#else +int +gfx_set_video_yuv_offsets(unsigned long yoffset, unsigned long uoffset, + unsigned long voffset) +#endif +{ + /* SAVE VALUE FOR FUTURE CLIPPING OF THE TOP OF THE VIDEO WINDOW */ + + gfx_vid_offset = yoffset; + gfx_vid_uoffset = uoffset; + gfx_vid_voffset = voffset; + + /* SET VIDEO BUFFER OFFSET IN DISPLAY CONTROLLER */ + /* Use private routine to abstract the display controller. */ + + gfx_set_display_video_yuv_offsets(yoffset, uoffset, voffset); + + return (0); +} + +/*---------------------------------------------------------------------------- + * gfx_set_video_yuv_pitch + * + * This routine sets the byte offset between consecutive scanlines of YUV video data + *---------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +castle_set_video_yuv_pitch(unsigned long ypitch, unsigned long uvpitch) +#else +int +gfx_set_video_yuv_pitch(unsigned long ypitch, unsigned long uvpitch) +#endif +{ + /* SET VIDEO PITCH IN DISPLAY CONTROLLER */ + /* Use private routine to abstract the display controller. */ + + gfx_set_display_video_yuv_pitch(ypitch, uvpitch); + + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_set_video_scale + * + * This routine sets the scale factor for the video overlay window. The + * size of the source and destination regions are specified in pixels. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +castle_set_video_scale(unsigned short srcw, unsigned short srch, + unsigned short dstw, unsigned short dsth) +#else +int +gfx_set_video_scale(unsigned short srcw, unsigned short srch, + unsigned short dstw, unsigned short dsth) +#endif +{ + unsigned long xscale, yscale, i; + unsigned long scale; + unsigned long temp; + + /* SAVE PARAMETERS */ + /* These are needed for clipping the video window later. Zero */ + /* values indicate that the corresponding scale value should */ + /* not be changed. */ + + if (dstw != 0) { + gfx_vid_srcw = srcw; + gfx_vid_dstw = dstw; + } + if (dsth != 0) { + gfx_vid_srch = srch; + gfx_vid_dsth = dsth; + } + + /* CALCULATE DISPLAY FILTER SCALE FACTORS */ + /* Zero width and height indicate don't care conditions */ + + if (dstw != 0) { + if (dstw <= srcw) + xscale = 0x10000; + else + xscale = (0x10000 * (unsigned long)srcw) / (unsigned long)dstw; + + WRITE_VID32(CASTLE_VIDEO_XSCALE, xscale); + } + if (dsth != 0) { + if (dsth <= srch) + yscale = 0x10000; + else + yscale = (0x10000 * (unsigned long)srch) / (unsigned long)dsth; + + WRITE_VID32(CASTLE_VIDEO_YSCALE, yscale); + } + + /* ENABLE OR DISABLE FILTERING */ + + temp = READ_VID32(CASTLE_VIDEO_CONFIG); + if (READ_VID32(CASTLE_VIDEO_XSCALE) == 0x10000 && + READ_VID32(CASTLE_VIDEO_YSCALE) == 0x10000) { + WRITE_VID32(CASTLE_VIDEO_CONFIG, (temp | CASTLE_VCFG_SC_BYP)); + } else { + scale = READ_VID32(CASTLE_VIDEO_SCALER); + + WRITE_VID32(CASTLE_VIDEO_SCALER, scale & ~CASTLE_SCALE_128_PHASES); + WRITE_VID32(CASTLE_VIDEO_CONFIG, (temp & ~CASTLE_VCFG_SC_BYP)); + + /* PROGRAM THE COEFFICIENTS */ + + for (i = 0; i < 256; i++) { + WRITE_VID32((CASTLE_COEFFICIENT_BASE + (i << 3)), + DurangoVideoFilter[i][0]); + WRITE_VID32((CASTLE_COEFFICIENT_BASE + (i << 3) + 4), + DurangoVideoFilter[i][1]); + } + } + /* CALL ROUTINE TO UPDATE WINDOW POSITION */ + /* This is required because the scale values affect the number of */ + /* source data pixels that need to be clipped, as well as the */ + /* amount of data that needs to be transferred. */ + + gfx_set_video_window(gfx_vid_xpos, gfx_vid_ypos, gfx_vid_width, + gfx_vid_height); + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_set_video_window + * + * This routine sets the position and size of the video overlay window. The + * x and y positions are specified in screen relative coordinates, and may be + * negative. + * The size of destination region is specified in pixels. The line size + * indicates the number of bytes of source data per scanline. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +castle_set_video_window(short x, short y, unsigned short w, unsigned short h) +#else +int +gfx_set_video_window(short x, short y, unsigned short w, unsigned short h) +#endif +{ + unsigned long hadjust, vadjust; + unsigned long xstart, ystart, xend, yend; + unsigned long lock; + + lock = READ_REG32(DC3_UNLOCK); + + /* SAVE PARAMETERS */ + /* These are needed to call this routine if the scale value changes. */ + + gfx_vid_xpos = x; + gfx_vid_ypos = y; + gfx_vid_width = w; + gfx_vid_height = h; + + /* GET ADJUSTMENT VALUES */ + /* Use routines to abstract version of display controller. */ + + hadjust = gfx_get_htotal() - gfx_get_hsync_end() - 14l; + vadjust = gfx_get_vtotal() - gfx_get_vsync_end() + 1l; + + /* LEFT CLIPPING */ + + if (x < 0) { + gfx_set_video_left_crop((unsigned short)(-x)); + xstart = hadjust; + } else { + gfx_set_video_left_crop(0); + xstart = (unsigned long)x + hadjust; + } + + /* HORIZONTAL END */ + /* End positions in register are non-inclusive (one more than the actual + * end) */ + + if ((x + w) < gfx_get_hactive()) + xend = (unsigned long)x + (unsigned long)w + hadjust; + + /* RIGHT-CLIPPING */ + else + xend = (unsigned long)gfx_get_hactive() + hadjust; + + /* VERTICAL START */ + + ystart = (unsigned long)y + vadjust; + + /* VERTICAL END */ + + if ((y + h) < gfx_get_vactive()) + yend = (unsigned long)y + (unsigned long)h + vadjust; + + /* BOTTOM-CLIPPING */ + else + yend = (unsigned long)gfx_get_vactive() + vadjust; + + /* SET VIDEO POSITION */ + + WRITE_VID32(CASTLE_VIDEO_X_POS, (xend << 16) | xstart); + WRITE_VID32(CASTLE_VIDEO_Y_POS, (yend << 16) | ystart); + + /* SET COLOR KEY REGION */ + + WRITE_REG32(DC3_UNLOCK, DC3_UNLOCK_VALUE); + WRITE_REG32(DC3_COLOR_KEY_X, + ((xend - hadjust) << 16) | (xstart - hadjust)); + WRITE_REG32(DC3_COLOR_KEY_Y, + ((yend - vadjust) << 16) | (ystart - vadjust)); + WRITE_REG32(DC3_UNLOCK, lock); + + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_set_video_left_crop + * + * This routine sets the number of pixels which will be cropped from the + * beginning of each video line. The video window will begin to display only + * from the pixel following the cropped pixels, and the cropped pixels + * will be ignored. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +castle_set_video_left_crop(unsigned short x) +#else +int +gfx_set_video_left_crop(unsigned short x) +#endif +{ + unsigned long vcfg, initread; + + vcfg = READ_VID32(CASTLE_VIDEO_CONFIG) & ~CASTLE_VCFG_INIT_READ_MASK; + + /* CLIPPING ON LEFT */ + /* Adjust initial read for scale, checking for divide by zero. All video */ + /* formats must be clipped on a 4-pixel boundary */ + + if (gfx_vid_dstw) { + initread = (unsigned long)x *gfx_vid_srcw / gfx_vid_dstw; + } else + initread = 0; + + /* SET INITIAL READ ADDRESS */ + + vcfg = vcfg | ((initread << 14) & CASTLE_VCFG_INIT_READ_MASK); + WRITE_VID32(CASTLE_VIDEO_CONFIG, vcfg); + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_set_video_color_key + * + * This routine specifies the color key value and mask for the video overlay + * hardware. To disable color key, the color and mask should both be set to + * zero. The hardware uses the color key in the following equation: + * + * ((source data) & (color key mask)) == ((color key) & (color key mask)) + * + * If "graphics" is set to TRUE, the source data is graphics, and color key + * is an RGB value. If "graphics" is set to FALSE, the source data is video, + * and the color key is an RGB value that is compared to the video data after + * it has gone through color space conversion (CSC). + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +castle_set_video_color_key(unsigned long key, unsigned long mask, + int graphics) +#else +int +gfx_set_video_color_key(unsigned long key, unsigned long mask, int graphics) +#endif +{ + unsigned long dcfg; + + /* ENABLE OR DISABLE COLOR KEY LOGIC IN THE DISPLAY CONTROLLER */ + /* When chroma key is enabled, the color key logic should be */ + /* disabled in the VG to allow for per-pixel alpha blending. */ + + gfx_set_display_video_color_key(key, mask, graphics); + + dcfg = READ_VID32(CASTLE_DISPLAY_CONFIG); + + if (graphics) + dcfg &= ~CASTLE_DCFG_VG_CK; + else + dcfg |= CASTLE_DCFG_VG_CK; + + WRITE_VID32(CASTLE_DISPLAY_CONFIG, dcfg); + WRITE_VID32(CASTLE_VIDEO_COLOR_KEY, key & 0xFFFFFF); + WRITE_VID32(CASTLE_VIDEO_COLOR_MASK, mask & 0xFFFFFF); + + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_set_video_palette + * + * This routine loads the video hardware palette. If a NULL pointer is + * specified, the palette is bypassed (for Castle, this means loading the + * palette with identity values). + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +castle_set_video_palette(unsigned long *palette) +#else +int +gfx_set_video_palette(unsigned long *palette) +#endif +{ + unsigned long i, entry; + + /* LOAD CASTLE VIDEO PALETTE */ + + WRITE_VID32(CASTLE_PALETTE_ADDRESS, 0); + for (i = 0; i < 256; i++) { + if (palette) + entry = palette[i]; + else + entry = i | (i << 8) | (i << 16); + WRITE_VID32(CASTLE_PALETTE_DATA, entry); + } + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_set_video_palette_entry + * + * This routine loads a single entry of the video hardware palette. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +castle_set_video_palette_entry(unsigned long index, unsigned long palette) +#else +int +gfx_set_video_palette_entry(unsigned long index, unsigned long palette) +#endif +{ + if (index > 0xFF) + return GFX_STATUS_BAD_PARAMETER; + + /* SET A SINGLE ENTRY */ + + WRITE_VID32(CASTLE_PALETTE_ADDRESS, index); + WRITE_VID32(CASTLE_PALETTE_DATA, palette); + + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_set_video_request() + * + * This routine sets the horizontal (pixel) and vertical (line) video request + * values. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +castle_set_video_request(short x, short y) +#else +int +gfx_set_video_request(short x, short y) +#endif +{ + /* SET DISPLAY FILTER VIDEO REQUEST */ + + x += gfx_get_htotal() - gfx_get_hsync_end() - 2; + y += gfx_get_vtotal() - gfx_get_vsync_end() + 1; + + if ((x < 0) || (x > CASTLE_VIDEO_REQUEST_MASK) || + (y < 0) || (y > CASTLE_VIDEO_REQUEST_MASK)) + return GFX_STATUS_BAD_PARAMETER; + + WRITE_VID32(CASTLE_VIDEO_REQUEST, + ((unsigned long)x << CASTLE_VIDEO_X_REQUEST_POS) | ((unsigned long)y + << CASTLE_VIDEO_Y_REQUEST_POS)); + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_set_video_cursor() + * + * This routine configures the video hardware cursor. + * If the "mask"ed bits in the graphics pixel match "key", then either + * "color1"or "color2" will be used for this pixel, according to the value of + * bit number "select_color2" of the graphics pixel. + * + * key - 24 bit RGB value + * mask - 24 bit mask + * color1, color2 - RGB or YUV, depending on the current color space + * conversion select_color2 - value between 0 to 23 + * + * To disable match, a "mask" and "key" value of 0xffffff should be set, + * because the graphics pixels incoming to the video processor have maximum 16 + * bits set (0xF8FCF8). + * + * This feature is useful for disabling alpha blending of the cursor. + * Otherwise cursor image would be blurred (or completely invisible if video + * alpha is maximum value). + * Note: the cursor pixel replacements take place both inside and outside the + * video overlay window. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +castle_set_video_cursor(unsigned long key, unsigned long mask, + unsigned short select_color2, unsigned long color1, unsigned long color2) +#else +int +gfx_set_video_cursor(unsigned long key, unsigned long mask, + unsigned short select_color2, unsigned long color1, unsigned long color2) +#endif +{ + if (select_color2 > CASTLE_CURSOR_COLOR_BITS) + return GFX_STATUS_BAD_PARAMETER; + key = + (key & CASTLE_COLOR_MASK) | ((unsigned long)select_color2 << + CASTLE_CURSOR_COLOR_KEY_OFFSET_POS); + WRITE_VID32(CASTLE_CURSOR_COLOR_KEY, key); + WRITE_VID32(CASTLE_CURSOR_COLOR_MASK, mask); + WRITE_VID32(CASTLE_CURSOR_COLOR_1, color1); + WRITE_VID32(CASTLE_CURSOR_COLOR_2, color2); + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_set_video_cursor_enable() + * + * This routine enables or disables the cursor color key mechanism. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +castle_set_video_cursor_enable(int enable) +#else +int +gfx_set_video_cursor_enable(int enable) +#endif +{ + unsigned long temp = READ_VID32(CASTLE_CURSOR_COLOR_KEY); + + if (enable) + temp |= CASTLE_CURSOR_COLOR_KEY_ENABLE; + else + temp &= ~CASTLE_CURSOR_COLOR_KEY_ENABLE; + + WRITE_VID32(CASTLE_CURSOR_COLOR_KEY, temp); + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_set_alpha_enable + * + * This routine enables or disables the currently selected alpha region. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +castle_set_alpha_enable(int enable) +#else +int +gfx_set_alpha_enable(int enable) +#endif +{ + unsigned long address = 0, value = 0; + + if (gfx_alpha_select > 2) + return (GFX_STATUS_UNSUPPORTED); + address = CASTLE_ALPHA_CONTROL_1 + ((unsigned long)gfx_alpha_select << 5); + value = READ_VID32(address); + if (enable) + value |= CASTLE_ACTRL_WIN_ENABLE; + else + value &= ~(CASTLE_ACTRL_WIN_ENABLE); + WRITE_VID32(address, value); + return (GFX_STATUS_OK); +} + +/*--------------------------------------------------------------------------- + * gfx_set_alpha_window + * + * This routine sets the size of the currently selected alpha region. + * Note: "x" and "y" are signed to enable using negative values needed for + * implementing workarounds of hardware issues. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +castle_set_alpha_window(short x, short y, + unsigned short width, unsigned short height) +#else +int +gfx_set_alpha_window(short x, short y, + unsigned short width, unsigned short height) +#endif +{ + unsigned long address = 0; + + /* CHECK FOR CLIPPING */ + + if ((x + width) > gfx_get_hactive()) + width = gfx_get_hactive() - x; + if ((y + height) > gfx_get_vactive()) + height = gfx_get_vactive() - y; + + /* ADJUST POSITIONS */ + + x += gfx_get_htotal() - gfx_get_hsync_end() - 2; + y += gfx_get_vtotal() - gfx_get_vsync_end() + 1; + + if (gfx_alpha_select > 2) + return (GFX_STATUS_UNSUPPORTED); + address = CASTLE_ALPHA_XPOS_1 + ((unsigned long)gfx_alpha_select << 5); + + /* END POSITIONS IN REGISTERS ARE NON-INCLUSIVE (ONE MORE THAN ACTUAL END) + * */ + + WRITE_VID32(address, (unsigned long)x | + ((unsigned long)(x + width) << 16)); + WRITE_VID32(address + 8, (unsigned long)y | + ((unsigned long)(y + height) << 16)); + return (GFX_STATUS_OK); +} + +/*--------------------------------------------------------------------------- + * gfx_set_alpha_value + * + * This routine sets the alpha value for the currently selected alpha + * region. It also specifies an increment/decrement value for fading. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +castle_set_alpha_value(unsigned char alpha, char delta) +#else +int +gfx_set_alpha_value(unsigned char alpha, char delta) +#endif +{ + unsigned long address = 0, value = 0; + + if (gfx_alpha_select > 2) + return (GFX_STATUS_UNSUPPORTED); + address = CASTLE_ALPHA_CONTROL_1 + ((unsigned long)gfx_alpha_select << 5); + value = READ_VID32(address); + value &= CASTLE_ACTRL_WIN_ENABLE; /* keep only enable bit */ + value |= (unsigned long)alpha; + value |= (((unsigned long)delta) & 0xff) << 8; + value |= CASTLE_ACTRL_LOAD_ALPHA; + WRITE_VID32(address, value); + return (GFX_STATUS_OK); +} + +/*--------------------------------------------------------------------------- + * gfx_set_alpha_priority + * + * This routine sets the priority of the currently selected alpha region. + * A higher value indicates a higher priority. + * Note: Priority of enabled alpha windows must be different. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +castle_set_alpha_priority(int priority) +#else +int +gfx_set_alpha_priority(int priority) +#endif +{ + unsigned long pos = 0, value = 0; + + if (priority > 3) + return (GFX_STATUS_BAD_PARAMETER); + if (gfx_alpha_select > 2) + return (GFX_STATUS_UNSUPPORTED); + value = READ_VID32(CASTLE_VID_ALPHA_CONTROL); + pos = 16 + (gfx_alpha_select << 1); + value &= ~(0x03l << pos); + value |= (unsigned long)priority << pos; + WRITE_VID32(CASTLE_VID_ALPHA_CONTROL, value); + return (GFX_STATUS_OK); +} + +/*--------------------------------------------------------------------------- + * gfx_set_alpha_color + * + * This routine sets the color to be displayed inside the currently selected + * alpha window when there is a color key match (when the alpha color + * mechanism is enabled). + * "color" is an RGB value (for RGB blending) or a YUV value (for YUV + * blending). + * In Interlaced YUV blending mode, Y/2 value should be used. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +castle_set_alpha_color(unsigned long color) +#else +int +gfx_set_alpha_color(unsigned long color) +#endif +{ + unsigned long address = 0; + + if (gfx_alpha_select > 2) + return (GFX_STATUS_UNSUPPORTED); + address = CASTLE_ALPHA_COLOR_1 + ((unsigned long)gfx_alpha_select << 5); + WRITE_VID32(address, color); + return (GFX_STATUS_OK); +} + +/*--------------------------------------------------------------------------- + * gfx_set_alpha_color_enable + * + * Enable or disable the color mechanism in the alpha window. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +castle_set_alpha_color_enable(int enable) +#else +int +gfx_set_alpha_color_enable(int enable) +#endif +{ + unsigned long color; + unsigned long address = 0; + + if (gfx_alpha_select > 2) + return (GFX_STATUS_UNSUPPORTED); + address = CASTLE_ALPHA_COLOR_1 + ((unsigned long)gfx_alpha_select << 5); + color = READ_VID32(address); + if (enable) + color |= CASTLE_ALPHA_COLOR_ENABLE; + else + color &= ~CASTLE_ALPHA_COLOR_ENABLE; + WRITE_VID32(address, color); + return (GFX_STATUS_OK); +} + +/*--------------------------------------------------------------------------- + * gfx_set_no_ck_outside_alpha + * + * This function affects where inside the video window color key or chroma + * key comparison is done: + * If enable is TRUE, color/chroma key comparison is performed only inside + * the enabled alpha windows. Outside the (enabled) alpha windows, only video + * is displayed if color key is used, and only graphics is displayed if chroma + * key is used. + * If enable is FALSE, color/chroma key comparison is performed in all the + * video window area. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +castle_set_no_ck_outside_alpha(int enable) +#else +int +gfx_set_no_ck_outside_alpha(int enable) +#endif +{ + unsigned long value; + + value = READ_VID32(CASTLE_VID_ALPHA_CONTROL); + if (enable) + WRITE_VID32(CASTLE_VID_ALPHA_CONTROL, + value | CASTLE_NO_CK_OUTSIDE_ALPHA); + else + WRITE_VID32(CASTLE_VID_ALPHA_CONTROL, + value & ~CASTLE_NO_CK_OUTSIDE_ALPHA); + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_get_clock_frequency + * + * This routine returns the current clock frequency in 16.16 format. + * It reads the current register value and finds the match in the table. + * If no match is found, this routine returns 0. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +unsigned long +castle_get_clock_frequency(void) +#else +unsigned long +gfx_get_clock_frequency(void) +#endif +{ + Q_WORD msr_value; + unsigned int index; + unsigned long value, mask = 0x00001FFF; + + /* READ PLL SETTING */ + + gfx_msr_read(RC_ID_MCP, MCP_DOTPLL, &msr_value); + value = msr_value.high & mask; + + /* SEARCH FOR A MATCH */ + + for (index = 0; index < NUM_CASTLE_FREQUENCIES; index++) { + if ((CASTLE_PLLtable[index].pll_value & mask) == value) + return (CASTLE_PLLtable[index].frequency); + } + return (0); +} + +/*************************************************************/ +/* READ ROUTINES | INCLUDED FOR DIAGNOSTIC PURPOSES ONLY */ +/*************************************************************/ + +#if GFX_READ_ROUTINES + +/*--------------------------------------------------------------------------- + * gfx_get_sync_polarities + * + * This routine returns the polarities of the sync pulses: + * Bit 0: Set if negative horizontal polarity. + * Bit 1: Set if negative vertical polarity. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +castle_get_sync_polarities(void) +#else +int +gfx_get_sync_polarities(void) +#endif +{ + int polarities = 0; + + if (READ_VID32(CASTLE_DISPLAY_CONFIG) & CASTLE_DCFG_CRT_HSYNC_POL) + polarities |= 1; + if (READ_VID32(CASTLE_DISPLAY_CONFIG) & CASTLE_DCFG_CRT_VSYNC_POL) + polarities |= 2; + return (polarities); +} + +/*--------------------------------------------------------------------------- + * gfx_get_video_palette_entry + * + * This routine returns a single palette entry. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +castle_get_video_palette_entry(unsigned long index, unsigned long *palette) +#else +int +gfx_get_video_palette_entry(unsigned long index, unsigned long *palette) +#endif +{ + if (index > 0xFF) + return GFX_STATUS_BAD_PARAMETER; + + /* READ A SINGLE ENTRY */ + + WRITE_VID32(CASTLE_PALETTE_ADDRESS, index); + *palette = READ_VID32(CASTLE_PALETTE_DATA); + + return (GFX_STATUS_OK); +} + +/*---------------------------------------------------------------------------- + * gfx_get_video_enable + * + * This routine returns the value "one" if video overlay is currently enabled, + * otherwise it returns the value "zero". + *---------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +castle_get_video_enable(void) +#else +int +gfx_get_video_enable(void) +#endif +{ + if (READ_VID32(CASTLE_VIDEO_CONFIG) & CASTLE_VCFG_VID_EN) + return (1); + return (0); +} + +/*---------------------------------------------------------------------------- + * gfx_get_video_format + * + * This routine returns the current video overlay format. + *---------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +castle_get_video_format(void) +#else +int +gfx_get_video_format(void) +#endif +{ + unsigned long ctrl, vcfg; + + ctrl = READ_VID32(CASTLE_VID_ALPHA_CONTROL); + vcfg = READ_VID32(CASTLE_VIDEO_CONFIG); + + if (ctrl & CASTLE_VIDEO_INPUT_IS_RGB) { + switch (vcfg & CASTLE_VCFG_VID_INP_FORMAT) { + case CASTLE_VCFG_UYVY_FORMAT: + return VIDEO_FORMAT_RGB; + case CASTLE_VCFG_Y2YU_FORMAT: + return VIDEO_FORMAT_P2M_P2L_P1M_P1L; + case CASTLE_VCFG_YUYV_FORMAT: + return VIDEO_FORMAT_P1M_P1L_P2M_P2L; + case CASTLE_VCFG_YVYU_FORMAT: + return VIDEO_FORMAT_P1M_P2L_P2M_P1L; + } + } + + if (vcfg & CASTLE_VCFG_4_2_0_MODE) { + switch (vcfg & CASTLE_VCFG_VID_INP_FORMAT) { + case CASTLE_VCFG_UYVY_FORMAT: + return VIDEO_FORMAT_Y0Y1Y2Y3; + case CASTLE_VCFG_Y2YU_FORMAT: + return VIDEO_FORMAT_Y3Y2Y1Y0; + case CASTLE_VCFG_YUYV_FORMAT: + return VIDEO_FORMAT_Y1Y0Y3Y2; + case CASTLE_VCFG_YVYU_FORMAT: + return VIDEO_FORMAT_Y1Y2Y3Y0; + } + } else { + switch (vcfg & CASTLE_VCFG_VID_INP_FORMAT) { + case CASTLE_VCFG_UYVY_FORMAT: + return VIDEO_FORMAT_UYVY; + case CASTLE_VCFG_Y2YU_FORMAT: + return VIDEO_FORMAT_Y2YU; + case CASTLE_VCFG_YUYV_FORMAT: + return VIDEO_FORMAT_YUYV; + case CASTLE_VCFG_YVYU_FORMAT: + return VIDEO_FORMAT_YVYU; + } + } + return (GFX_STATUS_ERROR); +} + +/*---------------------------------------------------------------------------- + * gfx_get_video_src_size + * + * This routine returns the size of the source video overlay buffer. The + * return value is (height << 16) | width. + *---------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +unsigned long +castle_get_video_src_size(void) +#else +unsigned long +gfx_get_video_src_size(void) +#endif +{ + unsigned long width, height; + + /* DETERMINE SOURCE WIDTH FROM THE DISPLAY FILTER VIDEO LINE SIZE */ + + width = (READ_VID32(CASTLE_VIDEO_CONFIG) >> 7) & 0x000001FE; + if (READ_VID32(CASTLE_VIDEO_CONFIG) & CASTLE_VCFG_LINE_SIZE_UPPER) + width += 512l; + if (READ_VID32(CASTLE_VIDEO_CONFIG) & CASTLE_VCFG_LINE_SIZE_BIT9) + width += 1024l; + + /* DETERMINE SOURCE HEIGHT FROM THE DISPLAY FILTER SCALE REGISTER */ + + height = READ_VID32(CASTLE_VIDEO_SCALER) & 0x7FF; + + return ((height << 16) | width); +} + +/*---------------------------------------------------------------------------- + * gfx_get_video_line_size + * + * This routine returns the line size of the source video overlay buffer, in + * pixels. + *---------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +unsigned long +castle_get_video_line_size(void) +#else +unsigned long +gfx_get_video_line_size(void) +#endif +{ + unsigned long width = 0; + + /* DETERMINE SOURCE WIDTH FROM THE CASTLE VIDEO LINE SIZE */ + + width = (READ_VID32(CASTLE_VIDEO_CONFIG) >> 7) & 0x000001FE; + if (READ_VID32(CASTLE_VIDEO_CONFIG) & CASTLE_VCFG_LINE_SIZE_UPPER) + width += 512l; + return (width); +} + +/*---------------------------------------------------------------------------- + * gfx_get_video_xclip + * + * This routine returns the number of bytes clipped on the left side of a + * video overlay line (skipped at beginning). + *---------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +unsigned long +castle_get_video_xclip(void) +#else +unsigned long +gfx_get_video_xclip(void) +#endif +{ + unsigned long clip = 0; + + /* DETERMINE SOURCE WIDTH FROM THE CASTLE VIDEO LINE SIZE */ + + clip = ((READ_VID32(CASTLE_VIDEO_CONFIG) >> 16) & 0x001FF) << 3; + return (clip); +} + +/*---------------------------------------------------------------------------- + * gfx_get_video_offset + * + * This routine returns the current offset for the video overlay buffer. + *---------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +unsigned long +castle_get_video_offset(void) +#else +unsigned long +gfx_get_video_offset(void) +#endif +{ + return (gfx_get_display_video_offset()); +} + +/*---------------------------------------------------------------------------- + * gfx_get_video_yuv_offsets + * + * This routine returns the current offsets for the video overlay buffer when in 4:2:0. + *---------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +void +castle_get_video_yuv_offsets(unsigned long *yoffset, unsigned long *uoffset, + unsigned long *voffset) +#else +void +gfx_get_video_yuv_offsets(unsigned long *yoffset, unsigned long *uoffset, + unsigned long *voffset) +#endif +{ + gfx_get_display_video_yuv_offsets(yoffset, uoffset, voffset); +} + +/*---------------------------------------------------------------------------- + * gfx_get_video_yuv_pitch + * + * This routine returns the current pitch values for the video overlay buffer. + *---------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +void +castle_get_video_yuv_pitch(unsigned long *ypitch, unsigned long *uvpitch) +#else +void +gfx_get_video_yuv_pitch(unsigned long *ypitch, unsigned long *uvpitch) +#endif +{ + gfx_get_display_video_yuv_pitch(ypitch, uvpitch); +} + +/*--------------------------------------------------------------------------- + * gfx_get_video_dst_size + * + * This routine returns the size of the displayed video overlay window. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +unsigned long +castle_get_video_dst_size(void) +#else +unsigned long +gfx_get_video_dst_size(void) +#endif +{ + unsigned long xsize, ysize; + + xsize = READ_VID32(CASTLE_VIDEO_X_POS); + xsize = ((xsize >> 16) & 0x7FF) - (xsize & 0x7FF); + ysize = READ_VID32(CASTLE_VIDEO_Y_POS); + ysize = ((ysize >> 16) & 0x7FF) - (ysize & 0x7FF); + return ((ysize << 16) | xsize); +} + +/*--------------------------------------------------------------------------- + * gfx_get_video_position + * + * This routine returns the position of the video overlay window. The + * return value is (ypos << 16) | xpos. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +unsigned long +castle_get_video_position(void) +#else +unsigned long +gfx_get_video_position(void) +#endif +{ + unsigned long hadjust, vadjust; + unsigned long xpos, ypos; + + /* READ HARDWARE POSITION */ + + xpos = READ_VID32(CASTLE_VIDEO_X_POS) & 0x000007FF; + ypos = READ_VID32(CASTLE_VIDEO_Y_POS) & 0x000007FF; + + /* GET ADJUSTMENT VALUES */ + /* Use routines to abstract version of display controller. */ + + hadjust = + (unsigned long)gfx_get_htotal() - (unsigned long)gfx_get_hsync_end() - + 14l; + vadjust = + (unsigned long)gfx_get_vtotal() - (unsigned long)gfx_get_vsync_end() + + 1l; + xpos -= hadjust; + ypos -= vadjust; + return ((ypos << 16) | (xpos & 0x0000FFFF)); +} + +/*--------------------------------------------------------------------------- + * gfx_get_video_color_key + * + * This routine returns the current video color key value. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +unsigned long +castle_get_video_color_key(void) +#else +unsigned long +gfx_get_video_color_key(void) +#endif +{ + if (READ_VID32(CASTLE_DISPLAY_CONFIG) & CASTLE_DCFG_VG_CK) + return (READ_VID32(CASTLE_VIDEO_COLOR_KEY)); + else + return (gfx_get_display_video_color_key()); +} + +/*--------------------------------------------------------------------------- + * gfx_get_video_color_key_mask + * + * This routine returns the current video color mask value. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +unsigned long +castle_get_video_color_key_mask(void) +#else +unsigned long +gfx_get_video_color_key_mask(void) +#endif +{ + if (READ_VID32(CASTLE_DISPLAY_CONFIG) & CASTLE_DCFG_VG_CK) + return (READ_VID32(CASTLE_VIDEO_COLOR_MASK)); + else + return (gfx_get_display_video_color_key_mask()); +} + +/*--------------------------------------------------------------------------- + * gfx_get_video_color_key_src + * + * This routine returns 0 for video data compare, 1 for graphics data. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +castle_get_video_color_key_src(void) +#else +int +gfx_get_video_color_key_src(void) +#endif +{ + if (READ_VID32(CASTLE_DISPLAY_CONFIG) & CASTLE_DCFG_VG_CK) + return (0); + return (1); +} + +/*--------------------------------------------------------------------------- + * gfx_get_video_request + * + * This routine returns the horizontal (pixel) and vertical (lines) video + * request values. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +castle_get_video_request(short *x, short *y) +#else +int +gfx_get_video_request(short *x, short *y) +#endif +{ + unsigned long request = 0; + + request = (READ_VID32(CASTLE_VIDEO_REQUEST)); + *x = (short)((request >> CASTLE_VIDEO_X_REQUEST_POS) & + CASTLE_VIDEO_REQUEST_MASK); + *y = (short)((request >> CASTLE_VIDEO_Y_REQUEST_POS) & + CASTLE_VIDEO_REQUEST_MASK); + + *x -= gfx_get_htotal() - gfx_get_hsync_end() - 2; + *y -= gfx_get_vtotal() - gfx_get_vsync_end() + 1; + + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_get_video_cursor() + * + * This routine configures the video hardware cursor. + * If the "mask"ed bits in the graphics pixel match "key", then either + * "color1" or "color2" will be used for this pixel, according to the value of + * the bit in offset "select_color2". + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +castle_get_video_cursor(unsigned long *key, unsigned long *mask, + unsigned short *select_color2, unsigned long *color1, + unsigned short *color2) +#else +int +gfx_get_video_cursor(unsigned long *key, unsigned long *mask, + unsigned short *select_color2, unsigned long *color1, + unsigned short *color2) +#endif +{ + *select_color2 = + (unsigned short)(READ_VID32(CASTLE_CURSOR_COLOR_KEY) >> + CASTLE_CURSOR_COLOR_KEY_OFFSET_POS); + *key = READ_VID32(CASTLE_CURSOR_COLOR_KEY) & CASTLE_COLOR_MASK; + *mask = READ_VID32(CASTLE_CURSOR_COLOR_MASK) & CASTLE_COLOR_MASK; + *color1 = READ_VID32(CASTLE_CURSOR_COLOR_1) & CASTLE_COLOR_MASK; + *color2 = + (unsigned short)(READ_VID32(CASTLE_CURSOR_COLOR_2) & + CASTLE_COLOR_MASK); + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_read_crc + * + * This routine returns the hardware CRC value, which is used for automated + * testing. The value is like a checksum, but will change if pixels move + * locations. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +unsigned long +castle_read_crc(void) +#else +unsigned long +gfx_read_crc(void) +#endif +{ + Q_WORD msr_value; + unsigned long crc = 0xFFFFFFFF; + + /* DISABLE 32-BIT CRCS */ + /* For GX1.x, this is a reserved bit, and is assumed to be a benign + * access */ + + gfx_msr_read(RC_ID_DF, CASTLE_MBD_MSR_DIAG_DF, &msr_value); + msr_value.low &= ~CASTLE_DIAG_32BIT_CRC; + gfx_msr_write(RC_ID_DF, CASTLE_MBD_MSR_DIAG_DF, &msr_value); + + if (gfx_test_timing_active()) { + /* WAIT UNTIL ACTIVE DISPLAY */ + + while (!gfx_test_vertical_active()) ; + + /* RESET CRC DURING ACTIVE DISPLAY */ + + WRITE_VID32(CASTLE_VID_CRC, 0); + WRITE_VID32(CASTLE_VID_CRC, 1); + + /* WAIT UNTIL NOT ACTIVE, THEN ACTIVE, NOT ACTIVE, THEN ACTIVE */ + + while (!gfx_test_vertical_active()) ; + while (gfx_test_vertical_active()) ; + while (!gfx_test_vertical_active()) ; + while (gfx_test_vertical_active()) ; + while (!gfx_test_vertical_active()) ; + crc = READ_VID32(CASTLE_VID_CRC) >> 8; + } + return (crc); +} + +/*--------------------------------------------------------------------------- + * gfx_read_crc32 + * + * This routine returns the 32-bit hardware CRC value, which is used for + * automated testing. The value is like a checksum, but will change if pixels + * move + * locations. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +unsigned long +castle_read_crc32(void) +#else +unsigned long +gfx_read_crc32(void) +#endif +{ + Q_WORD msr_value; + unsigned long crc = 0xFFFFFFFF; + + /* ENABLE 32-BIT CRCS */ + /* For GX1.x, this is a reserved bit, and is assumed to be a benign + * access */ + + gfx_msr_read(RC_ID_DF, CASTLE_MBD_MSR_DIAG_DF, &msr_value); + msr_value.low |= CASTLE_DIAG_32BIT_CRC; + gfx_msr_write(RC_ID_DF, CASTLE_MBD_MSR_DIAG_DF, &msr_value); + + if (gfx_test_timing_active()) { + /* WAIT UNTIL ACTIVE DISPLAY */ + + while (!gfx_test_vertical_active()) ; + + /* RESET CRC DURING ACTIVE DISPLAY */ + + WRITE_VID32(CASTLE_VID_CRC, 0); + WRITE_VID32(CASTLE_VID_CRC, 1); + + /* WAIT UNTIL NOT ACTIVE, THEN ACTIVE, NOT ACTIVE, THEN ACTIVE */ + + while (!gfx_test_vertical_active()) ; + while (gfx_test_vertical_active()) ; + while (!gfx_test_vertical_active()) ; + while (gfx_test_vertical_active()) ; + while (!gfx_test_vertical_active()) ; + crc = READ_VID32(CASTLE_VID_CRC32); + } + return (crc); +} + +/*--------------------------------------------------------------------------- + * gfx_read_window_crc + * + * This routine returns the hardware CRC value for a subsection of the display + * This value is used to debug whole-screen CRC failures. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +unsigned long +castle_read_window_crc(int source, unsigned short x, unsigned short y, + unsigned short width, unsigned short height, int crc32) +#else +unsigned long +gfx_read_window_crc(int source, unsigned short x, unsigned short y, + unsigned short width, unsigned short height, int crc32) +#endif +{ + Q_WORD msr_value; + unsigned long xpos, ypos, crc = 0; + unsigned long old_fmt = 0; + unsigned int vsync_active_base, vsync_inactive_base, hsync_active_base; + unsigned int vsync_active_shift, vsync_inactive_shift, hsync_active_shift; + unsigned int vsync_bit, hsync_bit, sync_polarities = 0; + + /* CONFIGURE DISPLAY FILTER TO LOAD DATA ONTO LOWER 32-BITS */ + + msr_value.high = 0; + msr_value.low = + (source == CRC_SOURCE_GFX_DATA) ? (RCDF_MBD_DIAG_EN0 | 0x0000000F) + : (RCDF_MBD_DIAG_EN0 | 0x0000000B); + gfx_msr_write(RC_ID_DF, MBD_MSR_DIAG, &msr_value); + + /* CONFIGURE DISPLAY FILTER FOR APPROPRIATE OUTPUT */ + + if (source != CRC_SOURCE_GFX_DATA) { + gfx_msr_read(RC_ID_DF, MBD_MSR_CONFIG, &msr_value); + old_fmt = msr_value.low; + msr_value.low &= ~(RCDF_CONFIG_FMT_MASK); + msr_value.low |= + ((source == + CRC_SOURCE_FP_DATA) ? RCDF_CONFIG_FMT_FP : + RCDF_CONFIG_FMT_CRT); + gfx_msr_write(RC_ID_DF, MBD_MSR_CONFIG, &msr_value); + } + + /* CONFIGURE MCP TO LOAD REGB DATA ONTO UPPER 32-BITS */ + + msr_value.low = MCP_MBD_DIAG_EN1 | 0x00050000; + gfx_msr_write(RC_ID_MCP, MBD_MSR_DIAG, &msr_value); + + /* ENABLE HW CLOCK GATING AND SET MCP CLOCK TO DOT CLOCK */ + + msr_value.low = 1l; + gfx_msr_write(RC_ID_MCP, MBD_MSR_PM, &msr_value); + msr_value.low = 0; + gfx_msr_write(RC_ID_MCP, MCP_DBGCLKCTL, &msr_value); + msr_value.low = 3; + gfx_msr_write(RC_ID_MCP, MCP_DBGCLKCTL, &msr_value); + + /* DISABLE MCP ACTIONS */ + + msr_value.high = 0x00000000; + msr_value.low = 0x00000000; + gfx_msr_write(RC_ID_MCP, MCP_DIAGCTL, &msr_value); + + /* SET APPROPRIATE BASE ADDRESS */ + /* M-Sets use normal diag bits, while N-Sets use inverted diag bits */ + /* We thus use the M-sets when polling for a high signal and the N */ + /* sets when polling for a low signal. */ + + if (source != CRC_SOURCE_GFX_DATA) { + sync_polarities = gfx_get_sync_polarities(); + vsync_bit = 29; + hsync_bit = 30; + } else { + vsync_bit = 25; + hsync_bit = 26; + } + + if (sync_polarities & 1) { + hsync_active_base = MCP_SETM0CTL; + hsync_active_shift = 2; + } else { + hsync_active_base = MCP_SETN0CTL; + hsync_active_shift = 1; + } + if (sync_polarities & 2) { + vsync_active_base = MCP_SETM0CTL; + vsync_inactive_base = MCP_SETN0CTL; + vsync_active_shift = 2; + vsync_inactive_shift = 1; + } else { + vsync_active_base = MCP_SETN0CTL; + vsync_inactive_base = MCP_SETM0CTL; + vsync_active_shift = 1; + vsync_inactive_shift = 2; + } + + /* SET STATE TRANSITIONS */ + + /* STATE 0-1 TRANSITION (SET 0) */ + /* XState = 00 and VSync Inactive */ + /* Note: DF VSync = Diag Bus Bit 29 */ + /* VG VSync = Diag Bus Bit 25 */ + + msr_value.low = 0x000000A0; + msr_value.high = 0x00008000 | ((unsigned long)vsync_bit << 16) | + ((unsigned long)vsync_bit << 21) | ((unsigned long)vsync_bit << 26); + gfx_msr_write(RC_ID_MCP, vsync_inactive_base, &msr_value); + + /* STATE 1-2 TRANSITION (SET 4) */ + /* XState = 01 and VSync Active */ + + msr_value.low = 0x000000C0; + gfx_msr_write(RC_ID_MCP, vsync_active_base + 4, &msr_value); + + /* STATE 2-3 TRANSITION (SET 1) */ + /* XState = 10 and VSync Inactive */ + + msr_value.low = 0x00000120; + gfx_msr_write(RC_ID_MCP, vsync_inactive_base + 1, &msr_value); + + /* HORIZONTAL COUNTER (SET 5) */ + /* XState = 10 and HSync Active */ + /* Notes: DF HSync = Diag Bus Bit 30 */ + /* VG HSync = Diag Bus Bit 26 */ + + msr_value.high = 0x00008000 | ((unsigned long)hsync_bit << 16) | + ((unsigned long)hsync_bit << 21) | ((unsigned long)hsync_bit << 26); + msr_value.low = 0x00000120; + gfx_msr_write(RC_ID_MCP, hsync_active_base + 5, &msr_value); + + /* HORIZONTAL COUNTER RESET (SET 4) */ + /* XState = 10 and H. Counter = limit */ + /* Note: H. Counter is lower 16-bits of */ + /* RegB. */ + + msr_value.high = 0x00000000; + msr_value.low = 0x00000128; + gfx_msr_write(RC_ID_MCP, vsync_inactive_base + 4, &msr_value); + + /* CRC TRIGGER (SET 0) */ + /* Cmp0 <= xpos < Cmp1 */ + /* Cmp2 <= ypos < Cmp2 */ + + msr_value.high = 0x00000000; + msr_value.low = 0x10C20120; + gfx_msr_write(RC_ID_MCP, vsync_active_base, &msr_value); + + /* SET COMPARATOR VALUES */ + /* Note: The VG data outputs from the DF are delayed by one pixel clock. */ + /* In this mode, we thus add one to horizontal comparator limits. */ + + /* COMPARATOR 0 */ + /* Lower limit = xpos + (h_blank_pixels - 1) - 3 */ + /* Notes: */ + /* 1. 3 is the pipeline delay for MCP register */ + /* data to access the diag bus */ + /* 2. h_blank_pixels = HTOTAL - HSYNC_END */ + + xpos = (unsigned long)x + ((unsigned long)gfx_get_htotal() - + (unsigned long)gfx_get_hsync_end() - 1l) - 3l; + if (source == CRC_SOURCE_GFX_DATA) + xpos++; + msr_value.high = 0x00000000; + msr_value.low = xpos; + gfx_msr_write(RC_ID_MCP, MCP_CMPVAL0, &msr_value); + + /* COMPARATOR 1 */ + /* Upper limit = xpos + width + (h_blank_pixels - 1) - 3 */ + + msr_value.low = xpos + (unsigned long)width; + gfx_msr_write(RC_ID_MCP, MCP_CMPVAL0 + 2, &msr_value); + + /* COMPARATOR 2 */ + /* Lower limit = ypos + v_blank_pixels */ + /* Notes: */ + /* 1. v_blank_pixels = VTOTAL - VSYNC_END */ + + ypos = + (unsigned long)y + (unsigned long)gfx_get_vtotal() - + (unsigned long)gfx_get_vsync_end(); + msr_value.low = ypos << 16; + gfx_msr_write(RC_ID_MCP, MCP_CMPVAL0 + 4, &msr_value); + + /* COMPARATOR 3 */ + /* Upper limit = ypos + height + v_blank_pixels */ + + msr_value.low = (ypos + (unsigned long)height) << 16; + gfx_msr_write(RC_ID_MCP, MCP_CMPVAL0 + 6, &msr_value); + + /* SET COMPARATOR MASKS */ + + /* COMPARATORS 0 AND 1 REFER TO LOWER 16 BITS OF REGB */ + + msr_value.high = 0x00000000; + msr_value.low = 0x0000FFFF; + gfx_msr_write(RC_ID_MCP, MCP_CMPMASK0, &msr_value); + gfx_msr_write(RC_ID_MCP, MCP_CMPMASK0 + 2, &msr_value); + + /* COMPARATORS 2 AND 3 REFER TO UPPER 16 BITS OF REGB */ + + msr_value.low = 0xFFFF0000; + gfx_msr_write(RC_ID_MCP, MCP_CMPMASK0 + 4, &msr_value); + gfx_msr_write(RC_ID_MCP, MCP_CMPMASK0 + 6, &msr_value); + + /* SET REGA MASK TO CRC ONLY 24 BITS OF DATA */ + + msr_value.high = 0x00000000; + msr_value.low = 0x00FFFFFF; + gfx_msr_write(RC_ID_MCP, MCP_REGAMASK, &msr_value); + + /* SET REGB VALUE */ + /* Lower 16 bits use HTOTAL - SYNC TIME - 1 to set the counter rollover + * limit. */ + /* Upper 16 bits use 0xFFFF to remove auto-clear behavior. */ + + msr_value.high = 0x00000000; + msr_value.low = 0xFFFF0000 | + ((gfx_get_htotal() - (gfx_get_hsync_end() - gfx_get_hsync_start()) - + 1) & 0xFFFF); + gfx_msr_write(RC_ID_MCP, MCP_REGBVAL, &msr_value); + + /* PROGRAM ACTIONS */ + + /* GOTO STATE 01 */ + + msr_value.high = 0x00000000; + msr_value.low = 0x00000008 | (1l << vsync_inactive_shift); + gfx_msr_write(RC_ID_MCP, MCP_ACTION0 + 14, &msr_value); + + /* GOTO STATE 10 */ + + msr_value.low = 0x00080000 | (1l << (vsync_active_shift + 16)); + gfx_msr_write(RC_ID_MCP, MCP_ACTION0 + 15, &msr_value); + + /* GOTO STATE 11 */ + + msr_value.low = 0x00000080 | (1l << (vsync_inactive_shift + 4)); + gfx_msr_write(RC_ID_MCP, MCP_ACTION0 + 16, &msr_value); + + /* CLEAR REGB (COUNTERS) */ + /* RegB is cleared upon transitioning to state 10 */ + /* RegA is not cleared as the initial value must be 0x00000001 */ + + msr_value.low = 0x00080000 | (1l << (vsync_active_shift + 16)); + gfx_msr_write(RC_ID_MCP, MCP_ACTION0, &msr_value); + + /* CRC INTO REGA */ + /* INCREMENT H. COUNTER */ + /* cmp0 <= xpos < cmp1 */ + /* cmp2 <= ypos < cmp3 */ + /* XState = 10 */ + + msr_value.low = 0x00000008 | (1l << vsync_active_shift) | + 0x00800000 | (1l << (hsync_active_shift + 20)); + gfx_msr_write(RC_ID_MCP, MCP_ACTION0 + 1, &msr_value); + + /* INCREMENT V. COUNTER */ + /* V. Counter is incremented when the H. Counter */ + /* rolls over. */ + + msr_value.low = 0x00080000 | (1l << (vsync_inactive_shift + 16)); + gfx_msr_write(RC_ID_MCP, MCP_ACTION0 + 2, &msr_value); + + /* CLEAR ALL OTHER ACTIONS */ + /* This prevents side-effects from previous accesses to the MCP */ + /* debug logic. */ + msr_value.low = 0x00000000; + msr_value.high = 0x00000000; + gfx_msr_write(RC_ID_MCP, MCP_ACTION0 + 3, &msr_value); + gfx_msr_write(RC_ID_MCP, MCP_ACTION0 + 4, &msr_value); + gfx_msr_write(RC_ID_MCP, MCP_ACTION0 + 5, &msr_value); + gfx_msr_write(RC_ID_MCP, MCP_ACTION0 + 6, &msr_value); + gfx_msr_write(RC_ID_MCP, MCP_ACTION0 + 7, &msr_value); + gfx_msr_write(RC_ID_MCP, MCP_ACTION0 + 8, &msr_value); + gfx_msr_write(RC_ID_MCP, MCP_ACTION0 + 9, &msr_value); + gfx_msr_write(RC_ID_MCP, MCP_ACTION0 + 10, &msr_value); + gfx_msr_write(RC_ID_MCP, MCP_ACTION0 + 11, &msr_value); + gfx_msr_write(RC_ID_MCP, MCP_ACTION0 + 12, &msr_value); + gfx_msr_write(RC_ID_MCP, MCP_ACTION0 + 13, &msr_value); + gfx_msr_write(RC_ID_MCP, MCP_ACTION0 + 17, &msr_value); + gfx_msr_write(RC_ID_MCP, MCP_ACTION0 + 18, &msr_value); + gfx_msr_write(RC_ID_MCP, MCP_ACTION0 + 19, &msr_value); + gfx_msr_write(RC_ID_MCP, MCP_ACTION0 + 20, &msr_value); + + /* SET REGA CRC VALUE TO 1 OR 0 */ + + if (!crc32) + msr_value.low = 0x00000001; + gfx_msr_write(RC_ID_MCP, MCP_REGA, &msr_value); + + /* SET XSTATE TO 0 */ + + msr_value.low = 0; + msr_value.high = 0; + gfx_msr_write(RC_ID_MCP, MCP_XSTATE, &msr_value); + + /* CONFIGURE DIAG CONTROL */ + /* Set all four comparators to watch the upper diag bus. */ + /* Set REGA action1 to legacy CRC or 32-bit CRC. */ + /* Set REGB action1 to increment lower 16 bits and clear at limit. */ + /* Set REGB action2 to increment upper 16 bits. */ + /* Enable all actions. */ + + if (crc32) + msr_value.low = 0x9A820055; + else + msr_value.low = 0x9A840055; + msr_value.high = 0x00000000; + gfx_msr_write(RC_ID_MCP, MCP_DIAGCTL, &msr_value); + + /* DELAY TWO FRAMES */ + + while (!gfx_test_vertical_active()) ; + while (gfx_test_vertical_active()) ; + while (!gfx_test_vertical_active()) ; + while (gfx_test_vertical_active()) ; + while (!gfx_test_vertical_active()) ; + + /* VERIFY THAT XSTATE = 11 */ + + gfx_msr_read(RC_ID_MCP, MCP_XSTATE, &msr_value); + if ((msr_value.low & 3) == 3) { + gfx_msr_read(RC_ID_MCP, MCP_REGA, &msr_value); + + crc = msr_value.low; + if (!crc32) + crc &= 0xFFFFFF; + } + + /* DISABLE MCP AND DF DIAG BUS OUTPUTS */ + + msr_value.low = 0x00000000; + msr_value.high = 0x00000000; + gfx_msr_write(RC_ID_DF, MBD_MSR_DIAG, &msr_value); + gfx_msr_write(RC_ID_MCP, MBD_MSR_DIAG, &msr_value); + + /* DISABLE MCP ACTIONS */ + + msr_value.high = 0x00000000; + msr_value.low = 0x00000000; + gfx_msr_write(RC_ID_MCP, MCP_DIAGCTL, &msr_value); + + /* RESTORE PREVIOUS OUTPUT FORMAT */ + + if (source != CRC_SOURCE_GFX_DATA) { + gfx_msr_read(RC_ID_DF, MBD_MSR_CONFIG, &msr_value); + msr_value.low = old_fmt; + gfx_msr_write(RC_ID_DF, MBD_MSR_CONFIG, &msr_value); + } + return crc; +} + +/*--------------------------------------------------------------------------- + * gfx_get_alpha_enable + * + * This routine returns 1 if the selected alpha window is currently + * enabled, or 0 if it is currently disabled. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +void +castle_get_alpha_enable(int *enable) +#else +void +gfx_get_alpha_enable(int *enable) +#endif +{ + unsigned long value = 0; + + *enable = 0; + if (gfx_alpha_select <= 2) { + value = + READ_VID32(CASTLE_ALPHA_CONTROL_1 + + ((unsigned long)gfx_alpha_select << 5)); + if (value & CASTLE_ACTRL_WIN_ENABLE) + *enable = 1; + } + return; +} + +/*--------------------------------------------------------------------------- + * gfx_get_alpha_size + * + * This routine returns the size of the currently selected alpha region. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +void +castle_get_alpha_size(unsigned short *x, unsigned short *y, + unsigned short *width, unsigned short *height) +#else +void +gfx_get_alpha_size(unsigned short *x, unsigned short *y, + unsigned short *width, unsigned short *height) +#endif +{ + unsigned long value = 0; + + *x = 0; + *y = 0; + *width = 0; + *height = 0; + if (gfx_alpha_select <= 2) { + value = + READ_VID32(CASTLE_ALPHA_XPOS_1 + + ((unsigned long)gfx_alpha_select << 5)); + *x = (unsigned short)(value & 0x000007FF); + *width = (unsigned short)((value >> 16) & 0x000007FF) - *x; + value = + READ_VID32(CASTLE_ALPHA_YPOS_1 + + ((unsigned long)gfx_alpha_select << 5)); + *y = (unsigned short)(value & 0x000007FF); + *height = (unsigned short)((value >> 16) & 0x000007FF) - *y; + } + *x -= gfx_get_htotal() - gfx_get_hsync_end() - 2; + *y -= gfx_get_vtotal() - gfx_get_vsync_end() + 1; + return; +} + +/*--------------------------------------------------------------------------- + * gfx_get_alpha_value + * + * This routine returns the alpha value and increment/decrement value of + * the currently selected alpha region. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +void +castle_get_alpha_value(unsigned char *alpha, char *delta) +#else +void +gfx_get_alpha_value(unsigned char *alpha, char *delta) +#endif +{ + unsigned long value = 0; + + *alpha = 0; + *delta = 0; + if (gfx_alpha_select <= 2) { + value = + READ_VID32(CASTLE_ALPHA_CONTROL_1 + + ((unsigned long)gfx_alpha_select << 5)); + *alpha = (unsigned char)(value & 0x00FF); + *delta = (char)((value >> 8) & 0x00FF); + } + return; +} + +/*--------------------------------------------------------------------------- + * gfx_get_alpha_priority + * + * This routine returns the priority of the currently selected alpha region. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +void +castle_get_alpha_priority(int *priority) +#else +void +gfx_get_alpha_priority(int *priority) +#endif +{ + unsigned long pos = 0, value = 0; + + *priority = 0; + if (gfx_alpha_select <= 2) { + value = READ_VID32(CASTLE_VID_ALPHA_CONTROL); + pos = 16 + (gfx_alpha_select << 1); + *priority = (int)((value >> pos) & 3); + } + return; +} + +/*--------------------------------------------------------------------------- + * gfx_get_alpha_color + * + * This routine returns the color register value for the currently selected + * alpha region. Bit 24 is set if the color register is enabled. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +void +castle_get_alpha_color(unsigned long *color) +#else +void +gfx_get_alpha_color(unsigned long *color) +#endif +{ + *color = 0; + if (gfx_alpha_select <= 2) { + *color = + READ_VID32(CASTLE_ALPHA_COLOR_1 + + ((unsigned long)gfx_alpha_select << 5)); + } + return; +} + +#endif /* GFX_READ_ROUTINES */ + +/* END OF FILE */ diff --git a/src/gfx/vid_rdcl.c b/src/gfx/vid_rdcl.c new file mode 100644 index 0000000..ce03020 --- /dev/null +++ b/src/gfx/vid_rdcl.c @@ -0,0 +1,2887 @@ +/* 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 to control the Redcloud display filter video + * overlay hardware. + * */ + +unsigned long gfx_gamma_ram_redcloud[] = { + 0x00000000, 0x00040003, 0x00050104, 0x00060205, 0x00070306, 0x00080407, + 0x00090508, 0x000A0609, 0x000B070A, 0x000C080B, 0x000D090C, 0x000E0A0D, + 0x000F0B0E, 0x00100C0F, 0x00110D10, 0x00110E11, 0x00120F12, 0x00141013, + 0x00151114, 0x00161215, 0x00171316, 0x00181417, 0x00191518, 0x001A1619, + 0x001B171A, 0x001C181B, 0x001D191C, 0x001D1A1D, 0x001E1B1E, 0x00201C1F, + 0x00201D20, 0x00221E21, 0x00231F22, 0x00242023, 0x00252124, 0x00262225, + 0x00262326, 0x00282427, 0x00292528, 0x00292629, 0x002B272A, 0x002C282B, + 0x002D292C, 0x002E2A2D, 0x002F2B2E, 0x00302C2F, 0x00312D30, 0x00322E31, + 0x00332F32, 0x00343033, 0x00353134, 0x00363235, 0x00373336, 0x00383437, + 0x00393538, 0x003A3639, 0x003B373A, 0x003C383B, 0x003D393C, 0x003E3A3D, + 0x003F3B3E, 0x00403C3F, 0x00413D40, 0x00423E41, 0x00433F42, 0x00444043, + 0x00444144, 0x00454245, 0x00474346, 0x00484447, 0x00494548, 0x004A4649, + 0x004B474A, 0x004C484B, 0x004D494C, 0x004E4A4D, 0x004F4B4E, 0x00504C4F, + 0x00514D50, 0x00524E51, 0x00534F52, 0x00545053, 0x00555154, 0x00565255, + 0x00575356, 0x00585457, 0x00595558, 0x005A5659, 0x005B575A, 0x005C585B, + 0x005D595C, 0x005E5A5D, 0x005F5B5E, 0x00605C5F, 0x00615D60, 0x00625E61, + 0x00635F62, 0x00646063, 0x00656164, 0x00666265, 0x00676366, 0x00686467, + 0x00696568, 0x006A6669, 0x006B676A, 0x006C686B, 0x006D696C, 0x006E6A6D, + 0x006F6B6E, 0x00706C6F, 0x00716D70, 0x00726E71, 0x00736F72, 0x00747073, + 0x00757174, 0x00767275, 0x00777376, 0x00787477, 0x00797578, 0x007A7679, + 0x007B777A, 0x007C787B, 0x007D797C, 0x007E7A7D, 0x007F7B7E, 0x00807C7F, + 0x00817D80, 0x00827E81, 0x00837F82, 0x00848083, 0x00858184, 0x00868285, + 0x00878386, 0x00888487, 0x00898588, 0x008A8689, 0x008B878A, 0x008C888B, + 0x008D898C, 0x008E8A8D, 0x008F8B8E, 0x00908C8F, 0x00918D90, 0x00928E91, + 0x00938F92, 0x00949093, 0x00959194, 0x00969295, 0x00979396, 0x00989497, + 0x00999598, 0x009A9699, 0x009B979A, 0x009C989B, 0x009D999C, 0x009E9A9D, + 0x009F9B9E, 0x00A09C9F, 0x00A19DA0, 0x00A29EA1, 0x00A39FA2, 0x00A4A0A3, + 0x00A5A1A4, 0x00A6A2A5, 0x00A7A3A6, 0x00A8A4A7, 0x00A9A5A8, 0x00AAA6A9, + 0x00ABA7AA, 0x00ACA8AB, 0x00ADA9AC, 0x00AEAAAD, 0x00AFABAE, 0x00B0ACAF, + 0x00B1ADB0, 0x00B2AEB1, 0x00B3AFB2, 0x00B4B0B3, 0x00B5B1B4, 0x00B6B2B5, + 0x00B7B3B6, 0x00B8B4B7, 0x00B9B5B8, 0x00BAB6B9, 0x00BBB7BA, 0x00BCB8BB, + 0x00BDB9BC, 0x00BEBABD, 0x00BFBBBE, 0x00C0BCBF, 0x00C1BDC0, 0x00C2BEC1, + 0x00C3BFC2, 0x00C4C0C3, 0x00C5C1C4, 0x00C6C2C5, 0x00C7C3C6, 0x00C8C4C7, + 0x00C9C5C8, 0x00CAC6C9, 0x00CBC7CA, 0x00CCC8CB, 0x00CDC9CC, 0x00CECACD, + 0x00CFCBCE, 0x00D0CCCF, 0x00D1CDD0, 0x00D2CED1, 0x00D3CFD2, 0x00D4D0D3, + 0x00D5D1D4, 0x00D6D2D5, 0x00D7D3D6, 0x00D8D4D7, 0x00D9D5D8, 0x00DAD6D9, + 0x00DBD7DA, 0x00DCD8DB, 0x00DDD9DC, 0x00DEDADD, 0x00DFDBDE, 0x00E0DCDF, + 0x00E1DDE0, 0x00E2DEE1, 0x00E3DFE2, 0x00E4E0E3, 0x00E5E1E4, 0x00E6E2E5, + 0x00E7E3E6, 0x00E8E4E7, 0x00E9E5E8, 0x00EAE6E9, 0x00EBE7EA, 0x00ECE8EB, + 0x00EDE9EC, 0x00EEEAED, 0x00EFEBEE, 0x00F0ECEF, 0x00F1EDF0, 0x00F2EEF1, + 0x00F3EFF2, 0x00F4F0F3, 0x00F5F1F4, 0x00F6F2F5, 0x00F7F3F6, 0x00F8F4F7, + 0x00F9F5F8, 0x00FAF6F9, 0x00FBF7FA, 0x00FCF8FB, 0x00FDF9FC, 0x00FEFAFD, + 0x00FFFBFE, 0x00FFFCFE, 0x00FFFDFE, 0x00FFFFFF +}; + +/* REDCLOUD PLL TABLE */ + +typedef struct RCDFPLL +{ + long frequency; /* 16.16 fixed point frequency */ + unsigned long post_div3; /* MCP Frequency dividers and multipliers */ + unsigned long pre_mul2; + unsigned long pre_div2; + unsigned long pll_value; /* MCP DotPLL Register Upper 32(0x0015) */ +} RCDFPLLENTRY; + +RCDFPLLENTRY RCDF_PLLtable[] = { + {0x0018EC4D, 1, 0, 0, 0x0000099E}, /* 24.9230 */ + {0x00192CCC, 0, 0, 0, 0x00000037}, /* 25.1750 */ + {0x001C526E, 1, 0, 0, 0x000009DA}, /* 28.3220 */ + {0x001C8F5C, 1, 0, 0, 0x0000005E}, /* 28.5600 */ + {0x001F8000, 1, 0, 0, 0x000002D2}, /* 31.5000 */ + {0x00240000, 1, 0, 0, 0x000007E2}, /* 36.0000 */ + {0x00258000, 1, 0, 0, 0x0000057A}, /* 37.5000 */ + {0x0025E395, 1, 0, 0, 0x000007FA}, /* 37.8890 */ + {0x00280000, 1, 0, 0, 0x0000030A}, /* 40.0000 */ + {0x002B29BA, 0, 0, 0, 0x0000005F}, /* 43.1630 */ + {0x002CE666, 0, 0, 0, 0x00000063}, /* 44.9000 */ + {0x002DB851, 1, 0, 0, 0x00000BC9}, /* 45.7200 */ + {0x00318000, 0, 0, 0, 0x0000054B}, /* 49.5000 */ + {0x00320000, 0, 0, 0, 0x0000006F}, /* 50.0000 */ + {0x00325999, 0, 1, 0, 0x00000037}, /* 50.3500 */ + {0x00360000, 1, 1, 0, 0x00000B0D}, /* 54.0000 */ + {0x00384000, 0, 0, 0, 0x000007F7}, /* 56.2500 */ + {0x0038643F, 0, 0, 0, 0x000007F7}, /* 56.3916 */ + {0x0038A4DD, 0, 0, 0, 0x0000057B}, /* 56.6444 */ + {0x003B0000, 0, 1, 0, 0x00000707}, /* 59.0000 */ + {0x003C10A3, 0, 0, 0, 0x0000030B}, /* 60.0650 */ + {0x003F0000, 1, 1, 0, 0x00000B39}, /* 63.0000 */ + {0x00410000, 1, 0, 0, 0x00000545}, /* 65.0000 */ + {0x00442DD2, 1, 0, 0, 0x000002E1}, /* 68.1790 */ + {0x00438000, 1, 1, 0, 0x00000FC1}, /* 67.5000 */ + {0x0046CCCC, 1, 0, 0, 0x00000561}, /* 70.8000 */ + {0x00480000, 1, 0, 0, 0x000007E1}, /* 72.0000 */ + {0x004A7B22, 0, 1, 0, 0x00000F4A}, /* 74.4810 */ + {0x004B0000, 1, 0, 0, 0x000007F5}, /* 75.0000 */ + {0x004EC000, 1, 0, 0, 0x00000305}, /* 78.7500 */ + {0x00500000, 1, 1, 0, 0x00000709}, /* 80.0000 */ + {0x00519999, 0, 0, 0, 0x000009C6}, /* 81.6000 */ + {0x0059CCCC, 0, 1, 0, 0x00000262}, /* 89.8000 */ + {0x005E8000, 0, 0, 0, 0x000002D2}, /* 94.5000 */ + {0x00618560, 0, 0, 0, 0x00000546}, /* 97.5200 */ + {0x00630000, 0, 1, 0, 0x00000B4A}, /* 99.0000 */ + {0x00642FDF, 0, 0, 0, 0x0000006E}, /* 100.1870 */ + {0x00656B85, 0, 0, 0, 0x00000552}, /* 101.4200 */ + {0x006C0000, 0, 0, 0, 0x000007E2}, /* 108.0000 */ + {0x00708000, 0, 0, 0, 0x000007F6}, /* 112.5000 */ + {0x00714F1A, 0, 0, 0, 0x0000057A}, /* 113.3090 */ + {0x0077A666, 0, 0, 0, 0x0000030A}, /* 119.6500 */ + {0x00806666, 1, 0, 0, 0x00000068}, /* 128.4000 */ + {0x00820000, 1, 1, 0, 0x00000FB0}, /* 130.0000 */ + {0x00821999, 1, 0, 0, 0x00000544}, /* 130.1000 */ + {0x00858000, 1, 0, 0, 0x0000006C}, /* 133.5000 */ + {0x00870000, 1, 0, 0, 0x00000550}, /* 135.0000 */ + {0x00906147, 1, 0, 0, 0x000007E0}, /* 144.3800 */ + {0x009D8000, 1, 0, 0, 0x00000304}, /* 157.5000 */ + {0x00A20000, 0, 0, 0, 0x000002B1}, /* 162.0000 */ + {0x00A933F7, 0, 0, 0, 0x000002B9}, /* 169.2030 */ + {0x00ACCC49, 0, 1, 0, 0x0000002D}, /* 172.798 */ + {0x00AF8000, 0, 0, 0, 0x000002C1}, /* 175.5000 */ + {0x00BD0000, 0, 0, 0, 0x000002D1}, /* 189.0000 */ + {0x00BEF5C2, 0, 0, 0, 0x0000053D}, /* 190.9600 */ + {0x00C60000, 0, 0, 0, 0x00000549}, /* 198.0000 */ + {0x00CA8000, 0, 0, 0, 0x00000551}, /* 202.5000 */ + {0x00E58000, 0, 0, 0, 0x0000057D}, /* 229.5000 */ +}; + +#define NUM_RCDF_FREQUENCIES sizeof(RCDF_PLLtable)/sizeof(RCDFPLLENTRY) + +/*--------------------------------------------------------------------------- + * gfx_reset_video (PRIVATE ROUTINE: NOT PART OF DURANGO API) + * + * This routine is used to disable all components of video overlay before + * performing a mode switch. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +void +redcloud_reset_video(void) +#else +void +gfx_reset_video(void) +#endif +{ + gfx_set_video_enable(0); + gfx_select_alpha_region(1); + gfx_set_alpha_enable(0); + gfx_select_alpha_region(2); + gfx_set_alpha_enable(0); + + /* SET REGION 0 AFTER RESET */ + + gfx_select_alpha_region(0); + gfx_set_alpha_enable(0); +} + +/*---------------------------------------------------------------------------- + * gfx_set_display_control (PRIVATE ROUTINE: NOT PART OF DURANGO API) + * + * This routine configures the display output. + * + * "sync_polarities" is used to set the polarities of the sync pulses + * according to the following mask: + * + * Bit 0: If set to 1, negative horizontal polarity is programmed, + * otherwise positive horizontal polarity is programmed. + * Bit 1: If set to 1, negative vertical polarity is programmed, + * otherwise positive vertical polarity is programmed. + * + *---------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +redcloud_set_display_control(int sync_polarities) +#else +int +gfx_set_display_control(int sync_polarities) +#endif +{ + unsigned long power; + unsigned long dcfg; + + /* CONFIGURE DISPLAY OUTPUT FROM VIDEO PROCESSOR */ + + dcfg = READ_VID32(RCDF_DISPLAY_CONFIG); + dcfg &= ~(RCDF_DCFG_CRT_SYNC_SKW_MASK | RCDF_DCFG_PWR_SEQ_DLY_MASK | + RCDF_DCFG_CRT_HSYNC_POL | RCDF_DCFG_CRT_VSYNC_POL | + RCDF_DCFG_FP_PWR_EN | RCDF_DCFG_FP_DATA_EN); + + dcfg |= (RCDF_DCFG_CRT_SYNC_SKW_INIT | + RCDF_DCFG_PWR_SEQ_DLY_INIT | RCDF_DCFG_GV_PAL_BYP); + + if (PanelEnable) { + power = READ_VID32(RCDF_POWER_MANAGEMENT); + power |= RCDF_PM_PANEL_POWER_ON; + WRITE_VID32(RCDF_POWER_MANAGEMENT, power); + } + + /* SET APPROPRIATE SYNC POLARITIES */ + + if (sync_polarities & 0x1) + dcfg |= RCDF_DCFG_CRT_HSYNC_POL; + if (sync_polarities & 0x2) + dcfg |= RCDF_DCFG_CRT_VSYNC_POL; + + WRITE_VID32(RCDF_DISPLAY_CONFIG, dcfg); + + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_set_clock_frequency + * + * This routine sets the clock frequency, specified as a 16.16 fixed point + * value (0x00318000 = 49.5 MHz). It will set the closest frequency found + * in the lookup table. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +void +redcloud_set_clock_frequency(unsigned long frequency) +#else +void +gfx_set_clock_frequency(unsigned long frequency) +#endif +{ + Q_WORD msr_value, sys_value; + unsigned long sys_low; + unsigned int i, index = 0; + unsigned long value; + long timeout = 1000; + long min, diff; + + /* FIND THE REGISTER VALUES FOR THE DESIRED FREQUENCY */ + /* Search the table for the closest frequency (16.16 format). */ + + value = RCDF_PLLtable[0].pll_value; + min = (long)RCDF_PLLtable[0].frequency - frequency; + if (min < 0L) + min = -min; + for (i = 1; i < NUM_RCDF_FREQUENCIES; i++) { + diff = (long)RCDF_PLLtable[i].frequency - frequency; + if (diff < 0L) + diff = -diff; + if (diff < min) { + min = diff; + index = i; + } + } + + /* VERIFY THAT WE ARE NOT WRITING WHAT IS ALREADY IN THE REGISTERS */ + /* The Dot PLL reset bit is tied to VDD for flat panels. This can */ + /* cause a brief drop in flat panel power, which can cause serious */ + /* glitches on some panels. */ + + gfx_msr_read(RC_ID_MCP, MCP_DOTPLL, &msr_value); + gfx_msr_read(RC_ID_MCP, MCP_SYS_RSTPLL, &sys_value); + + sys_low = 0; + if (RCDF_PLLtable[index].post_div3) + sys_low |= MCP_DOTPOSTDIV3; + if (RCDF_PLLtable[index].pre_div2) + sys_low |= MCP_DOTPREDIV2; + if (RCDF_PLLtable[index].pre_mul2) + sys_low |= MCP_DOTPREMULT2; + + if ((msr_value.low & MCP_DOTPLL_LOCK) && + (msr_value.high == RCDF_PLLtable[index].pll_value) && + ((sys_value. + low & (MCP_DOTPOSTDIV3 | MCP_DOTPREDIV2 | MCP_DOTPREMULT2)) == + sys_low)) { + return; + } + + /* PROGRAM THE SETTINGS WITH THE RESET BIT SET */ + /* Clear the bypass bit to ensure that the programmed */ + /* M, N and P values are being used. */ + + msr_value.high = RCDF_PLLtable[index].pll_value; + msr_value.low |= 0x00000001; + msr_value.low &= ~MCP_DOTPLL_BYPASS; + gfx_msr_write(RC_ID_MCP, MCP_DOTPLL, &msr_value); + + /* PROGRAM THE MCP DIVIDER VALUES */ + + sys_value.low &= ~(MCP_DOTPOSTDIV3 | MCP_DOTPREDIV2 | MCP_DOTPREMULT2); + sys_value.low |= sys_low; + gfx_msr_write(RC_ID_MCP, MCP_SYS_RSTPLL, &sys_value); + + /* CLEAR THE RESET BIT */ + + msr_value.low &= 0xFFFFFFFE; + gfx_msr_write(RC_ID_MCP, MCP_DOTPLL, &msr_value); + + /* WAIT FOR LOCK BIT */ + + do { + gfx_msr_read(RC_ID_MCP, MCP_DOTPLL, &msr_value); + } while (timeout-- && !(msr_value.low & MCP_DOTPLL_LOCK)); +} + +/*--------------------------------------------------------------------------- + * gfx_set_crt_enable + * + * This routine enables or disables the CRT output from the video processor. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +redcloud_set_crt_enable(int enable) +#else +int +gfx_set_crt_enable(int enable) +#endif +{ + unsigned long config, misc; + + config = READ_VID32(RCDF_DISPLAY_CONFIG); + misc = READ_VID32(RCDF_VID_MISC); + + switch (enable) { + case CRT_DISABLE: /* DISABLE EVERYTHING */ + + WRITE_VID32(RCDF_DISPLAY_CONFIG, + config & ~(RCDF_DCFG_DIS_EN | RCDF_DCFG_HSYNC_EN | + RCDF_DCFG_VSYNC_EN | RCDF_DCFG_DAC_BL_EN)); + WRITE_VID32(RCDF_VID_MISC, misc | RCDF_DAC_POWER_DOWN); + break; + + case CRT_ENABLE: /* ENABLE CRT DISPLAY, INCLUDING DISPLAY LOGIC */ + + WRITE_VID32(RCDF_DISPLAY_CONFIG, + config | RCDF_DCFG_DIS_EN | RCDF_DCFG_HSYNC_EN | + RCDF_DCFG_VSYNC_EN | RCDF_DCFG_DAC_BL_EN); + WRITE_VID32(RCDF_VID_MISC, + misc & ~RCDF_DAC_POWER_DOWN & ~RCDF_ANALOG_POWER_DOWN); + break; + + case CRT_STANDBY: /* HSYNC:OFF VSYNC:ON */ + + WRITE_VID32(RCDF_DISPLAY_CONFIG, + (config & ~(RCDF_DCFG_DIS_EN | RCDF_DCFG_HSYNC_EN | + RCDF_DCFG_DAC_BL_EN)) | RCDF_DCFG_VSYNC_EN); + WRITE_VID32(RCDF_VID_MISC, misc | RCDF_DAC_POWER_DOWN); + break; + + case CRT_SUSPEND: /* HSYNC:ON VSYNC:OFF */ + + WRITE_VID32(RCDF_DISPLAY_CONFIG, + (config & ~(RCDF_DCFG_DIS_EN | RCDF_DCFG_VSYNC_EN | + RCDF_DCFG_DAC_BL_EN)) | RCDF_DCFG_HSYNC_EN); + WRITE_VID32(RCDF_VID_MISC, misc | RCDF_DAC_POWER_DOWN); + break; + + default: + return (GFX_STATUS_BAD_PARAMETER); + } + return (GFX_STATUS_OK); +} + +/*---------------------------------------------------------------------------- + * gfx_set_video_enable + * + * This routine enables or disables the video overlay functionality. + *---------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +redcloud_set_video_enable(int enable) +#else +int +gfx_set_video_enable(int enable) +#endif +{ + unsigned long vcfg; + + /* WAIT FOR VERTICAL BLANK TO START */ + /* Otherwise a glitch can be observed. */ + + if (gfx_test_timing_active()) { + if (!gfx_test_vertical_active()) { + while (!gfx_test_vertical_active()) ; + } + while (gfx_test_vertical_active()) ; + } + + vcfg = READ_VID32(RCDF_VIDEO_CONFIG); + if (enable) { + /* ENABLE VIDEO OVERLAY FROM DISPLAY CONTROLLER */ + /* Use private routine to abstract the display controller. */ + + gfx_set_display_video_enable(1); + + /* ENABLE DISPLAY FILTER VIDEO OVERLAY */ + + vcfg |= RCDF_VCFG_VID_EN; + WRITE_VID32(RCDF_VIDEO_CONFIG, vcfg); + } else { + /* DISABLE DISPLAY FILTER VIDEO OVERLAY */ + + vcfg &= ~RCDF_VCFG_VID_EN; + WRITE_VID32(RCDF_VIDEO_CONFIG, vcfg); + + /* DISABLE VIDEO OVERLAY FROM DISPLAY CONTROLLER */ + /* Use private routine to abstract the display controller. */ + + gfx_set_display_video_enable(0); + } + return (0); +} + +/*---------------------------------------------------------------------------- + * gfx_set_video_format + * + * Sets input video format type, to one of the YUV formats or to RGB. + *---------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +redcloud_set_video_format(unsigned long format) +#else +int +gfx_set_video_format(unsigned long format) +#endif +{ + unsigned long ctrl, vcfg = 0; + + /* SET THE DISPLAY FILTER VIDEO INPUT FORMAT */ + + vcfg = READ_VID32(RCDF_VIDEO_CONFIG); + ctrl = READ_VID32(RCDF_VID_ALPHA_CONTROL); + ctrl &= ~(RCDF_VIDEO_INPUT_IS_RGB | RCDF_CSC_VIDEO_YUV_TO_RGB); + vcfg &= ~(RCDF_VCFG_VID_INP_FORMAT | RCDF_VCFG_4_2_0_MODE); + switch (format) { + case VIDEO_FORMAT_UYVY: + vcfg |= RCDF_VCFG_UYVY_FORMAT; + ctrl |= RCDF_CSC_VIDEO_YUV_TO_RGB; + break; + case VIDEO_FORMAT_YUYV: + vcfg |= RCDF_VCFG_YUYV_FORMAT; + ctrl |= RCDF_CSC_VIDEO_YUV_TO_RGB; + break; + case VIDEO_FORMAT_Y2YU: + vcfg |= RCDF_VCFG_Y2YU_FORMAT; + ctrl |= RCDF_CSC_VIDEO_YUV_TO_RGB; + break; + case VIDEO_FORMAT_YVYU: + vcfg |= RCDF_VCFG_YVYU_FORMAT; + ctrl |= RCDF_CSC_VIDEO_YUV_TO_RGB; + break; + case VIDEO_FORMAT_Y0Y1Y2Y3: + vcfg |= RCDF_VCFG_UYVY_FORMAT; + ctrl |= RCDF_CSC_VIDEO_YUV_TO_RGB; + vcfg |= RCDF_VCFG_4_2_0_MODE; + break; + case VIDEO_FORMAT_Y3Y2Y1Y0: + vcfg |= RCDF_VCFG_Y2YU_FORMAT; + ctrl |= RCDF_CSC_VIDEO_YUV_TO_RGB; + vcfg |= RCDF_VCFG_4_2_0_MODE; + break; + case VIDEO_FORMAT_Y1Y0Y3Y2: + vcfg |= RCDF_VCFG_YUYV_FORMAT; + ctrl |= RCDF_CSC_VIDEO_YUV_TO_RGB; + vcfg |= RCDF_VCFG_4_2_0_MODE; + break; + case VIDEO_FORMAT_Y1Y2Y3Y0: + vcfg |= RCDF_VCFG_YVYU_FORMAT; + ctrl |= RCDF_CSC_VIDEO_YUV_TO_RGB; + vcfg |= RCDF_VCFG_4_2_0_MODE; + break; + case VIDEO_FORMAT_RGB: + ctrl |= RCDF_VIDEO_INPUT_IS_RGB; + vcfg |= RCDF_VCFG_UYVY_FORMAT; + break; + case VIDEO_FORMAT_P2M_P2L_P1M_P1L: + ctrl |= RCDF_VIDEO_INPUT_IS_RGB; + vcfg |= RCDF_VCFG_Y2YU_FORMAT; + break; + case VIDEO_FORMAT_P1M_P1L_P2M_P2L: + ctrl |= RCDF_VIDEO_INPUT_IS_RGB; + vcfg |= RCDF_VCFG_YUYV_FORMAT; + break; + case VIDEO_FORMAT_P1M_P2L_P2M_P1L: + ctrl |= RCDF_VIDEO_INPUT_IS_RGB; + vcfg |= RCDF_VCFG_YVYU_FORMAT; + break; + default: + return GFX_STATUS_BAD_PARAMETER; + } + WRITE_VID32(RCDF_VIDEO_CONFIG, vcfg); + WRITE_VID32(RCDF_VID_ALPHA_CONTROL, ctrl); + + /* SET THE VIDEO FORMAT IN THE DISPLAY CONTROLLER */ + /* Use private routine to abstract display controller. */ + + gfx_set_display_video_format(format); + return (0); +} + +/*---------------------------------------------------------------------------- + * gfx_set_video_size + * + * This routine specifies the size of the source data. It is used only + * to determine how much data to transfer per frame, and is not used to + * calculate the scaling value (that is handled by a separate routine). + *---------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +redcloud_set_video_size(unsigned short width, unsigned short height) +#else +int +gfx_set_video_size(unsigned short width, unsigned short height) +#endif +{ + unsigned long size, vcfg, vid_420, pitch; + + /* SET THE DISPLAY FILTER VIDEO LINE SIZE */ + /* Match the DC hardware alignment requirement. The line size must */ + /* always be 32-byte aligned. However, we can manage smaller */ + /* alignments by decreasing the pitch and clipping the video window. */ + /* The VG will fetch extra data for each line, but the decreased */ + /* pitch will ensure that it always begins fetching at the start of */ + /* the video line. */ + + vcfg = READ_VID32(RCDF_VIDEO_CONFIG); + + vid_420 = vcfg & RCDF_VCFG_4_2_0_MODE; + + vcfg &= ~(RCDF_VCFG_LINE_SIZE_LOWER_MASK | RCDF_VCFG_LINE_SIZE_UPPER); + + size = ((width >> 1) + 7) & 0xFFF8; + pitch = ((width << 1) + 7) & 0xFFF8; + + vcfg |= (size & 0x00FF) << 8; + if (size & 0x0100) + vcfg |= RCDF_VCFG_LINE_SIZE_UPPER; + WRITE_VID32(RCDF_VIDEO_CONFIG, vcfg); + + /* SET VIDEO BUFFER LINE SIZE IN DISPLAY CONTROLLER */ + /* Use private routine to abstract the display controller. */ + + gfx_set_display_video_size(width, height); + + /* SET VIDEO PITCH */ + /* We are only maintaining legacy for 4:2:2 video formats. */ + /* 4:2:0 video in previous chips was inadequate for most */ + /* common video formats. */ + + if (!vid_420) + gfx_set_video_yuv_pitch(pitch, pitch << 1); + + return (0); +} + +/*---------------------------------------------------------------------------- + * gfx_set_video_offset + * + * This routine sets the starting offset for the video buffer when only + * one offset needs to be specified. + *---------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +redcloud_set_video_offset(unsigned long offset) +#else +int +gfx_set_video_offset(unsigned long offset) +#endif +{ + /* SAVE VALUE FOR FUTURE CLIPPING OF THE TOP OF THE VIDEO WINDOW */ + + gfx_vid_offset = offset; + + /* SET VIDEO BUFFER OFFSET IN DISPLAY CONTROLLER */ + /* Use private routine to abstract the display controller. */ + + gfx_set_display_video_offset(offset); + return (0); +} + +/*---------------------------------------------------------------------------- + * gfx_set_video_yuv_offsets + * + * This routine sets the starting offset for the video buffer when displaying + * 4:2:0 video. + *---------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +redcloud_set_video_yuv_offsets(unsigned long yoffset, unsigned long uoffset, + unsigned long voffset) +#else +int +gfx_set_video_yuv_offsets(unsigned long yoffset, unsigned long uoffset, + unsigned long voffset) +#endif +{ + /* SAVE VALUE FOR FUTURE CLIPPING OF THE TOP OF THE VIDEO WINDOW */ + + gfx_vid_offset = yoffset; + gfx_vid_uoffset = uoffset; + gfx_vid_voffset = voffset; + + /* SET VIDEO BUFFER OFFSET IN DISPLAY CONTROLLER */ + /* Use private routine to abstract the display controller. */ + + gfx_set_display_video_yuv_offsets(yoffset, uoffset, voffset); + + return (0); +} + +/*---------------------------------------------------------------------------- + * gfx_set_video_yuv_pitch + * + * This routine sets the byte offset between consecutive scanlines of YUV video data + *---------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +redcloud_set_video_yuv_pitch(unsigned long ypitch, unsigned long uvpitch) +#else +int +gfx_set_video_yuv_pitch(unsigned long ypitch, unsigned long uvpitch) +#endif +{ + /* SET VIDEO PITCH IN DISPLAY CONTROLLER */ + /* Use private routine to abstract the display controller. */ + + gfx_set_display_video_yuv_pitch(ypitch, uvpitch); + + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_set_video_scale + * + * This routine sets the scale factor for the video overlay window. The + * size of the source and destination regions are specified in pixels. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +redcloud_set_video_scale(unsigned short srcw, unsigned short srch, + unsigned short dstw, unsigned short dsth) +#else +int +gfx_set_video_scale(unsigned short srcw, unsigned short srch, + unsigned short dstw, unsigned short dsth) +#endif +{ + unsigned long xscale, yscale; + + /* SAVE PARAMETERS (unless don't-care zero destination arguments are used) */ + /* These are needed for clipping the video window later. */ + + if (dstw != 0) { + gfx_vid_srcw = srcw; + gfx_vid_dstw = dstw; + } + if (dsth != 0) { + gfx_vid_srch = srch; + gfx_vid_dsth = dsth; + } + + /* CALCULATE DISPLAY FILTER SCALE FACTORS */ + /* Zero width and height indicate don't care conditions */ + /* Downscaling is performed in a separate function. */ + + if (dstw == 0) + xscale = READ_VID32(RCDF_VIDEO_SCALE) & 0xffff; + /* keep previous if don't-care argument */ + else if (dstw <= srcw) + xscale = 0x2000; + /* horizontal downscaling is currently done in a separate function */ + else if ((srcw == 1) || (dstw == 1)) + return GFX_STATUS_BAD_PARAMETER; + else + xscale = (0x2000l * (srcw - 1l)) / (dstw - 1l); + + if (dsth == 0) + yscale = (READ_VID32(RCDF_VIDEO_SCALE) & 0xffff0000) >> 16; + /* keep previous if don't-care argument */ + else if (dsth <= srch) + yscale = 0x2000; + /* vertical downscaling is handled in a separate function */ + else if ((srch == 1) || (dsth == 1)) + return GFX_STATUS_BAD_PARAMETER; + else + yscale = (0x2000l * (srch - 1l)) / (dsth - 1l); + + WRITE_VID32(RCDF_VIDEO_SCALE, (yscale << 16) | xscale); + + /* CALL ROUTINE TO UPDATE WINDOW POSITION */ + /* This is required because the scale values affect the number of */ + /* source data pixels that need to be clipped, as well as the */ + /* amount of data that needs to be transferred. */ + + gfx_set_video_window(gfx_vid_xpos, gfx_vid_ypos, gfx_vid_width, + gfx_vid_height); + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_set_video_vertical_downscale + * + * This routine sets the vertical downscale factor for the video overlay + * window. + * The height of the source and destination regions are specified in pixels. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +redcloud_set_video_vertical_downscale(unsigned short srch, + unsigned short dsth) +#else +int +gfx_set_video_vertical_downscale(unsigned short srch, unsigned short dsth) +#endif +{ + /* SET VIDEO SCALE IN DISPLAY CONTROLLER */ + /* Use private routine to abstract hardware */ + + gfx_set_display_video_downscale(srch, dsth); + return 0; +} + +/*--------------------------------------------------------------------------- + * gfx_set_video_vertical_downscale_enable + * + * This routine sets the vertical downscale enable for the video overlay + * window. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +void +redcloud_set_video_vertical_downscale_enable(int enable) +#else +void +gfx_set_video_vertical_downscale_enable(int enable) +#endif +{ + /* SET VIDEO SCALE IN DISPLAY CONTROLLER */ + /* Use private routine to abstract hardware */ + + gfx_set_display_video_vertical_downscale_enable(enable); +} + +/*--------------------------------------------------------------------------- + * gfx_set_video_downscale_config + * + * This routine sets the downscale type and factor for the video overlay + * window. + * Note: No downscaling support for RGB565 and YUV420 video formats. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +redcloud_set_video_downscale_config(unsigned short type, unsigned short m) +#else +int +gfx_set_video_downscale_config(unsigned short type, unsigned short m) +#endif +{ + unsigned long downscale; + + if ((m < 1) || (m > 16)) + return GFX_STATUS_BAD_PARAMETER; + + downscale = READ_VID32(RCDF_VIDEO_DOWNSCALER_CONTROL); + downscale &= + ~(RCDF_VIDEO_DOWNSCALE_FACTOR_MASK | RCDF_VIDEO_DOWNSCALE_TYPE_MASK); + downscale |= ((unsigned long)(m - 1) << RCDF_VIDEO_DOWNSCALE_FACTOR_POS); + switch (type) { + case VIDEO_DOWNSCALE_KEEP_1_OF: + downscale |= RCDF_VIDEO_DOWNSCALE_TYPE_A; + break; + case VIDEO_DOWNSCALE_DROP_1_OF: + downscale |= RCDF_VIDEO_DOWNSCALE_TYPE_B; + break; + default: + return GFX_STATUS_BAD_PARAMETER; + } + WRITE_VID32(RCDF_VIDEO_DOWNSCALER_CONTROL, downscale); + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_set_video_downscale_coefficients + * + * This routine sets the downscale filter coefficients. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +redcloud_set_video_downscale_coefficients(unsigned short coef1, + unsigned short coef2, unsigned short coef3, unsigned short coef4) +#else +int +gfx_set_video_downscale_coefficients(unsigned short coef1, + unsigned short coef2, unsigned short coef3, unsigned short coef4) +#endif +{ + if ((coef1 + coef2 + coef3 + coef4) != 16) + return GFX_STATUS_BAD_PARAMETER; + + WRITE_VID32(RCDF_VIDEO_DOWNSCALER_COEFFICIENTS, + ((unsigned long)coef1 << RCDF_VIDEO_DOWNSCALER_COEF1_POS) | + ((unsigned long)coef2 << RCDF_VIDEO_DOWNSCALER_COEF2_POS) | + ((unsigned long)coef3 << RCDF_VIDEO_DOWNSCALER_COEF3_POS) | + ((unsigned long)coef4 << RCDF_VIDEO_DOWNSCALER_COEF4_POS)); + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_set_video_downscale_enable + * + * This routine enables or disables downscaling for the video overlay window. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +redcloud_set_video_downscale_enable(int enable) +#else +int +gfx_set_video_downscale_enable(int enable) +#endif +{ + unsigned long downscale; + + downscale = READ_VID32(RCDF_VIDEO_DOWNSCALER_CONTROL); + if (enable) + downscale |= RCDF_VIDEO_DOWNSCALE_ENABLE; + else + downscale &= ~RCDF_VIDEO_DOWNSCALE_ENABLE; + WRITE_VID32(RCDF_VIDEO_DOWNSCALER_CONTROL, downscale); + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_set_video_window + * + * This routine sets the position and size of the video overlay window. The + * x and y positions are specified in screen relative coordinates, and may be + * negative. + * The size of destination region is specified in pixels. The line size + * indicates the number of bytes of source data per scanline. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +redcloud_set_video_window(short x, short y, unsigned short w, + unsigned short h) +#else +int +gfx_set_video_window(short x, short y, unsigned short w, unsigned short h) +#endif +{ + unsigned long hadjust, vadjust; + unsigned long xstart, ystart, xend, yend; + + /* SAVE PARAMETERS */ + /* These are needed to call this routine if the scale value changes. */ + + gfx_vid_xpos = x; + gfx_vid_ypos = y; + gfx_vid_width = w; + gfx_vid_height = h; + + /* GET ADJUSTMENT VALUES */ + /* Use routines to abstract version of display controller. */ + + hadjust = gfx_get_htotal() - gfx_get_hsync_end() - 14l; + vadjust = gfx_get_vtotal() - gfx_get_vsync_end() + 1l; + + /* LEFT CLIPPING */ + + if (x < 0) { + gfx_set_video_left_crop((unsigned short)(-x)); + xstart = hadjust; + } else { + gfx_set_video_left_crop(0); + xstart = (unsigned long)x + hadjust; + } + + /* HORIZONTAL END */ + /* End positions in register are non-inclusive (one more than the actual + * end) */ + + if ((x + w) < gfx_get_hactive()) + xend = (unsigned long)x + (unsigned long)w + hadjust; + + /* RIGHT-CLIPPING */ + else + xend = (unsigned long)gfx_get_hactive() + hadjust; + + /* VERTICAL START */ + + ystart = (unsigned long)y + vadjust; + + /* VERTICAL END */ + + if ((y + h) < gfx_get_vactive()) + yend = (unsigned long)y + (unsigned long)h + vadjust; + + /* BOTTOM-CLIPPING */ + else + yend = (unsigned long)gfx_get_vactive() + vadjust; + + /* SET VIDEO POSITION */ + + WRITE_VID32(RCDF_VIDEO_X_POS, (xend << 16) | xstart); + WRITE_VID32(RCDF_VIDEO_Y_POS, (yend << 16) | ystart); + + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_set_video_left_crop + * + * This routine sets the number of pixels which will be cropped from the + * beginning of each video line. The video window will begin to display only + * from the pixel following the cropped pixels, and the cropped pixels + * will be ignored. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +redcloud_set_video_left_crop(unsigned short x) +#else +int +gfx_set_video_left_crop(unsigned short x) +#endif +{ + unsigned long vcfg, initread; + + vcfg = READ_VID32(RCDF_VIDEO_CONFIG); + + /* CLIPPING ON LEFT */ + /* Adjust initial read for scale, checking for divide by zero. Mask the + * lower three bits when clipping 4:2:0 video. By masking the bits instead + * of rounding up we ensure that we always clip less than or equal to the + * desired number of pixels. This prevents visual artifacts from + * over-clipping. We mask three bits to meet the HW requirement that 4:2:0 + * clipping be 16-byte or 8-pixel aligned. + * */ + + if (gfx_vid_dstw) { + initread = (unsigned long)x *gfx_vid_srcw / gfx_vid_dstw; + + if (vcfg & RCDF_VCFG_4_2_0_MODE) + initread &= 0xFFF8; + } else + initread = 0; + + /* SET INITIAL READ ADDRESS */ + + vcfg &= ~RCDF_VCFG_INIT_READ_MASK; + vcfg |= (initread << 15) & RCDF_VCFG_INIT_READ_MASK; + WRITE_VID32(RCDF_VIDEO_CONFIG, vcfg); + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_set_video_color_key + * + * This routine specifies the color key value and mask for the video overlay + * hardware. To disable color key, the color and mask should both be set to + * zero. The hardware uses the color key in the following equation: + * + * ((source data) & (color key mask)) == ((color key) & (color key mask)) + * + * If "graphics" is set to TRUE, the source data is graphics, and color key + * is an RGB value. If "graphics" is set to FALSE, the source data is the + * video, and color key is a YUV value. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +redcloud_set_video_color_key(unsigned long key, unsigned long mask, + int graphics) +#else +int +gfx_set_video_color_key(unsigned long key, unsigned long mask, int graphics) +#endif +{ + unsigned long dcfg = 0; + + /* SET RCDF COLOR KEY VALUE */ + + WRITE_VID32(RCDF_VIDEO_COLOR_KEY, key); + WRITE_VID32(RCDF_VIDEO_COLOR_MASK, mask); + + /* SELECT GRAPHICS OR VIDEO DATA TO COMPARE TO THE COLOR KEY */ + + dcfg = READ_VID32(RCDF_DISPLAY_CONFIG); + if (graphics & 0x01) + dcfg &= ~RCDF_DCFG_VG_CK; + else + dcfg |= RCDF_DCFG_VG_CK; + WRITE_VID32(RCDF_DISPLAY_CONFIG, dcfg); + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_set_video_filter + * + * This routine enables or disables the video overlay filters. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +redcloud_set_video_filter(int xfilter, int yfilter) +#else +int +gfx_set_video_filter(int xfilter, int yfilter) +#endif +{ + unsigned long vcfg = 0; + + /* ENABLE OR DISABLE DISPLAY FILTER VIDEO OVERLAY FILTERS */ + + vcfg = READ_VID32(RCDF_VIDEO_CONFIG); + vcfg &= ~(RCDF_VCFG_X_FILTER_EN | RCDF_VCFG_Y_FILTER_EN); + if (xfilter) + vcfg |= RCDF_VCFG_X_FILTER_EN; + if (yfilter) + vcfg |= RCDF_VCFG_Y_FILTER_EN; + WRITE_VID32(RCDF_VIDEO_CONFIG, vcfg); + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_set_video_palette + * + * This routine loads the video hardware palette. If a NULL pointer is + * specified, the palette is bypassed (for Redcloud, this means loading the + * palette with identity values). + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +redcloud_set_video_palette(unsigned long *palette) +#else +int +gfx_set_video_palette(unsigned long *palette) +#endif +{ + unsigned long i, entry; + unsigned long misc, dcfg; + + /* ENABLE THE VIDEO PALETTE */ + /* Ensure that the video palette has an effect by routing video data */ + /* through the palette RAM and clearing the 'Bypass Both' bit. */ + + dcfg = READ_VID32(RCDF_DISPLAY_CONFIG); + misc = READ_VID32(RCDF_VID_MISC); + + dcfg |= RCDF_DCFG_GV_PAL_BYP; + misc &= ~RCDF_GAMMA_BYPASS_BOTH; + + WRITE_VID32(RCDF_DISPLAY_CONFIG, dcfg); + WRITE_VID32(RCDF_VID_MISC, misc); + + if (gfx_test_timing_active()) { + while (!gfx_test_vertical_active()) ; + while (gfx_test_vertical_active()) ; + while (!gfx_test_vertical_active()) ; + } + + /* LOAD REDCLOUD VIDEO PALETTE */ + + WRITE_VID32(RCDF_PALETTE_ADDRESS, 0); + for (i = 0; i < 256; i++) { + if (palette) + entry = palette[i]; + else + entry = gfx_gamma_ram_redcloud[i]; + WRITE_VID32(RCDF_PALETTE_DATA, entry); + } + + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_set_graphics_palette + * + * This routine loads the video hardware palette. If a NULL pointer is + * specified, the palette is bypassed (for Redcloud, this means loading the + * palette with identity values). Note that this routine is identical to + * gfx_set_video_palette, except that the hardware is updated to route + * graphics data through the palette. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +redcloud_set_graphics_palette(unsigned long *palette) +#else +int +gfx_set_graphics_palette(unsigned long *palette) +#endif +{ + unsigned long i, entry; + unsigned long misc, dcfg; + + /* ENABLE THE VIDEO PALETTE */ + /* Ensure that the video palette has an effect by routing video data */ + /* through the palette RAM and clearing the 'Bypass Both' bit. */ + + dcfg = READ_VID32(RCDF_DISPLAY_CONFIG); + misc = READ_VID32(RCDF_VID_MISC); + + dcfg &= ~RCDF_DCFG_GV_PAL_BYP; + misc &= ~RCDF_GAMMA_BYPASS_BOTH; + + WRITE_VID32(RCDF_DISPLAY_CONFIG, dcfg); + WRITE_VID32(RCDF_VID_MISC, misc); + + if (gfx_test_timing_active()) { + while (!gfx_test_vertical_active()) ; + while (gfx_test_vertical_active()) ; + while (!gfx_test_vertical_active()) ; + } + + /* LOAD REDCLOUD VIDEO PALETTE */ + + WRITE_VID32(RCDF_PALETTE_ADDRESS, 0); + for (i = 0; i < 256; i++) { + if (palette) + entry = palette[i]; + else + entry = gfx_gamma_ram_redcloud[i]; + WRITE_VID32(RCDF_PALETTE_DATA, entry); + } + + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_set_graphics_palette_entry + * + * This routine loads a single entry of the video hardware palette. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +redcloud_set_graphics_palette_entry(unsigned long index, + unsigned long palette) +#else +int +gfx_set_graphics_palette_entry(unsigned long index, unsigned long palette) +#endif +{ + unsigned long dcfg, misc; + + if (index > 0xFF) + return GFX_STATUS_BAD_PARAMETER; + + /* ENABLE THE VIDEO PALETTE */ + /* Ensure that the video palette has an effect by routing video data */ + /* through the palette RAM and clearing the 'Bypass Both' bit. */ + + dcfg = READ_VID32(RCDF_DISPLAY_CONFIG); + misc = READ_VID32(RCDF_VID_MISC); + + dcfg &= ~RCDF_DCFG_GV_PAL_BYP; + misc &= ~RCDF_GAMMA_BYPASS_BOTH; + + WRITE_VID32(RCDF_DISPLAY_CONFIG, dcfg); + WRITE_VID32(RCDF_VID_MISC, misc); + + /* SET A SINGLE ENTRY */ + + WRITE_VID32(RCDF_PALETTE_ADDRESS, index); + WRITE_VID32(RCDF_PALETTE_DATA, palette); + + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_set_video_palette_entry + * + * This routine loads a single entry of the video hardware palette. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +redcloud_set_video_palette_entry(unsigned long index, unsigned long palette) +#else +int +gfx_set_video_palette_entry(unsigned long index, unsigned long palette) +#endif +{ + unsigned long dcfg, misc; + + if (index > 0xFF) + return GFX_STATUS_BAD_PARAMETER; + + /* ENABLE THE VIDEO PALETTE */ + /* Ensure that the video palette has an effect by routing video data */ + /* through the palette RAM and clearing the 'Bypass Both' bit. */ + + dcfg = READ_VID32(RCDF_DISPLAY_CONFIG); + misc = READ_VID32(RCDF_VID_MISC); + + dcfg |= RCDF_DCFG_GV_PAL_BYP; + misc &= ~RCDF_GAMMA_BYPASS_BOTH; + + WRITE_VID32(RCDF_DISPLAY_CONFIG, dcfg); + WRITE_VID32(RCDF_VID_MISC, misc); + + /* SET A SINGLE ENTRY */ + + WRITE_VID32(RCDF_PALETTE_ADDRESS, index); + WRITE_VID32(RCDF_PALETTE_DATA, palette); + + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_set_video_palette_bypass + * + * This routine enables/disables the pallete RAM bypass. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +redcloud_set_video_palette_bypass(int enable) +#else +int +gfx_set_video_palette_bypass(int enable) +#endif +{ + unsigned long misc; + + misc = READ_VID32(RCDF_VID_MISC); + + if (enable) + misc |= RCDF_GAMMA_BYPASS_BOTH; + else + misc &= ~RCDF_GAMMA_BYPASS_BOTH; + + WRITE_VID32(RCDF_VID_MISC, misc); + + return 0; +} + +/*--------------------------------------------------------------------------- + * gfx_set_video_request() + * + * This routine sets the horizontal (pixel) and vertical (line) video request + * values. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +redcloud_set_video_request(short x, short y) +#else +int +gfx_set_video_request(short x, short y) +#endif +{ + /* SET DISPLAY FILTER VIDEO REQUEST */ + + x += gfx_get_htotal() - gfx_get_hsync_end() - 2; + y += gfx_get_vtotal() - gfx_get_vsync_end() + 1; + + if ((x < 0) || (x > RCDF_VIDEO_REQUEST_MASK) || + (y < 0) || (y > RCDF_VIDEO_REQUEST_MASK)) + return GFX_STATUS_BAD_PARAMETER; + + WRITE_VID32(RCDF_VIDEO_REQUEST, + ((unsigned long)x << RCDF_VIDEO_X_REQUEST_POS) | ((unsigned long)y << + RCDF_VIDEO_Y_REQUEST_POS)); + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_set_video_cursor() + * + * This routine configures the video hardware cursor. + * If the "mask"ed bits in the graphics pixel match "key", then either + * "color1" or "color2" will be used for this pixel, according to the value of + * bit number "select_color2" of the graphics pixel. + * + * key - 24 bit RGB value + * mask - 24 bit mask + * color1, color2 - RGB or YUV, depending on the current color space + * conversion select_color2 - value between 0 to 23 + * + * To disable match, a "mask" and "key" value of 0xffffff should be set, + * because the graphics pixels incoming to the video processor have maximum 16 + * bits set (0xF8FCF8). + * + * This feature is useful for disabling alpha blending of the cursor. + * Otherwise cursor image would be blurred (or completely invisible if video + * alpha is maximum value). + * Note: the cursor pixel replacements take place both inside and outside the + * video overlay window. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +redcloud_set_video_cursor(unsigned long key, unsigned long mask, + unsigned short select_color2, unsigned long color1, unsigned long color2) +#else +int +gfx_set_video_cursor(unsigned long key, unsigned long mask, + unsigned short select_color2, unsigned long color1, unsigned long color2) +#endif +{ + if (select_color2 > RCDF_CURSOR_COLOR_BITS) + return GFX_STATUS_BAD_PARAMETER; + key = + (key & RCDF_COLOR_MASK) | ((unsigned long)select_color2 << + RCDF_CURSOR_COLOR_KEY_OFFSET_POS); + WRITE_VID32(RCDF_CURSOR_COLOR_KEY, key); + WRITE_VID32(RCDF_CURSOR_COLOR_MASK, mask); + WRITE_VID32(RCDF_CURSOR_COLOR_1, color1); + WRITE_VID32(RCDF_CURSOR_COLOR_2, color2); + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_set_video_cursor() + * + * This routine configures the video hardware cursor. + * If the "mask"ed bits in the graphics pixel match "key", then either + * "color1"or "color2" will be used for this pixel, according to the value of + * bit number "select_color2" of the graphics pixel. + * + * key - 24 bit RGB value + * mask - 24 bit mask + * color1, color2 - RGB or YUV, depending on the current color space + * conversion select_color2 - value between 0 to 23 + * + * To disable match, a "mask" and "key" value of 0xffffff should be set, + * because the graphics pixels incoming to the video processor have maximum 16 + * bits set (0xF8FCF8). + * + * This feature is useful for disabling alpha blending of the cursor. + * Otherwise cursor image would be blurred (or completely invisible if video + * alpha is maximum value). + * Note: the cursor pixel replacements take place both inside and outside the + * video overlay window. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +redcloud_set_video_cursor_enable(int enable) +#else +int +gfx_set_video_cursor_enable(int enable) +#endif +{ + unsigned long temp = READ_VID32(RCDF_CURSOR_COLOR_KEY); + + if (enable) + temp |= RCDF_CURSOR_COLOR_KEY_ENABLE; + else + temp &= ~RCDF_CURSOR_COLOR_KEY_ENABLE; + + WRITE_VID32(RCDF_CURSOR_COLOR_KEY, temp); + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_set_alpha_enable + * + * This routine enables or disables the currently selected alpha region. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +redcloud_set_alpha_enable(int enable) +#else +int +gfx_set_alpha_enable(int enable) +#endif +{ + unsigned long address = 0, value = 0; + + if (gfx_alpha_select > 2) + return (GFX_STATUS_UNSUPPORTED); + address = RCDF_ALPHA_CONTROL_1 + ((unsigned long)gfx_alpha_select << 5); + value = READ_VID32(address); + if (enable) + value |= RCDF_ACTRL_WIN_ENABLE; + else + value &= ~(RCDF_ACTRL_WIN_ENABLE); + WRITE_VID32(address, value); + return (GFX_STATUS_OK); +} + +/*--------------------------------------------------------------------------- + * gfx_set_alpha_window + * + * This routine sets the size of the currently selected alpha region. + * Note: "x" and "y" are signed to enable using negative values needed for + * implementing workarounds of hardware issues. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +redcloud_set_alpha_window(short x, short y, + unsigned short width, unsigned short height) +#else +int +gfx_set_alpha_window(short x, short y, + unsigned short width, unsigned short height) +#endif +{ + unsigned long address = 0; + + /* CHECK FOR CLIPPING */ + + if ((x + width) > gfx_get_hactive()) + width = gfx_get_hactive() - x; + if ((y + height) > gfx_get_vactive()) + height = gfx_get_vactive() - y; + + /* ADJUST POSITIONS */ + + x += gfx_get_htotal() - gfx_get_hsync_end() - 2; + y += gfx_get_vtotal() - gfx_get_vsync_end() + 1; + + if (gfx_alpha_select > 2) + return (GFX_STATUS_UNSUPPORTED); + address = RCDF_ALPHA_XPOS_1 + ((unsigned long)gfx_alpha_select << 5); + + /* END POSITIONS IN REGISTERS ARE NON-INCLUSIVE (ONE MORE THAN ACTUAL END) + * */ + + WRITE_VID32(address, (unsigned long)x | + ((unsigned long)(x + width) << 16)); + WRITE_VID32(address + 8, (unsigned long)y | + ((unsigned long)(y + height) << 16)); + return (GFX_STATUS_OK); +} + +/*--------------------------------------------------------------------------- + * gfx_set_alpha_value + * + * This routine sets the alpha value for the currently selected alpha + * region. It also specifies an increment/decrement value for fading. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +redcloud_set_alpha_value(unsigned char alpha, char delta) +#else +int +gfx_set_alpha_value(unsigned char alpha, char delta) +#endif +{ + unsigned long address = 0, value = 0; + + if (gfx_alpha_select > 2) + return (GFX_STATUS_UNSUPPORTED); + address = RCDF_ALPHA_CONTROL_1 + ((unsigned long)gfx_alpha_select << 5); + value = READ_VID32(address); + value &= RCDF_ACTRL_WIN_ENABLE; /* keep only enable bit */ + value |= (unsigned long)alpha; + value |= (((unsigned long)delta) & 0xff) << 8; + value |= RCDF_ACTRL_LOAD_ALPHA; + WRITE_VID32(address, value); + return (GFX_STATUS_OK); +} + +/*--------------------------------------------------------------------------- + * gfx_set_alpha_priority + * + * This routine sets the priority of the currently selected alpha region. + * A higher value indicates a higher priority. + * Note: Priority of enabled alpha windows must be different. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +redcloud_set_alpha_priority(int priority) +#else +int +gfx_set_alpha_priority(int priority) +#endif +{ + unsigned long pos = 0, value = 0; + + if (priority > 3) + return (GFX_STATUS_BAD_PARAMETER); + if (gfx_alpha_select > 2) + return (GFX_STATUS_UNSUPPORTED); + value = READ_VID32(RCDF_VID_ALPHA_CONTROL); + pos = 16 + (gfx_alpha_select << 1); + value &= ~(0x03l << pos); + value |= (unsigned long)priority << pos; + WRITE_VID32(RCDF_VID_ALPHA_CONTROL, value); + return (GFX_STATUS_OK); +} + +/*--------------------------------------------------------------------------- + * gfx_set_alpha_color + * + * This routine sets the color to be displayed inside the currently selected + * alpha window when there is a color key match (when the alpha color + * mechanism is enabled). + * "color" is an RGB value (for RGB blending) or a YUV value (for YUV + * blending). + * In Interlaced YUV blending mode, Y/2 value should be used. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +redcloud_set_alpha_color(unsigned long color) +#else +int +gfx_set_alpha_color(unsigned long color) +#endif +{ + unsigned long address = 0; + + if (gfx_alpha_select > 2) + return (GFX_STATUS_UNSUPPORTED); + address = RCDF_ALPHA_COLOR_1 + ((unsigned long)gfx_alpha_select << 5); + WRITE_VID32(address, color); + return (GFX_STATUS_OK); +} + +/*--------------------------------------------------------------------------- + * gfx_set_alpha_color_enable + * + * Enable or disable the color mechanism in the alpha window. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +redcloud_set_alpha_color_enable(int enable) +#else +int +gfx_set_alpha_color_enable(int enable) +#endif +{ + unsigned long color; + unsigned long address = 0; + + if (gfx_alpha_select > 2) + return (GFX_STATUS_UNSUPPORTED); + address = RCDF_ALPHA_COLOR_1 + ((unsigned long)gfx_alpha_select << 5); + color = READ_VID32(address); + if (enable) + color |= RCDF_ALPHA_COLOR_ENABLE; + else + color &= ~RCDF_ALPHA_COLOR_ENABLE; + WRITE_VID32(address, color); + return (GFX_STATUS_OK); +} + +/*--------------------------------------------------------------------------- + * gfx_set_no_ck_outside_alpha + * + * This function affects where inside the video window color key or chroma + * key comparison is done: + * If enable is TRUE, color/chroma key comparison is performed only inside + * the enabled alpha windows. Outside the (enabled) alpha windows, only video + * is displayed if color key is used, and only graphics is displayed if chroma + * key is used. + * If enable is FALSE, color/chroma key comparison is performed in all the + * video window area. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +redcloud_set_no_ck_outside_alpha(int enable) +#else +int +gfx_set_no_ck_outside_alpha(int enable) +#endif +{ + unsigned long value; + + value = READ_VID32(RCDF_VID_ALPHA_CONTROL); + if (enable) + WRITE_VID32(RCDF_VID_ALPHA_CONTROL, value | RCDF_NO_CK_OUTSIDE_ALPHA); + else + WRITE_VID32(RCDF_VID_ALPHA_CONTROL, + value & ~RCDF_NO_CK_OUTSIDE_ALPHA); + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_get_clock_frequency + * + * This routine returns the current clock frequency in 16.16 format. + * It reads the current register value and finds the match in the table. + * If no match is found, this routine returns 0. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +unsigned long +redcloud_get_clock_frequency(void) +#else +unsigned long +gfx_get_clock_frequency(void) +#endif +{ + Q_WORD msr_value; + unsigned int index; + unsigned long value, mask = 0x00001FFF; + unsigned long post_div3 = 0, pre_mult2 = 0; + + /* READ PLL SETTING */ + + gfx_msr_read(RC_ID_MCP, MCP_DOTPLL, &msr_value); + value = msr_value.high & mask; + + /* READ DIVISOR SETTINGS */ + + gfx_msr_read(RC_ID_MCP, MCP_SYS_RSTPLL, &msr_value); + post_div3 = (msr_value.low & MCP_DOTPOSTDIV3) ? 1 : 0; + pre_mult2 = (msr_value.low & MCP_DOTPREMULT2) ? 1 : 0; + + /* SEARCH FOR A MATCH */ + + for (index = 0; index < NUM_RCDF_FREQUENCIES; index++) { + if ((RCDF_PLLtable[index].pll_value & mask) == value && + post_div3 == RCDF_PLLtable[index].post_div3 && + pre_mult2 == RCDF_PLLtable[index].pre_mul2) + return (RCDF_PLLtable[index].frequency); + } + return (0); +} + +/*************************************************************/ +/* READ ROUTINES | INCLUDED FOR DIAGNOSTIC PURPOSES ONLY */ +/*************************************************************/ + +#if GFX_READ_ROUTINES + +/*--------------------------------------------------------------------------- + * gfx_get_sync_polarities + * + * This routine returns the polarities of the sync pulses: + * Bit 0: Set if negative horizontal polarity. + * Bit 1: Set if negative vertical polarity. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +redcloud_get_sync_polarities(void) +#else +int +gfx_get_sync_polarities(void) +#endif +{ + int polarities = 0; + + if (READ_VID32(RCDF_DISPLAY_CONFIG) & RCDF_DCFG_CRT_HSYNC_POL) + polarities |= 1; + if (READ_VID32(RCDF_DISPLAY_CONFIG) & RCDF_DCFG_CRT_VSYNC_POL) + polarities |= 2; + return (polarities); +} + +/*--------------------------------------------------------------------------- + * gfx_get_video_palette_entry + * + * This routine returns a single palette entry. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +redcloud_get_video_palette_entry(unsigned long index, unsigned long *palette) +#else +int +gfx_get_video_palette_entry(unsigned long index, unsigned long *palette) +#endif +{ + if (index > 0xFF) + return GFX_STATUS_BAD_PARAMETER; + + /* READ A SINGLE ENTRY */ + + WRITE_VID32(RCDF_PALETTE_ADDRESS, index); + *palette = READ_VID32(RCDF_PALETTE_DATA); + + return (GFX_STATUS_OK); +} + +/*---------------------------------------------------------------------------- + * gfx_get_video_enable + * + * This routine returns the value "one" if video overlay is currently enabled, + * otherwise it returns the value "zero". + *---------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +redcloud_get_video_enable(void) +#else +int +gfx_get_video_enable(void) +#endif +{ + if (READ_VID32(RCDF_VIDEO_CONFIG) & RCDF_VCFG_VID_EN) + return (1); + return (0); +} + +/*---------------------------------------------------------------------------- + * gfx_get_video_format + * + * This routine returns the current video overlay format. + *---------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +redcloud_get_video_format(void) +#else +int +gfx_get_video_format(void) +#endif +{ + unsigned long ctrl, vcfg; + + ctrl = READ_VID32(RCDF_VID_ALPHA_CONTROL); + vcfg = READ_VID32(RCDF_VIDEO_CONFIG); + + if (ctrl & RCDF_VIDEO_INPUT_IS_RGB) { + switch (vcfg & RCDF_VCFG_VID_INP_FORMAT) { + case RCDF_VCFG_UYVY_FORMAT: + return VIDEO_FORMAT_RGB; + case RCDF_VCFG_Y2YU_FORMAT: + return VIDEO_FORMAT_P2M_P2L_P1M_P1L; + case RCDF_VCFG_YUYV_FORMAT: + return VIDEO_FORMAT_P1M_P1L_P2M_P2L; + case RCDF_VCFG_YVYU_FORMAT: + return VIDEO_FORMAT_P1M_P2L_P2M_P1L; + } + } + + if (vcfg & RCDF_VCFG_4_2_0_MODE) { + switch (vcfg & RCDF_VCFG_VID_INP_FORMAT) { + case RCDF_VCFG_UYVY_FORMAT: + return VIDEO_FORMAT_Y0Y1Y2Y3; + case RCDF_VCFG_Y2YU_FORMAT: + return VIDEO_FORMAT_Y3Y2Y1Y0; + case RCDF_VCFG_YUYV_FORMAT: + return VIDEO_FORMAT_Y1Y0Y3Y2; + case RCDF_VCFG_YVYU_FORMAT: + return VIDEO_FORMAT_Y1Y2Y3Y0; + } + } else { + switch (vcfg & RCDF_VCFG_VID_INP_FORMAT) { + case RCDF_VCFG_UYVY_FORMAT: + return VIDEO_FORMAT_UYVY; + case RCDF_VCFG_Y2YU_FORMAT: + return VIDEO_FORMAT_Y2YU; + case RCDF_VCFG_YUYV_FORMAT: + return VIDEO_FORMAT_YUYV; + case RCDF_VCFG_YVYU_FORMAT: + return VIDEO_FORMAT_YVYU; + } + } + return (GFX_STATUS_ERROR); +} + +/*---------------------------------------------------------------------------- + * gfx_get_video_src_size + * + * This routine returns the size of the source video overlay buffer. The + * return value is (height << 16) | width. + *---------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +unsigned long +redcloud_get_video_src_size(void) +#else +unsigned long +gfx_get_video_src_size(void) +#endif +{ + unsigned long width, height, scale, delta; + int down_enable; + + /* DETERMINE SOURCE WIDTH FROM THE DISPLAY FILTER VIDEO LINE SIZE */ + + width = (READ_VID32(RCDF_VIDEO_CONFIG) >> 7) & 0x000001FE; + if (READ_VID32(RCDF_VIDEO_CONFIG) & RCDF_VCFG_LINE_SIZE_UPPER) + width += 512l; + + /* DETERMINE SOURCE HEIGHT FROM THE DISPLAY FILTER HEIGHT AND SCALE VALUES + * There is no true "source buffer size" in Redcloud. Instead, the VG + * module provides video data as needed on a per-line basis. The source + * buffer size is always assumed to equal the amount of required video + * data. The returned height is equal to the height of the required video + * buffer data (before all scaling.) + * */ + + scale = (READ_VID32(RCDF_VIDEO_SCALE) >> 16) & 0x3FFF; + height = ((READ_VID32(RCDF_VIDEO_Y_POS) >> 16) & 0x7FF) - + (READ_VID32(RCDF_VIDEO_Y_POS) & 0x7FF); + delta = gfx_get_video_downscale_delta(); + down_enable = gfx_get_video_vertical_downscale_enable(); + + /* REVERSE UPSCALING */ + + if (height) + height = ((scale * (height - 1l)) / 0x2000l) + 2l; + + /* REVERSE DOWNSCALING */ + /* Original lines = height * (0x3FFF + delta) / 0x3FFF */ + /* As this may cause rounding errors, we add 1 to the */ + /* returned source size. The return value of this */ + /* function could thus be off by 1. */ + + if (down_enable && height) + height = ((height * (0x3FFFl + delta)) / 0x3FFFl) + 1; + + return ((height << 16) | width); +} + +/*---------------------------------------------------------------------------- + * gfx_get_video_line_size + * + * This routine returns the line size of the source video overlay buffer, in + * pixels. + *---------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +unsigned long +redcloud_get_video_line_size(void) +#else +unsigned long +gfx_get_video_line_size(void) +#endif +{ + unsigned long width = 0; + + /* DETERMINE SOURCE WIDTH FROM THE RCDF VIDEO LINE SIZE */ + + width = (READ_VID32(RCDF_VIDEO_CONFIG) >> 7) & 0x000001FE; + if (READ_VID32(RCDF_VIDEO_CONFIG) & RCDF_VCFG_LINE_SIZE_UPPER) + width += 512l; + return (width); +} + +/*---------------------------------------------------------------------------- + * gfx_get_video_xclip + * + * This routine returns the number of bytes clipped on the left side of a + * video overlay line (skipped at beginning). + *---------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +unsigned long +redcloud_get_video_xclip(void) +#else +unsigned long +gfx_get_video_xclip(void) +#endif +{ + unsigned long clip = 0; + + /* DETERMINE SOURCE WIDTH FROM THE RCDF VIDEO LINE SIZE */ + + clip = (READ_VID32(RCDF_VIDEO_CONFIG) >> 14) & 0x000007FC; + return (clip); +} + +/*---------------------------------------------------------------------------- + * gfx_get_video_offset + * + * This routine returns the current offset for the video overlay buffer. + *---------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +unsigned long +redcloud_get_video_offset(void) +#else +unsigned long +gfx_get_video_offset(void) +#endif +{ + return (gfx_get_display_video_offset()); +} + +/*---------------------------------------------------------------------------- + * gfx_get_video_yuv_offsets + * + * This routine returns the current offsets for the video overlay buffer when in 4:2:0. + *---------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +void +redcloud_get_video_yuv_offsets(unsigned long *yoffset, unsigned long *uoffset, + unsigned long *voffset) +#else +void +gfx_get_video_yuv_offsets(unsigned long *yoffset, unsigned long *uoffset, + unsigned long *voffset) +#endif +{ + gfx_get_display_video_yuv_offsets(yoffset, uoffset, voffset); +} + +/*---------------------------------------------------------------------------- + * gfx_get_video_yuv_pitch + * + * This routine returns the current pitch values for the video overlay buffer. + *---------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +void +redcloud_get_video_yuv_pitch(unsigned long *ypitch, unsigned long *uvpitch) +#else +void +gfx_get_video_yuv_pitch(unsigned long *ypitch, unsigned long *uvpitch) +#endif +{ + gfx_get_display_video_yuv_pitch(ypitch, uvpitch); +} + +/*--------------------------------------------------------------------------- + * gfx_get_video_scale + * + * This routine returns the scale factor for the video overlay window. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +unsigned long +redcloud_get_video_scale(void) +#else +unsigned long +gfx_get_video_scale(void) +#endif +{ + return (READ_VID32(RCDF_VIDEO_SCALE)); +} + +/*--------------------------------------------------------------------------- + * gfx_get_video_downscale_delta + * + * This routine returns the vertical downscale factor for the video overlay + * window. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +unsigned long +redcloud_get_video_downscale_delta(void) +#else +unsigned long +gfx_get_video_downscale_delta(void) +#endif +{ + /* USE PRIVATE ROUTINE TO ABSTRACT THE DIPSLAY CONTROLLER */ + + return (gfx_get_display_video_downscale_delta()); +} + +/*--------------------------------------------------------------------------- + * gfx_get_video_vertical_downscale_enable + * + * This routine returns the vertical downscale enable for the video overlay + * window. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +redcloud_get_video_vertical_downscale_enable(void) +#else +int +gfx_get_video_vertical_downscale_enable(void) +#endif +{ + /* USE PRIVATE ROUTINE TO ABSTRACT THE DIPSLAY CONTROLLER */ + + return (gfx_get_display_video_downscale_enable()); +} + +/*--------------------------------------------------------------------------- + * gfx_get_video_downscale_config + * + * This routine returns the current type and value of video downscaling. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +redcloud_get_video_downscale_config(unsigned short *type, unsigned short *m) +#else +int +gfx_get_video_downscale_config(unsigned short *type, unsigned short *m) +#endif +{ + unsigned long downscale; + + downscale = READ_VID32(RCDF_VIDEO_DOWNSCALER_CONTROL); + *m = (unsigned short)((downscale & RCDF_VIDEO_DOWNSCALE_FACTOR_MASK) >> + RCDF_VIDEO_DOWNSCALE_FACTOR_POS) + 1; + + switch (downscale & RCDF_VIDEO_DOWNSCALE_TYPE_MASK) { + case RCDF_VIDEO_DOWNSCALE_TYPE_A: + *type = VIDEO_DOWNSCALE_KEEP_1_OF; + break; + case RCDF_VIDEO_DOWNSCALE_TYPE_B: + *type = VIDEO_DOWNSCALE_DROP_1_OF; + break; + default: + return GFX_STATUS_ERROR; + break; + } + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_get_video_downscale_coefficients + * + * This routine returns the current video downscaling coefficients. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +void +redcloud_get_video_downscale_coefficients(unsigned short *coef1, + unsigned short *coef2, unsigned short *coef3, unsigned short *coef4) +#else +void +gfx_get_video_downscale_coefficients(unsigned short *coef1, + unsigned short *coef2, unsigned short *coef3, unsigned short *coef4) +#endif +{ + unsigned long coef; + + coef = READ_VID32(RCDF_VIDEO_DOWNSCALER_COEFFICIENTS); + *coef1 = + (unsigned short)((coef >> RCDF_VIDEO_DOWNSCALER_COEF1_POS) & + RCDF_VIDEO_DOWNSCALER_COEF_MASK); + *coef2 = + (unsigned short)((coef >> RCDF_VIDEO_DOWNSCALER_COEF2_POS) & + RCDF_VIDEO_DOWNSCALER_COEF_MASK); + *coef3 = + (unsigned short)((coef >> RCDF_VIDEO_DOWNSCALER_COEF3_POS) & + RCDF_VIDEO_DOWNSCALER_COEF_MASK); + *coef4 = + (unsigned short)((coef >> RCDF_VIDEO_DOWNSCALER_COEF4_POS) & + RCDF_VIDEO_DOWNSCALER_COEF_MASK); + return; +} + +/*--------------------------------------------------------------------------- + * gfx_get_video_downscale_enable + * + * This routine returns 1 if video downscaling is currently enabled, + * or 0 if it is currently disabled. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +void +redcloud_get_video_downscale_enable(int *enable) +#else +void +gfx_get_video_downscale_enable(int *enable) +#endif +{ + if (READ_VID32(RCDF_VIDEO_DOWNSCALER_CONTROL) & + RCDF_VIDEO_DOWNSCALE_ENABLE) + *enable = 1; + else + *enable = 0; + return; +} + +/*--------------------------------------------------------------------------- + * gfx_get_video_dst_size + * + * This routine returns the size of the displayed video overlay window. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +unsigned long +redcloud_get_video_dst_size(void) +#else +unsigned long +gfx_get_video_dst_size(void) +#endif +{ + unsigned long xsize, ysize; + + xsize = READ_VID32(RCDF_VIDEO_X_POS); + xsize = ((xsize >> 16) & 0x7FF) - (xsize & 0x7FF); + ysize = READ_VID32(RCDF_VIDEO_Y_POS); + ysize = ((ysize >> 16) & 0x7FF) - (ysize & 0x7FF); + return ((ysize << 16) | xsize); +} + +/*--------------------------------------------------------------------------- + * gfx_get_video_position + * + * This routine returns the position of the video overlay window. The + * return value is (ypos << 16) | xpos. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +unsigned long +redcloud_get_video_position(void) +#else +unsigned long +gfx_get_video_position(void) +#endif +{ + unsigned long hadjust, vadjust; + unsigned long xpos, ypos; + + /* READ HARDWARE POSITION */ + + xpos = READ_VID32(RCDF_VIDEO_X_POS) & 0x000007FF; + ypos = READ_VID32(RCDF_VIDEO_Y_POS) & 0x000007FF; + + /* GET ADJUSTMENT VALUES */ + /* Use routines to abstract version of display controller. */ + + hadjust = + (unsigned long)gfx_get_htotal() - (unsigned long)gfx_get_hsync_end() - + 14l; + vadjust = + (unsigned long)gfx_get_vtotal() - (unsigned long)gfx_get_vsync_end() + + 1l; + xpos -= hadjust; + ypos -= vadjust; + return ((ypos << 16) | (xpos & 0x0000FFFF)); +} + +/*--------------------------------------------------------------------------- + * gfx_get_video_color_key + * + * This routine returns the current video color key value. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +unsigned long +redcloud_get_video_color_key(void) +#else +unsigned long +gfx_get_video_color_key(void) +#endif +{ + return (READ_VID32(RCDF_VIDEO_COLOR_KEY)); +} + +/*--------------------------------------------------------------------------- + * gfx_get_video_color_key_mask + * + * This routine returns the current video color mask value. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +unsigned long +redcloud_get_video_color_key_mask(void) +#else +unsigned long +gfx_get_video_color_key_mask(void) +#endif +{ + return (READ_VID32(RCDF_VIDEO_COLOR_MASK)); +} + +/*--------------------------------------------------------------------------- + * gfx_get_video_color_key_src + * + * This routine returns 0 for video data compare, 1 for graphics data. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +redcloud_get_video_color_key_src(void) +#else +int +gfx_get_video_color_key_src(void) +#endif +{ + if (READ_VID32(RCDF_DISPLAY_CONFIG) & RCDF_DCFG_VG_CK) + return (0); + return (1); +} + +/*--------------------------------------------------------------------------- + * gfx_get_video_filter + * + * This routine returns if the filters are currently enabled. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +redcloud_get_video_filter(void) +#else +int +gfx_get_video_filter(void) +#endif +{ + int retval = 0; + + if (READ_VID32(RCDF_VIDEO_CONFIG) & RCDF_VCFG_X_FILTER_EN) + retval |= 1; + if (READ_VID32(RCDF_VIDEO_CONFIG) & RCDF_VCFG_Y_FILTER_EN) + retval |= 2; + return (retval); +} + +/*--------------------------------------------------------------------------- + * gfx_get_video_request + * + * This routine returns the horizontal (pixel) and vertical (lines) video + * request values. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +redcloud_get_video_request(short *x, short *y) +#else +int +gfx_get_video_request(short *x, short *y) +#endif +{ + unsigned long request = 0; + + request = (READ_VID32(RCDF_VIDEO_REQUEST)); + *x = (short)((request >> RCDF_VIDEO_X_REQUEST_POS) & + RCDF_VIDEO_REQUEST_MASK); + *y = (short)((request >> RCDF_VIDEO_Y_REQUEST_POS) & + RCDF_VIDEO_REQUEST_MASK); + + *x -= gfx_get_htotal() - gfx_get_hsync_end() - 2; + *y -= gfx_get_vtotal() - gfx_get_vsync_end() + 1; + + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_get_video_cursor() + * + * This routine configures the video hardware cursor. + * If the "mask"ed bits in the graphics pixel match "key", then either + * "color1" or "color2" will be used for this pixel, according to the value of + * the bit in offset "select_color2". + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +int +redcloud_get_video_cursor(unsigned long *key, unsigned long *mask, + unsigned short *select_color2, unsigned long *color1, + unsigned short *color2) +#else +int +gfx_get_video_cursor(unsigned long *key, unsigned long *mask, + unsigned short *select_color2, unsigned long *color1, + unsigned short *color2) +#endif +{ + *select_color2 = + (unsigned short)(READ_VID32(RCDF_CURSOR_COLOR_KEY) >> + RCDF_CURSOR_COLOR_KEY_OFFSET_POS); + *key = READ_VID32(RCDF_CURSOR_COLOR_KEY) & RCDF_COLOR_MASK; + *mask = READ_VID32(RCDF_CURSOR_COLOR_MASK) & RCDF_COLOR_MASK; + *color1 = READ_VID32(RCDF_CURSOR_COLOR_1) & RCDF_COLOR_MASK; + *color2 = + (unsigned short)(READ_VID32(RCDF_CURSOR_COLOR_2) & RCDF_COLOR_MASK); + return (0); +} + +/*--------------------------------------------------------------------------- + * gfx_read_crc + * + * This routine returns the hardware CRC value, which is used for automated + * testing. The value is like a checksum, but will change if pixels move + * locations. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +unsigned long +redcloud_read_crc(void) +#else +unsigned long +gfx_read_crc(void) +#endif +{ + Q_WORD msr_value; + unsigned long crc = 0xFFFFFFFF; + + /* DISABLE 32-BIT CRCS */ + /* For GX1.x, this is a reserved bit, and is assumed to be a benign + * access */ + + gfx_msr_read(RC_ID_DF, RCDF_MBD_MSR_DIAG_DF, &msr_value); + msr_value.low &= ~RCDF_DIAG_32BIT_CRC; + gfx_msr_write(RC_ID_DF, RCDF_MBD_MSR_DIAG_DF, &msr_value); + + if (gfx_test_timing_active()) { + /* WAIT UNTIL ACTIVE DISPLAY */ + + while (!gfx_test_vertical_active()) ; + + /* RESET CRC DURING ACTIVE DISPLAY */ + + WRITE_VID32(RCDF_VID_CRC, 0); + WRITE_VID32(RCDF_VID_CRC, 1); + + /* WAIT UNTIL NOT ACTIVE, THEN ACTIVE, NOT ACTIVE, THEN ACTIVE */ + + while (!gfx_test_vertical_active()) ; + while (gfx_test_vertical_active()) ; + while (!gfx_test_vertical_active()) ; + while (gfx_test_vertical_active()) ; + while (!gfx_test_vertical_active()) ; + crc = READ_VID32(RCDF_VID_CRC) >> 8; + } + return (crc); +} + +/*--------------------------------------------------------------------------- + * gfx_read_crc32 + * + * This routine returns the 32-bit hardware CRC value, which is used for + * automated testing. The value is like a checksum, but will change if pixels + * move locations. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +unsigned long +redcloud_read_crc32(void) +#else +unsigned long +gfx_read_crc32(void) +#endif +{ + Q_WORD msr_value; + unsigned long crc = 0xFFFFFFFF; + + /* ENABLE 32-BIT CRCS */ + /* For GX1.x, this is a reserved bit, and is assumed to be a benign + * access */ + + gfx_msr_read(RC_ID_DF, RCDF_MBD_MSR_DIAG_DF, &msr_value); + msr_value.low |= RCDF_DIAG_32BIT_CRC; + gfx_msr_write(RC_ID_DF, RCDF_MBD_MSR_DIAG_DF, &msr_value); + + if (gfx_test_timing_active()) { + /* WAIT UNTIL ACTIVE DISPLAY */ + + while (!gfx_test_vertical_active()) ; + + /* RESET CRC DURING ACTIVE DISPLAY */ + + WRITE_VID32(RCDF_VID_CRC, 0); + WRITE_VID32(RCDF_VID_CRC, 1); + + /* WAIT UNTIL NOT ACTIVE, THEN ACTIVE, NOT ACTIVE, THEN ACTIVE */ + + while (!gfx_test_vertical_active()) ; + while (gfx_test_vertical_active()) ; + while (!gfx_test_vertical_active()) ; + while (gfx_test_vertical_active()) ; + while (!gfx_test_vertical_active()) ; + crc = READ_VID32(RCDF_VID_CRC32); + } + return (crc); +} + +/*--------------------------------------------------------------------------- + * gfx_read_window_crc + * + * This routine returns the hardware CRC value for a subsection of the display + * This value is used to debug whole-screen CRC failures. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +unsigned long +redcloud_read_window_crc(int source, unsigned short x, unsigned short y, + unsigned short width, unsigned short height, int crc32) +#else +unsigned long +gfx_read_window_crc(int source, unsigned short x, unsigned short y, + unsigned short width, unsigned short height, int crc32) +#endif +{ + Q_WORD msr_value; + unsigned long xpos, ypos, crc = 0; + unsigned long old_fmt = 0; + unsigned int vsync_active_base, vsync_inactive_base, hsync_active_base; + unsigned int vsync_active_shift, vsync_inactive_shift, hsync_active_shift; + unsigned int vsync_bit, hsync_bit, sync_polarities = 0; + + /* CONFIGURE DISPLAY FILTER TO LOAD DATA ONTO LOWER 32-BITS */ + + msr_value.high = 0; + msr_value.low = + (source == CRC_SOURCE_GFX_DATA) ? (RCDF_MBD_DIAG_EN0 | 0x0000000F) + : (RCDF_MBD_DIAG_EN0 | 0x0000000B); + gfx_msr_write(RC_ID_DF, MBD_MSR_DIAG, &msr_value); + + /* CONFIGURE DISPLAY FILTER FOR APPROPRIATE OUTPUT */ + + if (source != CRC_SOURCE_GFX_DATA) { + gfx_msr_read(RC_ID_DF, MBD_MSR_CONFIG, &msr_value); + old_fmt = msr_value.low; + msr_value.low &= ~(RCDF_CONFIG_FMT_MASK); + msr_value.low |= + ((source == + CRC_SOURCE_FP_DATA) ? RCDF_CONFIG_FMT_FP : + RCDF_CONFIG_FMT_CRT); + gfx_msr_write(RC_ID_DF, MBD_MSR_CONFIG, &msr_value); + } + + /* CONFIGURE MCP TO LOAD REGB DATA ONTO UPPER 32-BITS */ + + msr_value.low = MCP_MBD_DIAG_EN1 | 0x00050000; + gfx_msr_write(RC_ID_MCP, MBD_MSR_DIAG, &msr_value); + + /* ENABLE HW CLOCK GATING AND SET MCP CLOCK TO DOT CLOCK */ + + msr_value.low = 1l; + gfx_msr_write(RC_ID_MCP, MBD_MSR_PM, &msr_value); + msr_value.low = 0; + gfx_msr_write(RC_ID_MCP, MCP_DBGCLKCTL, &msr_value); + msr_value.low = 3; + gfx_msr_write(RC_ID_MCP, MCP_DBGCLKCTL, &msr_value); + + /* DISABLE MCP ACTIONS */ + + msr_value.high = 0x00000000; + msr_value.low = 0x00000000; + gfx_msr_write(RC_ID_MCP, MCP_DIAGCTL, &msr_value); + + /* SET APPROPRIATE BASE ADDRESS */ + /* M-Sets use normal diag bits, while N-Sets use inverted diag bits */ + /* We thus use the M-sets when polling for a high signal and the N */ + /* sets when polling for a low signal. */ + + if (source != CRC_SOURCE_GFX_DATA) { + sync_polarities = gfx_get_sync_polarities(); + vsync_bit = 29; + hsync_bit = 30; + } else { + vsync_bit = 25; + hsync_bit = 26; + } + + if (sync_polarities & 1) { + hsync_active_base = MCP_SETM0CTL; + hsync_active_shift = 2; + } else { + hsync_active_base = MCP_SETN0CTL; + hsync_active_shift = 1; + } + if (sync_polarities & 2) { + vsync_active_base = MCP_SETM0CTL; + vsync_inactive_base = MCP_SETN0CTL; + vsync_active_shift = 2; + vsync_inactive_shift = 1; + } else { + vsync_active_base = MCP_SETN0CTL; + vsync_inactive_base = MCP_SETM0CTL; + vsync_active_shift = 1; + vsync_inactive_shift = 2; + } + + /* SET STATE TRANSITIONS */ + + /* STATE 0-1 TRANSITION (SET 0) */ + /* XState = 00 and VSync Inactive */ + /* Note: DF VSync = Diag Bus Bit 29 */ + /* VG VSync = Diag Bus Bit 25 */ + + msr_value.low = 0x000000A0; + msr_value.high = 0x00008000 | ((unsigned long)vsync_bit << 16) | + ((unsigned long)vsync_bit << 21) | ((unsigned long)vsync_bit << 26); + gfx_msr_write(RC_ID_MCP, vsync_inactive_base, &msr_value); + + /* STATE 1-2 TRANSITION (SET 4) */ + /* XState = 01 and VSync Active */ + + msr_value.low = 0x000000C0; + gfx_msr_write(RC_ID_MCP, vsync_active_base + 4, &msr_value); + + /* STATE 2-3 TRANSITION (SET 1) */ + /* XState = 10 and VSync Inactive */ + + msr_value.low = 0x00000120; + gfx_msr_write(RC_ID_MCP, vsync_inactive_base + 1, &msr_value); + + /* HORIZONTAL COUNTER (SET 5) */ + /* XState = 10 and HSync Active */ + /* Notes: DF HSync = Diag Bus Bit 30 */ + /* VG HSync = Diag Bus Bit 26 */ + + msr_value.high = 0x00008000 | ((unsigned long)hsync_bit << 16) | + ((unsigned long)hsync_bit << 21) | ((unsigned long)hsync_bit << 26); + msr_value.low = 0x00000120; + gfx_msr_write(RC_ID_MCP, hsync_active_base + 5, &msr_value); + + /* HORIZONTAL COUNTER RESET (SET 4) */ + /* XState = 10 and H. Counter = limit */ + /* Note: H. Counter is lower 16-bits of */ + /* RegB. */ + + msr_value.high = 0x00000000; + msr_value.low = 0x00000128; + gfx_msr_write(RC_ID_MCP, vsync_inactive_base + 4, &msr_value); + + /* CRC TRIGGER (SET 0) */ + /* Cmp0 <= xpos < Cmp1 */ + /* Cmp2 <= ypos < Cmp2 */ + + msr_value.high = 0x00000000; + msr_value.low = 0x10C20120; + gfx_msr_write(RC_ID_MCP, vsync_active_base, &msr_value); + + /* SET COMPARATOR VALUES */ + /* Note: The VG data outputs from the DF are delayed by one pixel clock. */ + /* In this mode, we thus add one to horizontal comparator limits. */ + + /* COMPARATOR 0 */ + /* Lower limit = xpos + (h_blank_pixels - 1) - 3 */ + /* Notes: */ + /* 1. 3 is the pipeline delay for MCP register */ + /* data to access the diag bus */ + /* 2. h_blank_pixels = HTOTAL - HSYNC_END */ + + xpos = (unsigned long)x + ((unsigned long)gfx_get_htotal() - + (unsigned long)gfx_get_hsync_end() - 1l) - 3l; + if (source == CRC_SOURCE_GFX_DATA) + xpos++; + msr_value.high = 0x00000000; + msr_value.low = xpos; + gfx_msr_write(RC_ID_MCP, MCP_CMPVAL0, &msr_value); + + /* COMPARATOR 1 */ + /* Upper limit = xpos + width + (h_blank_pixels - 1) - 3 */ + + msr_value.low = xpos + (unsigned long)width; + gfx_msr_write(RC_ID_MCP, MCP_CMPVAL0 + 2, &msr_value); + + /* COMPARATOR 2 */ + /* Lower limit = ypos + v_blank_pixels */ + /* Notes: */ + /* 1. v_blank_pixels = VTOTAL - VSYNC_END */ + + ypos = + (unsigned long)y + (unsigned long)gfx_get_vtotal() - + (unsigned long)gfx_get_vsync_end(); + msr_value.low = ypos << 16; + gfx_msr_write(RC_ID_MCP, MCP_CMPVAL0 + 4, &msr_value); + + /* COMPARATOR 3 */ + /* Upper limit = ypos + height + v_blank_pixels */ + + msr_value.low = (ypos + (unsigned long)height) << 16; + gfx_msr_write(RC_ID_MCP, MCP_CMPVAL0 + 6, &msr_value); + + /* SET COMPARATOR MASKS */ + + /* COMPARATORS 0 AND 1 REFER TO LOWER 16 BITS OF REGB */ + + msr_value.high = 0x00000000; + msr_value.low = 0x0000FFFF; + gfx_msr_write(RC_ID_MCP, MCP_CMPMASK0, &msr_value); + gfx_msr_write(RC_ID_MCP, MCP_CMPMASK0 + 2, &msr_value); + + /* COMPARATORS 2 AND 3 REFER TO UPPER 16 BITS OF REGB */ + + msr_value.low = 0xFFFF0000; + gfx_msr_write(RC_ID_MCP, MCP_CMPMASK0 + 4, &msr_value); + gfx_msr_write(RC_ID_MCP, MCP_CMPMASK0 + 6, &msr_value); + + /* SET REGA MASK TO CRC ONLY 24 BITS OF DATA */ + + msr_value.high = 0x00000000; + msr_value.low = 0x00FFFFFF; + gfx_msr_write(RC_ID_MCP, MCP_REGAMASK, &msr_value); + + /* SET REGB VALUE */ + /* Lower 16 bits use HTOTAL - SYNC TIME - 1 to set the counter rollover + * limit. */ + /* Upper 16 bits use 0xFFFF to remove auto-clear behavior. */ + + msr_value.high = 0x00000000; + msr_value.low = 0xFFFF0000 | + ((gfx_get_htotal() - (gfx_get_hsync_end() - gfx_get_hsync_start()) - + 1) & 0xFFFF); + gfx_msr_write(RC_ID_MCP, MCP_REGBVAL, &msr_value); + + /* PROGRAM ACTIONS */ + + /* GOTO STATE 01 */ + + msr_value.high = 0x00000000; + msr_value.low = 0x00000008 | (1l << vsync_inactive_shift); + gfx_msr_write(RC_ID_MCP, MCP_ACTION0 + 14, &msr_value); + + /* GOTO STATE 10 */ + + msr_value.low = 0x00080000 | (1l << (vsync_active_shift + 16)); + gfx_msr_write(RC_ID_MCP, MCP_ACTION0 + 15, &msr_value); + + /* GOTO STATE 11 */ + + msr_value.low = 0x00000080 | (1l << (vsync_inactive_shift + 4)); + gfx_msr_write(RC_ID_MCP, MCP_ACTION0 + 16, &msr_value); + + /* CLEAR REGB (COUNTERS) */ + /* RegB is cleared upon transitioning to state 10 */ + /* RegA is not cleared as the initial value must be 0x00000001 */ + + msr_value.low = 0x00080000 | (1l << (vsync_active_shift + 16)); + gfx_msr_write(RC_ID_MCP, MCP_ACTION0, &msr_value); + + /* CRC INTO REGA */ + /* INCREMENT H. COUNTER */ + /* cmp0 <= xpos < cmp1 */ + /* cmp2 <= ypos < cmp3 */ + /* XState = 10 */ + + msr_value.low = 0x00000008 | (1l << vsync_active_shift) | + 0x00800000 | (1l << (hsync_active_shift + 20)); + gfx_msr_write(RC_ID_MCP, MCP_ACTION0 + 1, &msr_value); + + /* INCREMENT V. COUNTER */ + /* V. Counter is incremented when the H. Counter */ + /* rolls over. */ + + msr_value.low = 0x00080000 | (1l << (vsync_inactive_shift + 16)); + gfx_msr_write(RC_ID_MCP, MCP_ACTION0 + 2, &msr_value); + + /* CLEAR ALL OTHER ACTIONS */ + /* This prevents side-effects from previous accesses to the MCP */ + /* debug logic. */ + msr_value.low = 0x00000000; + msr_value.high = 0x00000000; + gfx_msr_write(RC_ID_MCP, MCP_ACTION0 + 3, &msr_value); + gfx_msr_write(RC_ID_MCP, MCP_ACTION0 + 4, &msr_value); + gfx_msr_write(RC_ID_MCP, MCP_ACTION0 + 5, &msr_value); + gfx_msr_write(RC_ID_MCP, MCP_ACTION0 + 6, &msr_value); + gfx_msr_write(RC_ID_MCP, MCP_ACTION0 + 7, &msr_value); + gfx_msr_write(RC_ID_MCP, MCP_ACTION0 + 8, &msr_value); + gfx_msr_write(RC_ID_MCP, MCP_ACTION0 + 9, &msr_value); + gfx_msr_write(RC_ID_MCP, MCP_ACTION0 + 10, &msr_value); + gfx_msr_write(RC_ID_MCP, MCP_ACTION0 + 11, &msr_value); + gfx_msr_write(RC_ID_MCP, MCP_ACTION0 + 12, &msr_value); + gfx_msr_write(RC_ID_MCP, MCP_ACTION0 + 13, &msr_value); + gfx_msr_write(RC_ID_MCP, MCP_ACTION0 + 17, &msr_value); + gfx_msr_write(RC_ID_MCP, MCP_ACTION0 + 18, &msr_value); + gfx_msr_write(RC_ID_MCP, MCP_ACTION0 + 19, &msr_value); + gfx_msr_write(RC_ID_MCP, MCP_ACTION0 + 20, &msr_value); + + /* SET REGA CRC VALUE TO 1 OR 0 */ + + if (!crc32) + msr_value.low = 0x00000001; + gfx_msr_write(RC_ID_MCP, MCP_REGA, &msr_value); + + /* SET XSTATE TO 0 */ + + msr_value.low = 0; + msr_value.high = 0; + gfx_msr_write(RC_ID_MCP, MCP_XSTATE, &msr_value); + + /* CONFIGURE DIAG CONTROL */ + /* Set all four comparators to watch the upper diag bus. */ + /* Set REGA action1 to legacy CRC or 32-bit CRC. */ + /* Set REGB action1 to increment lower 16 bits and clear at limit. */ + /* Set REGB action2 to increment upper 16 bits. */ + /* Enable all actions. */ + + if (crc32) + msr_value.low = 0x9A820055; + else + msr_value.low = 0x9A840055; + msr_value.high = 0x00000000; + gfx_msr_write(RC_ID_MCP, MCP_DIAGCTL, &msr_value); + + /* DELAY TWO FRAMES */ + + while (!gfx_test_vertical_active()) ; + while (gfx_test_vertical_active()) ; + while (!gfx_test_vertical_active()) ; + while (gfx_test_vertical_active()) ; + while (!gfx_test_vertical_active()) ; + + /* VERIFY THAT XSTATE = 11 */ + + gfx_msr_read(RC_ID_MCP, MCP_XSTATE, &msr_value); + if ((msr_value.low & 3) == 3) { + gfx_msr_read(RC_ID_MCP, MCP_REGA, &msr_value); + + crc = msr_value.low; + if (!crc32) + crc &= 0xFFFFFF; + } + + /* DISABLE MCP AND DF DIAG BUS OUTPUTS */ + + msr_value.low = 0x00000000; + msr_value.high = 0x00000000; + gfx_msr_write(RC_ID_DF, MBD_MSR_DIAG, &msr_value); + gfx_msr_write(RC_ID_MCP, MBD_MSR_DIAG, &msr_value); + + /* DISABLE MCP ACTIONS */ + + msr_value.high = 0x00000000; + msr_value.low = 0x00000000; + gfx_msr_write(RC_ID_MCP, MCP_DIAGCTL, &msr_value); + + /* RESTORE PREVIOUS OUTPUT FORMAT */ + + if (source != CRC_SOURCE_GFX_DATA) { + gfx_msr_read(RC_ID_DF, MBD_MSR_CONFIG, &msr_value); + msr_value.low = old_fmt; + gfx_msr_write(RC_ID_DF, MBD_MSR_CONFIG, &msr_value); + } + return crc; +} + +/*--------------------------------------------------------------------------- + * gfx_get_alpha_enable + * + * This routine returns 1 if the selected alpha window is currently + * enabled, or 0 if it is currently disabled. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +void +redcloud_get_alpha_enable(int *enable) +#else +void +gfx_get_alpha_enable(int *enable) +#endif +{ + unsigned long value = 0; + + *enable = 0; + if (gfx_alpha_select <= 2) { + value = + READ_VID32(RCDF_ALPHA_CONTROL_1 + + ((unsigned long)gfx_alpha_select << 5)); + if (value & RCDF_ACTRL_WIN_ENABLE) + *enable = 1; + } + return; +} + +/*--------------------------------------------------------------------------- + * gfx_get_alpha_size + * + * This routine returns the size of the currently selected alpha region. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +void +redcloud_get_alpha_size(unsigned short *x, unsigned short *y, + unsigned short *width, unsigned short *height) +#else +void +gfx_get_alpha_size(unsigned short *x, unsigned short *y, + unsigned short *width, unsigned short *height) +#endif +{ + unsigned long value = 0; + + *x = 0; + *y = 0; + *width = 0; + *height = 0; + if (gfx_alpha_select <= 2) { + value = + READ_VID32(RCDF_ALPHA_XPOS_1 + + ((unsigned long)gfx_alpha_select << 5)); + *x = (unsigned short)(value & 0x000007FF); + *width = (unsigned short)((value >> 16) & 0x000007FF) - *x; + value = + READ_VID32(RCDF_ALPHA_YPOS_1 + + ((unsigned long)gfx_alpha_select << 5)); + *y = (unsigned short)(value & 0x000007FF); + *height = (unsigned short)((value >> 16) & 0x000007FF) - *y; + } + *x -= gfx_get_htotal() - gfx_get_hsync_end() - 2; + *y -= gfx_get_vtotal() - gfx_get_vsync_end() + 1; + return; +} + +/*--------------------------------------------------------------------------- + * gfx_get_alpha_value + * + * This routine returns the alpha value and increment/decrement value of + * the currently selected alpha region. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +void +redcloud_get_alpha_value(unsigned char *alpha, char *delta) +#else +void +gfx_get_alpha_value(unsigned char *alpha, char *delta) +#endif +{ + unsigned long value = 0; + + *alpha = 0; + *delta = 0; + if (gfx_alpha_select <= 2) { + value = + READ_VID32(RCDF_ALPHA_CONTROL_1 + + ((unsigned long)gfx_alpha_select << 5)); + *alpha = (unsigned char)(value & 0x00FF); + *delta = (char)((value >> 8) & 0x00FF); + } + return; +} + +/*--------------------------------------------------------------------------- + * gfx_get_alpha_priority + * + * This routine returns the priority of the currently selected alpha region. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +void +redcloud_get_alpha_priority(int *priority) +#else +void +gfx_get_alpha_priority(int *priority) +#endif +{ + unsigned long pos = 0, value = 0; + + *priority = 0; + if (gfx_alpha_select <= 2) { + value = READ_VID32(RCDF_VID_ALPHA_CONTROL); + pos = 16 + (gfx_alpha_select << 1); + *priority = (int)((value >> pos) & 3); + } + return; +} + +/*--------------------------------------------------------------------------- + * gfx_get_alpha_color + * + * This routine returns the color register value for the currently selected + * alpha region. Bit 24 is set if the color register is enabled. + *--------------------------------------------------------------------------- + */ +#if GFX_VIDEO_DYNAMIC +void +redcloud_get_alpha_color(unsigned long *color) +#else +void +gfx_get_alpha_color(unsigned long *color) +#endif +{ + *color = 0; + if (gfx_alpha_select <= 2) { + *color = + READ_VID32(RCDF_ALPHA_COLOR_1 + + ((unsigned long)gfx_alpha_select << 5)); + } + return; +} + +#endif /* GFX_READ_ROUTINES */ + +/* END OF FILE */ diff --git a/src/gfx/vip_1200.c b/src/gfx/vip_1200.c new file mode 100644 index 0000000..731e1b8 --- /dev/null +++ b/src/gfx/vip_1200.c @@ -0,0 +1,663 @@ +/* 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 to control the SC1200 video input port (VIP) + * hardware. + * */ + +/*---------------------------------------------------------------------------- + * gfx_set_vip_enable + * + * This routine enables or disables the writes to memory from the video port. + *---------------------------------------------------------------------------- + */ +#if GFX_VIP_DYNAMIC +int +sc1200_set_vip_enable(int enable) +#else +int +gfx_set_vip_enable(int enable) +#endif +{ + unsigned long value; + + value = READ_VIP32(SC1200_VIP_CONTROL); + if (enable) + value |= SC1200_VIP_DATA_CAPTURE_EN; + else + value &= ~SC1200_VIP_DATA_CAPTURE_EN; + WRITE_VIP32(SC1200_VIP_CONTROL, value); + return (0); +} + +/*---------------------------------------------------------------------------- + * gfx_set_vip_capture_run_mode + * + * This routine selects VIP capture run mode. + *---------------------------------------------------------------------------- + */ +#if GFX_VIP_DYNAMIC +int +sc1200_set_vip_capture_run_mode(int mode) +#else +int +gfx_set_vip_capture_run_mode(int mode) +#endif +{ + unsigned long value; + + value = READ_VIP32(SC1200_VIP_CONTROL); + value &= ~SC1200_CAPTURE_RUN_MODE_MASK; + switch (mode) { + case VIP_CAPTURE_STOP_LINE: + value |= SC1200_CAPTURE_RUN_MODE_STOP_LINE; + break; + case VIP_CAPTURE_STOP_FIELD: + value |= SC1200_CAPTURE_RUN_MODE_STOP_FIELD; + break; + case VIP_CAPTURE_START_FIELD: + value |= SC1200_CAPTURE_RUN_MODE_START; + break; + default: + return GFX_STATUS_BAD_PARAMETER; + } + WRITE_VIP32(SC1200_VIP_CONTROL, value); + return (0); +} + +/*---------------------------------------------------------------------------- + * gfx_set_vip_base + * + * This routine sets the odd and even base address values for the VIP memory + * buffer. + *---------------------------------------------------------------------------- + */ +#if GFX_VIP_DYNAMIC +int +sc1200_set_vip_base(unsigned long even, unsigned long odd) +#else +int +gfx_set_vip_base(unsigned long even, unsigned long odd) +#endif +{ + /* TRUE OFFSET IS SPECIFIED, NEED TO SET BIT 23 FOR HARDWARE */ + + if (even) + WRITE_VIP32(SC1200_VIP_EVEN_BASE, + even + (unsigned long)gfx_phys_fbptr); + if (odd) + WRITE_VIP32(SC1200_VIP_ODD_BASE, odd + (unsigned long)gfx_phys_fbptr); + return (0); +} + +/*---------------------------------------------------------------------------- + * gfx_set_vip_pitch + * + * This routine sets the number of bytes between scanlines for the VIP data. + *---------------------------------------------------------------------------- + */ +#if GFX_VIP_DYNAMIC +int +sc1200_set_vip_pitch(unsigned long pitch) +#else +int +gfx_set_vip_pitch(unsigned long pitch) +#endif +{ + WRITE_VIP32(SC1200_VIP_PITCH, pitch & SC1200_VIP_PITCH_MASK); + return (0); +} + +/*---------------------------------------------------------------------------- + * gfx_set_vip_mode + * + * This routine sets the VIP operating mode. + *---------------------------------------------------------------------------- + */ +#if GFX_VIP_DYNAMIC +int +sc1200_set_vip_mode(int mode) +#else +int +gfx_set_vip_mode(int mode) +#endif +{ + unsigned long config; + + config = READ_VIP32(SC1200_VIP_CONFIG); + config &= ~SC1200_VIP_MODE_MASK; + switch (mode) { + case VIP_MODE_C: + WRITE_VIP32(SC1200_VIP_CONFIG, config | SC1200_VIP_MODE_C); + break; + default: + return GFX_STATUS_BAD_PARAMETER; + } + return (0); +} + +/*---------------------------------------------------------------------------- + * gfx_set_vbi_enable + * + * This routine enables or disables the VBI data capture. + *---------------------------------------------------------------------------- + */ +#if GFX_VIP_DYNAMIC +int +sc1200_set_vbi_enable(int enable) +#else +int +gfx_set_vbi_enable(int enable) +#endif +{ + unsigned long value; + + value = READ_VIP32(SC1200_VIP_CONTROL); + if (enable) + value |= SC1200_VIP_VBI_CAPTURE_EN; + else + value &= ~SC1200_VIP_VBI_CAPTURE_EN; + WRITE_VIP32(SC1200_VIP_CONTROL, value); + return (0); +} + +/*---------------------------------------------------------------------------- + * gfx_set_vbi_mode + * + * This routine sets the VBI data types captured to memory. + * It receives a mask of all enabled types. + *---------------------------------------------------------------------------- + */ +#if GFX_VIP_DYNAMIC +int +sc1200_set_vbi_mode(int mode) +#else +int +gfx_set_vbi_mode(int mode) +#endif +{ + unsigned long config; + + config = READ_VIP32(SC1200_VIP_CONFIG); + config &= + ~(SC1200_VBI_ANCILLARY_TO_MEMORY | SC1200_VBI_TASK_A_TO_MEMORY | + SC1200_VBI_TASK_B_TO_MEMORY); + + if (mode & VBI_ANCILLARY) + config |= SC1200_VBI_ANCILLARY_TO_MEMORY; + if (mode & VBI_TASK_A) + config |= SC1200_VBI_TASK_A_TO_MEMORY; + if (mode & VBI_TASK_B) + config |= SC1200_VBI_TASK_B_TO_MEMORY; + WRITE_VIP32(SC1200_VIP_CONFIG, config); + return (0); +} + +/*---------------------------------------------------------------------------- + * gfx_set_vbi_base + * + * This routine sets the odd and even base address values for VBI capture. + * + * "even" and "odd" should contain 16-byte aligned physical addresses. + *---------------------------------------------------------------------------- + */ +#if GFX_VIP_DYNAMIC +int +sc1200_set_vbi_base(unsigned long even, unsigned long odd) +#else +int +gfx_set_vbi_base(unsigned long even, unsigned long odd) +#endif +{ + /* VIP HW REQUIRES THAT BASE ADDRESSES BE 16-BYTE ALIGNED */ + + if (even) + WRITE_VIP32(SC1200_VBI_EVEN_BASE, even & ~0xf); + if (odd) + WRITE_VIP32(SC1200_VBI_ODD_BASE, odd & ~0xf); + + return (0); +} + +/*---------------------------------------------------------------------------- + * gfx_set_vbi_pitch + * + * This routine sets the number of bytes between scanlines for VBI capture. + *---------------------------------------------------------------------------- + */ +#if GFX_VIP_DYNAMIC +int +sc1200_set_vbi_pitch(unsigned long pitch) +#else +int +gfx_set_vbi_pitch(unsigned long pitch) +#endif +{ + WRITE_VIP32(SC1200_VBI_PITCH, pitch & SC1200_VBI_PITCH_MASK); + return (0); +} + +/*---------------------------------------------------------------------------- + * gfx_set_vbi_direct + * + * This routine sets the VBI lines to be passed to the Direct VIP. + *---------------------------------------------------------------------------- + */ +#if GFX_VIP_DYNAMIC +int +sc1200_set_vbi_direct(unsigned long even_lines, unsigned long odd_lines) +#else +int +gfx_set_vbi_direct(unsigned long even_lines, unsigned long odd_lines) +#endif +{ + WRITE_VIP32(SC1200_EVEN_DIRECT_VBI_LINE_ENABLE, + even_lines & SC1200_DIRECT_VBI_LINE_ENABLE_MASK); + WRITE_VIP32(SC1200_ODD_DIRECT_VBI_LINE_ENABLE, + odd_lines & SC1200_DIRECT_VBI_LINE_ENABLE_MASK); + return (0); +} + +/*---------------------------------------------------------------------------- + * gfx_set_vbi_interrupt + * + * This routine enables or disables the VBI field interrupt. + *---------------------------------------------------------------------------- + */ +#if GFX_VIP_DYNAMIC +int +sc1200_set_vbi_interrupt(int enable) +#else +int +gfx_set_vbi_interrupt(int enable) +#endif +{ + unsigned long value; + + value = READ_VIP32(SC1200_VIP_CONTROL); + if (enable) + value |= SC1200_VIP_VBI_FIELD_INTERRUPT_EN; + else + value &= ~SC1200_VIP_VBI_FIELD_INTERRUPT_EN; + WRITE_VIP32(SC1200_VIP_CONTROL, value); + return (0); +} + +/*---------------------------------------------------------------------------- + * gfx_set_vip_bus_request_threshold_high + * + * This routine sets the VIP FIFO bus request threshold. + * If enable is TRUE, VIP FIFO will be set to issue a bus request when it + * filled with 64 bytes. If enable is FALSE, VIP FIFO will be set to issue a + * bus request when it filled with 32 bytes. + *---------------------------------------------------------------------------- + */ +#if GFX_VIP_DYNAMIC +int +sc1200_set_vip_bus_request_threshold_high(int enable) +#else +int +gfx_set_vip_bus_request_threshold_high(int enable) +#endif +{ + unsigned long value; + + value = READ_VIP32(SC1200_VIP_CONFIG); + if (enable) + value &= ~SC1200_VIP_BUS_REQUEST_THRESHOLD; + else + value |= SC1200_VIP_BUS_REQUEST_THRESHOLD; + WRITE_VIP32(SC1200_VIP_CONFIG, value); + return (0); +} + +/*---------------------------------------------------------------------------- + * gfx_set_vip_last_line + * + * This routine sets the maximum number of lines captured in each field. + *---------------------------------------------------------------------------- + */ +#if GFX_VIP_DYNAMIC +int +sc1200_set_vip_last_line(int last_line) +#else +int +gfx_set_vip_last_line(int last_line) +#endif +{ + unsigned long value; + + /* This feature is implemented in Rev C1 */ + if (gfx_chip_revision < SC1200_REV_C1) + return (GFX_STATUS_OK); + + value = READ_VIP32(SC1200_VIP_LINE_TARGET); + value &= ~SC1200_VIP_LAST_LINE_MASK; + value |= ((last_line & 0x3FF) << 16); + WRITE_VIP32(SC1200_VIP_LINE_TARGET, value); + return (GFX_STATUS_OK); +} + +/*---------------------------------------------------------------------------- + * gfx_test_vip_odd_field + * + * This routine returns 1 if the current VIP field is odd. Otherwise returns 0 + *---------------------------------------------------------------------------- + */ +#if GFX_VIP_DYNAMIC +int +sc1200_test_vip_odd_field(void) +#else +int +gfx_test_vip_odd_field(void) +#endif +{ + if (READ_VIP32(SC1200_VIP_STATUS) & SC1200_VIP_CURRENT_FIELD_ODD) + return (1); + else + return (0); +} + +/*---------------------------------------------------------------------------- + * gfx_test_vip_bases_updated + * + * This routine returns 1 if all of the VIP base registers have been updated, + * i.e. there is no base register which has been written with a new address, + * that VIP has not already captured or started capturing into the new address + *---------------------------------------------------------------------------- + */ +#if GFX_VIP_DYNAMIC +int +sc1200_test_vip_bases_updated(void) +#else +int +gfx_test_vip_bases_updated(void) +#endif +{ + if (READ_VIP32(SC1200_VIP_STATUS) & SC1200_VIP_BASE_NOT_UPDATED) + return (0); + else + return (1); +} + +/*---------------------------------------------------------------------------- + * gfx_test_vip_fifo_overflow + * + * This routine returns 1 if an overflow occurred on the FIFO between the VIP + * and the fast X-bus, 0 otherwise. + * If an overflow occurred, the overflow status indication is reset. + *---------------------------------------------------------------------------- + */ +#if GFX_VIP_DYNAMIC +int +sc1200_test_vip_fifo_overflow(void) +#else +int +gfx_test_vip_fifo_overflow(void) +#endif +{ + if (READ_VIP32(SC1200_VIP_STATUS) & SC1200_VIP_FIFO_OVERFLOW) { + /* Bits in vip status register are either read only or reset by + * writing 1 */ + WRITE_VIP32(SC1200_VIP_STATUS, SC1200_VIP_FIFO_OVERFLOW); + return (1); + } else { + return (0); + } +} + +/*---------------------------------------------------------------------------- + * gfx_get_vip_line + * + * This routine returns the number of the current video line being + * received by the VIP interface. + *---------------------------------------------------------------------------- + */ +#if GFX_VIP_DYNAMIC +int +sc1200_get_vip_line(void) +#else +int +gfx_get_vip_line(void) +#endif +{ + return (int)(READ_VIP32(SC1200_VIP_CURRENT_LINE) & + SC1200_VIP_CURRENT_LINE_MASK); +} + +/*---------------------------------------------------------------------------- + * gfx_get_vip_base + *---------------------------------------------------------------------------- + */ +#if GFX_VIP_DYNAMIC +unsigned long +sc1200_get_vip_base(int odd) +#else +unsigned long +gfx_get_vip_base(int odd) +#endif +{ + /* MASK BIT 23 AND ABOVE TO MAKE IT A TRUE OFFSET */ + + if (odd) + return (READ_VIP32(SC1200_VIP_ODD_BASE)); + return (READ_VIP32(SC1200_VIP_EVEN_BASE)); +} + +/*---------------------------------------------------------------------------- + * gfx_get_vbi_pitch + *---------------------------------------------------------------------------- + */ +#if GFX_VIP_DYNAMIC +unsigned long +sc1200_get_vbi_pitch(void) +#else +unsigned long +gfx_get_vbi_pitch(void) +#endif +{ + return (READ_VIP32(SC1200_VBI_PITCH) & SC1200_VBI_PITCH_MASK); +} + +/*************************************************************/ +/* READ ROUTINES | INCLUDED FOR DIAGNOSTIC PURPOSES ONLY */ +/*************************************************************/ + +#if GFX_READ_ROUTINES + +/*---------------------------------------------------------------------------- + * gfx_get_vip_enable + *---------------------------------------------------------------------------- + */ +#if GFX_VIP_DYNAMIC +int +sc1200_get_vip_enable(void) +#else +int +gfx_get_vip_enable(void) +#endif +{ + if (READ_VIP32(SC1200_VIP_CONTROL) & SC1200_VIP_DATA_CAPTURE_EN) + return (1); + return (0); +} + +/*---------------------------------------------------------------------------- + * gfx_get_vip_pitch + *---------------------------------------------------------------------------- + */ +#if GFX_VIP_DYNAMIC +unsigned long +sc1200_get_vip_pitch(void) +#else +unsigned long +gfx_get_vip_pitch(void) +#endif +{ + return (READ_VIP32(SC1200_VIP_PITCH) & SC1200_VIP_PITCH_MASK); +} + +/*---------------------------------------------------------------------------- + * gfx_get_vip_mode + *---------------------------------------------------------------------------- + */ +#if GFX_VIP_DYNAMIC +int +sc1200_get_vip_mode(void) +#else +int +gfx_get_vip_mode(void) +#endif +{ + switch (READ_VIP32(SC1200_VIP_CONFIG) & SC1200_VIP_MODE_MASK) { + case SC1200_VIP_MODE_C: + return VIP_MODE_C; + default: + return (0); + } +} + +/*---------------------------------------------------------------------------- + * gfx_get_vbi_enable + *---------------------------------------------------------------------------- + */ +#if GFX_VIP_DYNAMIC +int +sc1200_get_vbi_enable(void) +#else +int +gfx_get_vbi_enable(void) +#endif +{ + if (READ_VIP32(SC1200_VIP_CONTROL) & SC1200_VIP_VBI_CAPTURE_EN) + return (1); + return (0); +} + +/*---------------------------------------------------------------------------- + * gfx_get_vbi_mode + *---------------------------------------------------------------------------- + */ +#if GFX_VIP_DYNAMIC +int +sc1200_get_vbi_mode(void) +#else +int +gfx_get_vbi_mode(void) +#endif +{ + int config; + int mode = 0; + + config = + (int)(READ_VIP32(SC1200_VIP_CONFIG) & (SC1200_VBI_ANCILLARY_TO_MEMORY + | SC1200_VBI_TASK_A_TO_MEMORY | SC1200_VBI_TASK_B_TO_MEMORY)); + if (config & SC1200_VBI_ANCILLARY_TO_MEMORY) + mode |= VBI_ANCILLARY; + if (config & SC1200_VBI_TASK_A_TO_MEMORY) + mode |= VBI_TASK_A; + if (config & SC1200_VBI_TASK_B_TO_MEMORY) + mode |= VBI_TASK_B; + return mode; +} + +/*---------------------------------------------------------------------------- + * gfx_get_vbi_base + *---------------------------------------------------------------------------- + */ +#if GFX_VIP_DYNAMIC +unsigned long +sc1200_get_vbi_base(int odd) +#else +unsigned long +gfx_get_vbi_base(int odd) +#endif +{ + /* MASK BIT 23 AND ABOVE TO MAKE IT A TRUE OFFSET */ + + if (odd) + return (READ_VIP32(SC1200_VBI_ODD_BASE)); + return (READ_VIP32(SC1200_VBI_EVEN_BASE)); +} + +/*---------------------------------------------------------------------------- + * gfx_get_vbi_direct + *---------------------------------------------------------------------------- + */ +#if GFX_VIP_DYNAMIC +unsigned long +sc1200_get_vbi_direct(int odd) +#else +unsigned long +gfx_get_vbi_direct(int odd) +#endif +{ + /* MASK BIT 23 AND ABOVE TO MAKE IT A TRUE OFFSET */ + + if (odd) + return (READ_VIP32(SC1200_ODD_DIRECT_VBI_LINE_ENABLE) & + SC1200_DIRECT_VBI_LINE_ENABLE_MASK); + return (READ_VIP32(SC1200_EVEN_DIRECT_VBI_LINE_ENABLE) & + SC1200_DIRECT_VBI_LINE_ENABLE_MASK); +} + +/*--------------------------------------------------------------------------- + * gfx_get_vbi_interrupt + *---------------------------------------------------------------------------- + */ +#if GFX_VIP_DYNAMIC +int +sc1200_get_vbi_interrupt(void) +#else +int +gfx_get_vbi_interrupt(void) +#endif +{ + if (READ_VIP32(SC1200_VIP_CONTROL) & SC1200_VIP_VBI_FIELD_INTERRUPT_EN) + return (1); + return (0); +} + +/*---------------------------------------------------------------------------- + * gfx_get_vip_bus_request_threshold_high + *---------------------------------------------------------------------------- + */ +#if GFX_VIP_DYNAMIC +int +sc1200_get_vip_bus_request_threshold_high(void) +#else +int +gfx_get_vip_bus_request_threshold_high(void) +#endif +{ + if (READ_VIP32(SC1200_VIP_CONFIG) & SC1200_VIP_BUS_REQUEST_THRESHOLD) + return (1); + return (0); +} + +#endif /* GFX_READ_ROUTINES */ + +/* END OF FILE */ |