171d7fec4Smrg/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nsc/gfx/disp_gu1.c,v 1.4 2003/02/06 17:46:02 alanh Exp $ */
271d7fec4Smrg/*
371d7fec4Smrg * $Workfile: disp_gu1.c $
471d7fec4Smrg *
571d7fec4Smrg * This file contains routines for the first generation display controller.
671d7fec4Smrg *
771d7fec4Smrg * NSC_LIC_ALTERNATIVE_PREAMBLE
871d7fec4Smrg *
971d7fec4Smrg * Revision 1.0
1071d7fec4Smrg *
1171d7fec4Smrg * National Semiconductor Alternative GPL-BSD License
1271d7fec4Smrg *
1371d7fec4Smrg * National Semiconductor Corporation licenses this software
1471d7fec4Smrg * ("Software"):
1571d7fec4Smrg *
1671d7fec4Smrg *      Durango
1771d7fec4Smrg *
1871d7fec4Smrg * under one of the two following licenses, depending on how the
1971d7fec4Smrg * Software is received by the Licensee.
2071d7fec4Smrg *
2171d7fec4Smrg * If this Software is received as part of the Linux Framebuffer or
2271d7fec4Smrg * other GPL licensed software, then the GPL license designated
2371d7fec4Smrg * NSC_LIC_GPL applies to this Software; in all other circumstances
2471d7fec4Smrg * then the BSD-style license designated NSC_LIC_BSD shall apply.
2571d7fec4Smrg *
2671d7fec4Smrg * END_NSC_LIC_ALTERNATIVE_PREAMBLE */
2771d7fec4Smrg
2871d7fec4Smrg/* NSC_LIC_BSD
2971d7fec4Smrg *
3071d7fec4Smrg * National Semiconductor Corporation Open Source License for Durango
3171d7fec4Smrg *
3271d7fec4Smrg * (BSD License with Export Notice)
3371d7fec4Smrg *
3471d7fec4Smrg * Copyright (c) 1999-2001
3571d7fec4Smrg * National Semiconductor Corporation.
3671d7fec4Smrg * All rights reserved.
3771d7fec4Smrg *
3871d7fec4Smrg * Redistribution and use in source and binary forms, with or without
3971d7fec4Smrg * modification, are permitted provided that the following conditions
4071d7fec4Smrg * are met:
4171d7fec4Smrg *
4271d7fec4Smrg *   * Redistributions of source code must retain the above copyright
4371d7fec4Smrg *     notice, this list of conditions and the following disclaimer.
4471d7fec4Smrg *
4571d7fec4Smrg *   * Redistributions in binary form must reproduce the above
4671d7fec4Smrg *     copyright notice, this list of conditions and the following
4771d7fec4Smrg *     disclaimer in the documentation and/or other materials provided
4871d7fec4Smrg *     with the distribution.
4971d7fec4Smrg *
5071d7fec4Smrg *   * Neither the name of the National Semiconductor Corporation nor
5171d7fec4Smrg *     the names of its contributors may be used to endorse or promote
5271d7fec4Smrg *     products derived from this software without specific prior
5371d7fec4Smrg *     written permission.
5471d7fec4Smrg *
5571d7fec4Smrg * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
5671d7fec4Smrg * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
5771d7fec4Smrg * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
5871d7fec4Smrg * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
5971d7fec4Smrg * NATIONAL SEMICONDUCTOR CORPORATION OR CONTRIBUTORS BE LIABLE FOR ANY
6071d7fec4Smrg * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
6171d7fec4Smrg * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
6271d7fec4Smrg * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
6371d7fec4Smrg * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
6471d7fec4Smrg * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE,
6571d7fec4Smrg * INTELLECTUAL PROPERTY INFRINGEMENT, OR OTHERWISE) ARISING IN ANY WAY
6671d7fec4Smrg * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
6771d7fec4Smrg * OF SUCH DAMAGE.
6871d7fec4Smrg *
6971d7fec4Smrg * EXPORT LAWS: THIS LICENSE ADDS NO RESTRICTIONS TO THE EXPORT LAWS OF
7071d7fec4Smrg * YOUR JURISDICTION. It is licensee's responsibility to comply with
7171d7fec4Smrg * any export regulations applicable in licensee's jurisdiction. Under
7271d7fec4Smrg * CURRENT (2001) U.S. export regulations this software
7371d7fec4Smrg * is eligible for export from the U.S. and can be downloaded by or
7471d7fec4Smrg * otherwise exported or reexported worldwide EXCEPT to U.S. embargoed
7571d7fec4Smrg * destinations which include Cuba, Iraq, Libya, North Korea, Iran,
7671d7fec4Smrg * Syria, Sudan, Afghanistan and any other country to which the U.S.
7771d7fec4Smrg * has embargoed goods and services.
7871d7fec4Smrg *
7971d7fec4Smrg * END_NSC_LIC_BSD */
8071d7fec4Smrg
8171d7fec4Smrg/* NSC_LIC_GPL
8271d7fec4Smrg *
8371d7fec4Smrg * National Semiconductor Corporation Gnu General Public License for Durango
8471d7fec4Smrg *
8571d7fec4Smrg * (GPL License with Export Notice)
8671d7fec4Smrg *
8771d7fec4Smrg * Copyright (c) 1999-2001
8871d7fec4Smrg * National Semiconductor Corporation.
8971d7fec4Smrg * All rights reserved.
9071d7fec4Smrg *
9171d7fec4Smrg * Redistribution and use in source and binary forms, with or without
9271d7fec4Smrg * modification, are permitted under the terms of the GNU General
9371d7fec4Smrg * Public License as published by the Free Software Foundation; either
9471d7fec4Smrg * version 2 of the License, or (at your option) any later version
9571d7fec4Smrg *
9671d7fec4Smrg * In addition to the terms of the GNU General Public License, neither
9771d7fec4Smrg * the name of the National Semiconductor Corporation nor the names of
9871d7fec4Smrg * its contributors may be used to endorse or promote products derived
9971d7fec4Smrg * from this software without specific prior written permission.
10071d7fec4Smrg *
10171d7fec4Smrg * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
10271d7fec4Smrg * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
10371d7fec4Smrg * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
10471d7fec4Smrg * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
10571d7fec4Smrg * NATIONAL SEMICONDUCTOR CORPORATION OR CONTRIBUTORS BE LIABLE FOR ANY
10671d7fec4Smrg * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
10771d7fec4Smrg * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
10871d7fec4Smrg * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
10971d7fec4Smrg * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
11071d7fec4Smrg * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE,
11171d7fec4Smrg * INTELLECTUAL PROPERTY INFRINGEMENT, OR OTHERWISE) ARISING IN ANY WAY
11271d7fec4Smrg * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
11371d7fec4Smrg * OF SUCH DAMAGE. See the GNU General Public License for more details.
11471d7fec4Smrg *
11571d7fec4Smrg * EXPORT LAWS: THIS LICENSE ADDS NO RESTRICTIONS TO THE EXPORT LAWS OF
11671d7fec4Smrg * YOUR JURISDICTION. It is licensee's responsibility to comply with
11771d7fec4Smrg * any export regulations applicable in licensee's jurisdiction. Under
11871d7fec4Smrg * CURRENT (2001) U.S. export regulations this software
11971d7fec4Smrg * is eligible for export from the U.S. and can be downloaded by or
12071d7fec4Smrg * otherwise exported or reexported worldwide EXCEPT to U.S. embargoed
12171d7fec4Smrg * destinations which include Cuba, Iraq, Libya, North Korea, Iran,
12271d7fec4Smrg * Syria, Sudan, Afghanistan and any other country to which the U.S.
12371d7fec4Smrg * has embargoed goods and services.
12471d7fec4Smrg *
12571d7fec4Smrg * You should have received a copy of the GNU General Public License
12671d7fec4Smrg * along with this file; if not, write to the Free Software Foundation,
12771d7fec4Smrg * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
12871d7fec4Smrg *
12971d7fec4Smrg * END_NSC_LIC_GPL */
13071d7fec4Smrg
13171d7fec4Smrgvoid gu1_enable_compression(void);	/* private routine definition */
13271d7fec4Smrgvoid gu1_disable_compression(void);	/* private routine definition */
13371d7fec4Smrgvoid gfx_reset_video(void);		/* private routine definition */
13471d7fec4Smrgint gfx_set_display_control(int sync_polarities);	/* private routine definition */
13571d7fec4Smrgvoid gu1_delay_approximate(unsigned long milliseconds);
13671d7fec4Smrgvoid gu1_delay_precise(unsigned long milliseconds);
13771d7fec4Smrgint gu1_set_display_bpp(unsigned short bpp);
13871d7fec4Smrgint gu1_is_display_mode_supported(int xres, int yres, int bpp, int hz);
13971d7fec4Smrgint gu1_set_display_mode(int xres, int yres, int bpp, int hz);
14071d7fec4Smrgint gu1_set_display_timings(unsigned short bpp, unsigned short flags,
14171d7fec4Smrg			    unsigned short hactive,
14271d7fec4Smrg			    unsigned short hblank_start,
14371d7fec4Smrg			    unsigned short hsync_start,
14471d7fec4Smrg			    unsigned short hsync_end,
14571d7fec4Smrg			    unsigned short hblank_end, unsigned short htotal,
14671d7fec4Smrg			    unsigned short vactive,
14771d7fec4Smrg			    unsigned short vblank_start,
14871d7fec4Smrg			    unsigned short vsync_start,
14971d7fec4Smrg			    unsigned short vsync_end,
15071d7fec4Smrg			    unsigned short vblank_end, unsigned short vtotal,
15171d7fec4Smrg			    unsigned long frequency);
15271d7fec4Smrgint gu1_set_vtotal(unsigned short vtotal);
15371d7fec4Smrgvoid gu1_set_display_pitch(unsigned short pitch);
15471d7fec4Smrgvoid gu1_set_display_offset(unsigned long offset);
15571d7fec4Smrgint gu1_set_display_palette_entry(unsigned long index, unsigned long palette);
15671d7fec4Smrgint gu1_set_display_palette(unsigned long *palette);
15771d7fec4Smrgvoid gu1_video_shutdown(void);
15871d7fec4Smrgvoid gu1_set_clock_frequency(unsigned long frequency);
15971d7fec4Smrgint gu1_set_crt_enable(int enable);
16071d7fec4Smrgvoid gu1_set_cursor_enable(int enable);
16171d7fec4Smrgvoid gu1_set_cursor_colors(unsigned long bkcolor, unsigned long fgcolor);
16271d7fec4Smrgvoid gu1_set_cursor_position(unsigned long memoffset,
16371d7fec4Smrg			     unsigned short xpos, unsigned short ypos,
16471d7fec4Smrg			     unsigned short xhotspot,
16571d7fec4Smrg			     unsigned short yhotspot);
16671d7fec4Smrgvoid gu1_set_cursor_shape32(unsigned long memoffset, unsigned long *andmask,
16771d7fec4Smrg			    unsigned long *xormask);
16871d7fec4Smrgvoid gu1_set_cursor_shape64(unsigned long memoffset, unsigned long *andmask,
16971d7fec4Smrg			    unsigned long *xormask);
17071d7fec4Smrgvoid gu1_set_icon_enable(int enable);
17171d7fec4Smrgvoid gu1_set_icon_colors(unsigned long color0, unsigned long color1,
17271d7fec4Smrg			 unsigned long color2);
17371d7fec4Smrgvoid gu1_set_icon_position(unsigned long memoffset, unsigned short xpos);
17471d7fec4Smrgvoid gu1_set_icon_shape64(unsigned long memoffset, unsigned long *andmask,
17571d7fec4Smrg			  unsigned long *xormask, unsigned int lines);
17671d7fec4Smrg
17771d7fec4Smrgint gu1_set_compression_enable(int enable);
17871d7fec4Smrgint gu1_set_compression_offset(unsigned long offset);
17971d7fec4Smrgint gu1_set_compression_pitch(unsigned short pitch);
18071d7fec4Smrgint gu1_set_compression_size(unsigned short size);
18171d7fec4Smrgvoid gu1_set_display_priority_high(int enable);
18271d7fec4Smrgint gu1_test_timing_active(void);
18371d7fec4Smrgint gu1_test_vertical_active(void);
18471d7fec4Smrgint gu1_wait_vertical_blank(void);
18571d7fec4Smrgvoid gu1_delay_milliseconds(unsigned long milliseconds);
18671d7fec4Smrgvoid gu1_delay_microseconds(unsigned long microseconds);
18771d7fec4Smrgvoid gu1_enable_panning(int x, int y);
18871d7fec4Smrgint gu1_set_fixed_timings(int panelResX, int panelResY, unsigned short width,
18971d7fec4Smrg			  unsigned short height, unsigned short bpp);
19071d7fec4Smrgint gu1_set_panel_present(int panelResX, int panelResY, unsigned short width,
19171d7fec4Smrg			  unsigned short height, unsigned short bpp);
19271d7fec4Smrgvoid gu1_reset_timing_lock(void);
19371d7fec4Smrg
19471d7fec4Smrgint gu1_get_display_details(unsigned int mode, int *xres, int *yres, int *hz);
19571d7fec4Smrgunsigned short gu1_get_display_pitch(void);
19671d7fec4Smrgint gu1_get_vsa2_softvga_enable(void);
19771d7fec4Smrgint gu1_get_sync_polarities(void);
19871d7fec4Smrgunsigned long gu1_get_clock_frequency(void);
19971d7fec4Smrgunsigned long gu1_get_max_supported_pixel_clock(void);
20071d7fec4Smrgint gu1_mode_frequency_supported(int xres, int yres, int bpp,
20171d7fec4Smrg				 unsigned long frequency);
20271d7fec4Smrgint gu1_get_refreshrate_from_frequency(int xres, int yres, int bpp, int *hz,
20371d7fec4Smrg				       unsigned long frequency);
20471d7fec4Smrgint gu1_get_refreshrate_from_mode(int xres, int yres, int bpp, int *hz,
20571d7fec4Smrg				  unsigned long frequency);
20671d7fec4Smrgint gu1_get_frequency_from_refreshrate(int xres, int yres, int bpp, int hz,
20771d7fec4Smrg				       int *frequency);
20871d7fec4Smrgint gu1_get_display_mode_count(void);
20971d7fec4Smrgint gu1_get_display_mode(int *xres, int *yres, int *bpp, int *hz);
21071d7fec4Smrgunsigned long gu1_get_frame_buffer_line_size(void);
21171d7fec4Smrgunsigned short gu1_get_hactive(void);
21271d7fec4Smrgunsigned short gu1_get_hblank_start(void);
21371d7fec4Smrgunsigned short gu1_get_hsync_start(void);
21471d7fec4Smrgunsigned short gu1_get_hsync_end(void);
21571d7fec4Smrgunsigned short gu1_get_hblank_end(void);
21671d7fec4Smrgunsigned short gu1_get_htotal(void);
21771d7fec4Smrgunsigned short gu1_get_vactive(void);
21871d7fec4Smrgunsigned short gu1_get_vline(void);
21971d7fec4Smrgunsigned short gu1_get_vblank_start(void);
22071d7fec4Smrgunsigned short gu1_get_vsync_start(void);
22171d7fec4Smrgunsigned short gu1_get_vsync_end(void);
22271d7fec4Smrgunsigned short gu1_get_vblank_end(void);
22371d7fec4Smrgunsigned short gu1_get_vtotal(void);
22471d7fec4Smrgunsigned short gu1_get_display_bpp(void);
22571d7fec4Smrgunsigned long gu1_get_display_offset(void);
22671d7fec4Smrgint gu1_get_display_palette_entry(unsigned long index,
22771d7fec4Smrg				  unsigned long *palette);
22871d7fec4Smrgvoid gu1_get_display_palette(unsigned long *palette);
22971d7fec4Smrgunsigned long gu1_get_cursor_enable(void);
23071d7fec4Smrgunsigned long gu1_get_cursor_offset(void);
23171d7fec4Smrgunsigned long gu1_get_cursor_position(void);
23271d7fec4Smrgunsigned long gu1_get_cursor_clip(void);
23371d7fec4Smrgunsigned long gu1_get_cursor_color(int color);
23471d7fec4Smrgunsigned long gu1_get_icon_enable(void);
23571d7fec4Smrgunsigned long gu1_get_icon_offset(void);
23671d7fec4Smrgunsigned long gu1_get_icon_position(void);
23771d7fec4Smrgunsigned long gu1_get_icon_color(int color);
23871d7fec4Smrgint gu1_get_compression_enable(void);
23971d7fec4Smrgunsigned long gu1_get_compression_offset(void);
24071d7fec4Smrgunsigned short gu1_get_compression_pitch(void);
24171d7fec4Smrgunsigned short gu1_get_compression_size(void);
24271d7fec4Smrgint gu1_get_display_priority_high(void);
24371d7fec4Smrgint gu1_get_valid_bit(int line);
24471d7fec4Smrgvoid gu1_set_display_video_enable(int enable);
24571d7fec4Smrgint gu1_set_specified_mode(DISPLAYMODE * pMode, int bpp);
24671d7fec4Smrgvoid gu1_set_display_video_size(unsigned short width, unsigned short height);
24771d7fec4Smrgvoid gu1_set_display_video_offset(unsigned long offset);
24871d7fec4Smrgunsigned long gu1_get_display_video_offset(void);
24971d7fec4Smrgunsigned long gu1_get_display_video_size(void);
25071d7fec4Smrg
25171d7fec4Smrg/* VIDEO BUFFER SIZE */
25271d7fec4Smrg
25371d7fec4Smrgunsigned long vid_buf_size = 0;
25471d7fec4Smrgint vid_enabled = 0;
25571d7fec4Smrg
25671d7fec4Smrg/*-----------------------------------------------------------------------------
25771d7fec4Smrg * GU1_DELAY_APPROXIMATE (PRIVATE ROUTINE - NOT PART OF DURANGO API)
25871d7fec4Smrg *
25971d7fec4Smrg * Delay the requested number of milliseconds by reading a register.  This function
26071d7fec4Smrg * generally takes longer than the requested time.
26171d7fec4Smrg *-----------------------------------------------------------------------------*/
26271d7fec4Smrgvoid
26371d7fec4Smrggu1_delay_approximate(unsigned long milliseconds)
26471d7fec4Smrg{
26571d7fec4Smrg   /* ASSUME 300 MHz, 5 CLOCKS PER READ */
26671d7fec4Smrg
26771d7fec4Smrg#	define READS_PER_MILLISECOND 60000L
26871d7fec4Smrg
26971d7fec4Smrg   unsigned long loop;
27071d7fec4Smrg
27171d7fec4Smrg   loop = milliseconds * READS_PER_MILLISECOND;
27271d7fec4Smrg   while (loop-- > 0) {
27371d7fec4Smrg      READ_REG32(DC_UNLOCK);
27471d7fec4Smrg   }
27571d7fec4Smrg}
27671d7fec4Smrg
27771d7fec4Smrg/*-----------------------------------------------------------------------------
27871d7fec4Smrg * GU1_DELAY_PRECISE (PRIVATE ROUTINE - NOT PART OF DURANGO API)
27971d7fec4Smrg *
28071d7fec4Smrg * Delay the number of milliseconds on a more precise level, varying only by
28171d7fec4Smrg * 1/10 of a ms.  This function should only be called if an SC1200 is present.
28271d7fec4Smrg *-----------------------------------------------------------------------------*/
28371d7fec4Smrgvoid
28471d7fec4Smrggu1_delay_precise(unsigned long milliseconds)
28571d7fec4Smrg{
28671d7fec4Smrg#if GFX_VIDEO_SC1200
28771d7fec4Smrg
28871d7fec4Smrg#define LOOP 1000
28971d7fec4Smrg   unsigned long i, timer_start, timer_end, total_ticks, previous_ticks,
29071d7fec4Smrg	 temp_ticks;
29171d7fec4Smrg
29271d7fec4Smrg   /* Get current time */
29371d7fec4Smrg   timer_start = IND(SC1200_CB_BASE_ADDR + SC1200_CB_TMVALUE);
29471d7fec4Smrg
29571d7fec4Smrg   /* Calculate expected end time */
29671d7fec4Smrg   if (INB(SC1200_CB_BASE_ADDR + SC1200_CB_TMCNFG) & SC1200_TMCLKSEL_27MHZ)
29771d7fec4Smrg      total_ticks = 27000 * milliseconds;	/* timer resolution is 27 MHz */
29871d7fec4Smrg   else
29971d7fec4Smrg      total_ticks = 1000 * milliseconds;	/* timer resolution is 1 MHz */
30071d7fec4Smrg
30171d7fec4Smrg   if (total_ticks > ((unsigned long)0xffffffff - timer_start))	/* wrap-around */
30271d7fec4Smrg      timer_end = total_ticks - ((unsigned long)0xffffffff - timer_start);
30371d7fec4Smrg   else
30471d7fec4Smrg      timer_end = timer_start + total_ticks;
30571d7fec4Smrg
30671d7fec4Smrg   /* in case of wrap around */
30771d7fec4Smrg   if (timer_end < timer_start) {
30871d7fec4Smrg      previous_ticks = timer_start;
30971d7fec4Smrg      while (1) {
31071d7fec4Smrg	 temp_ticks = IND(SC1200_CB_BASE_ADDR + SC1200_CB_TMVALUE);
31171d7fec4Smrg	 if (temp_ticks < previous_ticks)
31271d7fec4Smrg	    break;
31371d7fec4Smrg	 else
31471d7fec4Smrg	    previous_ticks = temp_ticks;
31571d7fec4Smrg	 for (i = 0; i < LOOP; i++)
31671d7fec4Smrg	    READ_REG32(DC_UNLOCK);
31771d7fec4Smrg      }
31871d7fec4Smrg   }
31971d7fec4Smrg   /* now the non-wrap around part */
32071d7fec4Smrg   while (1) {
32171d7fec4Smrg      for (i = 0; i < LOOP; i++)
32271d7fec4Smrg	 READ_REG32(DC_UNLOCK);
32371d7fec4Smrg      if (IND(SC1200_CB_BASE_ADDR + SC1200_CB_TMVALUE) > timer_end)
32471d7fec4Smrg	 break;
32571d7fec4Smrg   }
32671d7fec4Smrg
32771d7fec4Smrg#endif /* GFX_VIDEO_SC1200 */
32871d7fec4Smrg}
32971d7fec4Smrg
33071d7fec4Smrg/*-----------------------------------------------------------------------------
33171d7fec4Smrg * WARNING!!!! INACCURATE DELAY MECHANISM
33271d7fec4Smrg *
33371d7fec4Smrg * In an effort to keep the code self contained and operating system
33471d7fec4Smrg * independent, the delay loop just performs reads of a display controller
33571d7fec4Smrg * register.  This time will vary for faster processors.  The delay can always
33671d7fec4Smrg * be longer than intended, only effecting the time of the mode switch
33771d7fec4Smrg * (obviously want it to still be under a second).  Problems with the hardware
33871d7fec4Smrg * only arise if the delay is not long enough.
33971d7fec4Smrg *
34071d7fec4Smrg * For the SC1200, the high resolution timer can be used as an accurate mechanism
34171d7fec4Smrg * for keeping time. However, in order to avoid a busy loop of IO reads, the
34271d7fec4Smrg * timer is polled in-between busy loops, and therefore the actual delay might
34371d7fec4Smrg * be longer than the requested delay by the time of one busy loop
34471d7fec4Smrg * (which on a 200 MHz system took 95 us)
34571d7fec4Smrg *
34671d7fec4Smrg * There are thus two delay functions which are called from the main API routine.
34771d7fec4Smrg * One is meant to be more precise and should only called if an SC1200 is present.
34871d7fec4Smrg *-----------------------------------------------------------------------------
34971d7fec4Smrg */
35071d7fec4Smrg#if GFX_DISPLAY_DYNAMIC
35171d7fec4Smrgvoid
35271d7fec4Smrggu1_delay_milliseconds(unsigned long milliseconds)
35371d7fec4Smrg#else
35471d7fec4Smrgvoid
35571d7fec4Smrggfx_delay_milliseconds(unsigned long milliseconds)
35671d7fec4Smrg#endif
35771d7fec4Smrg{
35871d7fec4Smrg#if GFX_VIDEO_SC1200
35971d7fec4Smrg
36071d7fec4Smrg#if GFX_VIDEO_DYNAMIC
36171d7fec4Smrg   if (gfx_video_type == GFX_VIDEO_TYPE_SC1200) {
36271d7fec4Smrg#endif
36371d7fec4Smrg      gu1_delay_precise(milliseconds);
36471d7fec4Smrg      return;
36571d7fec4Smrg#if GFX_VIDEO_DYNAMIC
36671d7fec4Smrg   }
36771d7fec4Smrg#endif
36871d7fec4Smrg
36971d7fec4Smrg#endif /* GFX_VIDEO_SC1200 */
37071d7fec4Smrg
37171d7fec4Smrg   gu1_delay_approximate(milliseconds);
37271d7fec4Smrg}
37371d7fec4Smrg
37471d7fec4Smrg#if GFX_DISPLAY_DYNAMIC
37571d7fec4Smrgvoid
37671d7fec4Smrggu1_delay_microseconds(unsigned long microseconds)
37771d7fec4Smrg#else
37871d7fec4Smrgvoid
37971d7fec4Smrggfx_delay_microseconds(unsigned long microseconds)
38071d7fec4Smrg#endif
38171d7fec4Smrg{
38271d7fec4Smrg   /* ASSUME 300 MHz, 2 CLOCKS PER INCREMENT */
38371d7fec4Smrg
38471d7fec4Smrg   unsigned long loop_count = microseconds * 150;
38571d7fec4Smrg
38671d7fec4Smrg   while (loop_count-- > 0) {
38771d7fec4Smrg      ;
38871d7fec4Smrg   }
38971d7fec4Smrg}
39071d7fec4Smrg
39171d7fec4Smrg/*-----------------------------------------------------------------------------
39271d7fec4Smrg * GFX_VIDEO_SHUTDOWN
39371d7fec4Smrg *
39471d7fec4Smrg * This routine disables the display controller output.
39571d7fec4Smrg *-----------------------------------------------------------------------------
39671d7fec4Smrg */
39771d7fec4Smrgvoid
39871d7fec4Smrggu1_video_shutdown(void)
39971d7fec4Smrg{
40071d7fec4Smrg   unsigned long unlock;
40171d7fec4Smrg   unsigned long gcfg, tcfg;
40271d7fec4Smrg
40371d7fec4Smrg   /* DISABLE COMPRESSION */
40471d7fec4Smrg
40571d7fec4Smrg   gu1_disable_compression();
40671d7fec4Smrg
40771d7fec4Smrg   /* ALSO DISABLE VIDEO */
40871d7fec4Smrg   /* Use private "reset video" routine to do all that is needed. */
40971d7fec4Smrg   /* SC1200, for example, also disables the alpha blending regions. */
41071d7fec4Smrg
41171d7fec4Smrg   gfx_reset_video();
41271d7fec4Smrg
41371d7fec4Smrg   /* UNLOCK THE DISPLAY CONTROLLER REGISTERS */
41471d7fec4Smrg
41571d7fec4Smrg   unlock = READ_REG32(DC_UNLOCK);
41671d7fec4Smrg   WRITE_REG32(DC_UNLOCK, DC_UNLOCK_VALUE);
41771d7fec4Smrg
41871d7fec4Smrg   /* READ THE CURRENT GX VALUES */
41971d7fec4Smrg
42071d7fec4Smrg   gcfg = READ_REG32(DC_GENERAL_CFG);
42171d7fec4Smrg   tcfg = READ_REG32(DC_TIMING_CFG);
42271d7fec4Smrg
42371d7fec4Smrg   /* BLANK THE GX DISPLAY AND DISABLE THE TIMING GENERATOR */
42471d7fec4Smrg
42571d7fec4Smrg   tcfg &= ~((unsigned long)DC_TCFG_BLKE | (unsigned long)DC_TCFG_TGEN);
42671d7fec4Smrg   WRITE_REG32(DC_TIMING_CFG, tcfg);
42771d7fec4Smrg
42871d7fec4Smrg   /* DELAY: WAIT FOR PENDING MEMORY REQUESTS */
42971d7fec4Smrg   /* This delay is used to make sure that all pending requests to the */
43071d7fec4Smrg   /* memory controller have completed before disabling the FIFO load. */
43171d7fec4Smrg
43271d7fec4Smrg   gfx_delay_milliseconds(1);
43371d7fec4Smrg
43471d7fec4Smrg   /* DISABLE DISPLAY FIFO LOAD AND DISABLE COMPRESSION */
43571d7fec4Smrg
43671d7fec4Smrg   gcfg &= ~(unsigned long)(DC_GCFG_DFLE | DC_GCFG_CMPE | DC_GCFG_DECE);
43771d7fec4Smrg   WRITE_REG32(DC_GENERAL_CFG, gcfg);
43871d7fec4Smrg   WRITE_REG32(DC_UNLOCK, unlock);
43971d7fec4Smrg   return;
44071d7fec4Smrg}
44171d7fec4Smrg
44271d7fec4Smrg/*-----------------------------------------------------------------------------
44371d7fec4Smrg * GFX_SET_DISPLAY_BPP
44471d7fec4Smrg *
44571d7fec4Smrg * This routine programs the bpp in the display controller.
44671d7fec4Smrg *-----------------------------------------------------------------------------
44771d7fec4Smrg */
44871d7fec4Smrg#if GFX_DISPLAY_DYNAMIC
44971d7fec4Smrgint
45071d7fec4Smrggu1_set_display_bpp(unsigned short bpp)
45171d7fec4Smrg#else
45271d7fec4Smrgint
45371d7fec4Smrggfx_set_display_bpp(unsigned short bpp)
45471d7fec4Smrg#endif
45571d7fec4Smrg{
45671d7fec4Smrg   unsigned long ocfg, lock;
45771d7fec4Smrg
45871d7fec4Smrg   lock = READ_REG32(DC_UNLOCK);
45971d7fec4Smrg   ocfg = READ_REG32(DC_OUTPUT_CFG) & ~(DC_OCFG_8BPP | DC_OCFG_555);
46071d7fec4Smrg
46171d7fec4Smrg   /* SET DC PIXEL FORMAT */
46271d7fec4Smrg
46371d7fec4Smrg   if (bpp == 8)
46471d7fec4Smrg      ocfg |= DC_OCFG_8BPP;
46571d7fec4Smrg   else if (bpp == 15)
46671d7fec4Smrg      ocfg |= DC_OCFG_555;
46771d7fec4Smrg   else if (bpp != 16)
46871d7fec4Smrg      return GFX_STATUS_BAD_PARAMETER;
46971d7fec4Smrg
47071d7fec4Smrg   WRITE_REG32(DC_UNLOCK, DC_UNLOCK_VALUE);
47171d7fec4Smrg   WRITE_REG32(DC_OUTPUT_CFG, ocfg);
47271d7fec4Smrg   WRITE_REG32(DC_UNLOCK, lock);
47371d7fec4Smrg
47471d7fec4Smrg   /* SET BPP IN GRAPHICS PIPELINE */
47571d7fec4Smrg
47671d7fec4Smrg   gfx_set_bpp(bpp);
47771d7fec4Smrg
47871d7fec4Smrg   return 0;
47971d7fec4Smrg}
48071d7fec4Smrg
48171d7fec4Smrg/*-----------------------------------------------------------------------------
48271d7fec4Smrg * GFX_SET_SPECIFIED_MODE
48371d7fec4Smrg * This routine uses the parameters in the specified display mode structure
48471d7fec4Smrg * to program the display controller hardware.
48571d7fec4Smrg *-----------------------------------------------------------------------------
48671d7fec4Smrg */
48771d7fec4Smrgint
48871d7fec4Smrggu1_set_specified_mode(DISPLAYMODE * pMode, int bpp)
48971d7fec4Smrg{
49071d7fec4Smrg   unsigned long unlock, value;
49171d7fec4Smrg   unsigned long gcfg, tcfg, ocfg;
49271d7fec4Smrg   unsigned long size, pitch;
49371d7fec4Smrg   unsigned long vid_buffer_size;
49471d7fec4Smrg   unsigned long hactive, vactive;
49571d7fec4Smrg
49671d7fec4Smrg   gbpp = bpp;
49771d7fec4Smrg
49871d7fec4Smrg   /* CHECK WHETHER TIMING CHANGE IS ALLOWED */
49971d7fec4Smrg   /* Flag used for locking also overrides timing change restriction */
50071d7fec4Smrg
50171d7fec4Smrg   if (gfx_timing_lock && !(pMode->flags & GFX_MODE_LOCK_TIMING))
50271d7fec4Smrg      return GFX_STATUS_ERROR;
50371d7fec4Smrg
50471d7fec4Smrg   /* SET GLOBAL FLAG */
50571d7fec4Smrg
50671d7fec4Smrg   if (pMode->flags & GFX_MODE_LOCK_TIMING)
50771d7fec4Smrg      gfx_timing_lock = 1;
50871d7fec4Smrg
50971d7fec4Smrg   /* DISABLE COMPRESSION */
51071d7fec4Smrg
51171d7fec4Smrg   gu1_disable_compression();
51271d7fec4Smrg
51371d7fec4Smrg   /* ALSO DISABLE VIDEO */
51471d7fec4Smrg   /* Use private "reset video" routine to do all that is needed. */
51571d7fec4Smrg   /* SC1200, for example, also disables the alpha blending regions. */
51671d7fec4Smrg
51771d7fec4Smrg   gfx_reset_video();
51871d7fec4Smrg
51971d7fec4Smrg   /* UNLOCK THE DISPLAY CONTROLLER REGISTERS */
52071d7fec4Smrg
52171d7fec4Smrg   unlock = READ_REG32(DC_UNLOCK);
52271d7fec4Smrg   WRITE_REG32(DC_UNLOCK, DC_UNLOCK_VALUE);
52371d7fec4Smrg
52471d7fec4Smrg   /* READ THE CURRENT GX VALUES */
52571d7fec4Smrg
52671d7fec4Smrg   gcfg = READ_REG32(DC_GENERAL_CFG);
52771d7fec4Smrg   tcfg = READ_REG32(DC_TIMING_CFG);
52871d7fec4Smrg
52971d7fec4Smrg   /* BLANK THE GX DISPLAY AND DISABLE THE TIMING GENERATOR */
53071d7fec4Smrg
53171d7fec4Smrg   tcfg &= ~((unsigned long)DC_TCFG_BLKE | (unsigned long)DC_TCFG_TGEN);
53271d7fec4Smrg   WRITE_REG32(DC_TIMING_CFG, tcfg);
53371d7fec4Smrg
53471d7fec4Smrg   /* DELAY: WAIT FOR PENDING MEMORY REQUESTS
53571d7fec4Smrg    * This delay is used to make sure that all pending requests to the
53671d7fec4Smrg    * memory controller have completed before disabling the FIFO load.
53771d7fec4Smrg    */
53871d7fec4Smrg
53971d7fec4Smrg   gfx_delay_milliseconds(1);
54071d7fec4Smrg
54171d7fec4Smrg   /* DISABLE DISPLAY FIFO LOAD AND DISABLE COMPRESSION */
54271d7fec4Smrg
54371d7fec4Smrg   gcfg &= ~(unsigned long)(DC_GCFG_DFLE | DC_GCFG_CMPE | DC_GCFG_DECE);
54471d7fec4Smrg   WRITE_REG32(DC_GENERAL_CFG, gcfg);
54571d7fec4Smrg
54671d7fec4Smrg   /* CLEAR THE "DCLK_MUL" FIELD */
54771d7fec4Smrg
54871d7fec4Smrg   gcfg &= ~(unsigned long)(DC_GCFG_DDCK | DC_GCFG_DPCK | DC_GCFG_DFCK);
54971d7fec4Smrg   gcfg &= ~(unsigned long)DC_GCFG_DCLK_MASK;
55071d7fec4Smrg   WRITE_REG32(DC_GENERAL_CFG, gcfg);
55171d7fec4Smrg
55271d7fec4Smrg   /* SET THE DOT CLOCK FREQUENCY */
55371d7fec4Smrg   /* Mask off the divide by two bit (bit 31) */
55471d7fec4Smrg
55571d7fec4Smrg   gfx_set_clock_frequency(pMode->frequency & 0x7FFFFFFF);
55671d7fec4Smrg
55771d7fec4Smrg   /* DELAY: WAIT FOR THE PLL TO SETTLE */
55871d7fec4Smrg   /* This allows the dot clock frequency that was just set to settle. */
55971d7fec4Smrg
56071d7fec4Smrg   gfx_delay_milliseconds(1);
56171d7fec4Smrg
56271d7fec4Smrg   /* SET THE "DCLK_MUL" FIELD OF DC_GENERAL_CFG */
56371d7fec4Smrg   /* The GX hardware divides the dot clock, so 2x really means that the */
56471d7fec4Smrg   /* internal dot clock equals the external dot clock. */
56571d7fec4Smrg
56671d7fec4Smrg   if (pMode->frequency & 0x80000000)
56771d7fec4Smrg      gcfg |= 0x0040;
56871d7fec4Smrg   else
56971d7fec4Smrg      gcfg |= 0x0080;
57071d7fec4Smrg   WRITE_REG32(DC_GENERAL_CFG, gcfg);
57171d7fec4Smrg
57271d7fec4Smrg   /* DELAY: WAIT FOR THE ADL TO LOCK */
57371d7fec4Smrg   /* This allows the clock generatation within GX to settle.  This is */
57471d7fec4Smrg   /* needed since some of the register writes that follow require that */
57571d7fec4Smrg   /* clock to be present. */
57671d7fec4Smrg
57771d7fec4Smrg   /* We do a few to ensure we're synced */
57871d7fec4Smrg   gfx_delay_milliseconds(1);
57971d7fec4Smrg   gfx_delay_milliseconds(1);
58071d7fec4Smrg   gfx_delay_milliseconds(1);
58171d7fec4Smrg   gfx_delay_milliseconds(1);
58271d7fec4Smrg   gfx_delay_milliseconds(1);
58371d7fec4Smrg   gfx_delay_milliseconds(1);
58471d7fec4Smrg
58571d7fec4Smrg   /* SET THE GX DISPLAY CONTROLLER PARAMETERS */
58671d7fec4Smrg
58771d7fec4Smrg   WRITE_REG32(DC_FB_ST_OFFSET, 0);
58871d7fec4Smrg   WRITE_REG32(DC_CB_ST_OFFSET, 0);
58971d7fec4Smrg   WRITE_REG32(DC_CURS_ST_OFFSET, 0);
59071d7fec4Smrg
59171d7fec4Smrg   /* SET LINE SIZE AND PITCH */
59271d7fec4Smrg   /* Flat panels use the current flat panel line size to    */
59371d7fec4Smrg   /* calculate the pitch, but load the true line size       */
59471d7fec4Smrg   /* for the mode into the "Frame Buffer Line Size" field   */
59571d7fec4Smrg   /* of DC_BUF_SIZE.                                        */
59671d7fec4Smrg
59771d7fec4Smrg   if (PanelEnable)
59871d7fec4Smrg      size = ModeWidth;
59971d7fec4Smrg   else
60071d7fec4Smrg      size = pMode->hactive;
60171d7fec4Smrg
60271d7fec4Smrg   if (bpp > 8)
60371d7fec4Smrg      size <<= 1;
60471d7fec4Smrg
60571d7fec4Smrg   /* ONLY PYRAMID SUPPORTS 4K LINE SIZE */
60671d7fec4Smrg
60771d7fec4Smrg   if (size <= 1024) {
60871d7fec4Smrg      pitch = 1024;
60971d7fec4Smrg
61071d7fec4Smrg      /* SPECIAL CASE  */
61171d7fec4Smrg      /* Graphics acceleration in 16-bit pixel line double modes */
61271d7fec4Smrg      /* requires a pitch of 2048.                               */
61371d7fec4Smrg
61471d7fec4Smrg      if ((pMode->flags & GFX_MODE_LINE_DOUBLE) && bpp > 8)
61571d7fec4Smrg	 pitch <<= 1;
61671d7fec4Smrg   } else {
61771d7fec4Smrg      if (gfx_cpu_version == GFX_CPU_PYRAMID)
61871d7fec4Smrg	 pitch = (size <= 2048) ? 2048 : 4096;
61971d7fec4Smrg      else
62071d7fec4Smrg	 pitch = 2048;
62171d7fec4Smrg   }
62271d7fec4Smrg   WRITE_REG32(DC_LINE_DELTA, pitch >> 2);
62371d7fec4Smrg
62471d7fec4Smrg   if (PanelEnable) {
62571d7fec4Smrg      size = pMode->hactive;
62671d7fec4Smrg      if (bpp > 8)
62771d7fec4Smrg	 size <<= 1;
62871d7fec4Smrg   }
62971d7fec4Smrg
63071d7fec4Smrg   /* SAVE PREVIOUSLY STORED VIDEO BUFFER SIZE */
63171d7fec4Smrg
63271d7fec4Smrg   vid_buffer_size = READ_REG32(DC_BUF_SIZE) & 0x3FFF0000;
63371d7fec4Smrg
63471d7fec4Smrg   /* ADD 2 TO SIZE FOR POSSIBLE START ADDRESS ALIGNMENTS */
63571d7fec4Smrg
63671d7fec4Smrg   WRITE_REG32(DC_BUF_SIZE, ((size >> 3) + 2) | vid_buffer_size);
63771d7fec4Smrg
63871d7fec4Smrg   /* ALWAYS ENABLE "PANEL" DATA FROM MEDIAGX */
63971d7fec4Smrg   /* That is really just the 18 BPP data bus to the companion chip */
64071d7fec4Smrg
64171d7fec4Smrg   ocfg = DC_OCFG_PCKE | DC_OCFG_PDEL | DC_OCFG_PDEH;
64271d7fec4Smrg
64371d7fec4Smrg   /* SET PIXEL FORMAT */
64471d7fec4Smrg
64571d7fec4Smrg   if (bpp == 8)
64671d7fec4Smrg      ocfg |= DC_OCFG_8BPP;
64771d7fec4Smrg   else if (bpp == 15)
64871d7fec4Smrg      ocfg |= DC_OCFG_555;
64971d7fec4Smrg
65071d7fec4Smrg   /* ENABLE TIMING GENERATOR, SYNCS, AND FP DATA */
65171d7fec4Smrg
65271d7fec4Smrg   tcfg = DC_TCFG_FPPE | DC_TCFG_HSYE | DC_TCFG_VSYE | DC_TCFG_BLKE |
65371d7fec4Smrg	 DC_TCFG_TGEN;
65471d7fec4Smrg
65571d7fec4Smrg   /* SET FIFO PRIORITY, DCLK MULTIPLIER, AND FIFO ENABLE */
65671d7fec4Smrg   /* Default 6/5 for FIFO, 2x for DCLK multiplier. */
65771d7fec4Smrg
65871d7fec4Smrg   gcfg = (6 << DC_GCFG_DFHPEL_POS) | (5 << DC_GCFG_DFHPSL_POS) |
65971d7fec4Smrg	 DC_GCFG_DFLE;
66071d7fec4Smrg
66171d7fec4Smrg   /* INCREASE FIFO PRIORITY FOR LARGE MODES */
66271d7fec4Smrg
66371d7fec4Smrg   if (pMode->hactive == 1280 && pMode->vactive == 1024) {
66471d7fec4Smrg      if ((bpp == 8) && (pMode->flags & GFX_MODE_85HZ))
66571d7fec4Smrg	 gcfg = (8l << DC_GCFG_DFHPEL_POS) | (7l << DC_GCFG_DFHPSL_POS) |
66671d7fec4Smrg	       DC_GCFG_DFLE;
66771d7fec4Smrg      if ((bpp > 8) && (pMode->flags & GFX_MODE_75HZ))
66871d7fec4Smrg	 gcfg = (7l << DC_GCFG_DFHPEL_POS) | (6l << DC_GCFG_DFHPSL_POS) |
66971d7fec4Smrg	       DC_GCFG_DFLE;
67071d7fec4Smrg      if ((bpp > 8) && (pMode->flags & GFX_MODE_85HZ))
67171d7fec4Smrg	 gcfg = (9l << DC_GCFG_DFHPEL_POS) | (8l << DC_GCFG_DFHPSL_POS) |
67271d7fec4Smrg	       DC_GCFG_DFLE;
67371d7fec4Smrg   }
67471d7fec4Smrg
67571d7fec4Smrg   /* SET DOT CLOCK MULTIPLIER */
67671d7fec4Smrg   /* Bit 31 of frequency indicates divide frequency by two */
67771d7fec4Smrg
67871d7fec4Smrg   if (pMode->frequency & 0x80000000)
67971d7fec4Smrg      gcfg |= (1l << DC_GCFG_DCLK_POS);
68071d7fec4Smrg   else
68171d7fec4Smrg      gcfg |= (2l << DC_GCFG_DCLK_POS);
68271d7fec4Smrg
68371d7fec4Smrg   /* DIVIDE VIDEO CLOCK */
68471d7fec4Smrg   /* CPU core frequencies above 266 MHz will divide the video */
68571d7fec4Smrg   /* clock by 4 to ensure that we are running below 150 MHz.  */
68671d7fec4Smrg
68771d7fec4Smrg   if (gfx_cpu_frequency > 266)
68871d7fec4Smrg      gcfg |= DC_GCFG_VCLK_DIV;
68971d7fec4Smrg
69071d7fec4Smrg   /* SET THE PIXEL AND LINE DOUBLE BITS IF NECESSARY */
69171d7fec4Smrg
69271d7fec4Smrg   hactive = pMode->hactive;
69371d7fec4Smrg   vactive = pMode->vactive;
69471d7fec4Smrg   gfx_line_double = 0;
69571d7fec4Smrg   gfx_pixel_double = 0;
69671d7fec4Smrg
69771d7fec4Smrg   if (pMode->flags & GFX_MODE_LINE_DOUBLE) {
69871d7fec4Smrg      gcfg |= DC_GCFG_LDBL;
69971d7fec4Smrg      hactive <<= 1;
70071d7fec4Smrg
70171d7fec4Smrg      /* SET GLOBAL FLAG */
70271d7fec4Smrg
70371d7fec4Smrg      gfx_line_double = 1;
70471d7fec4Smrg   }
70571d7fec4Smrg
70671d7fec4Smrg   if (pMode->flags & GFX_MODE_PIXEL_DOUBLE) {
70771d7fec4Smrg      tcfg |= DC_TCFG_PXDB;
70871d7fec4Smrg      vactive <<= 1;
70971d7fec4Smrg
71071d7fec4Smrg      /* SET GLOBAL FLAG */
71171d7fec4Smrg
71271d7fec4Smrg      gfx_pixel_double = 1;
71371d7fec4Smrg   }
71471d7fec4Smrg
71571d7fec4Smrg   /* COMBINE AND SET TIMING VALUES */
71671d7fec4Smrg
71771d7fec4Smrg   value = (unsigned long)(hactive - 1) |
71871d7fec4Smrg	 (((unsigned long)(pMode->htotal - 1)) << 16);
71971d7fec4Smrg   WRITE_REG32(DC_H_TIMING_1, value);
72071d7fec4Smrg   value = (unsigned long)(pMode->hblankstart - 1) |
72171d7fec4Smrg	 (((unsigned long)(pMode->hblankend - 1)) << 16);
72271d7fec4Smrg   WRITE_REG32(DC_H_TIMING_2, value);
72371d7fec4Smrg   value = (unsigned long)(pMode->hsyncstart - 1) |
72471d7fec4Smrg	 (((unsigned long)(pMode->hsyncend - 1)) << 16);
72571d7fec4Smrg   WRITE_REG32(DC_H_TIMING_3, value);
72671d7fec4Smrg   WRITE_REG32(DC_FP_H_TIMING, value);
72771d7fec4Smrg   value = (unsigned long)(vactive - 1) |
72871d7fec4Smrg	 (((unsigned long)(pMode->vtotal - 1)) << 16);
72971d7fec4Smrg   WRITE_REG32(DC_V_TIMING_1, value);
73071d7fec4Smrg   value = (unsigned long)(pMode->vblankstart - 1) |
73171d7fec4Smrg	 (((unsigned long)(pMode->vblankend - 1)) << 16);
73271d7fec4Smrg   WRITE_REG32(DC_V_TIMING_2, value);
73371d7fec4Smrg   value = (unsigned long)(pMode->vsyncstart - 1) |
73471d7fec4Smrg	 (((unsigned long)(pMode->vsyncend - 1)) << 16);
73571d7fec4Smrg   WRITE_REG32(DC_V_TIMING_3, value);
73671d7fec4Smrg   value = (unsigned long)(pMode->vsyncstart - 2) |
73771d7fec4Smrg	 (((unsigned long)(pMode->vsyncend - 2)) << 16);
73871d7fec4Smrg   WRITE_REG32(DC_FP_V_TIMING, value);
73971d7fec4Smrg
74071d7fec4Smrg   WRITE_REG32(DC_OUTPUT_CFG, ocfg);
74171d7fec4Smrg   WRITE_REG32(DC_TIMING_CFG, tcfg);
74271d7fec4Smrg   gfx_delay_milliseconds(1);		/* delay after TIMING_CFG */
74371d7fec4Smrg   WRITE_REG32(DC_GENERAL_CFG, gcfg);
74471d7fec4Smrg
74571d7fec4Smrg   /* ENABLE FLAT PANEL CENTERING */
74671d7fec4Smrg   /* For 640x480 modes displayed with the 9211 within a 800x600 */
74771d7fec4Smrg   /* flat panel display, turn on flat panel centering.          */
74871d7fec4Smrg
74971d7fec4Smrg   if (PanelEnable) {
75071d7fec4Smrg      if (ModeWidth < PanelWidth) {
75171d7fec4Smrg	 tcfg = READ_REG32(DC_TIMING_CFG);
75271d7fec4Smrg	 tcfg = tcfg | DC_TCFG_FCEN;
75371d7fec4Smrg	 WRITE_REG32(DC_TIMING_CFG, tcfg);
75471d7fec4Smrg	 gfx_delay_milliseconds(1);	/* delay after TIMING_CFG */
75571d7fec4Smrg      }
75671d7fec4Smrg   }
75771d7fec4Smrg
75871d7fec4Smrg   /* CONFIGURE DISPLAY OUTPUT FROM VIDEO PROCESSOR */
75971d7fec4Smrg
76071d7fec4Smrg   gfx_set_display_control(((pMode->flags & GFX_MODE_NEG_HSYNC) ? 1 : 0) |
76171d7fec4Smrg			   ((pMode->flags & GFX_MODE_NEG_VSYNC) ? 2 : 0));
76271d7fec4Smrg
76371d7fec4Smrg   /* RESTORE VALUE OF DC_UNLOCK */
76471d7fec4Smrg
76571d7fec4Smrg   WRITE_REG32(DC_UNLOCK, unlock);
76671d7fec4Smrg
76771d7fec4Smrg   /* ALSO WRITE GP_BLIT_STATUS FOR PITCH AND 8/18 BPP */
76871d7fec4Smrg   /* Remember, only Pyramid supports 4K line pitch    */
76971d7fec4Smrg
77071d7fec4Smrg   value = 0;
77171d7fec4Smrg   if (bpp > 8)
77271d7fec4Smrg      value |= BC_16BPP;
77371d7fec4Smrg   if ((gfx_cpu_version == GFX_CPU_PYRAMID) && (pitch > 2048))
77471d7fec4Smrg      value |= BC_FB_WIDTH_4096;
77571d7fec4Smrg   else if (pitch > 1024)
77671d7fec4Smrg      value |= BC_FB_WIDTH_2048;
77771d7fec4Smrg   WRITE_REG16(GP_BLIT_STATUS, (unsigned short)value);
77871d7fec4Smrg
77971d7fec4Smrg   return GFX_STATUS_OK;
78071d7fec4Smrg
78171d7fec4Smrg}					/* end gfx_set_specified_mode() */
78271d7fec4Smrg
78371d7fec4Smrg/*----------------------------------------------------------------------------
78471d7fec4Smrg * GFX_IS_DISPLAY_MODE_SUPPORTED
78571d7fec4Smrg *
78671d7fec4Smrg * This routine sets the specified display mode.
78771d7fec4Smrg *
78871d7fec4Smrg * Returns the index of the mode if successful and mode returned, -1 if the mode
78971d7fec4Smrg * could not be found.
79071d7fec4Smrg *----------------------------------------------------------------------------
79171d7fec4Smrg */
79271d7fec4Smrg#if GFX_DISPLAY_DYNAMIC
79371d7fec4Smrgint
79471d7fec4Smrggu1_is_display_mode_supported(int xres, int yres, int bpp, int hz)
79571d7fec4Smrg#else
79671d7fec4Smrgint
79771d7fec4Smrggfx_is_display_mode_supported(int xres, int yres, int bpp, int hz)
79871d7fec4Smrg#endif
79971d7fec4Smrg{
80071d7fec4Smrg   unsigned int mode = 0;
80171d7fec4Smrg   unsigned long hz_flag = 0, bpp_flag = 0;
80271d7fec4Smrg
80371d7fec4Smrg   /* SET FLAGS TO MATCH REFRESH RATE */
80471d7fec4Smrg
80571d7fec4Smrg   if (hz == 56)
80671d7fec4Smrg      hz_flag = GFX_MODE_56HZ;
80771d7fec4Smrg   else if (hz == 60)
80871d7fec4Smrg      hz_flag = GFX_MODE_60HZ;
80971d7fec4Smrg   else if (hz == 70)
81071d7fec4Smrg      hz_flag = GFX_MODE_70HZ;
81171d7fec4Smrg   else if (hz == 72)
81271d7fec4Smrg      hz_flag = GFX_MODE_72HZ;
81371d7fec4Smrg   else if (hz == 75)
81471d7fec4Smrg      hz_flag = GFX_MODE_75HZ;
81571d7fec4Smrg   else if (hz == 85)
81671d7fec4Smrg      hz_flag = GFX_MODE_85HZ;
81771d7fec4Smrg   else
81871d7fec4Smrg      return -1;
81971d7fec4Smrg
82071d7fec4Smrg   /* SET BPP FLAGS TO LIMIT MODE SELECTION */
82171d7fec4Smrg
82271d7fec4Smrg   if (bpp == 8)
82371d7fec4Smrg      bpp_flag = GFX_MODE_8BPP;
82471d7fec4Smrg   else if (bpp == 15)
82571d7fec4Smrg      bpp_flag = GFX_MODE_15BPP;
82671d7fec4Smrg   else if (bpp == 16)
82771d7fec4Smrg      bpp_flag = GFX_MODE_16BPP;
82871d7fec4Smrg   else
82971d7fec4Smrg      return -1;
83071d7fec4Smrg
83171d7fec4Smrg   /* ONLY PYRAMID SUPPORTS 4K PITCH */
83271d7fec4Smrg
83371d7fec4Smrg   if (gfx_cpu_version != GFX_CPU_PYRAMID && xres > 1024) {
83471d7fec4Smrg      if (bpp > 8)
83571d7fec4Smrg	 return (-1);			/* return with mode not found */
83671d7fec4Smrg   }
83771d7fec4Smrg
83871d7fec4Smrg   /* LOOP THROUGH THE AVAILABLE MODES TO FIND A MATCH */
83971d7fec4Smrg
84071d7fec4Smrg   for (mode = 0; mode < NUM_GX_DISPLAY_MODES; mode++) {
84171d7fec4Smrg      if ((DisplayParams[mode].hactive == (unsigned short)xres) &&
84271d7fec4Smrg	  (DisplayParams[mode].vactive == (unsigned short)yres) &&
84371d7fec4Smrg	  (DisplayParams[mode].flags & hz_flag) &&
84471d7fec4Smrg	  (DisplayParams[mode].flags & bpp_flag)) {
84571d7fec4Smrg
84671d7fec4Smrg	 /* SET THE DISPLAY CONTROLLER FOR THE SELECTED MODE */
84771d7fec4Smrg
84871d7fec4Smrg	 return (mode);
84971d7fec4Smrg      }
85071d7fec4Smrg   }
85171d7fec4Smrg   return (-1);
85271d7fec4Smrg}
85371d7fec4Smrg
85471d7fec4Smrg/*----------------------------------------------------------------------------
85571d7fec4Smrg * GFX_SET_DISPLAY_MODE
85671d7fec4Smrg *
85771d7fec4Smrg * This routine sets the specified display mode.
85871d7fec4Smrg *
85971d7fec4Smrg * Returns 1 if successful, 0 if mode could not be set.
86071d7fec4Smrg *----------------------------------------------------------------------------
86171d7fec4Smrg */
86271d7fec4Smrg#if GFX_DISPLAY_DYNAMIC
86371d7fec4Smrgint
86471d7fec4Smrggu1_set_display_mode(int xres, int yres, int bpp, int hz)
86571d7fec4Smrg#else
86671d7fec4Smrgint
86771d7fec4Smrggfx_set_display_mode(int xres, int yres, int bpp, int hz)
86871d7fec4Smrg#endif
86971d7fec4Smrg{
87071d7fec4Smrg   int mode;
87171d7fec4Smrg
87271d7fec4Smrg   /* DISABLE FLAT PANEL */
87371d7fec4Smrg   /* Flat Panel settings are enabled by the function gfx_set_fixed_timings */
87471d7fec4Smrg   /* and disabled by gfx_set_display_mode.                                 */
87571d7fec4Smrg
87671d7fec4Smrg   PanelEnable = 0;
87771d7fec4Smrg
87871d7fec4Smrg   mode = gfx_is_display_mode_supported(xres, yres, bpp, hz);
87971d7fec4Smrg   if (mode >= 0) {
88071d7fec4Smrg      if (gu1_set_specified_mode(&DisplayParams[mode], bpp) == GFX_STATUS_OK)
88171d7fec4Smrg	 return (1);
88271d7fec4Smrg   }
88371d7fec4Smrg   return (0);
88471d7fec4Smrg}
88571d7fec4Smrg
88671d7fec4Smrg/*----------------------------------------------------------------------------
88771d7fec4Smrg * GFX_SET_DISPLAY_TIMINGS
88871d7fec4Smrg *
88971d7fec4Smrg * This routine sets the display controller mode using the specified timing
89071d7fec4Smrg * values (as opposed to using the tables internal to Durango).
89171d7fec4Smrg *
89271d7fec4Smrg * Returns GFX_STATUS_OK on success, GFX_STATUS_ERROR otherwise.
89371d7fec4Smrg *----------------------------------------------------------------------------
89471d7fec4Smrg */
89571d7fec4Smrg#if GFX_DISPLAY_DYNAMIC
89671d7fec4Smrgint
89771d7fec4Smrggu1_set_display_timings(unsigned short bpp, unsigned short flags,
89871d7fec4Smrg			unsigned short hactive, unsigned short hblankstart,
89971d7fec4Smrg			unsigned short hsyncstart, unsigned short hsyncend,
90071d7fec4Smrg			unsigned short hblankend, unsigned short htotal,
90171d7fec4Smrg			unsigned short vactive, unsigned short vblankstart,
90271d7fec4Smrg			unsigned short vsyncstart, unsigned short vsyncend,
90371d7fec4Smrg			unsigned short vblankend, unsigned short vtotal,
90471d7fec4Smrg			unsigned long frequency)
90571d7fec4Smrg#else
90671d7fec4Smrgint
90771d7fec4Smrggfx_set_display_timings(unsigned short bpp, unsigned short flags,
90871d7fec4Smrg			unsigned short hactive, unsigned short hblankstart,
90971d7fec4Smrg			unsigned short hsyncstart, unsigned short hsyncend,
91071d7fec4Smrg			unsigned short hblankend, unsigned short htotal,
91171d7fec4Smrg			unsigned short vactive, unsigned short vblankstart,
91271d7fec4Smrg			unsigned short vsyncstart, unsigned short vsyncend,
91371d7fec4Smrg			unsigned short vblankend, unsigned short vtotal,
91471d7fec4Smrg			unsigned long frequency)
91571d7fec4Smrg#endif
91671d7fec4Smrg{
91771d7fec4Smrg   /* SET MODE STRUCTURE WITH SPECIFIED VALUES */
91871d7fec4Smrg
91971d7fec4Smrg   gfx_display_mode.flags = 0;
92071d7fec4Smrg   if (flags & 1)
92171d7fec4Smrg      gfx_display_mode.flags |= GFX_MODE_NEG_HSYNC;
92271d7fec4Smrg   if (flags & 2)
92371d7fec4Smrg      gfx_display_mode.flags |= GFX_MODE_NEG_VSYNC;
92471d7fec4Smrg   if (flags & 0x1000)
92571d7fec4Smrg      gfx_display_mode.flags |= GFX_MODE_LOCK_TIMING;
92671d7fec4Smrg   gfx_display_mode.hactive = hactive;
92771d7fec4Smrg   gfx_display_mode.hblankstart = hblankstart;
92871d7fec4Smrg   gfx_display_mode.hsyncstart = hsyncstart;
92971d7fec4Smrg   gfx_display_mode.hsyncend = hsyncend;
93071d7fec4Smrg   gfx_display_mode.hblankend = hblankend;
93171d7fec4Smrg   gfx_display_mode.htotal = htotal;
93271d7fec4Smrg   gfx_display_mode.vactive = vactive;
93371d7fec4Smrg   gfx_display_mode.vblankstart = vblankstart;
93471d7fec4Smrg   gfx_display_mode.vsyncstart = vsyncstart;
93571d7fec4Smrg   gfx_display_mode.vsyncend = vsyncend;
93671d7fec4Smrg   gfx_display_mode.vblankend = vblankend;
93771d7fec4Smrg   gfx_display_mode.vtotal = vtotal;
93871d7fec4Smrg   gfx_display_mode.frequency = frequency;
93971d7fec4Smrg
94071d7fec4Smrg   /* CALL ROUTINE TO SET MODE */
94171d7fec4Smrg
94271d7fec4Smrg   return (gu1_set_specified_mode(&gfx_display_mode, bpp));
94371d7fec4Smrg}
94471d7fec4Smrg
94571d7fec4Smrg/*----------------------------------------------------------------------------
94671d7fec4Smrg * GFX_SET_VTOTAL
94771d7fec4Smrg *
94871d7fec4Smrg * This routine sets the display controller vertical total to
94971d7fec4Smrg * "vtotal". As a side effect it also sets vertical blank end.
95071d7fec4Smrg * It should be used when only this value needs to be changed,
95171d7fec4Smrg * due to speed considerations.
95271d7fec4Smrg *
95371d7fec4Smrg * Note: it is the caller's responsibility to make sure that
95471d7fec4Smrg * a legal vtotal is used, i.e. that "vtotal" is greater than or
95571d7fec4Smrg * equal to vsync end.
95671d7fec4Smrg *
95771d7fec4Smrg * Always returns 0.
95871d7fec4Smrg *----------------------------------------------------------------------------
95971d7fec4Smrg */
96071d7fec4Smrg#if GFX_DISPLAY_DYNAMIC
96171d7fec4Smrgint
96271d7fec4Smrggu1_set_vtotal(unsigned short vtotal)
96371d7fec4Smrg#else
96471d7fec4Smrgint
96571d7fec4Smrggfx_set_vtotal(unsigned short vtotal)
96671d7fec4Smrg#endif
96771d7fec4Smrg{
96871d7fec4Smrg   unsigned long unlock, tcfg, timing1, timing2;
96971d7fec4Smrg
97071d7fec4Smrg   /* UNLOCK THE DISPLAY CONTROLLER REGISTERS */
97171d7fec4Smrg
97271d7fec4Smrg   unlock = READ_REG32(DC_UNLOCK);
97371d7fec4Smrg   WRITE_REG32(DC_UNLOCK, DC_UNLOCK_VALUE);
97471d7fec4Smrg
97571d7fec4Smrg   /* READ THE CURRENT GX VALUES */
97671d7fec4Smrg
97771d7fec4Smrg   tcfg = READ_REG32(DC_TIMING_CFG);
97871d7fec4Smrg   timing1 = READ_REG32(DC_V_TIMING_1);
97971d7fec4Smrg   timing2 = READ_REG32(DC_V_TIMING_2);
98071d7fec4Smrg
98171d7fec4Smrg   /* DISABLE THE TIMING GENERATOR */
98271d7fec4Smrg
98371d7fec4Smrg   WRITE_REG32(DC_TIMING_CFG, tcfg & ~(unsigned long)DC_TCFG_TGEN);
98471d7fec4Smrg
98571d7fec4Smrg   /* WRITE NEW TIMING VALUES */
98671d7fec4Smrg
98771d7fec4Smrg   WRITE_REG32(DC_V_TIMING_1,
98871d7fec4Smrg	       (timing1 & 0xffff) | (unsigned long)(vtotal - 1) << 16);
98971d7fec4Smrg   WRITE_REG32(DC_V_TIMING_2,
99071d7fec4Smrg	       (timing2 & 0xffff) | (unsigned long)(vtotal - 1) << 16);
99171d7fec4Smrg
99271d7fec4Smrg   /* RESTORE GX VALUES */
99371d7fec4Smrg
99471d7fec4Smrg   WRITE_REG32(DC_TIMING_CFG, tcfg);
99571d7fec4Smrg   WRITE_REG32(DC_UNLOCK, unlock);
99671d7fec4Smrg
99771d7fec4Smrg   return (0);
99871d7fec4Smrg}
99971d7fec4Smrg
100071d7fec4Smrg/*---------------------------------------------------------------------------
100171d7fec4Smrg * gfx_set_display_pitch
100271d7fec4Smrg *
100371d7fec4Smrg * This routine sets the pitch of the frame buffer to the specified value.
100471d7fec4Smrg *---------------------------------------------------------------------------
100571d7fec4Smrg */
100671d7fec4Smrg#if GFX_DISPLAY_DYNAMIC
100771d7fec4Smrgvoid
100871d7fec4Smrggu1_set_display_pitch(unsigned short pitch)
100971d7fec4Smrg#else
101071d7fec4Smrgvoid
101171d7fec4Smrggfx_set_display_pitch(unsigned short pitch)
101271d7fec4Smrg#endif
101371d7fec4Smrg{
101471d7fec4Smrg   unsigned long value = 0;
101571d7fec4Smrg   unsigned long lock = READ_REG32(DC_UNLOCK);
101671d7fec4Smrg
101771d7fec4Smrg   value = READ_REG32(DC_LINE_DELTA) & 0xFFFFF000;
101871d7fec4Smrg   value |= (pitch >> 2);
101971d7fec4Smrg   WRITE_REG32(DC_UNLOCK, DC_UNLOCK_VALUE);
102071d7fec4Smrg   WRITE_REG32(DC_LINE_DELTA, value);
102171d7fec4Smrg   WRITE_REG32(DC_UNLOCK, lock);
102271d7fec4Smrg
102371d7fec4Smrg   /* ALSO UPDATE PITCH IN GRAPHICS ENGINE */
102471d7fec4Smrg   /* Pyramid alone supports 4K line pitch */
102571d7fec4Smrg
102671d7fec4Smrg   value = (unsigned long)READ_REG16(GP_BLIT_STATUS);
102771d7fec4Smrg   value &= ~(BC_FB_WIDTH_2048 | BC_FB_WIDTH_4096);
102871d7fec4Smrg
102971d7fec4Smrg   if ((gfx_cpu_version == GFX_CPU_PYRAMID) && (pitch > 2048))
103071d7fec4Smrg      value |= BC_FB_WIDTH_4096;
103171d7fec4Smrg
103271d7fec4Smrg   else if (pitch > 1024)
103371d7fec4Smrg      value |= BC_FB_WIDTH_2048;
103471d7fec4Smrg
103571d7fec4Smrg   WRITE_REG16(GP_BLIT_STATUS, (unsigned short)value);
103671d7fec4Smrg   return;
103771d7fec4Smrg}
103871d7fec4Smrg
103971d7fec4Smrg/*---------------------------------------------------------------------------
104071d7fec4Smrg * gfx_set_display_offset
104171d7fec4Smrg *
104271d7fec4Smrg * This routine sets the start address of the frame buffer.  It is
104371d7fec4Smrg * typically used to pan across a virtual desktop (frame buffer larger than
104471d7fec4Smrg * the displayed screen) or to flip the display between multiple buffers.
104571d7fec4Smrg *---------------------------------------------------------------------------
104671d7fec4Smrg */
104771d7fec4Smrg#if GFX_DISPLAY_DYNAMIC
104871d7fec4Smrgvoid
104971d7fec4Smrggu1_set_display_offset(unsigned long offset)
105071d7fec4Smrg#else
105171d7fec4Smrgvoid
105271d7fec4Smrggfx_set_display_offset(unsigned long offset)
105371d7fec4Smrg#endif
105471d7fec4Smrg{
105571d7fec4Smrg   /* UPDATE FRAME BUFFER OFFSET */
105671d7fec4Smrg
105771d7fec4Smrg   unsigned long lock;
105871d7fec4Smrg
105971d7fec4Smrg   lock = READ_REG32(DC_UNLOCK);
106071d7fec4Smrg   WRITE_REG32(DC_UNLOCK, DC_UNLOCK_VALUE);
106171d7fec4Smrg
106271d7fec4Smrg   /* START ADDRESS EFFECTS DISPLAY COMPRESSION */
106371d7fec4Smrg   /* Disable compression for non-zero start addresss values.            */
106471d7fec4Smrg   /* Enable compression if offset is zero and comression is intended to */
106571d7fec4Smrg   /* be enabled from a previous call to "gfx_set_compression_enable".   */
106671d7fec4Smrg   /* Compression should be disabled BEFORE the offset is changed        */
106771d7fec4Smrg   /* and enabled AFTER the offset is changed.                           */
106871d7fec4Smrg
106971d7fec4Smrg   if (offset == 0) {
107071d7fec4Smrg      WRITE_REG32(DC_FB_ST_OFFSET, offset);
107171d7fec4Smrg      if (gfx_compression_enabled) {
107271d7fec4Smrg	 /* WAIT FOR THE OFFSET TO BE LATCHED */
107371d7fec4Smrg	 gfx_wait_vertical_blank();
107471d7fec4Smrg	 gu1_enable_compression();
107571d7fec4Smrg      }
107671d7fec4Smrg   } else {
107771d7fec4Smrg      /* ONLY DISABLE COMPRESSION ONCE */
107871d7fec4Smrg
107971d7fec4Smrg      if (gfx_compression_active)
108071d7fec4Smrg	 gu1_disable_compression();
108171d7fec4Smrg
108271d7fec4Smrg      WRITE_REG32(DC_FB_ST_OFFSET, offset);
108371d7fec4Smrg   }
108471d7fec4Smrg
108571d7fec4Smrg   WRITE_REG32(DC_UNLOCK, lock);
108671d7fec4Smrg}
108771d7fec4Smrg
108871d7fec4Smrg/*---------------------------------------------------------------------------
108971d7fec4Smrg * gfx_set_display_palette_entry
109071d7fec4Smrg *
109171d7fec4Smrg * This routine sets an palette entry in the display controller.
109271d7fec4Smrg * A 32-bit X:R:G:B value.
109371d7fec4Smrg *---------------------------------------------------------------------------
109471d7fec4Smrg */
109571d7fec4Smrg#if GFX_DISPLAY_DYNAMIC
109671d7fec4Smrgint
109771d7fec4Smrggu1_set_display_palette_entry(unsigned long index, unsigned long palette)
109871d7fec4Smrg#else
109971d7fec4Smrgint
110071d7fec4Smrggfx_set_display_palette_entry(unsigned long index, unsigned long palette)
110171d7fec4Smrg#endif
110271d7fec4Smrg{
110371d7fec4Smrg   unsigned long data;
110471d7fec4Smrg
110571d7fec4Smrg   if (index > 0xFF)
110671d7fec4Smrg      return GFX_STATUS_BAD_PARAMETER;
110771d7fec4Smrg
110871d7fec4Smrg   WRITE_REG32(DC_PAL_ADDRESS, index);
110971d7fec4Smrg   data = ((palette >> 2) & 0x0003F) |
111071d7fec4Smrg	 ((palette >> 4) & 0x00FC0) | ((palette >> 6) & 0x3F000);
111171d7fec4Smrg   WRITE_REG32(DC_PAL_DATA, data);
111271d7fec4Smrg
111371d7fec4Smrg   return (0);
111471d7fec4Smrg}
111571d7fec4Smrg
111671d7fec4Smrg/*---------------------------------------------------------------------------
111771d7fec4Smrg * gfx_set_display_palette
111871d7fec4Smrg *
111971d7fec4Smrg * This routine sets the entire palette in the display controller.
112071d7fec4Smrg * A pointer is provided to a 256 entry table of 32-bit X:R:G:B values.
112171d7fec4Smrg * Restriction:
112271d7fec4Smrg * Due to SC1200 Issue #748 (in Notes DB) this function should be called only
112371d7fec4Smrg * when DCLK is active, i.e PLL is already powered up and genlock is not active.
112471d7fec4Smrg *---------------------------------------------------------------------------
112571d7fec4Smrg */
112671d7fec4Smrg#if GFX_DISPLAY_DYNAMIC
112771d7fec4Smrgint
112871d7fec4Smrggu1_set_display_palette(unsigned long *palette)
112971d7fec4Smrg#else
113071d7fec4Smrgint
113171d7fec4Smrggfx_set_display_palette(unsigned long *palette)
113271d7fec4Smrg#endif
113371d7fec4Smrg{
113471d7fec4Smrg   unsigned long data, i;
113571d7fec4Smrg
113671d7fec4Smrg   WRITE_REG32(DC_PAL_ADDRESS, 0);
113771d7fec4Smrg   if (palette) {
113871d7fec4Smrg      for (i = 0; i < 256; i++) {
113971d7fec4Smrg	 /* CONVERT 24 BPP COLOR DATA TO 18 BPP COLOR DATA */
114071d7fec4Smrg
114171d7fec4Smrg	 data = ((palette[i] >> 2) & 0x0003F) |
114271d7fec4Smrg	       ((palette[i] >> 4) & 0x00FC0) | ((palette[i] >> 6) & 0x3F000);
114371d7fec4Smrg	 WRITE_REG32(DC_PAL_DATA, data);
114471d7fec4Smrg      }
114571d7fec4Smrg   }
114671d7fec4Smrg   return (0);
114771d7fec4Smrg}
114871d7fec4Smrg
114971d7fec4Smrg/*---------------------------------------------------------------------------
115071d7fec4Smrg * gfx_set_cursor_enable
115171d7fec4Smrg *
115271d7fec4Smrg * This routine enables or disables the hardware cursor.
115371d7fec4Smrg *
115471d7fec4Smrg * WARNING: The cusrsor start offset must be set by setting the cursor
115571d7fec4Smrg * position before calling this routine to assure that memory reads do not
115671d7fec4Smrg * go past the end of graphics memory (this can hang GXm).
115771d7fec4Smrg *---------------------------------------------------------------------------
115871d7fec4Smrg */
115971d7fec4Smrg#if GFX_DISPLAY_DYNAMIC
116071d7fec4Smrgvoid
116171d7fec4Smrggu1_set_cursor_enable(int enable)
116271d7fec4Smrg#else
116371d7fec4Smrgvoid
116471d7fec4Smrggfx_set_cursor_enable(int enable)
116571d7fec4Smrg#endif
116671d7fec4Smrg{
116771d7fec4Smrg   unsigned long unlock, gcfg;
116871d7fec4Smrg
116971d7fec4Smrg   /* SET OR CLEAR CURSOR ENABLE BIT */
117071d7fec4Smrg
117171d7fec4Smrg   unlock = READ_REG32(DC_UNLOCK);
117271d7fec4Smrg   gcfg = READ_REG32(DC_GENERAL_CFG);
117371d7fec4Smrg   if (enable)
117471d7fec4Smrg      gcfg |= DC_GCFG_CURE;
117571d7fec4Smrg   else
117671d7fec4Smrg      gcfg &= ~(DC_GCFG_CURE);
117771d7fec4Smrg
117871d7fec4Smrg   /* WRITE NEW REGISTER VALUE */
117971d7fec4Smrg
118071d7fec4Smrg   WRITE_REG32(DC_UNLOCK, DC_UNLOCK_VALUE);
118171d7fec4Smrg   WRITE_REG32(DC_GENERAL_CFG, gcfg);
118271d7fec4Smrg   WRITE_REG32(DC_UNLOCK, unlock);
118371d7fec4Smrg}
118471d7fec4Smrg
118571d7fec4Smrg/*---------------------------------------------------------------------------
118671d7fec4Smrg * gfx_set_cursor_colors
118771d7fec4Smrg *
118871d7fec4Smrg * This routine sets the colors of the hardware cursor.
118971d7fec4Smrg * Restriction:
119071d7fec4Smrg * Due to SC1200 Issue #748 (in Notes DB) this function should be called only
119171d7fec4Smrg * when DCLK is active, i.e PLL is already powered up.
119271d7fec4Smrg *---------------------------------------------------------------------------
119371d7fec4Smrg */
119471d7fec4Smrg#if GFX_DISPLAY_DYNAMIC
119571d7fec4Smrgvoid
119671d7fec4Smrggu1_set_cursor_colors(unsigned long bkcolor, unsigned long fgcolor)
119771d7fec4Smrg#else
119871d7fec4Smrgvoid
119971d7fec4Smrggfx_set_cursor_colors(unsigned long bkcolor, unsigned long fgcolor)
120071d7fec4Smrg#endif
120171d7fec4Smrg{
120271d7fec4Smrg   unsigned long value;
120371d7fec4Smrg
120471d7fec4Smrg   /* If genlock is enabled DCLK might be disabled in vertical blank. */
120571d7fec4Smrg   /* Due to SC1200 Issue #748 in Notes DB this would fail the cursor color settings */
120671d7fec4Smrg   /* So Wait for vertical blank to end */
120771d7fec4Smrg
120871d7fec4Smrg#if GFX_VIDEO_SC1200
120971d7fec4Smrg   if (gfx_test_timing_active())
121071d7fec4Smrg      while ((gfx_get_vline()) > gfx_get_vactive()) ;
121171d7fec4Smrg#endif
121271d7fec4Smrg
121371d7fec4Smrg   /* SET CURSOR COLORS */
121471d7fec4Smrg
121571d7fec4Smrg   WRITE_REG32(DC_PAL_ADDRESS, 0x100);
121671d7fec4Smrg   value = ((bkcolor & 0x000000FC) >> 2) |
121771d7fec4Smrg	 ((bkcolor & 0x0000FC00) >> (2 + 8 - 6)) |
121871d7fec4Smrg	 ((bkcolor & 0x00FC0000) >> (2 + 16 - 12));
121971d7fec4Smrg   WRITE_REG32(DC_PAL_DATA, value);
122071d7fec4Smrg   value = ((fgcolor & 0x000000FC) >> 2) |
122171d7fec4Smrg	 ((fgcolor & 0x0000FC00) >> (2 + 8 - 6)) |
122271d7fec4Smrg	 ((fgcolor & 0x00FC0000) >> (2 + 16 - 12));
122371d7fec4Smrg   WRITE_REG32(DC_PAL_DATA, value);
122471d7fec4Smrg}
122571d7fec4Smrg
122671d7fec4Smrg/*---------------------------------------------------------------------------
122771d7fec4Smrg * gfx_set_cursor_position
122871d7fec4Smrg *
122971d7fec4Smrg * This routine sets the position of the hardware cusror.  The starting
123071d7fec4Smrg * offset of the cursor buffer must be specified so that the routine can
123171d7fec4Smrg * properly clip scanlines if the cursor is off the top of the screen.
123271d7fec4Smrg *---------------------------------------------------------------------------
123371d7fec4Smrg */
123471d7fec4Smrg#if GFX_DISPLAY_DYNAMIC
123571d7fec4Smrgvoid
123671d7fec4Smrggu1_set_cursor_position(unsigned long memoffset,
123771d7fec4Smrg			unsigned short xpos, unsigned short ypos,
123871d7fec4Smrg			unsigned short xhotspot, unsigned short yhotspot)
123971d7fec4Smrg#else
124071d7fec4Smrgvoid
124171d7fec4Smrggfx_set_cursor_position(unsigned long memoffset,
124271d7fec4Smrg			unsigned short xpos, unsigned short ypos,
124371d7fec4Smrg			unsigned short xhotspot, unsigned short yhotspot)
124471d7fec4Smrg#endif
124571d7fec4Smrg{
124671d7fec4Smrg   unsigned long unlock;
124771d7fec4Smrg
124871d7fec4Smrg   short x, y;
124971d7fec4Smrg   short xoffset = 0;
125071d7fec4Smrg   short yoffset = 0;
125171d7fec4Smrg
125271d7fec4Smrg   /* SUPPORT CURSOR IN EMULATED VGA MODES */
125371d7fec4Smrg   /* Timings are for twice the resolution */
125471d7fec4Smrg
125571d7fec4Smrg   if (gfx_pixel_double)
125671d7fec4Smrg      xpos <<= 1;
125771d7fec4Smrg   if (gfx_line_double)
125871d7fec4Smrg      ypos <<= 1;
125971d7fec4Smrg
126071d7fec4Smrg   x = (short)xpos - (short)xhotspot;
126171d7fec4Smrg   y = (short)ypos - (short)yhotspot;
126271d7fec4Smrg   if (x < -31)
126371d7fec4Smrg      return;
126471d7fec4Smrg   if (y < -31)
126571d7fec4Smrg      return;
126671d7fec4Smrg   if (x < 0) {
126771d7fec4Smrg      xoffset = -x;
126871d7fec4Smrg      x = 0;
126971d7fec4Smrg   }
127071d7fec4Smrg   if (y < 0) {
127171d7fec4Smrg      yoffset = -y;
127271d7fec4Smrg      y = 0;
127371d7fec4Smrg   }
127471d7fec4Smrg   memoffset += (unsigned long)yoffset << 3;
127571d7fec4Smrg
127671d7fec4Smrg   if (PanelEnable) {
127771d7fec4Smrg      if ((ModeWidth > PanelWidth) || (ModeHeight > PanelHeight)) {
127871d7fec4Smrg	 gfx_enable_panning(xpos, ypos);
127971d7fec4Smrg	 x = x - (short)panelLeft;
128071d7fec4Smrg	 y = y - (short)panelTop;
128171d7fec4Smrg      }
128271d7fec4Smrg   }
128371d7fec4Smrg
128471d7fec4Smrg   /* SET CURSOR POSITION */
128571d7fec4Smrg
128671d7fec4Smrg   unlock = READ_REG32(DC_UNLOCK);
128771d7fec4Smrg   WRITE_REG32(DC_UNLOCK, DC_UNLOCK_VALUE);
128871d7fec4Smrg   WRITE_REG32(DC_CURS_ST_OFFSET, memoffset);
128971d7fec4Smrg   WRITE_REG32(DC_CURSOR_X, (unsigned long)x |
129071d7fec4Smrg	       (((unsigned long)xoffset) << 11));
129171d7fec4Smrg   WRITE_REG32(DC_CURSOR_Y, (unsigned long)y |
129271d7fec4Smrg	       (((unsigned long)yoffset) << 11));
129371d7fec4Smrg   WRITE_REG32(DC_UNLOCK, unlock);
129471d7fec4Smrg}
129571d7fec4Smrg
129671d7fec4Smrg/*---------------------------------------------------------------------------
129771d7fec4Smrg * gfx_set_cursor_shape32
129871d7fec4Smrg *
129971d7fec4Smrg * This routine loads 32x32 cursor data into the specified location in
130071d7fec4Smrg * graphics memory.
130171d7fec4Smrg *---------------------------------------------------------------------------
130271d7fec4Smrg */
130371d7fec4Smrg#if GFX_DISPLAY_DYNAMIC
130471d7fec4Smrgvoid
130571d7fec4Smrggu1_set_cursor_shape32(unsigned long memoffset,
130671d7fec4Smrg		       unsigned long *andmask, unsigned long *xormask)
130771d7fec4Smrg#else
130871d7fec4Smrgvoid
130971d7fec4Smrggfx_set_cursor_shape32(unsigned long memoffset,
131071d7fec4Smrg		       unsigned long *andmask, unsigned long *xormask)
131171d7fec4Smrg#endif
131271d7fec4Smrg{
131371d7fec4Smrg   int i;
131471d7fec4Smrg   unsigned long value;
131571d7fec4Smrg
131671d7fec4Smrg   for (i = 0; i < 32; i++) {
131771d7fec4Smrg      /* CONVERT TO 16 BITS AND MASK, 16 BITS XOR MASK PER DWORD */
131871d7fec4Smrg
131971d7fec4Smrg      value = (andmask[i] & 0xFFFF0000) | (xormask[i] >> 16);
132071d7fec4Smrg      WRITE_FB32(memoffset, value);
132171d7fec4Smrg      memoffset += 4;
132271d7fec4Smrg      value = (andmask[i] << 16) | (xormask[i] & 0x0000FFFF);
132371d7fec4Smrg      WRITE_FB32(memoffset, value);
132471d7fec4Smrg      memoffset += 4;
132571d7fec4Smrg   }
132671d7fec4Smrg}
132771d7fec4Smrg
132871d7fec4Smrg/*---------------------------------------------------------------------------
132971d7fec4Smrg * gu1_enable_compression
133071d7fec4Smrg *
133171d7fec4Smrg * This is a private routine to this module (not exposed in the Durango API).
133271d7fec4Smrg * It enables display compression.
133371d7fec4Smrg *---------------------------------------------------------------------------
133471d7fec4Smrg */
133571d7fec4Smrgvoid
133671d7fec4Smrggu1_enable_compression(void)
133771d7fec4Smrg{
133871d7fec4Smrg   int i;
133971d7fec4Smrg   unsigned long unlock, gcfg, offset;
134071d7fec4Smrg
134171d7fec4Smrg   /* DO NOT ENABLE IF START ADDRESS IS NOT ZERO */
134271d7fec4Smrg
134371d7fec4Smrg   offset = READ_REG32(DC_FB_ST_OFFSET) & 0x003FFFFF;
134471d7fec4Smrg   if (offset != 0)
134571d7fec4Smrg      return;
134671d7fec4Smrg
134771d7fec4Smrg   /* DO NOT ENABLE IF WE ARE WITHIN AN EMULATED VGA MODE */
134871d7fec4Smrg
134971d7fec4Smrg   if (gfx_line_double || gfx_pixel_double)
135071d7fec4Smrg      return;
135171d7fec4Smrg
135271d7fec4Smrg   /* SET GLOBAL INDICATOR */
135371d7fec4Smrg
135471d7fec4Smrg   gfx_compression_active = 1;
135571d7fec4Smrg
135671d7fec4Smrg   /* CLEAR DIRTY/VALID BITS IN MEMORY CONTROLLER */
135771d7fec4Smrg   /* Software is required to do this before enabling compression. */
135871d7fec4Smrg   /* Don't want controller to think that old lines are still valid. */
135971d7fec4Smrg
136071d7fec4Smrg   for (i = 0; i < 1024; i++) {
136171d7fec4Smrg      WRITE_REG32(MC_DR_ADD, i);
136271d7fec4Smrg      WRITE_REG32(MC_DR_ACC, 0);
136371d7fec4Smrg   }
136471d7fec4Smrg
136571d7fec4Smrg   /* TURN ON COMPRESSION CONTROL BITS */
136671d7fec4Smrg
136771d7fec4Smrg   unlock = READ_REG32(DC_UNLOCK);
136871d7fec4Smrg   gcfg = READ_REG32(DC_GENERAL_CFG);
136971d7fec4Smrg   gcfg |= DC_GCFG_CMPE | DC_GCFG_DECE;
137071d7fec4Smrg   WRITE_REG32(DC_UNLOCK, DC_UNLOCK_VALUE);
137171d7fec4Smrg   WRITE_REG32(DC_GENERAL_CFG, gcfg);
137271d7fec4Smrg   WRITE_REG32(DC_UNLOCK, unlock);
137371d7fec4Smrg}
137471d7fec4Smrg
137571d7fec4Smrg/*---------------------------------------------------------------------------
137671d7fec4Smrg * gu1_disable_compression
137771d7fec4Smrg *
137871d7fec4Smrg * This is a private routine to this module (not exposed in the Durango API).
137971d7fec4Smrg * It disables display compression.
138071d7fec4Smrg *---------------------------------------------------------------------------
138171d7fec4Smrg */
138271d7fec4Smrgvoid
138371d7fec4Smrggu1_disable_compression(void)
138471d7fec4Smrg{
138571d7fec4Smrg   unsigned long unlock, gcfg;
138671d7fec4Smrg
138771d7fec4Smrg   /* SET GLOBAL INDICATOR */
138871d7fec4Smrg
138971d7fec4Smrg   gfx_compression_active = 0;
139071d7fec4Smrg
139171d7fec4Smrg   /* TURN OFF COMPRESSION CONTROL BITS */
139271d7fec4Smrg
139371d7fec4Smrg   unlock = READ_REG32(DC_UNLOCK);
139471d7fec4Smrg   gcfg = READ_REG32(DC_GENERAL_CFG);
139571d7fec4Smrg   gcfg &= ~(DC_GCFG_CMPE | DC_GCFG_DECE);
139671d7fec4Smrg   WRITE_REG32(DC_UNLOCK, DC_UNLOCK_VALUE);
139771d7fec4Smrg   WRITE_REG32(DC_GENERAL_CFG, gcfg);
139871d7fec4Smrg   WRITE_REG32(DC_UNLOCK, unlock);
139971d7fec4Smrg}
140071d7fec4Smrg
140171d7fec4Smrg/*---------------------------------------------------------------------------
140271d7fec4Smrg * gfx_set_compression_enable
140371d7fec4Smrg *
140471d7fec4Smrg * This routine enables or disables display compression.
140571d7fec4Smrg *---------------------------------------------------------------------------
140671d7fec4Smrg */
140771d7fec4Smrg#if GFX_DISPLAY_DYNAMIC
140871d7fec4Smrgint
140971d7fec4Smrggu1_set_compression_enable(int enable)
141071d7fec4Smrg#else
141171d7fec4Smrgint
141271d7fec4Smrggfx_set_compression_enable(int enable)
141371d7fec4Smrg#endif
141471d7fec4Smrg{
141571d7fec4Smrg   /* SET GLOBAL VARIABLE FOR INTENDED STATE */
141671d7fec4Smrg   /* Compression can only be enabled for non-zero start address values. */
141771d7fec4Smrg   /* Keep state to enable compression on start address changes. */
141871d7fec4Smrg
141971d7fec4Smrg   gfx_compression_enabled = enable;
142071d7fec4Smrg   if (enable)
142171d7fec4Smrg      gu1_enable_compression();
142271d7fec4Smrg   else
142371d7fec4Smrg      gu1_disable_compression();
142471d7fec4Smrg   return (0);
142571d7fec4Smrg}
142671d7fec4Smrg
142771d7fec4Smrg/*---------------------------------------------------------------------------
142871d7fec4Smrg * gfx_set_compression_offset
142971d7fec4Smrg *
143071d7fec4Smrg * This routine sets the base offset for the compression buffer.
143171d7fec4Smrg *---------------------------------------------------------------------------
143271d7fec4Smrg */
143371d7fec4Smrg#if GFX_DISPLAY_DYNAMIC
143471d7fec4Smrgint
143571d7fec4Smrggu1_set_compression_offset(unsigned long offset)
143671d7fec4Smrg#else
143771d7fec4Smrgint
143871d7fec4Smrggfx_set_compression_offset(unsigned long offset)
143971d7fec4Smrg#endif
144071d7fec4Smrg{
144171d7fec4Smrg   unsigned long lock;
144271d7fec4Smrg
144371d7fec4Smrg   /* MUST BE 16-BYTE ALIGNED FOR GXLV */
144471d7fec4Smrg
144571d7fec4Smrg   if (offset & 0x0F)
144671d7fec4Smrg      return (1);
144771d7fec4Smrg
144871d7fec4Smrg   /* SET REGISTER VALUE */
144971d7fec4Smrg
145071d7fec4Smrg   lock = READ_REG32(DC_UNLOCK);
145171d7fec4Smrg   WRITE_REG32(DC_UNLOCK, DC_UNLOCK_VALUE);
145271d7fec4Smrg   WRITE_REG32(DC_CB_ST_OFFSET, offset);
145371d7fec4Smrg   WRITE_REG32(DC_UNLOCK, lock);
145471d7fec4Smrg   return (0);
145571d7fec4Smrg}
145671d7fec4Smrg
145771d7fec4Smrg/*---------------------------------------------------------------------------
145871d7fec4Smrg * gfx_set_compression_pitch
145971d7fec4Smrg *
146071d7fec4Smrg * This routine sets the pitch, in bytes, of the compression buffer.
146171d7fec4Smrg *---------------------------------------------------------------------------
146271d7fec4Smrg */
146371d7fec4Smrg#if GFX_DISPLAY_DYNAMIC
146471d7fec4Smrgint
146571d7fec4Smrggu1_set_compression_pitch(unsigned short pitch)
146671d7fec4Smrg#else
146771d7fec4Smrgint
146871d7fec4Smrggfx_set_compression_pitch(unsigned short pitch)
146971d7fec4Smrg#endif
147071d7fec4Smrg{
147171d7fec4Smrg   unsigned long lock, line_delta;
147271d7fec4Smrg
147371d7fec4Smrg   /* SET REGISTER VALUE */
147471d7fec4Smrg
147571d7fec4Smrg   lock = READ_REG32(DC_UNLOCK);
147671d7fec4Smrg   line_delta = READ_REG32(DC_LINE_DELTA) & 0xFF800FFF;
147771d7fec4Smrg   line_delta |= ((unsigned long)pitch << 10l) & 0x007FF000;
147871d7fec4Smrg   WRITE_REG32(DC_UNLOCK, DC_UNLOCK_VALUE);
147971d7fec4Smrg   WRITE_REG32(DC_LINE_DELTA, line_delta);
148071d7fec4Smrg   WRITE_REG32(DC_UNLOCK, lock);
148171d7fec4Smrg   return (0);
148271d7fec4Smrg}
148371d7fec4Smrg
148471d7fec4Smrg/*---------------------------------------------------------------------------
148571d7fec4Smrg * gfx_set_compression_size
148671d7fec4Smrg *
148771d7fec4Smrg * This routine sets the line size of the compression buffer, which is the
148871d7fec4Smrg * maximum number of bytes allowed to store a compressed line.
148971d7fec4Smrg *---------------------------------------------------------------------------
149071d7fec4Smrg */
149171d7fec4Smrg#if GFX_DISPLAY_DYNAMIC
149271d7fec4Smrgint
149371d7fec4Smrggu1_set_compression_size(unsigned short size)
149471d7fec4Smrg#else
149571d7fec4Smrgint
149671d7fec4Smrggfx_set_compression_size(unsigned short size)
149771d7fec4Smrg#endif
149871d7fec4Smrg{
149971d7fec4Smrg   unsigned long lock, buf_size;
150071d7fec4Smrg
150171d7fec4Smrg   /* SUBTRACT 16 FROM SIZE                          */
150271d7fec4Smrg   /* The display controller will actually write     */
150371d7fec4Smrg   /* 2 extra QWords.  So, if we assume that "size"  */
150471d7fec4Smrg   /* refers to the allocated size, we must subtract */
150571d7fec4Smrg   /* 16 bytes.                                      */
150671d7fec4Smrg
150771d7fec4Smrg   size -= 16;
150871d7fec4Smrg
150971d7fec4Smrg   /* SET REGISTER VALUE */
151071d7fec4Smrg
151171d7fec4Smrg   lock = READ_REG32(DC_UNLOCK);
151271d7fec4Smrg   buf_size = READ_REG32(DC_BUF_SIZE) & 0xFFFF01FF;
151371d7fec4Smrg   buf_size |= (((size >> 2) + 1) & 0x7F) << 9;
151471d7fec4Smrg   WRITE_REG32(DC_UNLOCK, DC_UNLOCK_VALUE);
151571d7fec4Smrg   WRITE_REG32(DC_BUF_SIZE, buf_size);
151671d7fec4Smrg   WRITE_REG32(DC_UNLOCK, lock);
151771d7fec4Smrg   return (0);
151871d7fec4Smrg}
151971d7fec4Smrg
152071d7fec4Smrg/*---------------------------------------------------------------------------
152171d7fec4Smrg * gfx_set_display_video_enable (PRIVATE ROUTINE - NOT PART OF API)
152271d7fec4Smrg *
152371d7fec4Smrg * This routine enables/disables video on GX.
152471d7fec4Smrg *---------------------------------------------------------------------------
152571d7fec4Smrg */
152671d7fec4Smrg#if GFX_DISPLAY_DYNAMIC
152771d7fec4Smrgvoid
152871d7fec4Smrggu1_set_display_video_enable(int enable)
152971d7fec4Smrg#else
153071d7fec4Smrgvoid
153171d7fec4Smrggfx_set_display_video_enable(int enable)
153271d7fec4Smrg#endif
153371d7fec4Smrg{
153471d7fec4Smrg   unsigned long lock, gcfg, buf_size;
153571d7fec4Smrg
153671d7fec4Smrg   lock = READ_REG32(DC_UNLOCK);
153771d7fec4Smrg   gcfg = READ_REG32(DC_GENERAL_CFG);
153871d7fec4Smrg   buf_size = READ_REG32(DC_BUF_SIZE);
153971d7fec4Smrg
154071d7fec4Smrg   WRITE_REG32(DC_UNLOCK, DC_UNLOCK_VALUE);
154171d7fec4Smrg
154271d7fec4Smrg   vid_enabled = enable;
154371d7fec4Smrg
154471d7fec4Smrg   /* SET THE BUFFER SIZE TO A NON-ZERO VALUE ONLY WHEN */
154571d7fec4Smrg   /* ENABLING VIDEO                                    */
154671d7fec4Smrg
154771d7fec4Smrg   if (enable) {
154871d7fec4Smrg      gcfg |= (DC_GCFG_VIDE | DC_GCFG_VRDY);
154971d7fec4Smrg      WRITE_REG32(DC_GENERAL_CFG, gcfg);
155071d7fec4Smrg
155171d7fec4Smrg      WRITE_REG32(DC_BUF_SIZE, (buf_size & 0x0000FFFFl) | vid_buf_size);
155271d7fec4Smrg   }
155371d7fec4Smrg
155471d7fec4Smrg   /* CLEAR THE VIDEO BUFFER SIZE WHEN DISABLING VIDEO  */
155571d7fec4Smrg
155671d7fec4Smrg   else {
155771d7fec4Smrg      gcfg &= ~(DC_GCFG_VIDE);
155871d7fec4Smrg      WRITE_REG32(DC_GENERAL_CFG, gcfg);
155971d7fec4Smrg
156071d7fec4Smrg      vid_buf_size = buf_size & 0xFFFF0000l;
156171d7fec4Smrg      WRITE_REG32(DC_BUF_SIZE, buf_size & 0x0000FFFFl);
156271d7fec4Smrg   }
156371d7fec4Smrg
156471d7fec4Smrg   WRITE_REG32(DC_UNLOCK, lock);
156571d7fec4Smrg   return;
156671d7fec4Smrg}
156771d7fec4Smrg
156871d7fec4Smrg/*---------------------------------------------------------------------------
156971d7fec4Smrg * gfx_set_display_video_size (PRIVATE ROUTINE - NOT PART OF API)
157071d7fec4Smrg *
157171d7fec4Smrg * This routine is called by "gfx_set_video_size".  It abstracts the
157271d7fec4Smrg * version of the display controller from the video overlay routines.
157371d7fec4Smrg *---------------------------------------------------------------------------
157471d7fec4Smrg */
157571d7fec4Smrg#if GFX_DISPLAY_DYNAMIC
157671d7fec4Smrgvoid
157771d7fec4Smrggu1_set_display_video_size(unsigned short width, unsigned short height)
157871d7fec4Smrg#else
157971d7fec4Smrgvoid
158071d7fec4Smrggfx_set_display_video_size(unsigned short width, unsigned short height)
158171d7fec4Smrg#endif
158271d7fec4Smrg{
158371d7fec4Smrg   unsigned long lock, size, value;
158471d7fec4Smrg
158571d7fec4Smrg   size = (unsigned long)(width << 1) * (unsigned long)height;
158671d7fec4Smrg
158771d7fec4Smrg   /* STORE THE VIDEO BUFFER SIZE AS A GLOBAL */
158871d7fec4Smrg
158971d7fec4Smrg   vid_buf_size = ((size + 63) >> 6) << 16;
159071d7fec4Smrg
159171d7fec4Smrg   /* DO NOT SET THE VIDEO SIZE IF VIDEO IS DISABLED */
159271d7fec4Smrg
159371d7fec4Smrg   if (!vid_enabled)
159471d7fec4Smrg      return;
159571d7fec4Smrg
159671d7fec4Smrg   lock = READ_REG32(DC_UNLOCK);
159771d7fec4Smrg   WRITE_REG32(DC_UNLOCK, DC_UNLOCK_VALUE);
159871d7fec4Smrg   value = READ_REG32(DC_BUF_SIZE) & 0x0000FFFF;
159971d7fec4Smrg   value |= vid_buf_size;
160071d7fec4Smrg   WRITE_REG32(DC_BUF_SIZE, value);
160171d7fec4Smrg   WRITE_REG32(DC_UNLOCK, lock);
160271d7fec4Smrg}
160371d7fec4Smrg
160471d7fec4Smrg/*---------------------------------------------------------------------------
160571d7fec4Smrg * gfx_set_display_video_offset (PRIVATE ROUTINE - NOT PART OF API)
160671d7fec4Smrg *
160771d7fec4Smrg * This routine is called by "gfx_set_video_offset".  It abstracts the
160871d7fec4Smrg * version of the display controller from the video overlay routines.
160971d7fec4Smrg *---------------------------------------------------------------------------
161071d7fec4Smrg */
161171d7fec4Smrg#if GFX_DISPLAY_DYNAMIC
161271d7fec4Smrgvoid
161371d7fec4Smrggu1_set_display_video_offset(unsigned long offset)
161471d7fec4Smrg#else
161571d7fec4Smrgvoid
161671d7fec4Smrggfx_set_display_video_offset(unsigned long offset)
161771d7fec4Smrg#endif
161871d7fec4Smrg{
161971d7fec4Smrg   unsigned long lock;
162071d7fec4Smrg
162171d7fec4Smrg   lock = READ_REG32(DC_UNLOCK);
162271d7fec4Smrg   WRITE_REG32(DC_UNLOCK, DC_UNLOCK_VALUE);
162371d7fec4Smrg   offset &= 0x003FFFFF;
162471d7fec4Smrg   WRITE_REG32(DC_VID_ST_OFFSET, offset);
162571d7fec4Smrg   WRITE_REG32(DC_UNLOCK, lock);
162671d7fec4Smrg}
162771d7fec4Smrg
162871d7fec4Smrg/*---------------------------------------------------------------------------
162971d7fec4Smrg * gfx_set_display_priority_high
163071d7fec4Smrg *
163171d7fec4Smrg * This routine controls the x-bus round robin arbitration mechanism.
163271d7fec4Smrg * When enable is TRUE, graphics pipeline requests and non-critical display
163371d7fec4Smrg * controller requests are arbitrated at the same priority as processor
163471d7fec4Smrg * requests. When FALSE processor requests are arbitrated at a higher priority.
163571d7fec4Smrg *---------------------------------------------------------------------------
163671d7fec4Smrg */
163771d7fec4Smrg#if GFX_DISPLAY_DYNAMIC
163871d7fec4Smrgvoid
163971d7fec4Smrggu1_set_display_priority_high(int enable)
164071d7fec4Smrg#else
164171d7fec4Smrgvoid
164271d7fec4Smrggfx_set_display_priority_high(int enable)
164371d7fec4Smrg#endif
164471d7fec4Smrg{
164571d7fec4Smrg   unsigned long lock, control;
164671d7fec4Smrg
164771d7fec4Smrg   lock = READ_REG32(DC_UNLOCK);
164871d7fec4Smrg   control = READ_REG32(MC_MEM_CNTRL1);
164971d7fec4Smrg   WRITE_REG32(DC_UNLOCK, DC_UNLOCK_VALUE);
165071d7fec4Smrg   if (enable)
165171d7fec4Smrg      control |= MC_XBUSARB;
165271d7fec4Smrg   else
165371d7fec4Smrg      control &= ~(MC_XBUSARB);
165471d7fec4Smrg   WRITE_REG32(MC_MEM_CNTRL1, control);
165571d7fec4Smrg   WRITE_REG32(DC_UNLOCK, lock);
165671d7fec4Smrg   return;
165771d7fec4Smrg}
165871d7fec4Smrg
165971d7fec4Smrg/*---------------------------------------------------------------------------
166071d7fec4Smrg * gfx_test_timing_active
166171d7fec4Smrg *---------------------------------------------------------------------------
166271d7fec4Smrg */
166371d7fec4Smrg#if GFX_DISPLAY_DYNAMIC
166471d7fec4Smrgint
166571d7fec4Smrggu1_test_timing_active(void)
166671d7fec4Smrg#else
166771d7fec4Smrgint
166871d7fec4Smrggfx_test_timing_active(void)
166971d7fec4Smrg#endif
167071d7fec4Smrg{
167171d7fec4Smrg   if (READ_REG32(DC_TIMING_CFG) & DC_TCFG_TGEN)
167271d7fec4Smrg      return (1);
167371d7fec4Smrg   else
167471d7fec4Smrg      return (0);
167571d7fec4Smrg}
167671d7fec4Smrg
167771d7fec4Smrg/*---------------------------------------------------------------------------
167871d7fec4Smrg * gfx_test_vertical_active
167971d7fec4Smrg *---------------------------------------------------------------------------
168071d7fec4Smrg */
168171d7fec4Smrg#if GFX_DISPLAY_DYNAMIC
168271d7fec4Smrgint
168371d7fec4Smrggu1_test_vertical_active(void)
168471d7fec4Smrg#else
168571d7fec4Smrgint
168671d7fec4Smrggfx_test_vertical_active(void)
168771d7fec4Smrg#endif
168871d7fec4Smrg{
168971d7fec4Smrg   if (READ_REG32(DC_TIMING_CFG) & DC_TCFG_VNA)
169071d7fec4Smrg      return (0);
169171d7fec4Smrg   else
169271d7fec4Smrg      return (1);
169371d7fec4Smrg}
169471d7fec4Smrg
169571d7fec4Smrg/*---------------------------------------------------------------------------
169671d7fec4Smrg * gfx_wait_vertical_blank
169771d7fec4Smrg *---------------------------------------------------------------------------
169871d7fec4Smrg */
169971d7fec4Smrg#if GFX_DISPLAY_DYNAMIC
170071d7fec4Smrgint
170171d7fec4Smrggu1_wait_vertical_blank(void)
170271d7fec4Smrg#else
170371d7fec4Smrgint
170471d7fec4Smrggfx_wait_vertical_blank(void)
170571d7fec4Smrg#endif
170671d7fec4Smrg{
170771d7fec4Smrg   if (gfx_test_timing_active()) {
170871d7fec4Smrg      while (!gfx_test_vertical_active()) ;
170971d7fec4Smrg      while (gfx_test_vertical_active()) ;
171071d7fec4Smrg   }
171171d7fec4Smrg   return (0);
171271d7fec4Smrg}
171371d7fec4Smrg
171471d7fec4Smrg/*---------------------------------------------------------------------------
171571d7fec4Smrg * gfx_enable_panning
171671d7fec4Smrg *
171771d7fec4Smrg * This routine  enables the panning when the Mode is bigger than the panel
171871d7fec4Smrg * size.
171971d7fec4Smrg *---------------------------------------------------------------------------
172071d7fec4Smrg */
172171d7fec4Smrg#if GFX_DISPLAY_DYNAMIC
172271d7fec4Smrgvoid
172371d7fec4Smrggu1_enable_panning(int x, int y)
172471d7fec4Smrg#else
172571d7fec4Smrgvoid
172671d7fec4Smrggfx_enable_panning(int x, int y)
172771d7fec4Smrg#endif
172871d7fec4Smrg{
172971d7fec4Smrg   unsigned long modeBytesPerPixel;
173071d7fec4Smrg   unsigned long modeBytesPerScanline = 0;
173171d7fec4Smrg   unsigned long startAddress = 0;
173271d7fec4Smrg
173371d7fec4Smrg   modeBytesPerPixel = (gbpp + 7) / 8;
173471d7fec4Smrg   modeBytesPerScanline =
173571d7fec4Smrg	 (((ModeWidth + 1023) / 1024) * 1024) * modeBytesPerPixel;
173671d7fec4Smrg
173771d7fec4Smrg   /* TEST FOR NO-WORK */
173871d7fec4Smrg
173971d7fec4Smrg   if (x >= DeltaX && (unsigned short)x < (PanelWidth + DeltaX) &&
174071d7fec4Smrg       y >= DeltaY && (unsigned short)y < (PanelHeight + DeltaY))
174171d7fec4Smrg      return;
174271d7fec4Smrg
174371d7fec4Smrg   /* ADJUST PANNING VARIABLES WHEN CURSOR EXCEEDS BOUNDARY       */
174471d7fec4Smrg   /* Test the boundary conditions for each coordinate and update */
174571d7fec4Smrg   /* all variables and the starting offset accordingly.          */
174671d7fec4Smrg
174771d7fec4Smrg   if (x < DeltaX)
174871d7fec4Smrg      DeltaX = x;
174971d7fec4Smrg
175071d7fec4Smrg   else if ((unsigned short)x >= (DeltaX + PanelWidth))
175171d7fec4Smrg      DeltaX = x - PanelWidth + 1;
175271d7fec4Smrg
175371d7fec4Smrg   if (y < DeltaY)
175471d7fec4Smrg      DeltaY = y;
175571d7fec4Smrg
175671d7fec4Smrg   else if ((unsigned short)y >= (DeltaY + PanelHeight))
175771d7fec4Smrg      DeltaY = y - PanelHeight + 1;
175871d7fec4Smrg
175971d7fec4Smrg   /* CALCULATE THE START OFFSET */
176071d7fec4Smrg
176171d7fec4Smrg   startAddress =
176271d7fec4Smrg	 (DeltaX * modeBytesPerPixel) + (DeltaY * modeBytesPerScanline);
176371d7fec4Smrg
176471d7fec4Smrg   gfx_set_display_offset(startAddress);
176571d7fec4Smrg
176671d7fec4Smrg   /* SET PANEL COORDINATES                    */
176771d7fec4Smrg   /* Panel's x position must be DWORD aligned */
176871d7fec4Smrg
176971d7fec4Smrg   panelTop = DeltaY;
177071d7fec4Smrg   panelLeft = DeltaX * modeBytesPerPixel;
177171d7fec4Smrg
177271d7fec4Smrg   if (panelLeft & 3)
177371d7fec4Smrg      panelLeft = (panelLeft & 0xFFFFFFFC) + 4;
177471d7fec4Smrg
177571d7fec4Smrg   panelLeft /= modeBytesPerPixel;
177671d7fec4Smrg
177771d7fec4Smrg}
177871d7fec4Smrg
177971d7fec4Smrg/*---------------------------------------------------------------------------
178071d7fec4Smrg * gfx_set_fixed_timings
178171d7fec4Smrg *---------------------------------------------------------------------------
178271d7fec4Smrg */
178371d7fec4Smrg#if GFX_DISPLAY_DYNAMIC
178471d7fec4Smrgint
178571d7fec4Smrggu1_set_fixed_timings(int panelResX, int panelResY, unsigned short width,
178671d7fec4Smrg		      unsigned short height, unsigned short bpp)
178771d7fec4Smrg#else
178871d7fec4Smrgint
178971d7fec4Smrggfx_set_fixed_timings(int panelResX, int panelResY, unsigned short width,
179071d7fec4Smrg		      unsigned short height, unsigned short bpp)
179171d7fec4Smrg#endif
179271d7fec4Smrg{
179371d7fec4Smrg   unsigned int mode;
179471d7fec4Smrg
179571d7fec4Smrg   ModeWidth = width;
179671d7fec4Smrg   ModeHeight = height;
179771d7fec4Smrg   PanelWidth = (unsigned short)panelResX;
179871d7fec4Smrg   PanelHeight = (unsigned short)panelResY;
179971d7fec4Smrg   PanelEnable = 1;
180071d7fec4Smrg
180171d7fec4Smrg   /* LOOP THROUGH THE AVAILABLE MODES TO FIND A MATCH */
180271d7fec4Smrg   for (mode = 0; mode < NUM_FIXED_TIMINGS_MODES; mode++) {
180371d7fec4Smrg      if ((FixedParams[mode].xres == width) &&
180471d7fec4Smrg	  (FixedParams[mode].yres == height) &&
180571d7fec4Smrg	  (FixedParams[mode].panelresx == panelResX) &&
180671d7fec4Smrg	  (FixedParams[mode].panelresy == panelResY)) {
180771d7fec4Smrg
180871d7fec4Smrg	 /* SET THE 92xx FOR THE SELECTED MODE */
180971d7fec4Smrg	 FIXEDTIMINGS *fmode = &FixedParams[mode];
181071d7fec4Smrg
181171d7fec4Smrg	 gfx_set_display_timings(bpp, 3, fmode->hactive, fmode->hblankstart,
181271d7fec4Smrg				 fmode->hsyncstart, fmode->hsyncend,
181371d7fec4Smrg				 fmode->hblankend, fmode->htotal,
181471d7fec4Smrg				 fmode->vactive, fmode->vblankstart,
181571d7fec4Smrg				 fmode->vsyncstart, fmode->vsyncend,
181671d7fec4Smrg				 fmode->vblankend, fmode->vtotal,
181771d7fec4Smrg				 fmode->frequency);
181871d7fec4Smrg
181971d7fec4Smrg	 return (1);
182071d7fec4Smrg      }					/* end if() */
182171d7fec4Smrg   }					/* end for() */
182271d7fec4Smrg
182371d7fec4Smrg   return (-1);
182471d7fec4Smrg}
182571d7fec4Smrg
182671d7fec4Smrg/*---------------------------------------------------------------------------
182771d7fec4Smrg * gfx_set_panel_present
182871d7fec4Smrg *---------------------------------------------------------------------------
182971d7fec4Smrg */
183071d7fec4Smrg#if GFX_DISPLAY_DYNAMIC
183171d7fec4Smrgint
183271d7fec4Smrggu1_set_panel_present(int panelResX, int panelResY, unsigned short width,
183371d7fec4Smrg		      unsigned short height, unsigned short bpp)
183471d7fec4Smrg#else
183571d7fec4Smrgint
183671d7fec4Smrggfx_set_panel_present(int panelResX, int panelResY, unsigned short width,
183771d7fec4Smrg		      unsigned short height, unsigned short bpp)
183871d7fec4Smrg#endif
183971d7fec4Smrg{
184071d7fec4Smrg   /* SET VALID BPP         */
184171d7fec4Smrg   /* 16BPP is the default. */
184271d7fec4Smrg
184371d7fec4Smrg   if (bpp != 8 && bpp != 15 && bpp != 16)
184471d7fec4Smrg      bpp = 16;
184571d7fec4Smrg
184671d7fec4Smrg   /* RECORD PANEL PARAMETERS */
184771d7fec4Smrg   /* This routine does not touch any panel timings.  It is used when custom panel */
184871d7fec4Smrg   /* settings are set up in advance by the BIOS or an application, but the        */
184971d7fec4Smrg   /* application still requires access to other panel functionality provided by   */
185071d7fec4Smrg   /* Durango (i.e. panning).                                                      */
185171d7fec4Smrg
185271d7fec4Smrg   ModeWidth = width;
185371d7fec4Smrg   ModeHeight = height;
185471d7fec4Smrg   PanelWidth = (unsigned short)panelResX;
185571d7fec4Smrg   PanelHeight = (unsigned short)panelResY;
185671d7fec4Smrg   PanelEnable = 1;
185771d7fec4Smrg   gbpp = bpp;
185871d7fec4Smrg
185971d7fec4Smrg   /* PROGRAM THE BPP IN THE DISPLAY CONTROLLER */
186071d7fec4Smrg
186171d7fec4Smrg   gfx_set_display_bpp(bpp);
186271d7fec4Smrg
186371d7fec4Smrg   return (GFX_STATUS_OK);
186471d7fec4Smrg}
186571d7fec4Smrg
186671d7fec4Smrg/*-----------------------------------------------------------------------*
186771d7fec4Smrg * THE FOLLOWING READ ROUTINES ARE ALWAYS INCLUDED:                      *
186871d7fec4Smrg * gfx_get_hsync_end, gfx_get_htotal, gfx_get_vsync_end, gfx_get_vtotal  *
186971d7fec4Smrg * are used by the video overlay routines.                               *
187071d7fec4Smrg *                                                                       *
187171d7fec4Smrg * gfx_get_vline and gfx_vactive are used to prevent an issue for the    *
187271d7fec4Smrg * SC1200.                                                               *
187371d7fec4Smrg *                                                                       *
187471d7fec4Smrg * The others are part of the Durango API.                               *
187571d7fec4Smrg *-----------------------------------------------------------------------*/
187671d7fec4Smrg
187771d7fec4Smrg/*---------------------------------------------------------------------------
187871d7fec4Smrg * gfx_get_display_pitch
187971d7fec4Smrg *
188071d7fec4Smrg * This routine returns the current pitch of the frame buffer, in bytes.
188171d7fec4Smrg *---------------------------------------------------------------------------
188271d7fec4Smrg */
188371d7fec4Smrg#if GFX_DISPLAY_DYNAMIC
188471d7fec4Smrgunsigned short
188571d7fec4Smrggu1_get_display_pitch(void)
188671d7fec4Smrg#else
188771d7fec4Smrgunsigned short
188871d7fec4Smrggfx_get_display_pitch(void)
188971d7fec4Smrg#endif
189071d7fec4Smrg{
189171d7fec4Smrg   unsigned long value;
189271d7fec4Smrg
189371d7fec4Smrg   if (gfx_cpu_version == GFX_CPU_PYRAMID) {	/* Pyramid update for 4KB line pitch */
189471d7fec4Smrg      value = (READ_REG32(DC_LINE_DELTA) & 0x07FF) << 2;
189571d7fec4Smrg   } else {
189671d7fec4Smrg      value = (READ_REG32(DC_LINE_DELTA) & 0x03FF) << 2;
189771d7fec4Smrg   }
189871d7fec4Smrg
189971d7fec4Smrg   return ((unsigned short)value);
190071d7fec4Smrg}
190171d7fec4Smrg
190271d7fec4Smrg/*----------------------------------------------------------------------------
190371d7fec4Smrg * GFX_GET_DISPLAY_DETAILS
190471d7fec4Smrg *
190571d7fec4Smrg * This routine gets the specified display mode.
190671d7fec4Smrg *
190771d7fec4Smrg * Returns 1 if successful, 0 if mode could not be get.
190871d7fec4Smrg *----------------------------------------------------------------------------
190971d7fec4Smrg */
191071d7fec4Smrg#if GFX_DISPLAY_DYNAMIC
191171d7fec4Smrgint
191271d7fec4Smrggu1_get_display_details(unsigned int mode, int *xres, int *yres, int *hz)
191371d7fec4Smrg#else
191471d7fec4Smrgint
191571d7fec4Smrggfx_get_display_details(unsigned int mode, int *xres, int *yres, int *hz)
191671d7fec4Smrg#endif
191771d7fec4Smrg{
191871d7fec4Smrg   if (mode < NUM_GX_DISPLAY_MODES) {
191971d7fec4Smrg      if (DisplayParams[mode].flags & GFX_MODE_56HZ)
192071d7fec4Smrg	 *hz = 56;
192171d7fec4Smrg      else if (DisplayParams[mode].flags & GFX_MODE_60HZ)
192271d7fec4Smrg	 *hz = 60;
192371d7fec4Smrg      else if (DisplayParams[mode].flags & GFX_MODE_70HZ)
192471d7fec4Smrg	 *hz = 70;
192571d7fec4Smrg      else if (DisplayParams[mode].flags & GFX_MODE_72HZ)
192671d7fec4Smrg	 *hz = 72;
192771d7fec4Smrg      else if (DisplayParams[mode].flags & GFX_MODE_75HZ)
192871d7fec4Smrg	 *hz = 75;
192971d7fec4Smrg      else if (DisplayParams[mode].flags & GFX_MODE_85HZ)
193071d7fec4Smrg	 *hz = 85;
193171d7fec4Smrg
193271d7fec4Smrg      *xres = DisplayParams[mode].hactive;
193371d7fec4Smrg      *yres = DisplayParams[mode].vactive;
193471d7fec4Smrg
193571d7fec4Smrg      return (1);
193671d7fec4Smrg   }
193771d7fec4Smrg   return (0);
193871d7fec4Smrg}
193971d7fec4Smrg
194071d7fec4Smrg/*----------------------------------------------------------------------------
194171d7fec4Smrg * GFX_GET_DISPLAY_MODE_COUNT
194271d7fec4Smrg *
194371d7fec4Smrg * Returns number of modes supported.
194471d7fec4Smrg *----------------------------------------------------------------------------
194571d7fec4Smrg */
194671d7fec4Smrg#if GFX_DISPLAY_DYNAMIC
194771d7fec4Smrgint
194871d7fec4Smrggu1_get_display_mode_count(void)
194971d7fec4Smrg#else
195071d7fec4Smrgint
195171d7fec4Smrggfx_get_display_mode_count(void)
195271d7fec4Smrg#endif
195371d7fec4Smrg{
195471d7fec4Smrg   return (NUM_GX_DISPLAY_MODES);
195571d7fec4Smrg}
195671d7fec4Smrg
195771d7fec4Smrg/*----------------------------------------------------------------------------
195871d7fec4Smrg * gfx_get_frame_buffer_line_size
195971d7fec4Smrg *
196071d7fec4Smrg * Returns the current frame buffer line size, in bytes
196171d7fec4Smrg *----------------------------------------------------------------------------
196271d7fec4Smrg */
196371d7fec4Smrg#if GFX_DISPLAY_DYNAMIC
196471d7fec4Smrgunsigned long
196571d7fec4Smrggu1_get_frame_buffer_line_size(void)
196671d7fec4Smrg#else
196771d7fec4Smrgunsigned long
196871d7fec4Smrggfx_get_frame_buffer_line_size(void)
196971d7fec4Smrg#endif
197071d7fec4Smrg{
197171d7fec4Smrg   return ((READ_REG32(DC_BUF_SIZE) & 0x1FF) << 3);
197271d7fec4Smrg}
197371d7fec4Smrg
197471d7fec4Smrg/*----------------------------------------------------------------------------
197571d7fec4Smrg * gfx_mode_frequency_supported
197671d7fec4Smrg *
197771d7fec4Smrg * This routine examines if the requested mode with pixel frequency is supported.
197871d7fec4Smrg *
197971d7fec4Smrg * Returns >0 if successful , <0 if freq. could not be found and matched.
198071d7fec4Smrg *----------------------------------------------------------------------------
198171d7fec4Smrg */
198271d7fec4Smrg#if GFX_DISPLAY_DYNAMIC
198371d7fec4Smrgint
198471d7fec4Smrggu1_mode_frequency_supported(int xres, int yres, int bpp,
198571d7fec4Smrg			     unsigned long frequency)
198671d7fec4Smrg#else
198771d7fec4Smrgint
198871d7fec4Smrggfx_mode_frequency_supported(int xres, int yres, int bpp,
198971d7fec4Smrg			     unsigned long frequency)
199071d7fec4Smrg#endif
199171d7fec4Smrg{
199271d7fec4Smrg   unsigned int index;
199371d7fec4Smrg   unsigned long value;
199471d7fec4Smrg   unsigned long bpp_flag = 0;
199571d7fec4Smrg
199671d7fec4Smrg   bpp_flag = GFX_MODE_8BPP;
199771d7fec4Smrg   if (bpp > 8)
199871d7fec4Smrg      bpp_flag = GFX_MODE_16BPP;
199971d7fec4Smrg
200071d7fec4Smrg   for (index = 0; index < NUM_GX_DISPLAY_MODES; index++) {
200171d7fec4Smrg      if ((DisplayParams[index].hactive == (unsigned short)xres) &&
200271d7fec4Smrg	  (DisplayParams[index].vactive == (unsigned short)yres) &&
200371d7fec4Smrg	  (DisplayParams[index].flags & bpp_flag) &&
200471d7fec4Smrg	  (DisplayParams[index].frequency == frequency)) {
200571d7fec4Smrg	 int hz = 0;
200671d7fec4Smrg
200771d7fec4Smrg	 value = DisplayParams[index].flags;
200871d7fec4Smrg
200971d7fec4Smrg	 if (value & GFX_MODE_60HZ)
201071d7fec4Smrg	    hz = 60;
201171d7fec4Smrg	 else if (value & GFX_MODE_70HZ)
201271d7fec4Smrg	    hz = 70;
201371d7fec4Smrg	 else if (value & GFX_MODE_72HZ)
201471d7fec4Smrg	    hz = 72;
201571d7fec4Smrg	 else if (value & GFX_MODE_75HZ)
201671d7fec4Smrg	    hz = 75;
201771d7fec4Smrg	 else if (value & GFX_MODE_85HZ)
201871d7fec4Smrg	    hz = 85;
201971d7fec4Smrg	 return (hz);
202071d7fec4Smrg      }
202171d7fec4Smrg   }
202271d7fec4Smrg   return (-1);
202371d7fec4Smrg}
202471d7fec4Smrg
202571d7fec4Smrg/*----------------------------------------------------------------------------
202671d7fec4Smrg * gfx_refreshrate_from_frequency
202771d7fec4Smrg *
202871d7fec4Smrg * This routine maps the frequency to close match refresh rate
202971d7fec4Smrg *
203071d7fec4Smrg * Returns .
203171d7fec4Smrg *----------------------------------------------------------------------------
203271d7fec4Smrg */
203371d7fec4Smrg#if GFX_DISPLAY_DYNAMIC
203471d7fec4Smrgint
203571d7fec4Smrggu1_get_refreshrate_from_frequency(int xres, int yres, int bpp, int *hz,
203671d7fec4Smrg				   unsigned long frequency)
203771d7fec4Smrg#else
203871d7fec4Smrgint
203971d7fec4Smrggfx_get_refreshrate_from_frequency(int xres, int yres, int bpp, int *hz,
204071d7fec4Smrg				   unsigned long frequency)
204171d7fec4Smrg#endif
204271d7fec4Smrg{
204371d7fec4Smrg   unsigned int index, closematch = 0;
204471d7fec4Smrg   unsigned long value;
204571d7fec4Smrg   unsigned long bpp_flag = 0;
204671d7fec4Smrg   long min, diff;
204771d7fec4Smrg
204871d7fec4Smrg   *hz = 60;
204971d7fec4Smrg
205071d7fec4Smrg   bpp_flag = GFX_MODE_8BPP;
205171d7fec4Smrg   if (bpp > 8)
205271d7fec4Smrg      bpp_flag = GFX_MODE_16BPP;
205371d7fec4Smrg
205471d7fec4Smrg   /* FIND THE REGISTER VALUES FOR THE DESIRED FREQUENCY */
205571d7fec4Smrg   /* Search the table for the closest frequency (16.16 format). */
205671d7fec4Smrg
205771d7fec4Smrg   min = 0x7fffffff;
205871d7fec4Smrg   for (index = 0; index < NUM_GX_DISPLAY_MODES; index++) {
205971d7fec4Smrg      if ((DisplayParams[index].htotal == (unsigned short)xres) &&
206071d7fec4Smrg	  (DisplayParams[index].vtotal == (unsigned short)yres) &&
206171d7fec4Smrg	  (DisplayParams[index].flags & bpp_flag)) {
206271d7fec4Smrg	 diff = (long)frequency - (long)DisplayParams[index].frequency;
206371d7fec4Smrg	 if (diff < 0)
206471d7fec4Smrg	    diff = -diff;
206571d7fec4Smrg
206671d7fec4Smrg	 if (diff < min) {
206771d7fec4Smrg	    min = diff;
206871d7fec4Smrg	    closematch = index;
206971d7fec4Smrg	 }
207071d7fec4Smrg      }
207171d7fec4Smrg   }
207271d7fec4Smrg
207371d7fec4Smrg   value = DisplayParams[closematch].flags;
207471d7fec4Smrg
207571d7fec4Smrg   if (value & GFX_MODE_60HZ)
207671d7fec4Smrg      *hz = 60;
207771d7fec4Smrg   else if (value & GFX_MODE_70HZ)
207871d7fec4Smrg      *hz = 70;
207971d7fec4Smrg   else if (value & GFX_MODE_72HZ)
208071d7fec4Smrg      *hz = 72;
208171d7fec4Smrg   else if (value & GFX_MODE_75HZ)
208271d7fec4Smrg      *hz = 75;
208371d7fec4Smrg   else if (value & GFX_MODE_85HZ)
208471d7fec4Smrg      *hz = 85;
208571d7fec4Smrg
208671d7fec4Smrg   return (1);
208771d7fec4Smrg}
208871d7fec4Smrg
208971d7fec4Smrg/*----------------------------------------------------------------------------
209071d7fec4Smrg * gfx_refreshrate_from_mode
209171d7fec4Smrg *
209271d7fec4Smrg * This routine is identical to the gfx_get_refreshrate_from_frequency,
209371d7fec4Smrg * except that the active timing values are compared instead of the total
209471d7fec4Smrg * values.  Some modes (such as 70Hz and 72Hz) may be confused in this routine.
209571d7fec4Smrg *
209671d7fec4Smrg * Returns .
209771d7fec4Smrg *----------------------------------------------------------------------------
209871d7fec4Smrg */
209971d7fec4Smrg#if GFX_DISPLAY_DYNAMIC
210071d7fec4Smrgint
210171d7fec4Smrggu1_get_refreshrate_from_mode(int xres, int yres, int bpp, int *hz,
210271d7fec4Smrg			      unsigned long frequency)
210371d7fec4Smrg#else
210471d7fec4Smrgint
210571d7fec4Smrggfx_get_refreshrate_from_mode(int xres, int yres, int bpp, int *hz,
210671d7fec4Smrg			      unsigned long frequency)
210771d7fec4Smrg#endif
210871d7fec4Smrg{
210971d7fec4Smrg   unsigned int index, closematch = 0;
211071d7fec4Smrg   unsigned long value;
211171d7fec4Smrg   unsigned long bpp_flag = 0;
211271d7fec4Smrg   long min, diff;
211371d7fec4Smrg
211471d7fec4Smrg   *hz = 60;
211571d7fec4Smrg
211671d7fec4Smrg   bpp_flag = GFX_MODE_8BPP;
211771d7fec4Smrg   if (bpp > 8)
211871d7fec4Smrg      bpp_flag = GFX_MODE_16BPP;
211971d7fec4Smrg
212071d7fec4Smrg   /* FIND THE REGISTER VALUES FOR THE DESIRED FREQUENCY */
212171d7fec4Smrg   /* Search the table for the closest frequency (16.16 format). */
212271d7fec4Smrg
212371d7fec4Smrg   min = 0x7fffffff;
212471d7fec4Smrg   for (index = 0; index < NUM_GX_DISPLAY_MODES; index++) {
212571d7fec4Smrg      if ((DisplayParams[index].hactive == (unsigned short)xres) &&
212671d7fec4Smrg	  (DisplayParams[index].vactive == (unsigned short)yres) &&
212771d7fec4Smrg	  (DisplayParams[index].flags & bpp_flag)) {
212871d7fec4Smrg	 diff = (long)frequency - (long)DisplayParams[index].frequency;
212971d7fec4Smrg	 if (diff < 0)
213071d7fec4Smrg	    diff = -diff;
213171d7fec4Smrg
213271d7fec4Smrg	 if (diff < min) {
213371d7fec4Smrg	    min = diff;
213471d7fec4Smrg	    closematch = index;
213571d7fec4Smrg	 }
213671d7fec4Smrg      }
213771d7fec4Smrg   }
213871d7fec4Smrg
213971d7fec4Smrg   value = DisplayParams[closematch].flags;
214071d7fec4Smrg
214171d7fec4Smrg   if (value & GFX_MODE_60HZ)
214271d7fec4Smrg      *hz = 60;
214371d7fec4Smrg   else if (value & GFX_MODE_70HZ)
214471d7fec4Smrg      *hz = 70;
214571d7fec4Smrg   else if (value & GFX_MODE_72HZ)
214671d7fec4Smrg      *hz = 72;
214771d7fec4Smrg   else if (value & GFX_MODE_75HZ)
214871d7fec4Smrg      *hz = 75;
214971d7fec4Smrg   else if (value & GFX_MODE_85HZ)
215071d7fec4Smrg      *hz = 85;
215171d7fec4Smrg
215271d7fec4Smrg   return (1);
215371d7fec4Smrg}
215471d7fec4Smrg
215571d7fec4Smrg/*----------------------------------------------------------------------------
215671d7fec4Smrg * gfx_get_frequency_from_refreshrate
215771d7fec4Smrg *
215871d7fec4Smrg * This routine maps the refresh rate to the closest matching PLL frequency.
215971d7fec4Smrg *----------------------------------------------------------------------------
216071d7fec4Smrg */
216171d7fec4Smrg#if GFX_DISPLAY_DYNAMIC
216271d7fec4Smrgint
216371d7fec4Smrggu1_get_frequency_from_refreshrate(int xres, int yres, int bpp, int hz,
216471d7fec4Smrg				   int *frequency)
216571d7fec4Smrg#else
216671d7fec4Smrgint
216771d7fec4Smrggfx_get_frequency_from_refreshrate(int xres, int yres, int bpp, int hz,
216871d7fec4Smrg				   int *frequency)
216971d7fec4Smrg#endif
217071d7fec4Smrg{
217171d7fec4Smrg   int retval = -1;
217271d7fec4Smrg   unsigned long hz_flag = 0;
217371d7fec4Smrg   unsigned long index, bpp_flag = 0;
217471d7fec4Smrg
217571d7fec4Smrg   *frequency = 0;
217671d7fec4Smrg
217771d7fec4Smrg   if (hz == 60)
217871d7fec4Smrg      hz_flag = GFX_MODE_60HZ;
217971d7fec4Smrg   else if (hz == 70)
218071d7fec4Smrg      hz_flag = GFX_MODE_70HZ;
218171d7fec4Smrg   else if (hz == 72)
218271d7fec4Smrg      hz_flag = GFX_MODE_72HZ;
218371d7fec4Smrg   else if (hz == 75)
218471d7fec4Smrg      hz_flag = GFX_MODE_75HZ;
218571d7fec4Smrg   else if (hz == 85)
218671d7fec4Smrg      hz_flag = GFX_MODE_85HZ;
218771d7fec4Smrg
218871d7fec4Smrg   bpp_flag = GFX_MODE_8BPP;
218971d7fec4Smrg   if (bpp > 8)
219071d7fec4Smrg      bpp_flag = GFX_MODE_16BPP;
219171d7fec4Smrg
219271d7fec4Smrg   /* FIND THE REGISTER VALUES FOR THE DESIRED FREQUENCY */
219371d7fec4Smrg
219471d7fec4Smrg   for (index = 0; index < NUM_GX_DISPLAY_MODES; index++) {
219571d7fec4Smrg      if ((DisplayParams[index].hactive == (unsigned short)xres) &&
219671d7fec4Smrg	  (DisplayParams[index].vactive == (unsigned short)yres) &&
219771d7fec4Smrg	  (DisplayParams[index].flags & bpp_flag) &&
219871d7fec4Smrg	  (DisplayParams[index].flags & hz_flag)) {
219971d7fec4Smrg	 *frequency = DisplayParams[index].frequency;
220071d7fec4Smrg	 retval = 1;
220171d7fec4Smrg      }
220271d7fec4Smrg   }
220371d7fec4Smrg   return retval;
220471d7fec4Smrg}
220571d7fec4Smrg
220671d7fec4Smrg/*---------------------------------------------------------------------------
220771d7fec4Smrg * gfx_get_max_supported_pixel_clock
220871d7fec4Smrg *
220971d7fec4Smrg * This routine returns the maximum recommended speed for the pixel clock.  The
221071d7fec4Smrg * return value is an integer of the format xxxyyy, where xxx.yyy is the maximum
221171d7fec4Smrg * floating point pixel clock speed.
221271d7fec4Smrg *---------------------------------------------------------------------------
221371d7fec4Smrg */
221471d7fec4Smrg#if GFX_DISPLAY_DYNAMIC
221571d7fec4Smrgunsigned long
221671d7fec4Smrggu1_get_max_supported_pixel_clock(void)
221771d7fec4Smrg#else
221871d7fec4Smrgunsigned long
221971d7fec4Smrggfx_get_max_supported_pixel_clock(void)
222071d7fec4Smrg#endif
222171d7fec4Smrg{
222271d7fec4Smrg   /* ALL CHIPS CAN HANDLE 1280X1024@85HZ - 157.5 MHz */
222371d7fec4Smrg
222471d7fec4Smrg   return 157500;
222571d7fec4Smrg}
222671d7fec4Smrg
222771d7fec4Smrg/*----------------------------------------------------------------------------
222871d7fec4Smrg * gfx_get_display_mode
222971d7fec4Smrg *
223071d7fec4Smrg * This routine gets the specified display mode.
223171d7fec4Smrg *
223271d7fec4Smrg * Returns >0 if successful and mode returned, <0 if mode could not be found.
223371d7fec4Smrg *----------------------------------------------------------------------------
223471d7fec4Smrg */
223571d7fec4Smrg#if GFX_DISPLAY_DYNAMIC
223671d7fec4Smrgint
223771d7fec4Smrggu1_get_display_mode(int *xres, int *yres, int *bpp, int *hz)
223871d7fec4Smrg#else
223971d7fec4Smrgint
224071d7fec4Smrggfx_get_display_mode(int *xres, int *yres, int *bpp, int *hz)
224171d7fec4Smrg#endif
224271d7fec4Smrg{
224371d7fec4Smrg   unsigned int mode = 0;
224471d7fec4Smrg   unsigned long pll_freq = 0, bpp_flag = 0;
224571d7fec4Smrg
224671d7fec4Smrg   *xres = gfx_get_hactive();
224771d7fec4Smrg   *yres = gfx_get_vactive();
224871d7fec4Smrg   *bpp = gfx_get_display_bpp();
224971d7fec4Smrg   pll_freq = gfx_get_clock_frequency();
225071d7fec4Smrg
225171d7fec4Smrg   /* SUPPORT EMULATED VGA MODES */
225271d7fec4Smrg
225371d7fec4Smrg   if (gfx_pixel_double)
225471d7fec4Smrg      *xres >>= 1;
225571d7fec4Smrg
225671d7fec4Smrg   if (gfx_line_double)
225771d7fec4Smrg      *yres >>= 1;
225871d7fec4Smrg
225971d7fec4Smrg   /* SET BPP FLAGS TO LIMIT MODE SELECTION */
226071d7fec4Smrg
226171d7fec4Smrg   bpp_flag = GFX_MODE_8BPP;
226271d7fec4Smrg   if (*bpp > 8)
226371d7fec4Smrg      bpp_flag = GFX_MODE_16BPP;
226471d7fec4Smrg
226571d7fec4Smrg   for (mode = 0; mode < NUM_GX_DISPLAY_MODES; mode++) {
226671d7fec4Smrg      if ((DisplayParams[mode].hactive == (unsigned short)*xres) &&
226771d7fec4Smrg	  (DisplayParams[mode].vactive == (unsigned short)*yres) &&
226871d7fec4Smrg	  (DisplayParams[mode].frequency == pll_freq) &&
226971d7fec4Smrg	  (DisplayParams[mode].flags & bpp_flag)) {
227071d7fec4Smrg
227171d7fec4Smrg	 pll_freq = DisplayParams[mode].flags;
227271d7fec4Smrg
227371d7fec4Smrg	 if (pll_freq & GFX_MODE_56HZ)
227471d7fec4Smrg	    *hz = 56;
227571d7fec4Smrg	 else if (pll_freq & GFX_MODE_60HZ)
227671d7fec4Smrg	    *hz = 60;
227771d7fec4Smrg	 else if (pll_freq & GFX_MODE_70HZ)
227871d7fec4Smrg	    *hz = 70;
227971d7fec4Smrg	 else if (pll_freq & GFX_MODE_72HZ)
228071d7fec4Smrg	    *hz = 72;
228171d7fec4Smrg	 else if (pll_freq & GFX_MODE_75HZ)
228271d7fec4Smrg	    *hz = 75;
228371d7fec4Smrg	 else if (pll_freq & GFX_MODE_85HZ)
228471d7fec4Smrg	    *hz = 85;
228571d7fec4Smrg
228671d7fec4Smrg	 return (1);
228771d7fec4Smrg      }
228871d7fec4Smrg   }
228971d7fec4Smrg   return (-1);
229071d7fec4Smrg}
229171d7fec4Smrg
229271d7fec4Smrg/*---------------------------------------------------------------------------
229371d7fec4Smrg * gfx_get_hactive
229471d7fec4Smrg *---------------------------------------------------------------------------
229571d7fec4Smrg */
229671d7fec4Smrg#if GFX_DISPLAY_DYNAMIC
229771d7fec4Smrgunsigned short
229871d7fec4Smrggu1_get_hactive(void)
229971d7fec4Smrg#else
230071d7fec4Smrgunsigned short
230171d7fec4Smrggfx_get_hactive(void)
230271d7fec4Smrg#endif
230371d7fec4Smrg{
230471d7fec4Smrg   return ((unsigned short)((READ_REG32(DC_H_TIMING_1) & 0x07F8) + 8));
230571d7fec4Smrg}
230671d7fec4Smrg
230771d7fec4Smrg/*---------------------------------------------------------------------------
230871d7fec4Smrg * gfx_get_hsync_start
230971d7fec4Smrg *---------------------------------------------------------------------------
231071d7fec4Smrg */
231171d7fec4Smrg#if GFX_DISPLAY_DYNAMIC
231271d7fec4Smrgunsigned short
231371d7fec4Smrggu1_get_hsync_start(void)
231471d7fec4Smrg#else
231571d7fec4Smrgunsigned short
231671d7fec4Smrggfx_get_hsync_start(void)
231771d7fec4Smrg#endif
231871d7fec4Smrg{
231971d7fec4Smrg   return ((unsigned short)((READ_REG32(DC_H_TIMING_3) & 0x07F8) + 8));
232071d7fec4Smrg}
232171d7fec4Smrg
232271d7fec4Smrg/*---------------------------------------------------------------------------
232371d7fec4Smrg * gfx_get_hsync_end
232471d7fec4Smrg *---------------------------------------------------------------------------
232571d7fec4Smrg */
232671d7fec4Smrg#if GFX_DISPLAY_DYNAMIC
232771d7fec4Smrgunsigned short
232871d7fec4Smrggu1_get_hsync_end(void)
232971d7fec4Smrg#else
233071d7fec4Smrgunsigned short
233171d7fec4Smrggfx_get_hsync_end(void)
233271d7fec4Smrg#endif
233371d7fec4Smrg{
233471d7fec4Smrg   return ((unsigned short)(((READ_REG32(DC_H_TIMING_3) >> 16) & 0x07F8) +
233571d7fec4Smrg			    8));
233671d7fec4Smrg}
233771d7fec4Smrg
233871d7fec4Smrg/*---------------------------------------------------------------------------
233971d7fec4Smrg * gfx_get_htotal
234071d7fec4Smrg *---------------------------------------------------------------------------
234171d7fec4Smrg */
234271d7fec4Smrg#if GFX_DISPLAY_DYNAMIC
234371d7fec4Smrgunsigned short
234471d7fec4Smrggu1_get_htotal(void)
234571d7fec4Smrg#else
234671d7fec4Smrgunsigned short
234771d7fec4Smrggfx_get_htotal(void)
234871d7fec4Smrg#endif
234971d7fec4Smrg{
235071d7fec4Smrg   return ((unsigned short)(((READ_REG32(DC_H_TIMING_1) >> 16) & 0x07F8) +
235171d7fec4Smrg			    8));
235271d7fec4Smrg}
235371d7fec4Smrg
235471d7fec4Smrg/*---------------------------------------------------------------------------
235571d7fec4Smrg * gfx_get_vactive
235671d7fec4Smrg *---------------------------------------------------------------------------
235771d7fec4Smrg */
235871d7fec4Smrg#if GFX_DISPLAY_DYNAMIC
235971d7fec4Smrgunsigned short
236071d7fec4Smrggu1_get_vactive(void)
236171d7fec4Smrg#else
236271d7fec4Smrgunsigned short
236371d7fec4Smrggfx_get_vactive(void)
236471d7fec4Smrg#endif
236571d7fec4Smrg{
236671d7fec4Smrg   return ((unsigned short)((READ_REG32(DC_V_TIMING_1) & 0x07FF) + 1));
236771d7fec4Smrg}
236871d7fec4Smrg
236971d7fec4Smrg/*---------------------------------------------------------------------------
237071d7fec4Smrg * gfx_get_vsync_end
237171d7fec4Smrg *---------------------------------------------------------------------------
237271d7fec4Smrg */
237371d7fec4Smrg#if GFX_DISPLAY_DYNAMIC
237471d7fec4Smrgunsigned short
237571d7fec4Smrggu1_get_vsync_end(void)
237671d7fec4Smrg#else
237771d7fec4Smrgunsigned short
237871d7fec4Smrggfx_get_vsync_end(void)
237971d7fec4Smrg#endif
238071d7fec4Smrg{
238171d7fec4Smrg   return ((unsigned short)(((READ_REG32(DC_V_TIMING_3) >> 16) & 0x07FF) +
238271d7fec4Smrg			    1));
238371d7fec4Smrg}
238471d7fec4Smrg
238571d7fec4Smrg/*---------------------------------------------------------------------------
238671d7fec4Smrg * gfx_get_vtotal
238771d7fec4Smrg *---------------------------------------------------------------------------
238871d7fec4Smrg */
238971d7fec4Smrg#if GFX_DISPLAY_DYNAMIC
239071d7fec4Smrgunsigned short
239171d7fec4Smrggu1_get_vtotal(void)
239271d7fec4Smrg#else
239371d7fec4Smrgunsigned short
239471d7fec4Smrggfx_get_vtotal(void)
239571d7fec4Smrg#endif
239671d7fec4Smrg{
239771d7fec4Smrg   return ((unsigned short)(((READ_REG32(DC_V_TIMING_1) >> 16) & 0x07FF) +
239871d7fec4Smrg			    1));
239971d7fec4Smrg}
240071d7fec4Smrg
240171d7fec4Smrg/*-----------------------------------------------------------------------------
240271d7fec4Smrg * gfx_get_display_bpp
240371d7fec4Smrg *
240471d7fec4Smrg * This routine returns the current color depth of the active display.
240571d7fec4Smrg *-----------------------------------------------------------------------------
240671d7fec4Smrg */
240771d7fec4Smrg#if GFX_DISPLAY_DYNAMIC
240871d7fec4Smrgunsigned short
240971d7fec4Smrggu1_get_display_bpp(void)
241071d7fec4Smrg#else
241171d7fec4Smrgunsigned short
241271d7fec4Smrggfx_get_display_bpp(void)
241371d7fec4Smrg#endif
241471d7fec4Smrg{
241571d7fec4Smrg   switch (READ_REG32(DC_OUTPUT_CFG) & 3) {
241671d7fec4Smrg   case 0:
241771d7fec4Smrg      return (16);
241871d7fec4Smrg   case 2:
241971d7fec4Smrg      return (15);
242071d7fec4Smrg   }
242171d7fec4Smrg   return (8);
242271d7fec4Smrg}
242371d7fec4Smrg
242471d7fec4Smrg/*---------------------------------------------------------------------------
242571d7fec4Smrg * gfx_get_vline
242671d7fec4Smrg *---------------------------------------------------------------------------
242771d7fec4Smrg */
242871d7fec4Smrg#if GFX_DISPLAY_DYNAMIC
242971d7fec4Smrgunsigned short
243071d7fec4Smrggu1_get_vline(void)
243171d7fec4Smrg#else
243271d7fec4Smrgunsigned short
243371d7fec4Smrggfx_get_vline(void)
243471d7fec4Smrg#endif
243571d7fec4Smrg{
243671d7fec4Smrg   unsigned short current_scan_line;
243771d7fec4Smrg
243871d7fec4Smrg   /* Read similar value twice to ensure that the value is not transitioning */
243971d7fec4Smrg
244071d7fec4Smrg   do
244171d7fec4Smrg      current_scan_line = (unsigned short)READ_REG32(DC_V_LINE_CNT) & 0x07FF;
244271d7fec4Smrg   while (current_scan_line !=
244371d7fec4Smrg	  (unsigned short)(READ_REG32(DC_V_LINE_CNT) & 0x07FF));
244471d7fec4Smrg
244571d7fec4Smrg   return (current_scan_line);
244671d7fec4Smrg}
244771d7fec4Smrg
244871d7fec4Smrg/*-----------------------------------------------------------------------------
244971d7fec4Smrg * gfx_get_display_offset
245071d7fec4Smrg *-----------------------------------------------------------------------------
245171d7fec4Smrg */
245271d7fec4Smrg#if GFX_DISPLAY_DYNAMIC
245371d7fec4Smrgunsigned long
245471d7fec4Smrggu1_get_display_offset(void)
245571d7fec4Smrg#else
245671d7fec4Smrgunsigned long
245771d7fec4Smrggfx_get_display_offset(void)
245871d7fec4Smrg#endif
245971d7fec4Smrg{
246071d7fec4Smrg   return (READ_REG32(DC_FB_ST_OFFSET) & 0x003FFFFF);
246171d7fec4Smrg}
246271d7fec4Smrg
246371d7fec4Smrg/*-----------------------------------------------------------------------------
246471d7fec4Smrg * gfx_get_cursor_offset
246571d7fec4Smrg *-----------------------------------------------------------------------------
246671d7fec4Smrg */
246771d7fec4Smrg#if GFX_DISPLAY_DYNAMIC
246871d7fec4Smrgunsigned long
246971d7fec4Smrggu1_get_cursor_offset(void)
247071d7fec4Smrg#else
247171d7fec4Smrgunsigned long
247271d7fec4Smrggfx_get_cursor_offset(void)
247371d7fec4Smrg#endif
247471d7fec4Smrg{
247571d7fec4Smrg   return (READ_REG32(DC_CURS_ST_OFFSET) & 0x003FFFFF);
247671d7fec4Smrg}
247771d7fec4Smrg
247871d7fec4Smrg#if GFX_READ_ROUTINES
247971d7fec4Smrg
248071d7fec4Smrg/*************************************************************/
248171d7fec4Smrg/*  READ ROUTINES  |  INCLUDED FOR DIAGNOSTIC PURPOSES ONLY  */
248271d7fec4Smrg/*************************************************************/
248371d7fec4Smrg
248471d7fec4Smrg/*---------------------------------------------------------------------------
248571d7fec4Smrg * gfx_get_hblank_start
248671d7fec4Smrg *---------------------------------------------------------------------------
248771d7fec4Smrg */
248871d7fec4Smrg#if GFX_DISPLAY_DYNAMIC
248971d7fec4Smrgunsigned short
249071d7fec4Smrggu1_get_hblank_start(void)
249171d7fec4Smrg#else
249271d7fec4Smrgunsigned short
249371d7fec4Smrggfx_get_hblank_start(void)
249471d7fec4Smrg#endif
249571d7fec4Smrg{
249671d7fec4Smrg   return ((unsigned short)((READ_REG32(DC_H_TIMING_2) & 0x07F8) + 8));
249771d7fec4Smrg}
249871d7fec4Smrg
249971d7fec4Smrg/*---------------------------------------------------------------------------
250071d7fec4Smrg * gfx_get_hblank_end
250171d7fec4Smrg *---------------------------------------------------------------------------
250271d7fec4Smrg */
250371d7fec4Smrg#if GFX_DISPLAY_DYNAMIC
250471d7fec4Smrgunsigned short
250571d7fec4Smrggu1_get_hblank_end(void)
250671d7fec4Smrg#else
250771d7fec4Smrgunsigned short
250871d7fec4Smrggfx_get_hblank_end(void)
250971d7fec4Smrg#endif
251071d7fec4Smrg{
251171d7fec4Smrg   return ((unsigned short)(((READ_REG32(DC_H_TIMING_2) >> 16) & 0x07F8) +
251271d7fec4Smrg			    8));
251371d7fec4Smrg}
251471d7fec4Smrg
251571d7fec4Smrg/*---------------------------------------------------------------------------
251671d7fec4Smrg * gfx_get_vblank_start
251771d7fec4Smrg *---------------------------------------------------------------------------
251871d7fec4Smrg */
251971d7fec4Smrg#if GFX_DISPLAY_DYNAMIC
252071d7fec4Smrgunsigned short
252171d7fec4Smrggu1_get_vblank_start(void)
252271d7fec4Smrg#else
252371d7fec4Smrgunsigned short
252471d7fec4Smrggfx_get_vblank_start(void)
252571d7fec4Smrg#endif
252671d7fec4Smrg{
252771d7fec4Smrg   return ((unsigned short)((READ_REG32(DC_V_TIMING_2) & 0x07FF) + 1));
252871d7fec4Smrg}
252971d7fec4Smrg
253071d7fec4Smrg/*---------------------------------------------------------------------------
253171d7fec4Smrg * gfx_get_vsync_start
253271d7fec4Smrg *---------------------------------------------------------------------------
253371d7fec4Smrg */
253471d7fec4Smrg#if GFX_DISPLAY_DYNAMIC
253571d7fec4Smrgunsigned short
253671d7fec4Smrggu1_get_vsync_start(void)
253771d7fec4Smrg#else
253871d7fec4Smrgunsigned short
253971d7fec4Smrggfx_get_vsync_start(void)
254071d7fec4Smrg#endif
254171d7fec4Smrg{
254271d7fec4Smrg   return ((unsigned short)((READ_REG32(DC_V_TIMING_3) & 0x07FF) + 1));
254371d7fec4Smrg}
254471d7fec4Smrg
254571d7fec4Smrg/*---------------------------------------------------------------------------
254671d7fec4Smrg * gfx_get_vblank_end
254771d7fec4Smrg *---------------------------------------------------------------------------
254871d7fec4Smrg */
254971d7fec4Smrg#if GFX_DISPLAY_DYNAMIC
255071d7fec4Smrgunsigned short
255171d7fec4Smrggu1_get_vblank_end(void)
255271d7fec4Smrg#else
255371d7fec4Smrgunsigned short
255471d7fec4Smrggfx_get_vblank_end(void)
255571d7fec4Smrg#endif
255671d7fec4Smrg{
255771d7fec4Smrg   return ((unsigned short)(((READ_REG32(DC_V_TIMING_2) >> 16) & 0x07FF) +
255871d7fec4Smrg			    1));
255971d7fec4Smrg}
256071d7fec4Smrg
256171d7fec4Smrg/*-----------------------------------------------------------------------------
256271d7fec4Smrg * gfx_get_display_palette_entry
256371d7fec4Smrg *-----------------------------------------------------------------------------
256471d7fec4Smrg */
256571d7fec4Smrg#if GFX_DISPLAY_DYNAMIC
256671d7fec4Smrgint
256771d7fec4Smrggu1_get_display_palette_entry(unsigned long index, unsigned long *palette)
256871d7fec4Smrg#else
256971d7fec4Smrgint
257071d7fec4Smrggfx_get_display_palette_entry(unsigned long index, unsigned long *palette)
257171d7fec4Smrg#endif
257271d7fec4Smrg{
257371d7fec4Smrg   unsigned long data;
257471d7fec4Smrg
257571d7fec4Smrg   if (index > 0xFF)
257671d7fec4Smrg      return GFX_STATUS_BAD_PARAMETER;
257771d7fec4Smrg
257871d7fec4Smrg   WRITE_REG32(DC_PAL_ADDRESS, index);
257971d7fec4Smrg   data = READ_REG32(DC_PAL_DATA);
258071d7fec4Smrg   data = ((data << 2) & 0x000000FC) |
258171d7fec4Smrg	 ((data << 4) & 0x0000FC00) | ((data << 6) & 0x00FC0000);
258271d7fec4Smrg
258371d7fec4Smrg   *palette = data;
258471d7fec4Smrg
258571d7fec4Smrg   return 0;
258671d7fec4Smrg}
258771d7fec4Smrg
258871d7fec4Smrg/*-----------------------------------------------------------------------------
258971d7fec4Smrg * gfx_get_display_palette
259071d7fec4Smrg *-----------------------------------------------------------------------------
259171d7fec4Smrg */
259271d7fec4Smrg#if GFX_DISPLAY_DYNAMIC
259371d7fec4Smrgvoid
259471d7fec4Smrggu1_get_display_palette(unsigned long *palette)
259571d7fec4Smrg#else
259671d7fec4Smrgvoid
259771d7fec4Smrggfx_get_display_palette(unsigned long *palette)
259871d7fec4Smrg#endif
259971d7fec4Smrg{
260071d7fec4Smrg   unsigned long i, data;
260171d7fec4Smrg
260271d7fec4Smrg   WRITE_REG32(DC_PAL_ADDRESS, 0);
260371d7fec4Smrg   for (i = 0; i < 256; i++) {
260471d7fec4Smrg      data = READ_REG32(DC_PAL_DATA);
260571d7fec4Smrg      data = ((data << 2) & 0x000000FC) |
260671d7fec4Smrg	    ((data << 4) & 0x0000FC00) | ((data << 6) & 0x00FC0000);
260771d7fec4Smrg      palette[i] = data;
260871d7fec4Smrg   }
260971d7fec4Smrg}
261071d7fec4Smrg
261171d7fec4Smrg/*-----------------------------------------------------------------------------
261271d7fec4Smrg * gfx_get_cursor_enable
261371d7fec4Smrg *-----------------------------------------------------------------------------
261471d7fec4Smrg */
261571d7fec4Smrg#if GFX_DISPLAY_DYNAMIC
261671d7fec4Smrgunsigned long
261771d7fec4Smrggu1_get_cursor_enable(void)
261871d7fec4Smrg#else
261971d7fec4Smrgunsigned long
262071d7fec4Smrggfx_get_cursor_enable(void)
262171d7fec4Smrg#endif
262271d7fec4Smrg{
262371d7fec4Smrg   return (READ_REG32(DC_GENERAL_CFG) & DC_GCFG_CURE);
262471d7fec4Smrg}
262571d7fec4Smrg
262671d7fec4Smrg/*-----------------------------------------------------------------------------
262771d7fec4Smrg * gfx_get_cursor_position
262871d7fec4Smrg *-----------------------------------------------------------------------------
262971d7fec4Smrg */
263071d7fec4Smrg#if GFX_DISPLAY_DYNAMIC
263171d7fec4Smrgunsigned long
263271d7fec4Smrggu1_get_cursor_position(void)
263371d7fec4Smrg#else
263471d7fec4Smrgunsigned long
263571d7fec4Smrggfx_get_cursor_position(void)
263671d7fec4Smrg#endif
263771d7fec4Smrg{
263871d7fec4Smrg   return ((READ_REG32(DC_CURSOR_X) & 0x07FF) |
263971d7fec4Smrg	   ((READ_REG32(DC_CURSOR_Y) << 16) & 0x03FF0000));
264071d7fec4Smrg}
264171d7fec4Smrg
264271d7fec4Smrg/*-----------------------------------------------------------------------------
264371d7fec4Smrg * gfx_get_cursor_clip
264471d7fec4Smrg *-----------------------------------------------------------------------------
264571d7fec4Smrg */
264671d7fec4Smrg#if GFX_DISPLAY_DYNAMIC
264771d7fec4Smrgunsigned long
264871d7fec4Smrggu1_get_cursor_clip(void)
264971d7fec4Smrg#else
265071d7fec4Smrgunsigned long
265171d7fec4Smrggfx_get_cursor_clip(void)
265271d7fec4Smrg#endif
265371d7fec4Smrg{
265471d7fec4Smrg   return (((READ_REG32(DC_CURSOR_X) >> 11) & 0x01F) |
265571d7fec4Smrg	   ((READ_REG32(DC_CURSOR_Y) << 5) & 0x1F0000));
265671d7fec4Smrg}
265771d7fec4Smrg
265871d7fec4Smrg/*-----------------------------------------------------------------------------
265971d7fec4Smrg * gfx_get_cursor_color
266071d7fec4Smrg *-----------------------------------------------------------------------------
266171d7fec4Smrg */
266271d7fec4Smrg#if GFX_DISPLAY_DYNAMIC
266371d7fec4Smrgunsigned long
266471d7fec4Smrggu1_get_cursor_color(int color)
266571d7fec4Smrg#else
266671d7fec4Smrgunsigned long
266771d7fec4Smrggfx_get_cursor_color(int color)
266871d7fec4Smrg#endif
266971d7fec4Smrg{
267071d7fec4Smrg   unsigned long data;
267171d7fec4Smrg
267271d7fec4Smrg   if (color) {
267371d7fec4Smrg      WRITE_REG32(DC_PAL_ADDRESS, 0x101);
267471d7fec4Smrg   } else {
267571d7fec4Smrg      WRITE_REG32(DC_PAL_ADDRESS, 0x100);
267671d7fec4Smrg   }
267771d7fec4Smrg   data = READ_REG32(DC_PAL_DATA);
267871d7fec4Smrg   data = ((data << 6) & 0x00FC0000) |
267971d7fec4Smrg	 ((data << 4) & 0x0000FC00) | ((data << 2) & 0x000000FC);
268071d7fec4Smrg   return (data);
268171d7fec4Smrg}
268271d7fec4Smrg
268371d7fec4Smrg/*-----------------------------------------------------------------------------
268471d7fec4Smrg * gfx_get_compression_enable
268571d7fec4Smrg *-----------------------------------------------------------------------------
268671d7fec4Smrg */
268771d7fec4Smrg#if GFX_DISPLAY_DYNAMIC
268871d7fec4Smrgint
268971d7fec4Smrggu1_get_compression_enable(void)
269071d7fec4Smrg#else
269171d7fec4Smrgint
269271d7fec4Smrggfx_get_compression_enable(void)
269371d7fec4Smrg#endif
269471d7fec4Smrg{
269571d7fec4Smrg   unsigned long gcfg;
269671d7fec4Smrg
269771d7fec4Smrg   gcfg = READ_REG32(DC_GENERAL_CFG);
269871d7fec4Smrg   if (gcfg & DC_GCFG_CMPE)
269971d7fec4Smrg      return (1);
270071d7fec4Smrg   else
270171d7fec4Smrg      return (0);
270271d7fec4Smrg}
270371d7fec4Smrg
270471d7fec4Smrg/*-----------------------------------------------------------------------------
270571d7fec4Smrg * gfx_get_compression_offset
270671d7fec4Smrg *-----------------------------------------------------------------------------
270771d7fec4Smrg */
270871d7fec4Smrg#if GFX_DISPLAY_DYNAMIC
270971d7fec4Smrgunsigned long
271071d7fec4Smrggu1_get_compression_offset(void)
271171d7fec4Smrg#else
271271d7fec4Smrgunsigned long
271371d7fec4Smrggfx_get_compression_offset(void)
271471d7fec4Smrg#endif
271571d7fec4Smrg{
271671d7fec4Smrg   unsigned long offset;
271771d7fec4Smrg
271871d7fec4Smrg   offset = READ_REG32(DC_CB_ST_OFFSET) & 0x003FFFFF;
271971d7fec4Smrg   return (offset);
272071d7fec4Smrg}
272171d7fec4Smrg
272271d7fec4Smrg/*-----------------------------------------------------------------------------
272371d7fec4Smrg * gfx_get_compression_pitch
272471d7fec4Smrg *-----------------------------------------------------------------------------
272571d7fec4Smrg */
272671d7fec4Smrg#if GFX_DISPLAY_DYNAMIC
272771d7fec4Smrgunsigned short
272871d7fec4Smrggu1_get_compression_pitch(void)
272971d7fec4Smrg#else
273071d7fec4Smrgunsigned short
273171d7fec4Smrggfx_get_compression_pitch(void)
273271d7fec4Smrg#endif
273371d7fec4Smrg{
273471d7fec4Smrg   unsigned short pitch;
273571d7fec4Smrg
273671d7fec4Smrg   pitch = (unsigned short)(READ_REG32(DC_LINE_DELTA) >> 12) & 0x07FF;
273771d7fec4Smrg   return (pitch << 2);
273871d7fec4Smrg}
273971d7fec4Smrg
274071d7fec4Smrg/*-----------------------------------------------------------------------------
274171d7fec4Smrg * gfx_get_compression_size
274271d7fec4Smrg *-----------------------------------------------------------------------------
274371d7fec4Smrg */
274471d7fec4Smrg#if GFX_DISPLAY_DYNAMIC
274571d7fec4Smrgunsigned short
274671d7fec4Smrggu1_get_compression_size(void)
274771d7fec4Smrg#else
274871d7fec4Smrgunsigned short
274971d7fec4Smrggfx_get_compression_size(void)
275071d7fec4Smrg#endif
275171d7fec4Smrg{
275271d7fec4Smrg   unsigned short size;
275371d7fec4Smrg
275471d7fec4Smrg   size = (unsigned short)((READ_REG32(DC_BUF_SIZE) >> 9) & 0x7F) - 1;
275571d7fec4Smrg   return ((size << 2) + 16);
275671d7fec4Smrg}
275771d7fec4Smrg
275871d7fec4Smrg/*-----------------------------------------------------------------------------
275971d7fec4Smrg * gfx_get_valid_bit
276071d7fec4Smrg *-----------------------------------------------------------------------------
276171d7fec4Smrg */
276271d7fec4Smrg#if GFX_DISPLAY_DYNAMIC
276371d7fec4Smrgint
276471d7fec4Smrggu1_get_valid_bit(int line)
276571d7fec4Smrg#else
276671d7fec4Smrgint
276771d7fec4Smrggfx_get_valid_bit(int line)
276871d7fec4Smrg#endif
276971d7fec4Smrg{
277071d7fec4Smrg   int valid;
277171d7fec4Smrg
277271d7fec4Smrg   WRITE_REG32(MC_DR_ADD, line);
277371d7fec4Smrg   valid = (int)READ_REG32(MC_DR_ACC) & 1;
277471d7fec4Smrg   return (valid);
277571d7fec4Smrg}
277671d7fec4Smrg
277771d7fec4Smrg/*---------------------------------------------------------------------------
277871d7fec4Smrg * gfx_get_display_video_offset (PRIVATE ROUTINE - NOT PART OF API)
277971d7fec4Smrg *
278071d7fec4Smrg * This routine is called by "gfx_get_video_offset".  It abstracts the
278171d7fec4Smrg * version of the display controller from the video overlay routines.
278271d7fec4Smrg *---------------------------------------------------------------------------
278371d7fec4Smrg */
278471d7fec4Smrg#if GFX_DISPLAY_DYNAMIC
278571d7fec4Smrgunsigned long
278671d7fec4Smrggu1_get_display_video_offset(void)
278771d7fec4Smrg#else
278871d7fec4Smrgunsigned long
278971d7fec4Smrggfx_get_display_video_offset(void)
279071d7fec4Smrg#endif
279171d7fec4Smrg{
279271d7fec4Smrg   return (READ_REG32(DC_VID_ST_OFFSET) & 0x003FFFFF);
279371d7fec4Smrg}
279471d7fec4Smrg
279571d7fec4Smrg/*---------------------------------------------------------------------------
279671d7fec4Smrg * gfx_get_display_video_size (PRIVATE ROUTINE - NOT PART OF API)
279771d7fec4Smrg *
279871d7fec4Smrg * This routine is called by "gfx_get_video_size".  It abstracts the
279971d7fec4Smrg * version of the display controller from the video overlay routines.
280071d7fec4Smrg *---------------------------------------------------------------------------
280171d7fec4Smrg */
280271d7fec4Smrg#if GFX_DISPLAY_DYNAMIC
280371d7fec4Smrgunsigned long
280471d7fec4Smrggu1_get_display_video_size(void)
280571d7fec4Smrg#else
280671d7fec4Smrgunsigned long
280771d7fec4Smrggfx_get_display_video_size(void)
280871d7fec4Smrg#endif
280971d7fec4Smrg{
281071d7fec4Smrg   /* RETURN TOTAL SIZE, IN BYTES */
281171d7fec4Smrg
281271d7fec4Smrg   return ((READ_REG32(DC_BUF_SIZE) >> 10) & 0x000FFFC0);
281371d7fec4Smrg}
281471d7fec4Smrg
281571d7fec4Smrg/*-----------------------------------------------------------------------------
281671d7fec4Smrg * gfx_get_display_priority_high
281771d7fec4Smrg *-----------------------------------------------------------------------------
281871d7fec4Smrg */
281971d7fec4Smrg#if GFX_DISPLAY_DYNAMIC
282071d7fec4Smrgint
282171d7fec4Smrggu1_get_display_priority_high(void)
282271d7fec4Smrg#else
282371d7fec4Smrgint
282471d7fec4Smrggfx_get_display_priority_high(void)
282571d7fec4Smrg#endif
282671d7fec4Smrg{
282771d7fec4Smrg   if (READ_REG32(MC_MEM_CNTRL1) & MC_XBUSARB)
282871d7fec4Smrg      return (1);
282971d7fec4Smrg   else
283071d7fec4Smrg      return (0);
283171d7fec4Smrg}
283271d7fec4Smrg
283371d7fec4Smrg#endif /* GFX_READ_ROUTINES */
283471d7fec4Smrg
283571d7fec4Smrg/* END OF FILE */
2836