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