vid_rdcl.c revision 71d7fec4
1/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nsc/gfx/vid_rdcl.c,v 1.3 2003/02/21 16:51:10 alanh Exp $ */
2/*
3 * $Workfile: vid_rdcl.c $
4 *
5 * This file contains routines to control the Redcloud display filter video overlay hardware.
6 *
7 * NSC_LIC_ALTERNATIVE_PREAMBLE
8 *
9 * Revision 1.0
10 *
11 * National Semiconductor Alternative GPL-BSD License
12 *
13 * National Semiconductor Corporation licenses this software
14 * ("Software"):
15 *
16 *      Durango
17 *
18 * under one of the two following licenses, depending on how the
19 * Software is received by the Licensee.
20 *
21 * If this Software is received as part of the Linux Framebuffer or
22 * other GPL licensed software, then the GPL license designated
23 * NSC_LIC_GPL applies to this Software; in all other circumstances
24 * then the BSD-style license designated NSC_LIC_BSD shall apply.
25 *
26 * END_NSC_LIC_ALTERNATIVE_PREAMBLE */
27
28/* NSC_LIC_BSD
29 *
30 * National Semiconductor Corporation Open Source License for Durango
31 *
32 * (BSD License with Export Notice)
33 *
34 * Copyright (c) 1999-2001
35 * National Semiconductor Corporation.
36 * All rights reserved.
37 *
38 * Redistribution and use in source and binary forms, with or without
39 * modification, are permitted provided that the following conditions
40 * are met:
41 *
42 *   * Redistributions of source code must retain the above copyright
43 *     notice, this list of conditions and the following disclaimer.
44 *
45 *   * Redistributions in binary form must reproduce the above
46 *     copyright notice, this list of conditions and the following
47 *     disclaimer in the documentation and/or other materials provided
48 *     with the distribution.
49 *
50 *   * Neither the name of the National Semiconductor Corporation nor
51 *     the names of its contributors may be used to endorse or promote
52 *     products derived from this software without specific prior
53 *     written permission.
54 *
55 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
56 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
57 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
58 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
59 * NATIONAL SEMICONDUCTOR CORPORATION OR CONTRIBUTORS BE LIABLE FOR ANY
60 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
61 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
62 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
63 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
64 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE,
65 * INTELLECTUAL PROPERTY INFRINGEMENT, OR OTHERWISE) ARISING IN ANY WAY
66 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
67 * OF SUCH DAMAGE.
68 *
69 * EXPORT LAWS: THIS LICENSE ADDS NO RESTRICTIONS TO THE EXPORT LAWS OF
70 * YOUR JURISDICTION. It is licensee's responsibility to comply with
71 * any export regulations applicable in licensee's jurisdiction. Under
72 * CURRENT (2001) U.S. export regulations this software
73 * is eligible for export from the U.S. and can be downloaded by or
74 * otherwise exported or reexported worldwide EXCEPT to U.S. embargoed
75 * destinations which include Cuba, Iraq, Libya, North Korea, Iran,
76 * Syria, Sudan, Afghanistan and any other country to which the U.S.
77 * has embargoed goods and services.
78 *
79 * END_NSC_LIC_BSD */
80
81/* NSC_LIC_GPL
82 *
83 * National Semiconductor Corporation Gnu General Public License for Durango
84 *
85 * (GPL License with Export Notice)
86 *
87 * Copyright (c) 1999-2001
88 * National Semiconductor Corporation.
89 * All rights reserved.
90 *
91 * Redistribution and use in source and binary forms, with or without
92 * modification, are permitted under the terms of the GNU General
93 * Public License as published by the Free Software Foundation; either
94 * version 2 of the License, or (at your option) any later version
95 *
96 * In addition to the terms of the GNU General Public License, neither
97 * the name of the National Semiconductor Corporation nor the names of
98 * its contributors may be used to endorse or promote products derived
99 * from this software without specific prior written permission.
100 *
101 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
102 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
103 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
104 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
105 * NATIONAL SEMICONDUCTOR CORPORATION OR CONTRIBUTORS BE LIABLE FOR ANY
106 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
107 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
108 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
109 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
110 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE,
111 * INTELLECTUAL PROPERTY INFRINGEMENT, OR OTHERWISE) ARISING IN ANY WAY
112 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
113 * OF SUCH DAMAGE. See the GNU General Public License for more details.
114 *
115 * EXPORT LAWS: THIS LICENSE ADDS NO RESTRICTIONS TO THE EXPORT LAWS OF
116 * YOUR JURISDICTION. It is licensee's responsibility to comply with
117 * any export regulations applicable in licensee's jurisdiction. Under
118 * CURRENT (2001) U.S. export regulations this software
119 * is eligible for export from the U.S. and can be downloaded by or
120 * otherwise exported or reexported worldwide EXCEPT to U.S. embargoed
121 * destinations which include Cuba, Iraq, Libya, North Korea, Iran,
122 * Syria, Sudan, Afghanistan and any other country to which the U.S.
123 * has embargoed goods and services.
124 *
125 * You should have received a copy of the GNU General Public License
126 * along with this file; if not, write to the Free Software Foundation,
127 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
128 *
129 * END_NSC_LIC_GPL */
130
131/* REDCLOUD PLL TABLE  */
132
133typedef struct RCDFPLL
134{
135   long frequency;			/* 16.16 fixed point frequency            */
136   unsigned long post_div3;		/* MCP Frequency dividers and multipliers */
137   unsigned long pre_mul2;
138   unsigned long pre_div2;
139   unsigned long pll_value;		/* MCP DotPLL Register Upper 32(0x0015)   */
140}
141RCDFPLLENTRY;
142
143RCDFPLLENTRY RCDF_PLLtable48MHz[] = {
144   {0x00192CCC, 0, 0, 0, 0x00000037},	/*  25.1750 */
145   {0x001C526E, 1, 1, 0, 0x00000B1A},	/*  28.3220 */
146   {0x001F8000, 1, 0, 0, 0x000002D2},	/*  31.5000 */
147   {0x00240000, 1, 1, 0, 0x00000FE2},	/*  36.0000 */
148   {0x00258000, 1, 0, 0, 0x0000057A},	/*  37.5000 */
149   {0x00280000, 1, 0, 0, 0x0000030A},	/*  40.0000 */
150   {0x002CE666, 0, 0, 0, 0x00000063},	/*  44.9000 */
151   {0x00318000, 0, 0, 0, 0x0000054B},	/*  49.5000 */
152   {0x00320000, 0, 0, 0, 0x0000026E},	/*  50.0000 */
153   {0x00325999, 0, 1, 0, 0x00000037},	/*  50.3500 */
154   {0x00360000, 1, 1, 0, 0x00000B0D},	/*  54.0000 */
155   {0x00384000, 0, 0, 0, 0x00000577},	/*  56.2500 */
156   {0x0038643F, 0, 0, 0, 0x000007F7},	/*  56.3916 */
157   {0x0038A4DD, 0, 0, 0, 0x0000057B},	/*  56.6444 */
158   {0x003B0000, 0, 1, 0, 0x00000707},	/*  59.0000 */
159   {0x003F0000, 1, 1, 0, 0x00000B39},	/*  63.0000 */
160   {0x00410000, 1, 1, 0, 0x00000B45},	/*  65.0000 */
161   {0x00438000, 1, 1, 0, 0x00000FC1},	/*  67.5000 */
162   {0x0046CCCC, 1, 0, 0, 0x00000561},	/*  70.8000 */
163   {0x00480000, 1, 0, 0, 0x000007E1},	/*  72.0000 */
164   {0x004B0000, 0, 0, 0, 0x00000052},	/*  75.0000 */
165   {0x004EC000, 0, 0, 0, 0x00000056},	/*  78.7500 */
166   {0x00500000, 1, 1, 0, 0x00000709},	/*  80.0000 */
167   {0x0059CCCC, 0, 1, 0, 0x00000262},	/*  89.8000 */
168   {0x005E8000, 0, 0, 0, 0x000002D2},	/*  94.5000 */
169   {0x00630000, 0, 1, 0, 0x00000B4A},	/*  99.0000 */
170   {0x00640000, 0, 1, 0, 0x00000036},	/* 100.0000 */
171   {0x006C0000, 0, 0, 0, 0x000007E2},	/* 108.0000 */
172   {0x00708000, 0, 0, 0, 0x000007F6},	/* 112.5000 */
173   {0x00820000, 1, 1, 0, 0x00000FB0},	/* 130.0000 */
174   {0x00870000, 1, 1, 0, 0x00000B50},	/* 135.0000 */
175   {0x009D8000, 0, 0, 0, 0x00000055},	/* 157.5000 */
176   {0x00A20000, 0, 0, 0, 0x000009C1},	/* 162.0000 */
177   {0x00AF8000, 0, 0, 0, 0x000002C1},	/* 175.5000 */
178   {0x00BD0000, 0, 0, 0, 0x000002D1},	/* 189.0000 */
179   {0x00CA8000, 0, 0, 0, 0x00000551},	/* 202.5000 */
180   {0x00E58000, 0, 0, 0, 0x0000057D},	/* 229.5000 */
181};
182
183RCDFPLLENTRY RCDF_PLLtable14MHz[] = {
184   {0x00192CCC, 0, 0, 0, 0x00000037},	/*  25.1750 */
185   {0x001C526E, 0, 0, 0, 0x00000B7B},	/*  28.3220 */
186   {0x001F8000, 0, 0, 0, 0x000004D3},	/*  31.5000 */
187   {0x00240000, 0, 0, 0, 0x00000BE3},	/*  36.0000 */
188   {0x00258000, 0, 0, 0, 0x0000074F},	/*  37.5000 */
189   {0x00280000, 0, 0, 0, 0x0000050B},	/*  40.0000 */
190   {0x002CE666, 0, 0, 0, 0x00000063},	/*  44.9000 */
191   {0x00318000, 0, 0, 0, 0x0000054B},	/*  49.5000 */
192   {0x00320000, 0, 0, 0, 0x0000026E},	/*  50.0000 */
193   {0x00325999, 0, 0, 0, 0x000007C3},	/*  50.3500 */
194   {0x00360000, 0, 0, 0, 0x000007E3},	/*  54.0000 */
195   {0x00384000, 0, 0, 0, 0x00000577},	/*  56.2500 */
196   {0x0038643F, 0, 0, 0, 0x000002FB},	/*  56.3916 */
197   {0x0038A4DD, 0, 0, 0, 0x0000057B},	/*  56.6444 */
198   {0x003B0000, 0, 0, 0, 0x0000058B},	/*  59.0000 */
199   {0x003F0000, 0, 0, 0, 0x0000095E},	/*  63.0000 */
200   {0x00410000, 0, 0, 0, 0x0000096A},	/*  65.0000 */
201   {0x00438000, 0, 0, 0, 0x00000BC2},	/*  67.5000 */
202   {0x0046CCCC, 0, 0, 0, 0x0000098A},	/*  70.8000 */
203   {0x00480000, 0, 0, 0, 0x00000BE2},	/*  72.0000 */
204   {0x004B0000, 0, 0, 0, 0x00000052},	/*  75.0000 */
205   {0x004EC000, 0, 0, 0, 0x00000056},	/*  78.7500 */
206   {0x00500000, 0, 0, 0, 0x0000050A},	/*  80.0000 */
207   {0x0059CCCC, 0, 0, 0, 0x0000078E},	/*  89.8000 */
208   {0x005E8000, 0, 0, 0, 0x000002D2},	/*  94.5000 */
209   {0x00630000, 0, 0, 0, 0x000011F6},	/*  99.0000 */
210   {0x00640000, 0, 0, 0, 0x0000054E},	/* 100.0000 */
211   {0x006C0000, 0, 0, 0, 0x000007E2},	/* 108.0000 */
212   {0x00708000, 0, 0, 0, 0x000002FA},	/* 112.5000 */
213   {0x00820000, 0, 0, 0, 0x00000BB1},	/* 130.0000 */
214   {0x00870000, 0, 0, 0, 0x00000975},	/* 135.0000 */
215   {0x009D8000, 0, 0, 0, 0x00000055},	/* 157.5000 */
216   {0x00A20000, 0, 0, 0, 0x000009C1},	/* 162.0000 */
217   {0x00AF8000, 0, 0, 0, 0x000002C1},	/* 175.5000 */
218   {0x00BD0000, 0, 0, 0, 0x00000539},	/* 189.0000 */
219   {0x00CA8000, 0, 0, 0, 0x00000551},	/* 202.5000 */
220   {0x00E58000, 0, 0, 0, 0x0000057D},	/* 229.5000 */
221};
222
223#define NUM_RCDF_FREQUENCIES sizeof(RCDF_PLLtable14MHz)/sizeof(RCDFPLLENTRY)
224
225int redcloud_set_video_enable(int enable);
226int redcloud_set_video_format(unsigned long format);
227int redcloud_set_video_size(unsigned short width, unsigned short height);
228int redcloud_set_video_yuv_pitch(unsigned long ypitch, unsigned long uvpitch);
229int redcloud_set_video_offset(unsigned long offset);
230int redcloud_set_video_yuv_offsets(unsigned long yoffset,
231				   unsigned long uoffset,
232				   unsigned long voffset);
233int redcloud_set_video_window(short x, short y, unsigned short w,
234			      unsigned short h);
235int redcloud_set_video_left_crop(unsigned short x);
236int redcloud_set_video_upscale(unsigned short srcw, unsigned short srch,
237			       unsigned short dstw, unsigned short dsth);
238int redcloud_set_video_scale(unsigned short srcw, unsigned short srch,
239			     unsigned short dstw, unsigned short dsth);
240int redcloud_set_video_vertical_downscale(unsigned short srch,
241					  unsigned short dsth);
242void redcloud_set_video_vertical_downscale_enable(int enable);
243int redcloud_set_video_downscale_config(unsigned short type,
244					unsigned short m);
245int redcloud_set_video_color_key(unsigned long key, unsigned long mask,
246				 int bluescreen);
247int redcloud_set_video_filter(int xfilter, int yfilter);
248int redcloud_set_video_palette(unsigned long *palette);
249int redcloud_set_video_palette_entry(unsigned long index,
250				     unsigned long color);
251int redcloud_set_video_downscale_coefficients(unsigned short coef1,
252					      unsigned short coef2,
253					      unsigned short coef3,
254					      unsigned short coef4);
255int redcloud_set_video_downscale_enable(int enable);
256int redcloud_set_video_source(VideoSourceType source);
257int redcloud_set_vbi_source(VbiSourceType source);
258int redcloud_set_vbi_lines(unsigned long even, unsigned long odd);
259int redcloud_set_vbi_total(unsigned long even, unsigned long odd);
260int redcloud_set_video_interlaced(int enable);
261int redcloud_set_color_space_YUV(int enable);
262int redcloud_set_vertical_scaler_offset(char offset);
263int redcloud_set_top_line_in_odd(int enable);
264int redcloud_set_genlock_delay(unsigned long delay);
265int redcloud_set_genlock_enable(int flags);
266int redcloud_set_video_cursor(unsigned long key, unsigned long mask,
267			      unsigned short select_color2,
268			      unsigned long color1, unsigned long color2);
269int redcloud_set_video_cursor_enable(int enable);
270int redcloud_set_video_request(short x, short y);
271
272int redcloud_select_alpha_region(int region);
273int redcloud_set_alpha_enable(int enable);
274int redcloud_set_alpha_window(short x, short y,
275			      unsigned short width, unsigned short height);
276int redcloud_set_alpha_value(unsigned char alpha, char delta);
277int redcloud_set_alpha_priority(int priority);
278int redcloud_set_alpha_color(unsigned long color);
279int redcloud_set_alpha_color_enable(int enable);
280int redcloud_set_no_ck_outside_alpha(int enable);
281int redcloud_disable_softvga(void);
282int redcloud_enable_softvga(void);
283int redcloud_set_macrovision_enable(int enable);
284void redcloud_reset_video(void);
285int redcloud_set_display_control(int sync_polarities);
286void redcloud_set_clock_frequency(unsigned long frequency);
287int redcloud_set_crt_enable(int enable);
288
289/* READ ROUTINES IN GFX_VID.C */
290
291int redcloud_get_video_enable(void);
292int redcloud_get_video_format(void);
293unsigned long redcloud_get_video_src_size(void);
294unsigned long redcloud_get_video_line_size(void);
295unsigned long redcloud_get_video_xclip(void);
296unsigned long redcloud_get_video_offset(void);
297void redcloud_get_video_yuv_offsets(unsigned long *yoffset,
298				    unsigned long *uoffset,
299				    unsigned long *voffset);
300void redcloud_get_video_yuv_pitch(unsigned long *ypitch,
301				  unsigned long *uvpitch);
302unsigned long redcloud_get_video_upscale(void);
303unsigned long redcloud_get_video_scale(void);
304unsigned long redcloud_get_video_downscale_delta(void);
305int redcloud_get_video_vertical_downscale_enable(void);
306int redcloud_get_video_downscale_config(unsigned short *type,
307					unsigned short *m);
308void redcloud_get_video_downscale_coefficients(unsigned short *coef1,
309					       unsigned short *coef2,
310					       unsigned short *coef3,
311					       unsigned short *coef4);
312void redcloud_get_video_downscale_enable(int *enable);
313unsigned long redcloud_get_video_dst_size(void);
314unsigned long redcloud_get_video_position(void);
315unsigned long redcloud_get_video_color_key(void);
316unsigned long redcloud_get_video_color_key_mask(void);
317int redcloud_get_video_palette_entry(unsigned long index,
318				     unsigned long *palette);
319int redcloud_get_video_color_key_src(void);
320int redcloud_get_video_filter(void);
321int redcloud_get_video_request(short *x, short *y);
322int redcloud_get_video_source(VideoSourceType * source);
323int redcloud_get_vbi_source(VbiSourceType * source);
324unsigned long redcloud_get_vbi_lines(int odd);
325unsigned long redcloud_get_vbi_total(int odd);
326int redcloud_get_video_interlaced(void);
327int redcloud_get_color_space_YUV(void);
328int redcloud_get_vertical_scaler_offset(char *offset);
329unsigned long redcloud_get_genlock_delay(void);
330int redcloud_get_genlock_enable(void);
331int redcloud_get_video_cursor(unsigned long *key, unsigned long *mask,
332			      unsigned short *select_color2,
333			      unsigned long *color1, unsigned short *color2);
334unsigned long redcloud_read_crc(void);
335unsigned long redcloud_read_crc32(void);
336unsigned long redcloud_read_window_crc(int source, unsigned short x,
337				       unsigned short y, unsigned short width,
338				       unsigned short height, int crc32);
339int redcloud_get_macrovision_enable(void);
340
341void redcloud_get_alpha_enable(int *enable);
342void redcloud_get_alpha_size(unsigned short *x, unsigned short *y,
343			     unsigned short *width, unsigned short *height);
344void redcloud_get_alpha_value(unsigned char *alpha, char *delta);
345void redcloud_get_alpha_priority(int *priority);
346void redcloud_get_alpha_color(unsigned long *color);
347unsigned long redcloud_get_clock_frequency(void);
348int redcloud_get_sync_polarities(void);
349
350/*---------------------------------------------------------------------------
351 * gfx_reset_video (PRIVATE ROUTINE: NOT PART OF DURANGO API)
352 *
353 * This routine is used to disable all components of video overlay before
354 * performing a mode switch.
355 *---------------------------------------------------------------------------
356 */
357#if GFX_VIDEO_DYNAMIC
358void
359redcloud_reset_video(void)
360#else
361void
362gfx_reset_video(void)
363#endif
364{
365   gfx_set_video_enable(0);
366   gfx_select_alpha_region(1);
367   gfx_set_alpha_enable(0);
368   gfx_select_alpha_region(2);
369   gfx_set_alpha_enable(0);
370
371   /* SET REGION 0 AFTER RESET */
372
373   gfx_select_alpha_region(0);
374   gfx_set_alpha_enable(0);
375}
376
377/*-----------------------------------------------------------------------------
378 * gfx_set_display_control (PRIVATE ROUTINE: NOT PART OF DURANGO API)
379 *
380 * This routine configures the display output.
381 *
382 * "sync_polarities" is used to set the polarities of the sync pulses according
383 * to the following mask:
384 *
385 *     Bit 0: If set to 1, negative horizontal polarity is programmed,
386 *            otherwise positive horizontal polarity is programmed.
387 *     Bit 1: If set to 1, negative vertical polarity is programmed,
388 *            otherwise positive vertical polarity is programmed.
389 *
390 *-----------------------------------------------------------------------------
391 */
392#if GFX_VIDEO_DYNAMIC
393int
394redcloud_set_display_control(int sync_polarities)
395#else
396int
397gfx_set_display_control(int sync_polarities)
398#endif
399{
400   unsigned long power;
401   unsigned long dcfg;
402
403   /* CONFIGURE DISPLAY OUTPUT FROM VIDEO PROCESSOR */
404
405   dcfg = READ_VID32(RCDF_DISPLAY_CONFIG);
406   dcfg &= ~(RCDF_DCFG_CRT_SYNC_SKW_MASK | RCDF_DCFG_PWR_SEQ_DLY_MASK |
407	     RCDF_DCFG_CRT_HSYNC_POL | RCDF_DCFG_CRT_VSYNC_POL |
408	     RCDF_DCFG_FP_PWR_EN | RCDF_DCFG_FP_DATA_EN);
409
410   dcfg |= (RCDF_DCFG_CRT_SYNC_SKW_INIT |
411	    RCDF_DCFG_PWR_SEQ_DLY_INIT | RCDF_DCFG_GV_PAL_BYP);
412
413   if (PanelEnable) {
414      power = READ_VID32(RCDF_POWER_MANAGEMENT);
415      power |= RCDF_PM_PANEL_POWER_ON;
416      WRITE_VID32(RCDF_POWER_MANAGEMENT, power);
417   }
418
419   /* SET APPROPRIATE SYNC POLARITIES */
420
421   if (sync_polarities & 0x1)
422      dcfg |= RCDF_DCFG_CRT_HSYNC_POL;
423   if (sync_polarities & 0x2)
424      dcfg |= RCDF_DCFG_CRT_VSYNC_POL;
425
426   WRITE_VID32(RCDF_DISPLAY_CONFIG, dcfg);
427
428   return (0);
429}
430
431/*---------------------------------------------------------------------------
432 * gfx_set_clock_frequency
433 *
434 * This routine sets the clock frequency, specified as a 16.16 fixed point
435 * value (0x00318000 = 49.5 MHz).  It will set the closest frequency found
436 * in the lookup table.
437 *---------------------------------------------------------------------------
438 */
439#if GFX_VIDEO_DYNAMIC
440void
441redcloud_set_clock_frequency(unsigned long frequency)
442#else
443void
444gfx_set_clock_frequency(unsigned long frequency)
445#endif
446{
447   Q_WORD msr_value;
448   unsigned int i, index = 0;
449   unsigned long value;
450   long timeout = 1000;
451   long min, diff;
452   RCDFPLLENTRY *PllTable;
453
454   /* READ PLL REFERENCE FREQUENCY */
455   /* The reference frequency of GX2 1.x is different from 2.x and above. */
456
457   if ((gfx_cpu_version & 0xFF00) >= 0x0200)
458      PllTable = RCDF_PLLtable48MHz;
459   else
460      PllTable = RCDF_PLLtable14MHz;
461
462   /* FIND THE REGISTER VALUES FOR THE DESIRED FREQUENCY */
463   /* Search the table for the closest frequency (16.16 format). */
464
465   value = PllTable[0].pll_value;
466   min = (long)PllTable[0].frequency - frequency;
467   if (min < 0L)
468      min = -min;
469   for (i = 1; i < NUM_RCDF_FREQUENCIES; i++) {
470      diff = (long)PllTable[i].frequency - frequency;
471      if (diff < 0L)
472	 diff = -diff;
473      if (diff < min) {
474	 min = diff;
475	 index = i;
476      }
477   }
478
479   /* PROGRAM THE SETTINGS WITH THE RESET BIT SET */
480   /* Clear the bypass bit to ensure that the programmed */
481   /* M, N and P values are being used.                  */
482
483   gfx_msr_read(RC_ID_MCP, MCP_DOTPLL, &msr_value);
484   msr_value.high = PllTable[index].pll_value;
485   msr_value.low |= 0x00000001;
486   msr_value.low &= ~MCP_DOTPLL_BYPASS;
487   gfx_msr_write(RC_ID_MCP, MCP_DOTPLL, &msr_value);
488
489   /* PROGRAM THE MCP DIVIDER VALUES */
490
491   gfx_msr_read(RC_ID_MCP, MCP_SYS_RSTPLL, &msr_value);
492   if (PllTable[index].post_div3)
493      msr_value.low |= MCP_DOTPOSTDIV3;
494   else
495      msr_value.low &= ~MCP_DOTPOSTDIV3;
496   if (PllTable[index].pre_div2)
497      msr_value.low |= MCP_DOTPREDIV2;
498   else
499      msr_value.low &= ~MCP_DOTPREDIV2;
500   if (PllTable[index].pre_mul2)
501      msr_value.low |= MCP_DOTPREMULT2;
502   else
503      msr_value.low &= ~MCP_DOTPREMULT2;
504   gfx_msr_write(RC_ID_MCP, MCP_SYS_RSTPLL, &msr_value);
505
506   /* CLEAR THE RESET BIT */
507
508   gfx_msr_read(RC_ID_MCP, MCP_DOTPLL, &msr_value);
509   msr_value.low &= 0xFFFFFFFE;
510   gfx_msr_write(RC_ID_MCP, MCP_DOTPLL, &msr_value);
511
512   /* WAIT FOR LOCK BIT */
513
514   do {
515      gfx_msr_read(RC_ID_MCP, MCP_DOTPLL, &msr_value);
516   } while (timeout-- && !(msr_value.low & MCP_DOTPLL_LOCK));
517}
518
519/*---------------------------------------------------------------------------
520 * gfx_set_crt_enable
521 *
522 * This routine enables or disables the CRT output from the video processor.
523 *---------------------------------------------------------------------------
524 */
525#if GFX_VIDEO_DYNAMIC
526int
527redcloud_set_crt_enable(int enable)
528#else
529int
530gfx_set_crt_enable(int enable)
531#endif
532{
533   unsigned long config, misc;
534
535   config = READ_VID32(RCDF_DISPLAY_CONFIG);
536   misc = READ_VID32(RCDF_VID_MISC);
537
538   switch (enable) {
539   case CRT_DISABLE:			/* DISABLE EVERYTHING */
540
541      WRITE_VID32(RCDF_DISPLAY_CONFIG,
542		  config & ~(RCDF_DCFG_DIS_EN | RCDF_DCFG_HSYNC_EN |
543			     RCDF_DCFG_VSYNC_EN | RCDF_DCFG_DAC_BL_EN));
544      WRITE_VID32(RCDF_VID_MISC, misc | RCDF_DAC_POWER_DOWN);
545      break;
546
547   case CRT_ENABLE:			/* ENABLE CRT DISPLAY, INCLUDING DISPLAY LOGIC */
548
549      WRITE_VID32(RCDF_DISPLAY_CONFIG,
550		  config | RCDF_DCFG_DIS_EN | RCDF_DCFG_HSYNC_EN |
551		  RCDF_DCFG_VSYNC_EN | RCDF_DCFG_DAC_BL_EN);
552      WRITE_VID32(RCDF_VID_MISC,
553		  misc & ~RCDF_DAC_POWER_DOWN & ~RCDF_ANALOG_POWER_DOWN);
554      break;
555
556   case CRT_STANDBY:			/* HSYNC:OFF VSYNC:ON */
557
558      WRITE_VID32(RCDF_DISPLAY_CONFIG,
559		  (config &
560		   ~(RCDF_DCFG_DIS_EN | RCDF_DCFG_HSYNC_EN |
561		     RCDF_DCFG_DAC_BL_EN)) | RCDF_DCFG_VSYNC_EN);
562      WRITE_VID32(RCDF_VID_MISC, misc | RCDF_DAC_POWER_DOWN);
563      break;
564
565   case CRT_SUSPEND:			/* HSYNC:ON VSYNC:OFF */
566
567      WRITE_VID32(RCDF_DISPLAY_CONFIG,
568		  (config &
569		   ~(RCDF_DCFG_DIS_EN | RCDF_DCFG_VSYNC_EN |
570		     RCDF_DCFG_DAC_BL_EN)) | RCDF_DCFG_HSYNC_EN);
571      WRITE_VID32(RCDF_VID_MISC, misc | RCDF_DAC_POWER_DOWN);
572      break;
573
574   default:
575      return (GFX_STATUS_BAD_PARAMETER);
576   }
577   return (GFX_STATUS_OK);
578}
579
580/*-----------------------------------------------------------------------------
581 * gfx_set_video_enable
582 *
583 * This routine enables or disables the video overlay functionality.
584 *-----------------------------------------------------------------------------
585 */
586#if GFX_VIDEO_DYNAMIC
587int
588redcloud_set_video_enable(int enable)
589#else
590int
591gfx_set_video_enable(int enable)
592#endif
593{
594   unsigned long vcfg;
595
596   /* WAIT FOR VERTICAL BLANK TO START */
597   /* Otherwise a glitch can be observed. */
598
599   if (gfx_test_timing_active()) {
600      if (!gfx_test_vertical_active()) {
601	 while (!gfx_test_vertical_active()) ;
602      }
603      while (gfx_test_vertical_active()) ;
604   }
605
606   vcfg = READ_VID32(RCDF_VIDEO_CONFIG);
607   if (enable) {
608      /* ENABLE VIDEO OVERLAY FROM DISPLAY CONTROLLER */
609      /* Use private routine to abstract the display controller. */
610
611      gfx_set_display_video_enable(1);
612
613      /* ENABLE DISPLAY FILTER VIDEO OVERLAY */
614
615      vcfg |= RCDF_VCFG_VID_EN;
616      WRITE_VID32(RCDF_VIDEO_CONFIG, vcfg);
617   } else {
618      /* DISABLE DISPLAY FILTER VIDEO OVERLAY */
619
620      vcfg &= ~RCDF_VCFG_VID_EN;
621      WRITE_VID32(RCDF_VIDEO_CONFIG, vcfg);
622
623      /* DISABLE VIDEO OVERLAY FROM DISPLAY CONTROLLER */
624      /* Use private routine to abstract the display controller. */
625
626      gfx_set_display_video_enable(0);
627   }
628   return (0);
629}
630
631/*-----------------------------------------------------------------------------
632 * gfx_set_video_format
633 *
634 * Sets input video format type, to one of the YUV formats or to RGB.
635 *-----------------------------------------------------------------------------
636 */
637#if GFX_VIDEO_DYNAMIC
638int
639redcloud_set_video_format(unsigned long format)
640#else
641int
642gfx_set_video_format(unsigned long format)
643#endif
644{
645   unsigned long ctrl, vcfg = 0;
646
647   /* SET THE DISPLAY FILTER VIDEO INPUT FORMAT */
648
649   vcfg = READ_VID32(RCDF_VIDEO_CONFIG);
650   ctrl = READ_VID32(RCDF_VID_ALPHA_CONTROL);
651   ctrl &= ~(RCDF_VIDEO_INPUT_IS_RGB | RCDF_CSC_VIDEO_YUV_TO_RGB);
652   vcfg &= ~(RCDF_VCFG_VID_INP_FORMAT | RCDF_VCFG_4_2_0_MODE);
653   switch (format) {
654   case VIDEO_FORMAT_UYVY:
655      vcfg |= RCDF_VCFG_UYVY_FORMAT;
656      ctrl |= RCDF_CSC_VIDEO_YUV_TO_RGB;
657      break;
658   case VIDEO_FORMAT_YUYV:
659      vcfg |= RCDF_VCFG_YUYV_FORMAT;
660      ctrl |= RCDF_CSC_VIDEO_YUV_TO_RGB;
661      break;
662   case VIDEO_FORMAT_Y2YU:
663      vcfg |= RCDF_VCFG_Y2YU_FORMAT;
664      ctrl |= RCDF_CSC_VIDEO_YUV_TO_RGB;
665      break;
666   case VIDEO_FORMAT_YVYU:
667      vcfg |= RCDF_VCFG_YVYU_FORMAT;
668      ctrl |= RCDF_CSC_VIDEO_YUV_TO_RGB;
669      break;
670   case VIDEO_FORMAT_Y0Y1Y2Y3:
671      vcfg |= RCDF_VCFG_UYVY_FORMAT;
672      ctrl |= RCDF_CSC_VIDEO_YUV_TO_RGB;
673      vcfg |= RCDF_VCFG_4_2_0_MODE;
674      break;
675   case VIDEO_FORMAT_Y3Y2Y1Y0:
676      vcfg |= RCDF_VCFG_Y2YU_FORMAT;
677      ctrl |= RCDF_CSC_VIDEO_YUV_TO_RGB;
678      vcfg |= RCDF_VCFG_4_2_0_MODE;
679      break;
680   case VIDEO_FORMAT_Y1Y0Y3Y2:
681      vcfg |= RCDF_VCFG_YUYV_FORMAT;
682      ctrl |= RCDF_CSC_VIDEO_YUV_TO_RGB;
683      vcfg |= RCDF_VCFG_4_2_0_MODE;
684      break;
685   case VIDEO_FORMAT_Y1Y2Y3Y0:
686      vcfg |= RCDF_VCFG_YVYU_FORMAT;
687      ctrl |= RCDF_CSC_VIDEO_YUV_TO_RGB;
688      vcfg |= RCDF_VCFG_4_2_0_MODE;
689      break;
690   case VIDEO_FORMAT_RGB:
691      ctrl |= RCDF_VIDEO_INPUT_IS_RGB;
692      vcfg |= RCDF_VCFG_UYVY_FORMAT;
693      break;
694   case VIDEO_FORMAT_P2M_P2L_P1M_P1L:
695      ctrl |= RCDF_VIDEO_INPUT_IS_RGB;
696      vcfg |= RCDF_VCFG_Y2YU_FORMAT;
697      break;
698   case VIDEO_FORMAT_P1M_P1L_P2M_P2L:
699      ctrl |= RCDF_VIDEO_INPUT_IS_RGB;
700      vcfg |= RCDF_VCFG_YUYV_FORMAT;
701      break;
702   case VIDEO_FORMAT_P1M_P2L_P2M_P1L:
703      ctrl |= RCDF_VIDEO_INPUT_IS_RGB;
704      vcfg |= RCDF_VCFG_YVYU_FORMAT;
705      break;
706   default:
707      return GFX_STATUS_BAD_PARAMETER;
708   }
709   WRITE_VID32(RCDF_VIDEO_CONFIG, vcfg);
710   WRITE_VID32(RCDF_VID_ALPHA_CONTROL, ctrl);
711
712   /* SET THE VIDEO FORMAT IN THE DISPLAY CONTROLLER      */
713   /* Use private routine to abstract display controller. */
714
715   gfx_set_display_video_format(format);
716   return (0);
717}
718
719/*-----------------------------------------------------------------------------
720 * gfx_set_video_size
721 *
722 * This routine specifies the size of the source data.  It is used only
723 * to determine how much data to transfer per frame, and is not used to
724 * calculate the scaling value (that is handled by a separate routine).
725 *-----------------------------------------------------------------------------
726 */
727#if GFX_VIDEO_DYNAMIC
728int
729redcloud_set_video_size(unsigned short width, unsigned short height)
730#else
731int
732gfx_set_video_size(unsigned short width, unsigned short height)
733#endif
734{
735   unsigned long size, vcfg, vid_420, pitch;
736
737   /* SET THE DISPLAY FILTER VIDEO LINE SIZE                            */
738   /* Match the DC hardware alignment requirement.  The line size must  */
739   /* always be 32-byte aligned.  However, we can manage smaller        */
740   /* alignments by decreasing the pitch and clipping the video window. */
741   /* The VG will fetch extra data for each line, but the decreased     */
742   /* pitch will ensure that it always begins fetching at the start of  */
743   /* the video line.                                                   */
744
745   vcfg = READ_VID32(RCDF_VIDEO_CONFIG);
746
747   vid_420 = vcfg & RCDF_VCFG_4_2_0_MODE;
748
749   vcfg &= ~(RCDF_VCFG_LINE_SIZE_LOWER_MASK | RCDF_VCFG_LINE_SIZE_UPPER);
750
751   size = ((width >> 1) + 7) & 0xFFF8;
752   pitch = ((width << 1) + 7) & 0xFFF8;
753
754   vcfg |= (size & 0x00FF) << 8;
755   if (size & 0x0100)
756      vcfg |= RCDF_VCFG_LINE_SIZE_UPPER;
757   WRITE_VID32(RCDF_VIDEO_CONFIG, vcfg);
758
759   /* SET VIDEO BUFFER LINE SIZE IN DISPLAY CONTROLLER */
760   /* Use private routine to abstract the display controller. */
761
762   gfx_set_display_video_size(width, height);
763
764   /* SET VIDEO PITCH */
765   /* We are only maintaining legacy for 4:2:2 video formats. */
766   /* 4:2:0 video in previous chips was inadequate for most   */
767   /* common video formats.                                   */
768
769   if (!vid_420)
770      gfx_set_video_yuv_pitch(pitch, pitch << 1);
771
772   return (0);
773}
774
775/*-----------------------------------------------------------------------------
776 * gfx_set_video_offset
777 *
778 * This routine sets the starting offset for the video buffer when only
779 * one offset needs to be specified.
780 *-----------------------------------------------------------------------------
781 */
782#if GFX_VIDEO_DYNAMIC
783int
784redcloud_set_video_offset(unsigned long offset)
785#else
786int
787gfx_set_video_offset(unsigned long offset)
788#endif
789{
790   /* SAVE VALUE FOR FUTURE CLIPPING OF THE TOP OF THE VIDEO WINDOW */
791
792   gfx_vid_offset = offset;
793
794   /* SET VIDEO BUFFER OFFSET IN DISPLAY CONTROLLER */
795   /* Use private routine to abstract the display controller. */
796
797   gfx_set_display_video_offset(offset);
798   return (0);
799}
800
801/*-----------------------------------------------------------------------------
802 * gfx_set_video_yuv_offsets
803 *
804 * This routine sets the starting offset for the video buffer when displaying
805 * 4:2:0 video.
806 *-----------------------------------------------------------------------------
807 */
808#if GFX_VIDEO_DYNAMIC
809int
810redcloud_set_video_yuv_offsets(unsigned long yoffset, unsigned long uoffset,
811			       unsigned long voffset)
812#else
813int
814gfx_set_video_yuv_offsets(unsigned long yoffset, unsigned long uoffset,
815			  unsigned long voffset)
816#endif
817{
818   /* SAVE VALUE FOR FUTURE CLIPPING OF THE TOP OF THE VIDEO WINDOW */
819
820   gfx_vid_offset = yoffset;
821   gfx_vid_uoffset = uoffset;
822   gfx_vid_voffset = voffset;
823
824   /* SET VIDEO BUFFER OFFSET IN DISPLAY CONTROLLER */
825   /* Use private routine to abstract the display controller. */
826
827   gfx_set_display_video_yuv_offsets(yoffset, uoffset, voffset);
828
829   return (0);
830}
831
832/*-----------------------------------------------------------------------------
833 * gfx_set_video_yuv_pitch
834 *
835 * This routine sets the byte offset between consecutive scanlines of YUV video data
836 *-----------------------------------------------------------------------------
837 */
838#if GFX_VIDEO_DYNAMIC
839int
840redcloud_set_video_yuv_pitch(unsigned long ypitch, unsigned long uvpitch)
841#else
842int
843gfx_set_video_yuv_pitch(unsigned long ypitch, unsigned long uvpitch)
844#endif
845{
846   /* SET VIDEO PITCH IN DISPLAY CONTROLLER */
847   /* Use private routine to abstract the display controller. */
848
849   gfx_set_display_video_yuv_pitch(ypitch, uvpitch);
850
851   return (0);
852}
853
854/*---------------------------------------------------------------------------
855 * gfx_set_video_scale
856 *
857 * This routine sets the scale factor for the video overlay window.  The
858 * size of the source and destination regions are specified in pixels.
859 *---------------------------------------------------------------------------
860 */
861#if GFX_VIDEO_DYNAMIC
862int
863redcloud_set_video_scale(unsigned short srcw, unsigned short srch,
864			 unsigned short dstw, unsigned short dsth)
865#else
866int
867gfx_set_video_scale(unsigned short srcw, unsigned short srch,
868		    unsigned short dstw, unsigned short dsth)
869#endif
870{
871   unsigned long xscale, yscale;
872
873   /* SAVE PARAMETERS (unless don't-care zero destination arguments are used) */
874   /* These are needed for clipping the video window later. */
875
876   if (dstw != 0) {
877      gfx_vid_srcw = srcw;
878      gfx_vid_dstw = dstw;
879   }
880   if (dsth != 0) {
881      gfx_vid_srch = srch;
882      gfx_vid_dsth = dsth;
883   }
884
885   /* CALCULATE DISPLAY FILTER SCALE FACTORS */
886   /* Zero width and height indicate don't care conditions */
887   /* Downscaling is performed in a separate function.     */
888
889   if (dstw == 0)
890      xscale = READ_VID32(RCDF_VIDEO_SCALE) & 0xffff;	/* keep previous if don't-care argument */
891   else if (dstw <= srcw)
892      xscale = 0x2000;			/* horizontal downscaling is currently done in a separate function */
893   else if ((srcw == 1) || (dstw == 1))
894      return GFX_STATUS_BAD_PARAMETER;
895   else
896      xscale = (0x2000l * (srcw - 1l)) / (dstw - 1l);
897
898   if (dsth == 0)
899      yscale = (READ_VID32(RCDF_VIDEO_SCALE) & 0xffff0000) >> 16;	/* keep previous if don't-care argument */
900   else if (dsth <= srch)
901      yscale = 0x2000;			/* vertical downscaling is handled in a separate function */
902   else if ((srch == 1) || (dsth == 1))
903      return GFX_STATUS_BAD_PARAMETER;
904   else
905      yscale = (0x2000l * (srch - 1l)) / (dsth - 1l);
906
907   WRITE_VID32(RCDF_VIDEO_SCALE, (yscale << 16) | xscale);
908
909   /* CALL ROUTINE TO UPDATE WINDOW POSITION */
910   /* This is required because the scale values affect the number of */
911   /* source data pixels that need to be clipped, as well as the     */
912   /* amount of data that needs to be transferred.                   */
913
914   gfx_set_video_window(gfx_vid_xpos, gfx_vid_ypos, gfx_vid_width,
915			gfx_vid_height);
916   return (0);
917}
918
919/*---------------------------------------------------------------------------
920 * gfx_set_video_vertical_downscale
921 *
922 * This routine sets the vertical downscale factor for the video overlay window.
923 * The height of the source and destination regions are specified in pixels.
924 *---------------------------------------------------------------------------
925 */
926#if GFX_VIDEO_DYNAMIC
927int
928redcloud_set_video_vertical_downscale(unsigned short srch,
929				      unsigned short dsth)
930#else
931int
932gfx_set_video_vertical_downscale(unsigned short srch, unsigned short dsth)
933#endif
934{
935   /* SET VIDEO SCALE IN DISPLAY CONTROLLER    */
936   /* Use private routine to abstract hardware */
937
938   gfx_set_display_video_downscale(srch, dsth);
939   return 0;
940}
941
942/*---------------------------------------------------------------------------
943 * gfx_set_video_vertical_downscale_enable
944 *
945 * This routine sets the vertical downscale enable for the video overlay window.
946 *---------------------------------------------------------------------------
947 */
948#if GFX_VIDEO_DYNAMIC
949void
950redcloud_set_video_vertical_downscale_enable(int enable)
951#else
952void
953gfx_set_video_vertical_downscale_enable(int enable)
954#endif
955{
956   /* SET VIDEO SCALE IN DISPLAY CONTROLLER    */
957   /* Use private routine to abstract hardware */
958
959   gfx_set_display_video_vertical_downscale_enable(enable);
960}
961
962/*---------------------------------------------------------------------------
963 * gfx_set_video_downscale_config
964 *
965 * This routine sets the downscale type and factor for the video overlay window.
966 * Note: No downscaling support for RGB565 and YUV420 video formats.
967 *---------------------------------------------------------------------------
968 */
969#if GFX_VIDEO_DYNAMIC
970int
971redcloud_set_video_downscale_config(unsigned short type, unsigned short m)
972#else
973int
974gfx_set_video_downscale_config(unsigned short type, unsigned short m)
975#endif
976{
977   unsigned long downscale;
978
979   if ((m < 1) || (m > 16))
980      return GFX_STATUS_BAD_PARAMETER;
981
982   downscale = READ_VID32(RCDF_VIDEO_DOWNSCALER_CONTROL);
983   downscale &=
984	 ~(RCDF_VIDEO_DOWNSCALE_FACTOR_MASK | RCDF_VIDEO_DOWNSCALE_TYPE_MASK);
985   downscale |= ((unsigned long)(m - 1) << RCDF_VIDEO_DOWNSCALE_FACTOR_POS);
986   switch (type) {
987   case VIDEO_DOWNSCALE_KEEP_1_OF:
988      downscale |= RCDF_VIDEO_DOWNSCALE_TYPE_A;
989      break;
990   case VIDEO_DOWNSCALE_DROP_1_OF:
991      downscale |= RCDF_VIDEO_DOWNSCALE_TYPE_B;
992      break;
993   default:
994      return GFX_STATUS_BAD_PARAMETER;
995   }
996   WRITE_VID32(RCDF_VIDEO_DOWNSCALER_CONTROL, downscale);
997   return (0);
998}
999
1000/*---------------------------------------------------------------------------
1001 * gfx_set_video_downscale_coefficients
1002 *
1003 * This routine sets the downscale filter coefficients.
1004 *---------------------------------------------------------------------------
1005 */
1006#if GFX_VIDEO_DYNAMIC
1007int
1008redcloud_set_video_downscale_coefficients(unsigned short coef1,
1009					  unsigned short coef2,
1010					  unsigned short coef3,
1011					  unsigned short coef4)
1012#else
1013int
1014gfx_set_video_downscale_coefficients(unsigned short coef1,
1015				     unsigned short coef2,
1016				     unsigned short coef3,
1017				     unsigned short coef4)
1018#endif
1019{
1020   if ((coef1 + coef2 + coef3 + coef4) != 16)
1021      return GFX_STATUS_BAD_PARAMETER;
1022
1023   WRITE_VID32(RCDF_VIDEO_DOWNSCALER_COEFFICIENTS,
1024	       ((unsigned long)coef1 << RCDF_VIDEO_DOWNSCALER_COEF1_POS) |
1025	       ((unsigned long)coef2 << RCDF_VIDEO_DOWNSCALER_COEF2_POS) |
1026	       ((unsigned long)coef3 << RCDF_VIDEO_DOWNSCALER_COEF3_POS) |
1027	       ((unsigned long)coef4 << RCDF_VIDEO_DOWNSCALER_COEF4_POS));
1028   return (0);
1029}
1030
1031/*---------------------------------------------------------------------------
1032 * gfx_set_video_downscale_enable
1033 *
1034 * This routine enables or disables downscaling for the video overlay window.
1035 *---------------------------------------------------------------------------
1036 */
1037#if GFX_VIDEO_DYNAMIC
1038int
1039redcloud_set_video_downscale_enable(int enable)
1040#else
1041int
1042gfx_set_video_downscale_enable(int enable)
1043#endif
1044{
1045   unsigned long downscale;
1046
1047   downscale = READ_VID32(RCDF_VIDEO_DOWNSCALER_CONTROL);
1048   if (enable)
1049      downscale |= RCDF_VIDEO_DOWNSCALE_ENABLE;
1050   else
1051      downscale &= ~RCDF_VIDEO_DOWNSCALE_ENABLE;
1052   WRITE_VID32(RCDF_VIDEO_DOWNSCALER_CONTROL, downscale);
1053   return (0);
1054}
1055
1056/*---------------------------------------------------------------------------
1057 * gfx_set_video_window
1058 *
1059 * This routine sets the position and size of the video overlay window.  The
1060 * x and y positions are specified in screen relative coordinates, and may be negative.
1061 * The size of destination region is specified in pixels.  The line size
1062 * indicates the number of bytes of source data per scanline.
1063 *---------------------------------------------------------------------------
1064 */
1065#if GFX_VIDEO_DYNAMIC
1066int
1067redcloud_set_video_window(short x, short y, unsigned short w,
1068			  unsigned short h)
1069#else
1070int
1071gfx_set_video_window(short x, short y, unsigned short w, unsigned short h)
1072#endif
1073{
1074   unsigned long hadjust, vadjust;
1075   unsigned long xstart, ystart, xend, yend;
1076
1077   /* SAVE PARAMETERS */
1078   /* These are needed to call this routine if the scale value changes. */
1079
1080   gfx_vid_xpos = x;
1081   gfx_vid_ypos = y;
1082   gfx_vid_width = w;
1083   gfx_vid_height = h;
1084
1085   /* GET ADJUSTMENT VALUES */
1086   /* Use routines to abstract version of display controller. */
1087
1088   hadjust = gfx_get_htotal() - gfx_get_hsync_end() - 14l;
1089   vadjust = gfx_get_vtotal() - gfx_get_vsync_end() + 1l;
1090
1091   /* HORIZONTAL START */
1092   xstart = (unsigned long)x + hadjust;
1093
1094   /* HORIZONTAL END */
1095   /* End positions in register are non-inclusive (one more than the actual end) */
1096
1097   if ((x + w) < gfx_get_hactive())
1098      xend = (unsigned long)x + (unsigned long)w + hadjust;
1099
1100   /* RIGHT-CLIPPING */
1101   else
1102      xend = (unsigned long)gfx_get_hactive() + hadjust;
1103
1104   /* VERTICAL START */
1105
1106   ystart = (unsigned long)y + vadjust;
1107
1108   /* VERTICAL END */
1109
1110   if ((y + h) < gfx_get_vactive())
1111      yend = (unsigned long)y + (unsigned long)h + vadjust;
1112
1113   /* BOTTOM-CLIPPING */
1114   else
1115      yend = (unsigned long)gfx_get_vactive() + vadjust;
1116
1117   /* SET VIDEO POSITION */
1118
1119   WRITE_VID32(RCDF_VIDEO_X_POS, (xend << 16) | xstart);
1120   WRITE_VID32(RCDF_VIDEO_Y_POS, (yend << 16) | ystart);
1121
1122   return (0);
1123}
1124
1125/*---------------------------------------------------------------------------
1126 * gfx_set_video_left_crop
1127 *
1128 * This routine sets the number of pixels which will be cropped from the
1129 * beginning of each video line. The video window will begin to display only
1130 * from the pixel following the cropped pixels, and the cropped pixels
1131 * will be ignored.
1132 *---------------------------------------------------------------------------
1133 */
1134#if GFX_VIDEO_DYNAMIC
1135int
1136redcloud_set_video_left_crop(unsigned short x)
1137#else
1138int
1139gfx_set_video_left_crop(unsigned short x)
1140#endif
1141{
1142   unsigned long vcfg, initread;
1143
1144   vcfg = READ_VID32(RCDF_VIDEO_CONFIG);
1145
1146   /* CLIPPING ON LEFT */
1147   /* Adjust initial read for scale, checking for divide by zero. Mask the     */
1148   /* lower three bits when clipping 4:2:0 video.  By masking the bits instead */
1149   /* of rounding up we ensure that we always clip less than or equal to the   */
1150   /* desired number of pixels.  This prevents visual artifacts from           */
1151   /* over-clipping.  We mask three bits to meet the HW requirement that 4:2:0 */
1152   /* clipping be 16-byte or 8-pixel aligned.                                  */
1153
1154   if (gfx_vid_dstw) {
1155      initread = (unsigned long)x *gfx_vid_srcw / gfx_vid_dstw;
1156
1157      if (vcfg & RCDF_VCFG_4_2_0_MODE)
1158	 initread &= 0xFFF8;
1159   } else
1160      initread = 0;
1161
1162   /* SET INITIAL READ ADDRESS */
1163
1164   vcfg &= ~RCDF_VCFG_INIT_READ_MASK;
1165   vcfg |= (initread << 15) & RCDF_VCFG_INIT_READ_MASK;
1166   WRITE_VID32(RCDF_VIDEO_CONFIG, vcfg);
1167   return (0);
1168}
1169
1170/*---------------------------------------------------------------------------
1171 * gfx_set_video_color_key
1172 *
1173 * This routine specifies the color key value and mask for the video overlay
1174 * hardware. To disable color key, the color and mask should both be set to
1175 * zero. The hardware uses the color key in the following equation:
1176 *
1177 * ((source data) & (color key mask)) == ((color key) & (color key mask))
1178 *
1179 * If "graphics" is set to TRUE, the source data is graphics, and color key
1180 * is an RGB value. If "graphics" is set to FALSE, the source data is the video,
1181 * and color key is a YUV value.
1182 *---------------------------------------------------------------------------
1183 */
1184#if GFX_VIDEO_DYNAMIC
1185int
1186redcloud_set_video_color_key(unsigned long key, unsigned long mask,
1187			     int graphics)
1188#else
1189int
1190gfx_set_video_color_key(unsigned long key, unsigned long mask, int graphics)
1191#endif
1192{
1193   unsigned long dcfg = 0;
1194
1195   /* SET RCDF COLOR KEY VALUE */
1196
1197   WRITE_VID32(RCDF_VIDEO_COLOR_KEY, key);
1198   WRITE_VID32(RCDF_VIDEO_COLOR_MASK, mask);
1199
1200   /* SELECT GRAPHICS OR VIDEO DATA TO COMPARE TO THE COLOR KEY */
1201
1202   dcfg = READ_VID32(RCDF_DISPLAY_CONFIG);
1203   if (graphics & 0x01)
1204      dcfg &= ~RCDF_DCFG_VG_CK;
1205   else
1206      dcfg |= RCDF_DCFG_VG_CK;
1207   WRITE_VID32(RCDF_DISPLAY_CONFIG, dcfg);
1208   return (0);
1209}
1210
1211/*---------------------------------------------------------------------------
1212 * gfx_set_video_filter
1213 *
1214 * This routine enables or disables the video overlay filters.
1215 *---------------------------------------------------------------------------
1216 */
1217#if GFX_VIDEO_DYNAMIC
1218int
1219redcloud_set_video_filter(int xfilter, int yfilter)
1220#else
1221int
1222gfx_set_video_filter(int xfilter, int yfilter)
1223#endif
1224{
1225   unsigned long vcfg = 0;
1226
1227   /* ENABLE OR DISABLE DISPLAY FILTER VIDEO OVERLAY FILTERS */
1228
1229   vcfg = READ_VID32(RCDF_VIDEO_CONFIG);
1230   vcfg &= ~(RCDF_VCFG_X_FILTER_EN | RCDF_VCFG_Y_FILTER_EN);
1231   if (xfilter)
1232      vcfg |= RCDF_VCFG_X_FILTER_EN;
1233   if (yfilter)
1234      vcfg |= RCDF_VCFG_Y_FILTER_EN;
1235   WRITE_VID32(RCDF_VIDEO_CONFIG, vcfg);
1236   return (0);
1237}
1238
1239/*---------------------------------------------------------------------------
1240 * gfx_set_video_palette
1241 *
1242 * This routine loads the video hardware palette.  If a NULL pointer is
1243 * specified, the palette is bypassed (for Redcloud, this means loading the
1244 * palette with identity values).
1245 *---------------------------------------------------------------------------
1246 */
1247#if GFX_VIDEO_DYNAMIC
1248int
1249redcloud_set_video_palette(unsigned long *palette)
1250#else
1251int
1252gfx_set_video_palette(unsigned long *palette)
1253#endif
1254{
1255   unsigned long i, entry;
1256
1257   /* LOAD REDCLOUD VIDEO PALETTE */
1258
1259   WRITE_VID32(RCDF_PALETTE_ADDRESS, 0);
1260   for (i = 0; i < 256; i++) {
1261      if (palette)
1262	 entry = palette[i];
1263      else
1264	 entry = i | (i << 8) | (i << 16);
1265      WRITE_VID32(RCDF_PALETTE_DATA, entry);
1266   }
1267   return (0);
1268}
1269
1270/*---------------------------------------------------------------------------
1271 * gfx_set_video_palette_entry
1272 *
1273 * This routine loads a single entry of the video hardware palette.
1274 *---------------------------------------------------------------------------
1275 */
1276#if GFX_VIDEO_DYNAMIC
1277int
1278redcloud_set_video_palette_entry(unsigned long index, unsigned long palette)
1279#else
1280int
1281gfx_set_video_palette_entry(unsigned long index, unsigned long palette)
1282#endif
1283{
1284   if (index > 0xFF)
1285      return GFX_STATUS_BAD_PARAMETER;
1286
1287   /* SET A SINGLE ENTRY */
1288
1289   WRITE_VID32(RCDF_PALETTE_ADDRESS, index);
1290   WRITE_VID32(RCDF_PALETTE_DATA, palette);
1291
1292   return (0);
1293}
1294
1295/*---------------------------------------------------------------------------
1296 * gfx_set_video_request()
1297 *
1298 * This routine sets the horizontal (pixel) and vertical (line) video request
1299 * values.
1300 *---------------------------------------------------------------------------
1301 */
1302#if GFX_VIDEO_DYNAMIC
1303int
1304redcloud_set_video_request(short x, short y)
1305#else
1306int
1307gfx_set_video_request(short x, short y)
1308#endif
1309{
1310   /* SET DISPLAY FILTER VIDEO REQUEST */
1311
1312   x += gfx_get_htotal() - gfx_get_hsync_end() - 2;
1313   y += gfx_get_vtotal() - gfx_get_vsync_end() + 1;
1314
1315   if ((x < 0) || (x > RCDF_VIDEO_REQUEST_MASK) ||
1316       (y < 0) || (y > RCDF_VIDEO_REQUEST_MASK))
1317      return GFX_STATUS_BAD_PARAMETER;
1318
1319   WRITE_VID32(RCDF_VIDEO_REQUEST,
1320	       ((unsigned long)x << RCDF_VIDEO_X_REQUEST_POS) |
1321	       ((unsigned long)y << RCDF_VIDEO_Y_REQUEST_POS));
1322   return (0);
1323}
1324
1325/*---------------------------------------------------------------------------
1326 * gfx_set_video_cursor()
1327 *
1328 * This routine configures the video hardware cursor.
1329 * If the "mask"ed bits in the graphics pixel match "key", then either "color1"
1330 * or "color2" will be used for this pixel, according to the value of bit
1331 * number "select_color2" of the graphics pixel.
1332 *
1333 * key - 24 bit RGB value
1334 * mask - 24 bit mask
1335 * color1, color2 - RGB or YUV, depending on the current color space conversion
1336 * select_color2 - value between 0 to 23
1337 *
1338 * To disable match, a "mask" and "key" value of 0xffffff should be set,
1339 * because the graphics pixels incoming to the video processor have maximum 16
1340 * bits set (0xF8FCF8).
1341 *
1342 * This feature is useful for disabling alpha blending of the cursor.
1343 * Otherwise cursor image would be blurred (or completely invisible if video
1344 * alpha is maximum value).
1345 * Note: the cursor pixel replacements take place both inside and outside the
1346 * video overlay window.
1347 *---------------------------------------------------------------------------
1348 */
1349#if GFX_VIDEO_DYNAMIC
1350int
1351redcloud_set_video_cursor(unsigned long key, unsigned long mask,
1352			  unsigned short select_color2, unsigned long color1,
1353			  unsigned long color2)
1354#else
1355int
1356gfx_set_video_cursor(unsigned long key, unsigned long mask,
1357		     unsigned short select_color2, unsigned long color1,
1358		     unsigned long color2)
1359#endif
1360{
1361   if (select_color2 > RCDF_CURSOR_COLOR_BITS)
1362      return GFX_STATUS_BAD_PARAMETER;
1363   key = (key & RCDF_COLOR_MASK) | ((unsigned long)select_color2 <<
1364				    RCDF_CURSOR_COLOR_KEY_OFFSET_POS);
1365   WRITE_VID32(RCDF_CURSOR_COLOR_KEY, key);
1366   WRITE_VID32(RCDF_CURSOR_COLOR_MASK, mask);
1367   WRITE_VID32(RCDF_CURSOR_COLOR_1, color1);
1368   WRITE_VID32(RCDF_CURSOR_COLOR_2, color2);
1369   return (0);
1370}
1371
1372/*---------------------------------------------------------------------------
1373 * gfx_set_video_cursor()
1374 *
1375 * This routine configures the video hardware cursor.
1376 * If the "mask"ed bits in the graphics pixel match "key", then either "color1"
1377 * or "color2" will be used for this pixel, according to the value of bit
1378 * number "select_color2" of the graphics pixel.
1379 *
1380 * key - 24 bit RGB value
1381 * mask - 24 bit mask
1382 * color1, color2 - RGB or YUV, depending on the current color space conversion
1383 * select_color2 - value between 0 to 23
1384 *
1385 * To disable match, a "mask" and "key" value of 0xffffff should be set,
1386 * because the graphics pixels incoming to the video processor have maximum 16
1387 * bits set (0xF8FCF8).
1388 *
1389 * This feature is useful for disabling alpha blending of the cursor.
1390 * Otherwise cursor image would be blurred (or completely invisible if video
1391 * alpha is maximum value).
1392 * Note: the cursor pixel replacements take place both inside and outside the
1393 * video overlay window.
1394 *---------------------------------------------------------------------------
1395 */
1396#if GFX_VIDEO_DYNAMIC
1397int
1398redcloud_set_video_cursor_enable(int enable)
1399#else
1400int
1401gfx_set_video_cursor_enable(int enable)
1402#endif
1403{
1404   unsigned long temp = READ_VID32(RCDF_CURSOR_COLOR_KEY);
1405
1406   if (enable)
1407      temp |= RCDF_CURSOR_COLOR_KEY_ENABLE;
1408   else
1409      temp &= ~RCDF_CURSOR_COLOR_KEY_ENABLE;
1410
1411   WRITE_VID32(RCDF_CURSOR_COLOR_KEY, temp);
1412   return (0);
1413}
1414
1415/*---------------------------------------------------------------------------
1416 * gfx_set_alpha_enable
1417 *
1418 * This routine enables or disables the currently selected alpha region.
1419 *---------------------------------------------------------------------------
1420 */
1421#if GFX_VIDEO_DYNAMIC
1422int
1423redcloud_set_alpha_enable(int enable)
1424#else
1425int
1426gfx_set_alpha_enable(int enable)
1427#endif
1428{
1429   unsigned long address = 0, value = 0;
1430
1431   if (gfx_alpha_select > 2)
1432      return (GFX_STATUS_UNSUPPORTED);
1433   address = RCDF_ALPHA_CONTROL_1 + ((unsigned long)gfx_alpha_select << 5);
1434   value = READ_VID32(address);
1435   if (enable)
1436      value |= RCDF_ACTRL_WIN_ENABLE;
1437   else
1438      value &= ~(RCDF_ACTRL_WIN_ENABLE);
1439   WRITE_VID32(address, value);
1440   return (GFX_STATUS_OK);
1441}
1442
1443/*---------------------------------------------------------------------------
1444 * gfx_set_alpha_window
1445 *
1446 * This routine sets the size of the currently selected alpha region.
1447 * Note: "x" and "y" are signed to enable using negative values needed for
1448 * implementing workarounds of hardware issues.
1449 *---------------------------------------------------------------------------
1450 */
1451#if GFX_VIDEO_DYNAMIC
1452int
1453redcloud_set_alpha_window(short x, short y,
1454			  unsigned short width, unsigned short height)
1455#else
1456int
1457gfx_set_alpha_window(short x, short y,
1458		     unsigned short width, unsigned short height)
1459#endif
1460{
1461   unsigned long address = 0;
1462
1463   /* CHECK FOR CLIPPING */
1464
1465   if ((x + width) > gfx_get_hactive())
1466      width = gfx_get_hactive() - x;
1467   if ((y + height) > gfx_get_vactive())
1468      height = gfx_get_vactive() - y;
1469
1470   /* ADJUST POSITIONS */
1471
1472   x += gfx_get_htotal() - gfx_get_hsync_end() - 2;
1473   y += gfx_get_vtotal() - gfx_get_vsync_end() + 1;
1474
1475   if (gfx_alpha_select > 2)
1476      return (GFX_STATUS_UNSUPPORTED);
1477   address = RCDF_ALPHA_XPOS_1 + ((unsigned long)gfx_alpha_select << 5);
1478
1479   /* END POSITIONS IN REGISTERS ARE NON-INCLUSIVE (ONE MORE THAN ACTUAL END) */
1480
1481   WRITE_VID32(address, (unsigned long)x |
1482	       ((unsigned long)(x + width) << 16));
1483   WRITE_VID32(address + 8, (unsigned long)y |
1484	       ((unsigned long)(y + height) << 16));
1485   return (GFX_STATUS_OK);
1486}
1487
1488/*---------------------------------------------------------------------------
1489 * gfx_set_alpha_value
1490 *
1491 * This routine sets the alpha value for the currently selected alpha
1492 * region.  It also specifies an increment/decrement value for fading.
1493 *---------------------------------------------------------------------------
1494 */
1495#if GFX_VIDEO_DYNAMIC
1496int
1497redcloud_set_alpha_value(unsigned char alpha, char delta)
1498#else
1499int
1500gfx_set_alpha_value(unsigned char alpha, char delta)
1501#endif
1502{
1503   unsigned long address = 0, value = 0;
1504
1505   if (gfx_alpha_select > 2)
1506      return (GFX_STATUS_UNSUPPORTED);
1507   address = RCDF_ALPHA_CONTROL_1 + ((unsigned long)gfx_alpha_select << 5);
1508   value = READ_VID32(address);
1509   value &= RCDF_ACTRL_WIN_ENABLE;	/* keep only enable bit */
1510   value |= (unsigned long)alpha;
1511   value |= (((unsigned long)delta) & 0xff) << 8;
1512   value |= RCDF_ACTRL_LOAD_ALPHA;
1513   WRITE_VID32(address, value);
1514   return (GFX_STATUS_OK);
1515}
1516
1517/*---------------------------------------------------------------------------
1518 * gfx_set_alpha_priority
1519 *
1520 * This routine sets the priority of the currently selected alpha region.
1521 * A higher value indicates a higher priority.
1522 * Note: Priority of enabled alpha windows must be different.
1523 *---------------------------------------------------------------------------
1524 */
1525#if GFX_VIDEO_DYNAMIC
1526int
1527redcloud_set_alpha_priority(int priority)
1528#else
1529int
1530gfx_set_alpha_priority(int priority)
1531#endif
1532{
1533   unsigned long pos = 0, value = 0;
1534
1535   if (priority > 3)
1536      return (GFX_STATUS_BAD_PARAMETER);
1537   if (gfx_alpha_select > 2)
1538      return (GFX_STATUS_UNSUPPORTED);
1539   value = READ_VID32(RCDF_VID_ALPHA_CONTROL);
1540   pos = 16 + (gfx_alpha_select << 1);
1541   value &= ~(0x03l << pos);
1542   value |= (unsigned long)priority << pos;
1543   WRITE_VID32(RCDF_VID_ALPHA_CONTROL, value);
1544   return (GFX_STATUS_OK);
1545}
1546
1547/*---------------------------------------------------------------------------
1548 * gfx_set_alpha_color
1549 *
1550 * This routine sets the color to be displayed inside the currently selected
1551 * alpha window when there is a color key match (when the alpha color
1552 * mechanism is enabled).
1553 * "color" is an RGB value (for RGB blending) or a YUV value (for YUV blending).
1554 * In Interlaced YUV blending mode, Y/2 value should be used.
1555 *---------------------------------------------------------------------------
1556 */
1557#if GFX_VIDEO_DYNAMIC
1558int
1559redcloud_set_alpha_color(unsigned long color)
1560#else
1561int
1562gfx_set_alpha_color(unsigned long color)
1563#endif
1564{
1565   unsigned long address = 0;
1566
1567   if (gfx_alpha_select > 2)
1568      return (GFX_STATUS_UNSUPPORTED);
1569   address = RCDF_ALPHA_COLOR_1 + ((unsigned long)gfx_alpha_select << 5);
1570   WRITE_VID32(address, color);
1571   return (GFX_STATUS_OK);
1572}
1573
1574/*---------------------------------------------------------------------------
1575 * gfx_set_alpha_color_enable
1576 *
1577 * Enable or disable the color mechanism in the alpha window.
1578 *---------------------------------------------------------------------------
1579 */
1580#if GFX_VIDEO_DYNAMIC
1581int
1582redcloud_set_alpha_color_enable(int enable)
1583#else
1584int
1585gfx_set_alpha_color_enable(int enable)
1586#endif
1587{
1588   unsigned long color;
1589   unsigned long address = 0;
1590
1591   if (gfx_alpha_select > 2)
1592      return (GFX_STATUS_UNSUPPORTED);
1593   address = RCDF_ALPHA_COLOR_1 + ((unsigned long)gfx_alpha_select << 5);
1594   color = READ_VID32(address);
1595   if (enable)
1596      color |= RCDF_ALPHA_COLOR_ENABLE;
1597   else
1598      color &= ~RCDF_ALPHA_COLOR_ENABLE;
1599   WRITE_VID32(address, color);
1600   return (GFX_STATUS_OK);
1601}
1602
1603/*---------------------------------------------------------------------------
1604 * gfx_set_no_ck_outside_alpha
1605 *
1606 * This function affects where inside the video window color key or chroma
1607 * key comparison is done:
1608 * If enable is TRUE, color/chroma key comparison is performed only inside
1609 * the enabled alpha windows. Outside the (enabled) alpha windows, only video
1610 * is displayed if color key is used, and only graphics is displayed if chroma
1611 * key is used.
1612 * If enable is FALSE, color/chroma key comparison is performed in all the
1613 * video window area.
1614 *---------------------------------------------------------------------------
1615 */
1616#if GFX_VIDEO_DYNAMIC
1617int
1618redcloud_set_no_ck_outside_alpha(int enable)
1619#else
1620int
1621gfx_set_no_ck_outside_alpha(int enable)
1622#endif
1623{
1624   unsigned long value;
1625
1626   value = READ_VID32(RCDF_VID_ALPHA_CONTROL);
1627   if (enable)
1628      WRITE_VID32(RCDF_VID_ALPHA_CONTROL, value | RCDF_NO_CK_OUTSIDE_ALPHA);
1629   else
1630      WRITE_VID32(RCDF_VID_ALPHA_CONTROL, value & ~RCDF_NO_CK_OUTSIDE_ALPHA);
1631   return (0);
1632}
1633
1634/*---------------------------------------------------------------------------
1635 * gfx_get_clock_frequency
1636 *
1637 * This routine returns the current clock frequency in 16.16 format.
1638 * It reads the current register value and finds the match in the table.
1639 * If no match is found, this routine returns 0.
1640 *---------------------------------------------------------------------------
1641 */
1642#if GFX_VIDEO_DYNAMIC
1643unsigned long
1644redcloud_get_clock_frequency(void)
1645#else
1646unsigned long
1647gfx_get_clock_frequency(void)
1648#endif
1649{
1650   Q_WORD msr_value;
1651   RCDFPLLENTRY *PLLTable;
1652   unsigned int index;
1653   unsigned long value, mask = 0x00001FFF;
1654   unsigned long post_div3 = 0, pre_mult2 = 0;
1655
1656   /* READ PLL SETTING */
1657
1658   gfx_msr_read(RC_ID_MCP, MCP_DOTPLL, &msr_value);
1659   value = msr_value.high & mask;
1660
1661   /* READ DIVISOR SETTINGS */
1662
1663   if ((gfx_cpu_version & 0xFF00) == 0x200) {
1664      PLLTable = RCDF_PLLtable48MHz;
1665
1666      gfx_msr_read(RC_ID_MCP, MCP_SYS_RSTPLL, &msr_value);
1667      post_div3 = (msr_value.low & MCP_DOTPOSTDIV3) ? 1 : 0;
1668      pre_mult2 = (msr_value.low & MCP_DOTPREMULT2) ? 1 : 0;
1669   } else
1670      PLLTable = RCDF_PLLtable14MHz;
1671
1672   /* SEARCH FOR A MATCH */
1673
1674   for (index = 0; index < NUM_RCDF_FREQUENCIES; index++) {
1675      if ((PLLTable[index].pll_value & mask) == value &&
1676	  post_div3 == PLLTable[index].post_div3 &&
1677	  pre_mult2 == PLLTable[index].pre_mul2)
1678	 return (PLLTable[index].frequency);
1679   }
1680   return (0);
1681}
1682
1683/*************************************************************/
1684/*  READ ROUTINES  |  INCLUDED FOR DIAGNOSTIC PURPOSES ONLY  */
1685/*************************************************************/
1686
1687#if GFX_READ_ROUTINES
1688
1689/*---------------------------------------------------------------------------
1690 * gfx_get_sync_polarities
1691 *
1692 * This routine returns the polarities of the sync pulses:
1693 *     Bit 0: Set if negative horizontal polarity.
1694 *     Bit 1: Set if negative vertical polarity.
1695 *---------------------------------------------------------------------------
1696 */
1697#if GFX_VIDEO_DYNAMIC
1698int
1699redcloud_get_sync_polarities(void)
1700#else
1701int
1702gfx_get_sync_polarities(void)
1703#endif
1704{
1705   int polarities = 0;
1706
1707   if (READ_VID32(RCDF_DISPLAY_CONFIG) & RCDF_DCFG_CRT_HSYNC_POL)
1708      polarities |= 1;
1709   if (READ_VID32(RCDF_DISPLAY_CONFIG) & RCDF_DCFG_CRT_VSYNC_POL)
1710      polarities |= 2;
1711   return (polarities);
1712}
1713
1714/*---------------------------------------------------------------------------
1715 * gfx_get_video_palette_entry
1716 *
1717 * This routine returns a single palette entry.
1718 *---------------------------------------------------------------------------
1719 */
1720#if GFX_VIDEO_DYNAMIC
1721int
1722redcloud_get_video_palette_entry(unsigned long index, unsigned long *palette)
1723#else
1724int
1725gfx_get_video_palette_entry(unsigned long index, unsigned long *palette)
1726#endif
1727{
1728   if (index > 0xFF)
1729      return GFX_STATUS_BAD_PARAMETER;
1730
1731   /* READ A SINGLE ENTRY */
1732
1733   WRITE_VID32(RCDF_PALETTE_ADDRESS, index);
1734   *palette = READ_VID32(RCDF_PALETTE_DATA);
1735
1736   return (GFX_STATUS_OK);
1737}
1738
1739/*-----------------------------------------------------------------------------
1740 * gfx_get_video_enable
1741 *
1742 * This routine returns the value "one" if video overlay is currently enabled,
1743 * otherwise it returns the value "zero".
1744 *-----------------------------------------------------------------------------
1745 */
1746#if GFX_VIDEO_DYNAMIC
1747int
1748redcloud_get_video_enable(void)
1749#else
1750int
1751gfx_get_video_enable(void)
1752#endif
1753{
1754   if (READ_VID32(RCDF_VIDEO_CONFIG) & RCDF_VCFG_VID_EN)
1755      return (1);
1756   return (0);
1757}
1758
1759/*-----------------------------------------------------------------------------
1760 * gfx_get_video_format
1761 *
1762 * This routine returns the current video overlay format.
1763 *-----------------------------------------------------------------------------
1764 */
1765#if GFX_VIDEO_DYNAMIC
1766int
1767redcloud_get_video_format(void)
1768#else
1769int
1770gfx_get_video_format(void)
1771#endif
1772{
1773   unsigned long ctrl, vcfg;
1774
1775   ctrl = READ_VID32(RCDF_VID_ALPHA_CONTROL);
1776   vcfg = READ_VID32(RCDF_VIDEO_CONFIG);
1777
1778   if (ctrl & RCDF_VIDEO_INPUT_IS_RGB) {
1779      switch (vcfg & RCDF_VCFG_VID_INP_FORMAT) {
1780      case RCDF_VCFG_UYVY_FORMAT:
1781	 return VIDEO_FORMAT_RGB;
1782      case RCDF_VCFG_Y2YU_FORMAT:
1783	 return VIDEO_FORMAT_P2M_P2L_P1M_P1L;
1784      case RCDF_VCFG_YUYV_FORMAT:
1785	 return VIDEO_FORMAT_P1M_P1L_P2M_P2L;
1786      case RCDF_VCFG_YVYU_FORMAT:
1787	 return VIDEO_FORMAT_P1M_P2L_P2M_P1L;
1788      }
1789   }
1790
1791   if (vcfg & RCDF_VCFG_4_2_0_MODE) {
1792      switch (vcfg & RCDF_VCFG_VID_INP_FORMAT) {
1793      case RCDF_VCFG_UYVY_FORMAT:
1794	 return VIDEO_FORMAT_Y0Y1Y2Y3;
1795      case RCDF_VCFG_Y2YU_FORMAT:
1796	 return VIDEO_FORMAT_Y3Y2Y1Y0;
1797      case RCDF_VCFG_YUYV_FORMAT:
1798	 return VIDEO_FORMAT_Y1Y0Y3Y2;
1799      case RCDF_VCFG_YVYU_FORMAT:
1800	 return VIDEO_FORMAT_Y1Y2Y3Y0;
1801      }
1802   } else {
1803      switch (vcfg & RCDF_VCFG_VID_INP_FORMAT) {
1804      case RCDF_VCFG_UYVY_FORMAT:
1805	 return VIDEO_FORMAT_UYVY;
1806      case RCDF_VCFG_Y2YU_FORMAT:
1807	 return VIDEO_FORMAT_Y2YU;
1808      case RCDF_VCFG_YUYV_FORMAT:
1809	 return VIDEO_FORMAT_YUYV;
1810      case RCDF_VCFG_YVYU_FORMAT:
1811	 return VIDEO_FORMAT_YVYU;
1812      }
1813   }
1814   return (GFX_STATUS_ERROR);
1815}
1816
1817/*-----------------------------------------------------------------------------
1818 * gfx_get_video_src_size
1819 *
1820 * This routine returns the size of the source video overlay buffer.  The
1821 * return value is (height << 16) | width.
1822 *-----------------------------------------------------------------------------
1823 */
1824#if GFX_VIDEO_DYNAMIC
1825unsigned long
1826redcloud_get_video_src_size(void)
1827#else
1828unsigned long
1829gfx_get_video_src_size(void)
1830#endif
1831{
1832   unsigned long width, height, scale, delta;
1833   int down_enable;
1834
1835   /* DETERMINE SOURCE WIDTH FROM THE DISPLAY FILTER VIDEO LINE SIZE */
1836
1837   width = (READ_VID32(RCDF_VIDEO_CONFIG) >> 7) & 0x000001FE;
1838   if (READ_VID32(RCDF_VIDEO_CONFIG) & RCDF_VCFG_LINE_SIZE_UPPER)
1839      width += 512l;
1840
1841   /* DETERMINE SOURCE HEIGHT FROM THE DISPLAY FILTER HEIGHT AND SCALE VALUES     */
1842   /* There is no true "source buffer size" in Redcloud.  Instead, the VG module  */
1843   /* provides video data as needed on a per-line basis.  The source buffer size  */
1844   /* is always assumed to equal the amount of required video data.  The returned */
1845   /* height is equal to the height of the required video buffer data (before all */
1846   /* scaling.)                                                                   */
1847
1848   scale = (READ_VID32(RCDF_VIDEO_SCALE) >> 16) & 0x3FFF;
1849   height = ((READ_VID32(RCDF_VIDEO_Y_POS) >> 16) & 0x7FF) -
1850	 (READ_VID32(RCDF_VIDEO_Y_POS) & 0x7FF);
1851   delta = gfx_get_video_downscale_delta();
1852   down_enable = gfx_get_video_vertical_downscale_enable();
1853
1854   /* REVERSE UPSCALING */
1855
1856   if (height)
1857      height = ((scale * (height - 1l)) / 0x2000l) + 2l;
1858
1859   /* REVERSE DOWNSCALING */
1860   /* Original lines = height * (0x3FFF + delta) / 0x3FFF */
1861   /* As this may cause rounding errors, we add 1 to the  */
1862   /* returned source size.  The return value of this     */
1863   /* function could thus be off by 1.                    */
1864
1865   if (down_enable && height)
1866      height = ((height * (0x3FFFl + delta)) / 0x3FFFl) + 1;
1867
1868   return ((height << 16) | width);
1869}
1870
1871/*-----------------------------------------------------------------------------
1872 * gfx_get_video_line_size
1873 *
1874 * This routine returns the line size of the source video overlay buffer, in
1875 * pixels.
1876 *-----------------------------------------------------------------------------
1877 */
1878#if GFX_VIDEO_DYNAMIC
1879unsigned long
1880redcloud_get_video_line_size(void)
1881#else
1882unsigned long
1883gfx_get_video_line_size(void)
1884#endif
1885{
1886   unsigned long width = 0;
1887
1888   /* DETERMINE SOURCE WIDTH FROM THE RCDF VIDEO LINE SIZE */
1889
1890   width = (READ_VID32(RCDF_VIDEO_CONFIG) >> 7) & 0x000001FE;
1891   if (READ_VID32(RCDF_VIDEO_CONFIG) & RCDF_VCFG_LINE_SIZE_UPPER)
1892      width += 512l;
1893   return (width);
1894}
1895
1896/*-----------------------------------------------------------------------------
1897 * gfx_get_video_xclip
1898 *
1899 * This routine returns the number of bytes clipped on the left side of a
1900 * video overlay line (skipped at beginning).
1901 *-----------------------------------------------------------------------------
1902 */
1903#if GFX_VIDEO_DYNAMIC
1904unsigned long
1905redcloud_get_video_xclip(void)
1906#else
1907unsigned long
1908gfx_get_video_xclip(void)
1909#endif
1910{
1911   unsigned long clip = 0;
1912
1913   /* DETERMINE SOURCE WIDTH FROM THE RCDF VIDEO LINE SIZE */
1914
1915   clip = (READ_VID32(RCDF_VIDEO_CONFIG) >> 14) & 0x000007FC;
1916   return (clip);
1917}
1918
1919/*-----------------------------------------------------------------------------
1920 * gfx_get_video_offset
1921 *
1922 * This routine returns the current offset for the video overlay buffer.
1923 *-----------------------------------------------------------------------------
1924 */
1925#if GFX_VIDEO_DYNAMIC
1926unsigned long
1927redcloud_get_video_offset(void)
1928#else
1929unsigned long
1930gfx_get_video_offset(void)
1931#endif
1932{
1933   return (gfx_get_display_video_offset());
1934}
1935
1936/*-----------------------------------------------------------------------------
1937 * gfx_get_video_yuv_offsets
1938 *
1939 * This routine returns the current offsets for the video overlay buffer when in 4:2:0.
1940 *-----------------------------------------------------------------------------
1941 */
1942#if GFX_VIDEO_DYNAMIC
1943void
1944redcloud_get_video_yuv_offsets(unsigned long *yoffset, unsigned long *uoffset,
1945			       unsigned long *voffset)
1946#else
1947void
1948gfx_get_video_yuv_offsets(unsigned long *yoffset, unsigned long *uoffset,
1949			  unsigned long *voffset)
1950#endif
1951{
1952   gfx_get_display_video_yuv_offsets(yoffset, uoffset, voffset);
1953}
1954
1955/*-----------------------------------------------------------------------------
1956 * gfx_get_video_yuv_pitch
1957 *
1958 * This routine returns the current pitch values for the video overlay buffer.
1959 *-----------------------------------------------------------------------------
1960 */
1961#if GFX_VIDEO_DYNAMIC
1962void
1963redcloud_get_video_yuv_pitch(unsigned long *ypitch, unsigned long *uvpitch)
1964#else
1965void
1966gfx_get_video_yuv_pitch(unsigned long *ypitch, unsigned long *uvpitch)
1967#endif
1968{
1969   gfx_get_display_video_yuv_pitch(ypitch, uvpitch);
1970}
1971
1972/*---------------------------------------------------------------------------
1973 * gfx_get_video_scale
1974 *
1975 * This routine returns the scale factor for the video overlay window.
1976 *---------------------------------------------------------------------------
1977 */
1978#if GFX_VIDEO_DYNAMIC
1979unsigned long
1980redcloud_get_video_scale(void)
1981#else
1982unsigned long
1983gfx_get_video_scale(void)
1984#endif
1985{
1986   return (READ_VID32(RCDF_VIDEO_SCALE));
1987}
1988
1989/*---------------------------------------------------------------------------
1990 * gfx_get_video_downscale_delta
1991 *
1992 * This routine returns the vertical downscale factor for the video overlay window.
1993 *---------------------------------------------------------------------------
1994 */
1995#if GFX_VIDEO_DYNAMIC
1996unsigned long
1997redcloud_get_video_downscale_delta(void)
1998#else
1999unsigned long
2000gfx_get_video_downscale_delta(void)
2001#endif
2002{
2003   /* USE PRIVATE ROUTINE TO ABSTRACT THE DIPSLAY CONTROLLER */
2004
2005   return (gfx_get_display_video_downscale_delta());
2006}
2007
2008/*---------------------------------------------------------------------------
2009 * gfx_get_video_vertical_downscale_enable
2010 *
2011 * This routine returns the vertical downscale enable for the video overlay window.
2012 *---------------------------------------------------------------------------
2013 */
2014#if GFX_VIDEO_DYNAMIC
2015int
2016redcloud_get_video_vertical_downscale_enable(void)
2017#else
2018int
2019gfx_get_video_vertical_downscale_enable(void)
2020#endif
2021{
2022   /* USE PRIVATE ROUTINE TO ABSTRACT THE DIPSLAY CONTROLLER */
2023
2024   return (gfx_get_display_video_downscale_enable());
2025}
2026
2027/*---------------------------------------------------------------------------
2028 * gfx_get_video_downscale_config
2029 *
2030 * This routine returns the current type and value of video downscaling.
2031 *---------------------------------------------------------------------------
2032 */
2033#if GFX_VIDEO_DYNAMIC
2034int
2035redcloud_get_video_downscale_config(unsigned short *type, unsigned short *m)
2036#else
2037int
2038gfx_get_video_downscale_config(unsigned short *type, unsigned short *m)
2039#endif
2040{
2041   unsigned long downscale;
2042
2043   downscale = READ_VID32(RCDF_VIDEO_DOWNSCALER_CONTROL);
2044   *m = (unsigned short)((downscale & RCDF_VIDEO_DOWNSCALE_FACTOR_MASK) >>
2045			 RCDF_VIDEO_DOWNSCALE_FACTOR_POS) + 1;
2046
2047   switch (downscale & RCDF_VIDEO_DOWNSCALE_TYPE_MASK) {
2048   case RCDF_VIDEO_DOWNSCALE_TYPE_A:
2049      *type = VIDEO_DOWNSCALE_KEEP_1_OF;
2050      break;
2051   case RCDF_VIDEO_DOWNSCALE_TYPE_B:
2052      *type = VIDEO_DOWNSCALE_DROP_1_OF;
2053      break;
2054   default:
2055      return GFX_STATUS_ERROR;
2056      break;
2057   }
2058   return (0);
2059}
2060
2061/*---------------------------------------------------------------------------
2062 * gfx_get_video_downscale_coefficients
2063 *
2064 * This routine returns the current video downscaling coefficients.
2065 *---------------------------------------------------------------------------
2066 */
2067#if GFX_VIDEO_DYNAMIC
2068void
2069redcloud_get_video_downscale_coefficients(unsigned short *coef1,
2070					  unsigned short *coef2,
2071					  unsigned short *coef3,
2072					  unsigned short *coef4)
2073#else
2074void
2075gfx_get_video_downscale_coefficients(unsigned short *coef1,
2076				     unsigned short *coef2,
2077				     unsigned short *coef3,
2078				     unsigned short *coef4)
2079#endif
2080{
2081   unsigned long coef;
2082
2083   coef = READ_VID32(RCDF_VIDEO_DOWNSCALER_COEFFICIENTS);
2084   *coef1 =
2085	 (unsigned short)((coef >> RCDF_VIDEO_DOWNSCALER_COEF1_POS) &
2086			  RCDF_VIDEO_DOWNSCALER_COEF_MASK);
2087   *coef2 =
2088	 (unsigned short)((coef >> RCDF_VIDEO_DOWNSCALER_COEF2_POS) &
2089			  RCDF_VIDEO_DOWNSCALER_COEF_MASK);
2090   *coef3 =
2091	 (unsigned short)((coef >> RCDF_VIDEO_DOWNSCALER_COEF3_POS) &
2092			  RCDF_VIDEO_DOWNSCALER_COEF_MASK);
2093   *coef4 =
2094	 (unsigned short)((coef >> RCDF_VIDEO_DOWNSCALER_COEF4_POS) &
2095			  RCDF_VIDEO_DOWNSCALER_COEF_MASK);
2096   return;
2097}
2098
2099/*---------------------------------------------------------------------------
2100 * gfx_get_video_downscale_enable
2101 *
2102 * This routine returns 1 if video downscaling is currently enabled,
2103 * or 0 if it is currently disabled.
2104 *---------------------------------------------------------------------------
2105 */
2106#if GFX_VIDEO_DYNAMIC
2107void
2108redcloud_get_video_downscale_enable(int *enable)
2109#else
2110void
2111gfx_get_video_downscale_enable(int *enable)
2112#endif
2113{
2114   if (READ_VID32(RCDF_VIDEO_DOWNSCALER_CONTROL) &
2115       RCDF_VIDEO_DOWNSCALE_ENABLE)
2116      *enable = 1;
2117   else
2118      *enable = 0;
2119   return;
2120}
2121
2122/*---------------------------------------------------------------------------
2123 * gfx_get_video_dst_size
2124 *
2125 * This routine returns the size of the displayed video overlay window.
2126 *---------------------------------------------------------------------------
2127 */
2128#if GFX_VIDEO_DYNAMIC
2129unsigned long
2130redcloud_get_video_dst_size(void)
2131#else
2132unsigned long
2133gfx_get_video_dst_size(void)
2134#endif
2135{
2136   unsigned long xsize, ysize;
2137
2138   xsize = READ_VID32(RCDF_VIDEO_X_POS);
2139   xsize = ((xsize >> 16) & 0x7FF) - (xsize & 0x7FF);
2140   ysize = READ_VID32(RCDF_VIDEO_Y_POS);
2141   ysize = ((ysize >> 16) & 0x7FF) - (ysize & 0x7FF);
2142   return ((ysize << 16) | xsize);
2143}
2144
2145/*---------------------------------------------------------------------------
2146 * gfx_get_video_position
2147 *
2148 * This routine returns the position of the video overlay window.  The
2149 * return value is (ypos << 16) | xpos.
2150 *---------------------------------------------------------------------------
2151 */
2152#if GFX_VIDEO_DYNAMIC
2153unsigned long
2154redcloud_get_video_position(void)
2155#else
2156unsigned long
2157gfx_get_video_position(void)
2158#endif
2159{
2160   unsigned long hadjust, vadjust;
2161   unsigned long xpos, ypos;
2162
2163   /* READ HARDWARE POSITION */
2164
2165   xpos = READ_VID32(RCDF_VIDEO_X_POS) & 0x000007FF;
2166   ypos = READ_VID32(RCDF_VIDEO_Y_POS) & 0x000007FF;
2167
2168   /* GET ADJUSTMENT VALUES */
2169   /* Use routines to abstract version of display controller. */
2170
2171   hadjust =
2172	 (unsigned long)gfx_get_htotal() -
2173	 (unsigned long)gfx_get_hsync_end() - 14l;
2174   vadjust =
2175	 (unsigned long)gfx_get_vtotal() -
2176	 (unsigned long)gfx_get_vsync_end() + 1l;
2177   xpos -= hadjust;
2178   ypos -= vadjust;
2179   return ((ypos << 16) | (xpos & 0x0000FFFF));
2180}
2181
2182/*---------------------------------------------------------------------------
2183 * gfx_get_video_color_key
2184 *
2185 * This routine returns the current video color key value.
2186 *---------------------------------------------------------------------------
2187 */
2188#if GFX_VIDEO_DYNAMIC
2189unsigned long
2190redcloud_get_video_color_key(void)
2191#else
2192unsigned long
2193gfx_get_video_color_key(void)
2194#endif
2195{
2196   return (READ_VID32(RCDF_VIDEO_COLOR_KEY));
2197}
2198
2199/*---------------------------------------------------------------------------
2200 * gfx_get_video_color_key_mask
2201 *
2202 * This routine returns the current video color mask value.
2203 *---------------------------------------------------------------------------
2204 */
2205#if GFX_VIDEO_DYNAMIC
2206unsigned long
2207redcloud_get_video_color_key_mask(void)
2208#else
2209unsigned long
2210gfx_get_video_color_key_mask(void)
2211#endif
2212{
2213   return (READ_VID32(RCDF_VIDEO_COLOR_MASK));
2214}
2215
2216/*---------------------------------------------------------------------------
2217 * gfx_get_video_color_key_src
2218 *
2219 * This routine returns 0 for video data compare, 1 for graphics data.
2220 *---------------------------------------------------------------------------
2221 */
2222#if GFX_VIDEO_DYNAMIC
2223int
2224redcloud_get_video_color_key_src(void)
2225#else
2226int
2227gfx_get_video_color_key_src(void)
2228#endif
2229{
2230   if (READ_VID32(RCDF_DISPLAY_CONFIG) & RCDF_DCFG_VG_CK)
2231      return (0);
2232   return (1);
2233}
2234
2235/*---------------------------------------------------------------------------
2236 * gfx_get_video_filter
2237 *
2238 * This routine returns if the filters are currently enabled.
2239 *---------------------------------------------------------------------------
2240 */
2241#if GFX_VIDEO_DYNAMIC
2242int
2243redcloud_get_video_filter(void)
2244#else
2245int
2246gfx_get_video_filter(void)
2247#endif
2248{
2249   int retval = 0;
2250
2251   if (READ_VID32(RCDF_VIDEO_CONFIG) & RCDF_VCFG_X_FILTER_EN)
2252      retval |= 1;
2253   if (READ_VID32(RCDF_VIDEO_CONFIG) & RCDF_VCFG_Y_FILTER_EN)
2254      retval |= 2;
2255   return (retval);
2256}
2257
2258/*---------------------------------------------------------------------------
2259 * gfx_get_video_request
2260 *
2261 * This routine returns the horizontal (pixel) and vertical (lines) video
2262 * request values.
2263 *---------------------------------------------------------------------------
2264 */
2265#if GFX_VIDEO_DYNAMIC
2266int
2267redcloud_get_video_request(short *x, short *y)
2268#else
2269int
2270gfx_get_video_request(short *x, short *y)
2271#endif
2272{
2273   unsigned long request = 0;
2274
2275   request = (READ_VID32(RCDF_VIDEO_REQUEST));
2276   *x = (short)((request >> RCDF_VIDEO_X_REQUEST_POS) &
2277		RCDF_VIDEO_REQUEST_MASK);
2278   *y = (short)((request >> RCDF_VIDEO_Y_REQUEST_POS) &
2279		RCDF_VIDEO_REQUEST_MASK);
2280
2281   *x -= gfx_get_htotal() - gfx_get_hsync_end() - 2;
2282   *y -= gfx_get_vtotal() - gfx_get_vsync_end() + 1;
2283
2284   return (0);
2285}
2286
2287/*---------------------------------------------------------------------------
2288 * gfx_get_video_cursor()
2289 *
2290 * This routine configures the video hardware cursor.
2291 * If the "mask"ed bits in the graphics pixel match "key", then either "color1"
2292 * or "color2" will be used for this pixel, according to the value of the bit
2293 * in offset "select_color2".
2294 *---------------------------------------------------------------------------
2295 */
2296#if GFX_VIDEO_DYNAMIC
2297int
2298redcloud_get_video_cursor(unsigned long *key, unsigned long *mask,
2299			  unsigned short *select_color2,
2300			  unsigned long *color1, unsigned short *color2)
2301#else
2302int
2303gfx_get_video_cursor(unsigned long *key, unsigned long *mask,
2304		     unsigned short *select_color2, unsigned long *color1,
2305		     unsigned short *color2)
2306#endif
2307{
2308   *select_color2 =
2309	 (unsigned short)(READ_VID32(RCDF_CURSOR_COLOR_KEY) >>
2310			  RCDF_CURSOR_COLOR_KEY_OFFSET_POS);
2311   *key = READ_VID32(RCDF_CURSOR_COLOR_KEY) & RCDF_COLOR_MASK;
2312   *mask = READ_VID32(RCDF_CURSOR_COLOR_MASK) & RCDF_COLOR_MASK;
2313   *color1 = READ_VID32(RCDF_CURSOR_COLOR_1) & RCDF_COLOR_MASK;
2314   *color2 =
2315	 (unsigned short)(READ_VID32(RCDF_CURSOR_COLOR_2) & RCDF_COLOR_MASK);
2316   return (0);
2317}
2318
2319/*---------------------------------------------------------------------------
2320 * gfx_read_crc
2321 *
2322 * This routine returns the hardware CRC value, which is used for automated
2323 * testing.  The value is like a checksum, but will change if pixels move
2324 * locations.
2325 *---------------------------------------------------------------------------
2326 */
2327#if GFX_VIDEO_DYNAMIC
2328unsigned long
2329redcloud_read_crc(void)
2330#else
2331unsigned long
2332gfx_read_crc(void)
2333#endif
2334{
2335   Q_WORD msr_value;
2336   unsigned long crc = 0xFFFFFFFF;
2337
2338   /* DISABLE 32-BIT CRCS */
2339   /* For GX1.x, this is a reserved bit, and is assumed to be a benign access */
2340
2341   gfx_msr_read(RC_ID_DF, RCDF_MBD_MSR_DIAG_DF, &msr_value);
2342   msr_value.low &= ~RCDF_DIAG_32BIT_CRC;
2343   gfx_msr_write(RC_ID_DF, RCDF_MBD_MSR_DIAG_DF, &msr_value);
2344
2345   if (gfx_test_timing_active()) {
2346      /* WAIT UNTIL ACTIVE DISPLAY */
2347
2348      while (!gfx_test_vertical_active()) ;
2349
2350      /* RESET CRC DURING ACTIVE DISPLAY */
2351
2352      WRITE_VID32(RCDF_VID_CRC, 0);
2353      WRITE_VID32(RCDF_VID_CRC, 1);
2354
2355      /* WAIT UNTIL NOT ACTIVE, THEN ACTIVE, NOT ACTIVE, THEN ACTIVE */
2356
2357      while (!gfx_test_vertical_active()) ;
2358      while (gfx_test_vertical_active()) ;
2359      while (!gfx_test_vertical_active()) ;
2360      while (gfx_test_vertical_active()) ;
2361      while (!gfx_test_vertical_active()) ;
2362      crc = READ_VID32(RCDF_VID_CRC) >> 8;
2363   }
2364   return (crc);
2365}
2366
2367/*---------------------------------------------------------------------------
2368 * gfx_read_crc32
2369 *
2370 * This routine returns the 32-bit hardware CRC value, which is used for automated
2371 * testing.  The value is like a checksum, but will change if pixels move
2372 * locations.
2373 *---------------------------------------------------------------------------
2374 */
2375#if GFX_VIDEO_DYNAMIC
2376unsigned long
2377redcloud_read_crc32(void)
2378#else
2379unsigned long
2380gfx_read_crc32(void)
2381#endif
2382{
2383   Q_WORD msr_value;
2384   unsigned long crc = 0xFFFFFFFF;
2385
2386   /* ENABLE 32-BIT CRCS */
2387   /* For GX1.x, this is a reserved bit, and is assumed to be a benign access */
2388
2389   gfx_msr_read(RC_ID_DF, RCDF_MBD_MSR_DIAG_DF, &msr_value);
2390   msr_value.low |= RCDF_DIAG_32BIT_CRC;
2391   gfx_msr_write(RC_ID_DF, RCDF_MBD_MSR_DIAG_DF, &msr_value);
2392
2393   if (gfx_test_timing_active()) {
2394      /* WAIT UNTIL ACTIVE DISPLAY */
2395
2396      while (!gfx_test_vertical_active()) ;
2397
2398      /* RESET CRC DURING ACTIVE DISPLAY */
2399
2400      WRITE_VID32(RCDF_VID_CRC, 0);
2401      WRITE_VID32(RCDF_VID_CRC, 1);
2402
2403      /* WAIT UNTIL NOT ACTIVE, THEN ACTIVE, NOT ACTIVE, THEN ACTIVE */
2404
2405      while (!gfx_test_vertical_active()) ;
2406      while (gfx_test_vertical_active()) ;
2407      while (!gfx_test_vertical_active()) ;
2408      while (gfx_test_vertical_active()) ;
2409      while (!gfx_test_vertical_active()) ;
2410      crc = READ_VID32(RCDF_VID_CRC32);
2411   }
2412   return (crc);
2413}
2414
2415/*---------------------------------------------------------------------------
2416 * gfx_read_window_crc
2417 *
2418 * This routine returns the hardware CRC value for a subsection of the display.
2419 * This value is used to debug whole-screen CRC failures.
2420 *---------------------------------------------------------------------------
2421 */
2422#if GFX_VIDEO_DYNAMIC
2423unsigned long
2424redcloud_read_window_crc(int source, unsigned short x, unsigned short y,
2425			 unsigned short width, unsigned short height,
2426			 int crc32)
2427#else
2428unsigned long
2429gfx_read_window_crc(int source, unsigned short x, unsigned short y,
2430		    unsigned short width, unsigned short height, int crc32)
2431#endif
2432{
2433   Q_WORD msr_value;
2434   unsigned long xpos, ypos, crc = 0;
2435   unsigned long old_fmt = 0;
2436   unsigned int vsync_active_base, vsync_inactive_base, hsync_active_base;
2437   unsigned int vsync_active_shift, vsync_inactive_shift, hsync_active_shift;
2438   unsigned int vsync_bit, hsync_bit, sync_polarities = 0;
2439
2440   /* CONFIGURE DISPLAY FILTER TO LOAD DATA ONTO LOWER 32-BITS */
2441
2442   msr_value.high = 0;
2443   msr_value.low =
2444	 (source == CRC_SOURCE_GFX_DATA) ? (RCDF_MBD_DIAG_EN0 | 0x0000000F)
2445	 : (RCDF_MBD_DIAG_EN0 | 0x0000000B);
2446   gfx_msr_write(RC_ID_DF, MBD_MSR_DIAG, &msr_value);
2447
2448   /* CONFIGURE DISPLAY FILTER FOR APPROPRIATE OUTPUT */
2449
2450   if (source != CRC_SOURCE_GFX_DATA) {
2451      gfx_msr_read(RC_ID_DF, MBD_MSR_CONFIG, &msr_value);
2452      old_fmt = msr_value.low;
2453      msr_value.low &= ~(RCDF_CONFIG_FMT_MASK);
2454      msr_value.low |= ((source == CRC_SOURCE_FP_DATA) ? RCDF_CONFIG_FMT_FP :
2455			RCDF_CONFIG_FMT_CRT);
2456      gfx_msr_write(RC_ID_DF, MBD_MSR_CONFIG, &msr_value);
2457   }
2458
2459   /* CONFIGURE MCP TO LOAD REGB DATA ONTO UPPER 32-BITS */
2460
2461   msr_value.low = MCP_MBD_DIAG_EN1 | 0x00050000;
2462   gfx_msr_write(RC_ID_MCP, MBD_MSR_DIAG, &msr_value);
2463
2464   /* ENABLE HW CLOCK GATING AND SET MCP CLOCK TO DOT CLOCK */
2465
2466   msr_value.low = 1l;
2467   gfx_msr_write(RC_ID_MCP, MBD_MSR_PM, &msr_value);
2468   msr_value.low = 0;
2469   gfx_msr_write(RC_ID_MCP, MCP_DBGCLKCTL, &msr_value);
2470   msr_value.low = 3;
2471   gfx_msr_write(RC_ID_MCP, MCP_DBGCLKCTL, &msr_value);
2472
2473   /* DISABLE MCP ACTIONS */
2474
2475   msr_value.high = 0x00000000;
2476   msr_value.low = 0x00000000;
2477   gfx_msr_write(RC_ID_MCP, MCP_DIAGCTL, &msr_value);
2478
2479   /* SET APPROPRIATE BASE ADDRESS */
2480   /* M-Sets use normal diag bits, while N-Sets use inverted diag bits */
2481   /* We thus use the M-sets when polling for a high signal and the N  */
2482   /* sets when polling for a low signal.                              */
2483
2484   if (source != CRC_SOURCE_GFX_DATA) {
2485      sync_polarities = gfx_get_sync_polarities();
2486      vsync_bit = 29;
2487      hsync_bit = 30;
2488   } else {
2489      vsync_bit = 25;
2490      hsync_bit = 26;
2491   }
2492
2493   if (sync_polarities & 1) {
2494      hsync_active_base = MCP_SETM0CTL;
2495      hsync_active_shift = 2;
2496   } else {
2497      hsync_active_base = MCP_SETN0CTL;
2498      hsync_active_shift = 1;
2499   }
2500   if (sync_polarities & 2) {
2501      vsync_active_base = MCP_SETM0CTL;
2502      vsync_inactive_base = MCP_SETN0CTL;
2503      vsync_active_shift = 2;
2504      vsync_inactive_shift = 1;
2505   } else {
2506      vsync_active_base = MCP_SETN0CTL;
2507      vsync_inactive_base = MCP_SETM0CTL;
2508      vsync_active_shift = 1;
2509      vsync_inactive_shift = 2;
2510   }
2511
2512   /* SET STATE TRANSITIONS          */
2513
2514   /* STATE 0-1 TRANSITION (SET 0)      */
2515   /* XState = 00 and VSync Inactive    */
2516   /* Note: DF VSync = Diag Bus Bit 29  */
2517   /*       VG VSync = Diag Bus Bit 25  */
2518
2519   msr_value.low = 0x000000A0;
2520   msr_value.high = 0x00008000 | ((unsigned long)vsync_bit << 16) |
2521	 ((unsigned long)vsync_bit << 21) | ((unsigned long)vsync_bit << 26);
2522   gfx_msr_write(RC_ID_MCP, vsync_inactive_base, &msr_value);
2523
2524   /* STATE 1-2 TRANSITION (SET 4)   */
2525   /* XState = 01 and VSync Active   */
2526
2527   msr_value.low = 0x000000C0;
2528   gfx_msr_write(RC_ID_MCP, vsync_active_base + 4, &msr_value);
2529
2530   /* STATE 2-3 TRANSITION (SET 1)   */
2531   /* XState = 10 and VSync Inactive */
2532
2533   msr_value.low = 0x00000120;
2534   gfx_msr_write(RC_ID_MCP, vsync_inactive_base + 1, &msr_value);
2535
2536   /* HORIZONTAL COUNTER (SET 5)         */
2537   /* XState = 10 and HSync Active       */
2538   /* Notes: DF HSync = Diag Bus Bit 30  */
2539   /*        VG HSync = Diag Bus Bit 26  */
2540
2541   msr_value.high = 0x00008000 | ((unsigned long)hsync_bit << 16) |
2542	 ((unsigned long)hsync_bit << 21) | ((unsigned long)hsync_bit << 26);
2543   msr_value.low = 0x00000120;
2544   gfx_msr_write(RC_ID_MCP, hsync_active_base + 5, &msr_value);
2545
2546   /* HORIZONTAL COUNTER RESET (SET 4)     */
2547   /* XState = 10 and H. Counter = limit   */
2548   /* Note: H. Counter is lower 16-bits of */
2549   /*       RegB.                          */
2550
2551   msr_value.high = 0x00000000;
2552   msr_value.low = 0x00000128;
2553   gfx_msr_write(RC_ID_MCP, vsync_inactive_base + 4, &msr_value);
2554
2555   /* CRC TRIGGER (SET 0)   */
2556   /* Cmp0 <= xpos <  Cmp1  */
2557   /* Cmp2 <= ypos <  Cmp2  */
2558
2559   msr_value.high = 0x00000000;
2560   msr_value.low = 0x10C20120;
2561   gfx_msr_write(RC_ID_MCP, vsync_active_base, &msr_value);
2562
2563   /* SET COMPARATOR VALUES */
2564   /* Note: The VG data outputs from the DF are delayed by one pixel clock. */
2565   /*       In this mode, we thus add one to horizontal comparator limits.  */
2566
2567   /* COMPARATOR 0                                        */
2568   /* Lower limit = xpos + (h_blank_pixels - 1) - 3       */
2569   /* Notes:                                              */
2570   /*   1. 3 is the pipeline delay for MCP register       */
2571   /*      data to access the diag bus                    */
2572   /*   2. h_blank_pixels = HTOTAL - HSYNC_END            */
2573
2574   xpos = (unsigned long)x + ((unsigned long)gfx_get_htotal() -
2575			      (unsigned long)gfx_get_hsync_end() - 1l) - 3l;
2576   if (source == CRC_SOURCE_GFX_DATA)
2577      xpos++;
2578   msr_value.high = 0x00000000;
2579   msr_value.low = xpos;
2580   gfx_msr_write(RC_ID_MCP, MCP_CMPVAL0, &msr_value);
2581
2582   /* COMPARATOR 1                                          */
2583   /* Upper limit = xpos + width + (h_blank_pixels - 1) - 3 */
2584
2585   msr_value.low = xpos + (unsigned long)width;
2586   gfx_msr_write(RC_ID_MCP, MCP_CMPVAL0 + 2, &msr_value);
2587
2588   /* COMPARATOR 2                                  */
2589   /* Lower limit = ypos + v_blank_pixels           */
2590   /* Notes:                                        */
2591   /*   1. v_blank_pixels = VTOTAL - VSYNC_END      */
2592
2593   ypos = (unsigned long)y + (unsigned long)gfx_get_vtotal() -
2594	 (unsigned long)gfx_get_vsync_end();
2595   msr_value.low = ypos << 16;
2596   gfx_msr_write(RC_ID_MCP, MCP_CMPVAL0 + 4, &msr_value);
2597
2598   /* COMPARATOR 3                                  */
2599   /* Upper limit = ypos + height + v_blank_pixels  */
2600
2601   msr_value.low = (ypos + (unsigned long)height) << 16;
2602   gfx_msr_write(RC_ID_MCP, MCP_CMPVAL0 + 6, &msr_value);
2603
2604   /* SET COMPARATOR MASKS */
2605
2606   /* COMPARATORS 0 AND 1 REFER TO LOWER 16 BITS OF REGB */
2607
2608   msr_value.high = 0x00000000;
2609   msr_value.low = 0x0000FFFF;
2610   gfx_msr_write(RC_ID_MCP, MCP_CMPMASK0, &msr_value);
2611   gfx_msr_write(RC_ID_MCP, MCP_CMPMASK0 + 2, &msr_value);
2612
2613   /* COMPARATORS 2 AND 3 REFER TO UPPER 16 BITS OF REGB */
2614
2615   msr_value.low = 0xFFFF0000;
2616   gfx_msr_write(RC_ID_MCP, MCP_CMPMASK0 + 4, &msr_value);
2617   gfx_msr_write(RC_ID_MCP, MCP_CMPMASK0 + 6, &msr_value);
2618
2619   /* SET REGA MASK TO CRC ONLY 24 BITS OF DATA */
2620
2621   msr_value.high = 0x00000000;
2622   msr_value.low = 0x00FFFFFF;
2623   gfx_msr_write(RC_ID_MCP, MCP_REGAMASK, &msr_value);
2624
2625   /* SET REGB VALUE */
2626   /* Lower 16 bits use HTOTAL - SYNC TIME - 1 to set the counter rollover limit. */
2627   /* Upper 16 bits use 0xFFFF to remove auto-clear behavior.     */
2628
2629   msr_value.high = 0x00000000;
2630   msr_value.low = 0xFFFF0000 |
2631	 ((gfx_get_htotal() - (gfx_get_hsync_end() - gfx_get_hsync_start()) -
2632	   1) & 0xFFFF);
2633   gfx_msr_write(RC_ID_MCP, MCP_REGBVAL, &msr_value);
2634
2635   /* PROGRAM ACTIONS */
2636
2637   /* GOTO STATE 01 */
2638
2639   msr_value.high = 0x00000000;
2640   msr_value.low = 0x00000008 | (1l << vsync_inactive_shift);
2641   gfx_msr_write(RC_ID_MCP, MCP_ACTION0 + 14, &msr_value);
2642
2643   /* GOTO STATE 10 */
2644
2645   msr_value.low = 0x00080000 | (1l << (vsync_active_shift + 16));
2646   gfx_msr_write(RC_ID_MCP, MCP_ACTION0 + 15, &msr_value);
2647
2648   /* GOTO STATE 11 */
2649
2650   msr_value.low = 0x00000080 | (1l << (vsync_inactive_shift + 4));
2651   gfx_msr_write(RC_ID_MCP, MCP_ACTION0 + 16, &msr_value);
2652
2653   /* CLEAR REGB (COUNTERS)  */
2654   /* RegB is cleared upon transitioning to state 10              */
2655   /* RegA is not cleared as the initial value must be 0x00000001 */
2656
2657   msr_value.low = 0x00080000 | (1l << (vsync_active_shift + 16));
2658   gfx_msr_write(RC_ID_MCP, MCP_ACTION0, &msr_value);
2659
2660   /* CRC INTO REGA        */
2661   /* INCREMENT H. COUNTER */
2662   /* cmp0 <= xpos < cmp1  */
2663   /* cmp2 <= ypos < cmp3  */
2664   /* XState = 10          */
2665
2666   msr_value.low = 0x00000008 | (1l << vsync_active_shift) |
2667	 0x00800000 | (1l << (hsync_active_shift + 20));
2668   gfx_msr_write(RC_ID_MCP, MCP_ACTION0 + 1, &msr_value);
2669
2670   /* INCREMENT V. COUNTER */
2671   /* V. Counter is incremented when the H. Counter */
2672   /* rolls over.                                   */
2673
2674   msr_value.low = 0x00080000 | (1l << (vsync_inactive_shift + 16));
2675   gfx_msr_write(RC_ID_MCP, MCP_ACTION0 + 2, &msr_value);
2676
2677   /* CLEAR ALL OTHER ACTIONS */
2678   /* This prevents side-effects from previous accesses to the MCP */
2679   /* debug logic.                                                 */
2680   msr_value.low = 0x00000000;
2681   msr_value.high = 0x00000000;
2682   gfx_msr_write(RC_ID_MCP, MCP_ACTION0 + 3, &msr_value);
2683   gfx_msr_write(RC_ID_MCP, MCP_ACTION0 + 4, &msr_value);
2684   gfx_msr_write(RC_ID_MCP, MCP_ACTION0 + 5, &msr_value);
2685   gfx_msr_write(RC_ID_MCP, MCP_ACTION0 + 6, &msr_value);
2686   gfx_msr_write(RC_ID_MCP, MCP_ACTION0 + 7, &msr_value);
2687   gfx_msr_write(RC_ID_MCP, MCP_ACTION0 + 8, &msr_value);
2688   gfx_msr_write(RC_ID_MCP, MCP_ACTION0 + 9, &msr_value);
2689   gfx_msr_write(RC_ID_MCP, MCP_ACTION0 + 10, &msr_value);
2690   gfx_msr_write(RC_ID_MCP, MCP_ACTION0 + 11, &msr_value);
2691   gfx_msr_write(RC_ID_MCP, MCP_ACTION0 + 12, &msr_value);
2692   gfx_msr_write(RC_ID_MCP, MCP_ACTION0 + 13, &msr_value);
2693   gfx_msr_write(RC_ID_MCP, MCP_ACTION0 + 17, &msr_value);
2694   gfx_msr_write(RC_ID_MCP, MCP_ACTION0 + 18, &msr_value);
2695   gfx_msr_write(RC_ID_MCP, MCP_ACTION0 + 19, &msr_value);
2696   gfx_msr_write(RC_ID_MCP, MCP_ACTION0 + 20, &msr_value);
2697
2698   /* SET REGA CRC VALUE TO 1 OR 0 */
2699
2700   if (!crc32)
2701      msr_value.low = 0x00000001;
2702   gfx_msr_write(RC_ID_MCP, MCP_REGA, &msr_value);
2703
2704   /* SET XSTATE TO 0 */
2705
2706   msr_value.low = 0;
2707   msr_value.high = 0;
2708   gfx_msr_write(RC_ID_MCP, MCP_XSTATE, &msr_value);
2709
2710   /* CONFIGURE DIAG CONTROL */
2711   /* Set all four comparators to watch the upper diag bus.           */
2712   /* Set REGA action1 to legacy CRC or 32-bit CRC.                   */
2713   /* Set REGB action1 to increment lower 16 bits and clear at limit. */
2714   /* Set REGB action2 to increment upper 16 bits.                    */
2715   /* Enable all actions.                                             */
2716
2717   if (crc32)
2718      msr_value.low = 0x9A820055;
2719   else
2720      msr_value.low = 0x9A840055;
2721   msr_value.high = 0x00000000;
2722   gfx_msr_write(RC_ID_MCP, MCP_DIAGCTL, &msr_value);
2723
2724   /* DELAY TWO FRAMES */
2725
2726   while (!gfx_test_vertical_active()) ;
2727   while (gfx_test_vertical_active()) ;
2728   while (!gfx_test_vertical_active()) ;
2729   while (gfx_test_vertical_active()) ;
2730   while (!gfx_test_vertical_active()) ;
2731
2732   /* VERIFY THAT XSTATE = 11 */
2733
2734   gfx_msr_read(RC_ID_MCP, MCP_XSTATE, &msr_value);
2735   if ((msr_value.low & 3) == 3) {
2736      gfx_msr_read(RC_ID_MCP, MCP_REGA, &msr_value);
2737
2738      crc = msr_value.low;
2739      if (!crc32)
2740	 crc &= 0xFFFFFF;
2741   }
2742
2743   /* DISABLE MCP AND DF DIAG BUS OUTPUTS */
2744
2745   msr_value.low = 0x00000000;
2746   msr_value.high = 0x00000000;
2747   gfx_msr_write(RC_ID_DF, MBD_MSR_DIAG, &msr_value);
2748   gfx_msr_write(RC_ID_MCP, MBD_MSR_DIAG, &msr_value);
2749
2750   /* DISABLE MCP ACTIONS */
2751
2752   msr_value.high = 0x00000000;
2753   msr_value.low = 0x00000000;
2754   gfx_msr_write(RC_ID_MCP, MCP_DIAGCTL, &msr_value);
2755
2756   /* RESTORE PREVIOUS OUTPUT FORMAT */
2757
2758   if (source != CRC_SOURCE_GFX_DATA) {
2759      gfx_msr_read(RC_ID_DF, MBD_MSR_CONFIG, &msr_value);
2760      msr_value.low = old_fmt;
2761      gfx_msr_write(RC_ID_DF, MBD_MSR_CONFIG, &msr_value);
2762   }
2763   return crc;
2764}
2765
2766/*---------------------------------------------------------------------------
2767 * gfx_get_alpha_enable
2768 *
2769 * This routine returns 1 if the selected alpha window is currently
2770 * enabled, or 0 if it is currently disabled.
2771 *---------------------------------------------------------------------------
2772 */
2773#if GFX_VIDEO_DYNAMIC
2774void
2775redcloud_get_alpha_enable(int *enable)
2776#else
2777void
2778gfx_get_alpha_enable(int *enable)
2779#endif
2780{
2781   unsigned long value = 0;
2782
2783   *enable = 0;
2784   if (gfx_alpha_select <= 2) {
2785      value =
2786	    READ_VID32(RCDF_ALPHA_CONTROL_1 +
2787		       ((unsigned long)gfx_alpha_select << 5));
2788      if (value & RCDF_ACTRL_WIN_ENABLE)
2789	 *enable = 1;
2790   }
2791   return;
2792}
2793
2794/*---------------------------------------------------------------------------
2795 * gfx_get_alpha_size
2796 *
2797 * This routine returns the size of the currently selected alpha region.
2798 *---------------------------------------------------------------------------
2799 */
2800#if GFX_VIDEO_DYNAMIC
2801void
2802redcloud_get_alpha_size(unsigned short *x, unsigned short *y,
2803			unsigned short *width, unsigned short *height)
2804#else
2805void
2806gfx_get_alpha_size(unsigned short *x, unsigned short *y,
2807		   unsigned short *width, unsigned short *height)
2808#endif
2809{
2810   unsigned long value = 0;
2811
2812   *x = 0;
2813   *y = 0;
2814   *width = 0;
2815   *height = 0;
2816   if (gfx_alpha_select <= 2) {
2817      value =
2818	    READ_VID32(RCDF_ALPHA_XPOS_1 +
2819		       ((unsigned long)gfx_alpha_select << 5));
2820      *x = (unsigned short)(value & 0x000007FF);
2821      *width = (unsigned short)((value >> 16) & 0x000007FF) - *x;
2822      value =
2823	    READ_VID32(RCDF_ALPHA_YPOS_1 +
2824		       ((unsigned long)gfx_alpha_select << 5));
2825      *y = (unsigned short)(value & 0x000007FF);
2826      *height = (unsigned short)((value >> 16) & 0x000007FF) - *y;
2827   }
2828   *x -= gfx_get_htotal() - gfx_get_hsync_end() - 2;
2829   *y -= gfx_get_vtotal() - gfx_get_vsync_end() + 1;
2830   return;
2831}
2832
2833/*---------------------------------------------------------------------------
2834 * gfx_get_alpha_value
2835 *
2836 * This routine returns the alpha value and increment/decrement value of
2837 * the currently selected alpha region.
2838 *---------------------------------------------------------------------------
2839 */
2840#if GFX_VIDEO_DYNAMIC
2841void
2842redcloud_get_alpha_value(unsigned char *alpha, char *delta)
2843#else
2844void
2845gfx_get_alpha_value(unsigned char *alpha, char *delta)
2846#endif
2847{
2848   unsigned long value = 0;
2849
2850   *alpha = 0;
2851   *delta = 0;
2852   if (gfx_alpha_select <= 2) {
2853      value =
2854	    READ_VID32(RCDF_ALPHA_CONTROL_1 +
2855		       ((unsigned long)gfx_alpha_select << 5));
2856      *alpha = (unsigned char)(value & 0x00FF);
2857      *delta = (char)((value >> 8) & 0x00FF);
2858   }
2859   return;
2860}
2861
2862/*---------------------------------------------------------------------------
2863 * gfx_get_alpha_priority
2864 *
2865 * This routine returns the priority of the currently selected alpha region.
2866 *---------------------------------------------------------------------------
2867 */
2868#if GFX_VIDEO_DYNAMIC
2869void
2870redcloud_get_alpha_priority(int *priority)
2871#else
2872void
2873gfx_get_alpha_priority(int *priority)
2874#endif
2875{
2876   unsigned long pos = 0, value = 0;
2877
2878   *priority = 0;
2879   if (gfx_alpha_select <= 2) {
2880      value = READ_VID32(RCDF_VID_ALPHA_CONTROL);
2881      pos = 16 + (gfx_alpha_select << 1);
2882      *priority = (int)((value >> pos) & 3);
2883   }
2884   return;
2885}
2886
2887/*---------------------------------------------------------------------------
2888 * gfx_get_alpha_color
2889 *
2890 * This routine returns the color register value for the currently selected
2891 * alpha region.  Bit 24 is set if the color register is enabled.
2892 *---------------------------------------------------------------------------
2893 */
2894#if GFX_VIDEO_DYNAMIC
2895void
2896redcloud_get_alpha_color(unsigned long *color)
2897#else
2898void
2899gfx_get_alpha_color(unsigned long *color)
2900#endif
2901{
2902   *color = 0;
2903   if (gfx_alpha_select <= 2) {
2904      *color =
2905	    READ_VID32(RCDF_ALPHA_COLOR_1 +
2906		       ((unsigned long)gfx_alpha_select << 5));
2907   }
2908   return;
2909}
2910
2911#endif /* GFX_READ_ROUTINES */
2912
2913/* END OF FILE */
2914