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