1f29dbc25Smrg/*
2f29dbc25Smrg * Copyright (c) 2006 Advanced Micro Devices, Inc.
3f29dbc25Smrg *
4f29dbc25Smrg * Permission is hereby granted, free of charge, to any person obtaining a
5f29dbc25Smrg * copy of this software and associated documentation files (the "Software"),
6f29dbc25Smrg * to deal in the Software without restriction, including without limitation
7f29dbc25Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8f29dbc25Smrg * and/or sell copies of the Software, and to permit persons to whom the
9f29dbc25Smrg * Software is furnished to do so, subject to the following conditions:
10f29dbc25Smrg *
11f29dbc25Smrg * The above copyright notice and this permission notice shall be included in
12f29dbc25Smrg * all copies or substantial portions of the Software.
13f29dbc25Smrg *
14f29dbc25Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15f29dbc25Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16f29dbc25Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17f29dbc25Smrg * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18f29dbc25Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19f29dbc25Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20f29dbc25Smrg * DEALINGS IN THE SOFTWARE.
21f29dbc25Smrg *
22f29dbc25Smrg * Neither the name of the Advanced Micro Devices, Inc. nor the names of its
23f29dbc25Smrg * contributors may be used to endorse or promote products derived from this
24f29dbc25Smrg * software without specific prior written permission.
25f29dbc25Smrg */
26f29dbc25Smrg
27f29dbc25Smrg /*
28f29dbc25Smrg  * Cimarron display filter routines.  These routines program the video
29f29dbc25Smrg  * hardware.
30f29dbc25Smrg  */
31f29dbc25Smrg
32f29dbc25Smrg/*---------------------------------------------------------------------------
33f29dbc25Smrg * df_set_crt_enable
34f29dbc25Smrg *
35f29dbc25Smrg * This routine enables or disables CRT output.
36f29dbc25Smrg *--------------------------------------------------------------------------*/
37f29dbc25Smrg
38f29dbc25Smrgint
39f29dbc25Smrgdf_set_crt_enable(int crt_output)
40f29dbc25Smrg{
41f29dbc25Smrg    unsigned long config, misc;
42f29dbc25Smrg
43f29dbc25Smrg    config = READ_VID32(DF_DISPLAY_CONFIG);
44f29dbc25Smrg    misc = READ_VID32(DF_VID_MISC);
45f29dbc25Smrg
46f29dbc25Smrg    switch (crt_output) {
47f29dbc25Smrg        /* DISABLE DISPLAY */
48f29dbc25Smrg
49f29dbc25Smrg    case DF_CRT_DISABLE:
50f29dbc25Smrg
51f29dbc25Smrg        config &= ~(DF_DCFG_DIS_EN | DF_DCFG_HSYNC_EN |
5204007ebaSmrg                    DF_DCFG_VSYNC_EN | DF_DCFG_DAC_BL_EN);
53f29dbc25Smrg        misc |= DF_DAC_POWER_DOWN;
54f29dbc25Smrg        break;
55f29dbc25Smrg
56f29dbc25Smrg        /* ENABLE THE DISPLAY */
57f29dbc25Smrg
58f29dbc25Smrg    case DF_CRT_ENABLE:
59f29dbc25Smrg
60f29dbc25Smrg        config |= (DF_DCFG_DIS_EN | DF_DCFG_HSYNC_EN |
6104007ebaSmrg                   DF_DCFG_VSYNC_EN | DF_DCFG_DAC_BL_EN);
62f29dbc25Smrg        misc &= ~(DF_DAC_POWER_DOWN | DF_ANALOG_POWER_DOWN);
63f29dbc25Smrg        break;
64f29dbc25Smrg
65f29dbc25Smrg        /* HSYNC:OFF VSYNC:ON */
66f29dbc25Smrg
67f29dbc25Smrg    case DF_CRT_STANDBY:
68f29dbc25Smrg
69f29dbc25Smrg        config = (config & ~(DF_DCFG_DIS_EN | DF_DCFG_HSYNC_EN |
7004007ebaSmrg                             DF_DCFG_DAC_BL_EN)) | DF_DCFG_VSYNC_EN;
71f29dbc25Smrg        misc |= DF_DAC_POWER_DOWN;
72f29dbc25Smrg        break;
73f29dbc25Smrg
74f29dbc25Smrg        /* HSYNC:ON VSYNC:OFF */
75f29dbc25Smrg
76f29dbc25Smrg    case DF_CRT_SUSPEND:
77f29dbc25Smrg
78f29dbc25Smrg        config = (config & ~(DF_DCFG_DIS_EN | DF_DCFG_VSYNC_EN |
7904007ebaSmrg                             DF_DCFG_DAC_BL_EN)) | DF_DCFG_HSYNC_EN;
80f29dbc25Smrg        misc |= DF_DAC_POWER_DOWN;
81f29dbc25Smrg        break;
82f29dbc25Smrg
83f29dbc25Smrg    default:
84f29dbc25Smrg        return CIM_STATUS_INVALIDPARAMS;
85f29dbc25Smrg    }
86f29dbc25Smrg
87f29dbc25Smrg    WRITE_VID32(DF_DISPLAY_CONFIG, config);
88f29dbc25Smrg    WRITE_VID32(DF_VID_MISC, misc);
89f29dbc25Smrg
90f29dbc25Smrg    return CIM_STATUS_OK;
91f29dbc25Smrg}
92f29dbc25Smrg
93f29dbc25Smrg/*---------------------------------------------------------------------------
94f29dbc25Smrg * df_set_panel_enable
95f29dbc25Smrg *
96f29dbc25Smrg * This routine enables or disables panel output.
97f29dbc25Smrg *--------------------------------------------------------------------------*/
98f29dbc25Smrg
99f29dbc25Smrgint
100f29dbc25Smrgdf_set_panel_enable(int enable)
101f29dbc25Smrg{
102f29dbc25Smrg    unsigned long pm;
103f29dbc25Smrg
104f29dbc25Smrg    pm = READ_VID32(DF_POWER_MANAGEMENT);
105f29dbc25Smrg
106f29dbc25Smrg    if (enable)
107f29dbc25Smrg        pm |= DF_PM_PANEL_ON;
108f29dbc25Smrg    else
109f29dbc25Smrg        pm &= ~DF_PM_PANEL_ON;
110f29dbc25Smrg
111f29dbc25Smrg    WRITE_VID32(DF_POWER_MANAGEMENT, pm);
112f29dbc25Smrg
113f29dbc25Smrg    return CIM_STATUS_OK;
114f29dbc25Smrg}
115f29dbc25Smrg
116f29dbc25Smrg/*---------------------------------------------------------------------------
117f29dbc25Smrg * df_configure_video_source
118f29dbc25Smrg *
119f29dbc25Smrg * This routine initializes all aspects of the source buffer for a video overlay.
120f29dbc25Smrg *--------------------------------------------------------------------------*/
121f29dbc25Smrg
122f29dbc25Smrgint
123f29dbc25Smrgdf_configure_video_source(DF_VIDEO_SOURCE_PARAMS * video_source_odd,
12404007ebaSmrg                          DF_VIDEO_SOURCE_PARAMS * video_source_even)
125f29dbc25Smrg{
126f29dbc25Smrg    unsigned long pitch, ctrl, vcfg;
127f29dbc25Smrg    unsigned long lock, vg_line, gcfg;
128f29dbc25Smrg    unsigned long width, size, scale;
129f29dbc25Smrg    unsigned long misc;
130f29dbc25Smrg
131f29dbc25Smrg    lock = READ_REG32(DC3_UNLOCK);
132f29dbc25Smrg    vg_line = READ_REG32(DC3_LINE_SIZE);
133f29dbc25Smrg    gcfg = READ_REG32(DC3_GENERAL_CFG);
134f29dbc25Smrg    vcfg = READ_VID32(DF_VIDEO_CONFIG);
135f29dbc25Smrg    ctrl = READ_VID32(DF_VID_ALPHA_CONTROL);
136f29dbc25Smrg    scale = READ_VID32(DF_VIDEO_SCALER);
137f29dbc25Smrg
138f29dbc25Smrg    /* STORE THE DESIRED SCALING PROCEDURE */
139f29dbc25Smrg    /* Cimarron supports two modes when programming the scale and position  */
140f29dbc25Smrg    /* of the video window.  The first mode is designed to implicitly apply */
14179d5fcd7Smrg    /* the graphics scale to any video operations.  The second applies the  */
142f29dbc25Smrg    /* video unchanged, allowing complete control by the user.  To allow    */
143f29dbc25Smrg    /* visibility between modules, the current mode is stored in a spare    */
144f29dbc25Smrg    /* bit in the DF miscellaneous register.                                */
145f29dbc25Smrg
146f29dbc25Smrg    misc = READ_VID32(DF_VID_MISC);
147f29dbc25Smrg    if (video_source_odd->flags & DF_SOURCEFLAG_IMPLICITSCALING)
148f29dbc25Smrg        misc |= DF_USER_IMPLICIT_SCALING;
149f29dbc25Smrg    else
150f29dbc25Smrg        misc &= DF_USER_IMPLICIT_SCALING;
151f29dbc25Smrg    WRITE_VID32(DF_VID_MISC, misc);
152f29dbc25Smrg
153f29dbc25Smrg    /* PARAMETER - VIDEO PITCH */
154f29dbc25Smrg
155f29dbc25Smrg    pitch =
15604007ebaSmrg        (video_source_odd->y_pitch >> 3) | ((video_source_odd->uv_pitch >> 3) <<
15704007ebaSmrg                                            16);
158f29dbc25Smrg
159f29dbc25Smrg    /* PARAMETER - VIDEO FORMAT */
160f29dbc25Smrg
161f29dbc25Smrg    gcfg &= ~DC3_GCFG_YUV_420;
162f29dbc25Smrg    vcfg &= ~(DF_VCFG_VID_INP_FORMAT | DF_VCFG_4_2_0_MODE);
163f29dbc25Smrg    ctrl &= ~(DF_VIDEO_INPUT_IS_RGB | DF_CSC_VIDEO_YUV_TO_RGB | DF_HD_VIDEO |
16404007ebaSmrg              DF_YUV_CSC_EN);
165f29dbc25Smrg
166f29dbc25Smrg    /* SELECT PIXEL ORDERING */
167f29dbc25Smrg
168f29dbc25Smrg    switch (video_source_odd->video_format & 3) {
169f29dbc25Smrg    case 0:
170f29dbc25Smrg        vcfg |= DF_VCFG_UYVY_FORMAT;
171f29dbc25Smrg        break;
172f29dbc25Smrg    case 1:
173f29dbc25Smrg        vcfg |= DF_VCFG_Y2YU_FORMAT;
174f29dbc25Smrg        break;
175f29dbc25Smrg    case 2:
176f29dbc25Smrg        vcfg |= DF_VCFG_YUYV_FORMAT;
177f29dbc25Smrg        break;
178f29dbc25Smrg    case 3:
179f29dbc25Smrg        vcfg |= DF_VCFG_YVYU_FORMAT;
180f29dbc25Smrg        break;
181f29dbc25Smrg    }
182f29dbc25Smrg
183f29dbc25Smrg    /* SELECT SOURCE FORMAT (4:2:2, 4:2:0, RGB) */
184f29dbc25Smrg
185f29dbc25Smrg    switch (video_source_odd->video_format >> 2) {
186f29dbc25Smrg    case 0:
187f29dbc25Smrg        ctrl |= DF_CSC_VIDEO_YUV_TO_RGB;
188f29dbc25Smrg        break;
189f29dbc25Smrg
190f29dbc25Smrg    case 1:
191f29dbc25Smrg        ctrl |= DF_CSC_VIDEO_YUV_TO_RGB;
192f29dbc25Smrg        vcfg |= DF_VCFG_4_2_0_MODE;
193f29dbc25Smrg        gcfg |= DC3_GCFG_YUV_420;
194f29dbc25Smrg        break;
195f29dbc25Smrg
196f29dbc25Smrg    case 2:
197f29dbc25Smrg        ctrl |= DF_VIDEO_INPUT_IS_RGB;
198f29dbc25Smrg        break;
199f29dbc25Smrg
200f29dbc25Smrg    default:
201f29dbc25Smrg        return CIM_STATUS_INVALIDPARAMS;
202f29dbc25Smrg    }
203f29dbc25Smrg
204f29dbc25Smrg    /* ALIGN TO APPROPRIATE OUTPUT COLOR SPACE                             */
205f29dbc25Smrg    /* We have assumed until this point that the output color space is RGB */
206f29dbc25Smrg    /* and the input (if YUV) is always SDTV video.                        */
207f29dbc25Smrg
208f29dbc25Smrg    if (video_source_odd->flags & DF_SOURCEFLAG_HDTVSOURCE)
209f29dbc25Smrg        ctrl |= DF_HD_VIDEO;
210f29dbc25Smrg
211f29dbc25Smrg    if (ctrl & DF_CSC_GRAPHICS_RGB_TO_YUV) {
212f29dbc25Smrg        /* YUV OUTPUT - DISABLE YUV->RGB AND ENABLE YUV->YUV */
213f29dbc25Smrg
214f29dbc25Smrg        ctrl &= ~DF_CSC_VIDEO_YUV_TO_RGB;
215f29dbc25Smrg
216f29dbc25Smrg        if ((!(ctrl & DF_HD_VIDEO) && (ctrl & DF_HD_GRAPHICS)) ||
217f29dbc25Smrg            ((ctrl & DF_HD_VIDEO) && !(ctrl & DF_HD_GRAPHICS))) {
218f29dbc25Smrg            ctrl |= DF_YUV_CSC_EN;
219f29dbc25Smrg        }
220f29dbc25Smrg    }
221f29dbc25Smrg
222f29dbc25Smrg    /* PARAMETER - DISPLAY FILTER BUFFER SIZE                        */
223f29dbc25Smrg    /* The line size in the video generator must be 32-byte aligned. */
224f29dbc25Smrg    /* However, smaller alignments are managed by setting the        */
225f29dbc25Smrg    /* appropriate pitch and clipping the video window.              */
226f29dbc25Smrg
227f29dbc25Smrg    vcfg &= ~(DF_VCFG_LINE_SIZE_LOWER_MASK | DF_VCFG_LINE_SIZE_BIT8 |
22804007ebaSmrg              DF_VCFG_LINE_SIZE_BIT9);
229f29dbc25Smrg
230f29dbc25Smrg    size = ((video_source_odd->width >> 1) + 7) & 0xFFF8;
231f29dbc25Smrg
232f29dbc25Smrg    vcfg |= (size & 0x00FF) << 8;
233f29dbc25Smrg    if (size & 0x0100)
234f29dbc25Smrg        vcfg |= DF_VCFG_LINE_SIZE_BIT8;
235f29dbc25Smrg    if (size & 0x0200)
236f29dbc25Smrg        vcfg |= DF_VCFG_LINE_SIZE_BIT9;
237f29dbc25Smrg
238f29dbc25Smrg    scale = (scale & ~0x7FF) | video_source_odd->height;
239f29dbc25Smrg
240f29dbc25Smrg    /* PARAMETER - VIDEO GENERATOR BUFFER SIZE */
241f29dbc25Smrg
242f29dbc25Smrg    vg_line &= ~DC3_LINE_SIZE_VLS_MASK;
243f29dbc25Smrg
244f29dbc25Smrg    if (gcfg & DC3_GCFG_YUV_420)
245f29dbc25Smrg        width = ((video_source_odd->width >> 1) + 7) & 0xFFF8;
246f29dbc25Smrg    else
247f29dbc25Smrg        width = ((video_source_odd->width << 1) + 31) & 0xFFE0;
248f29dbc25Smrg
249f29dbc25Smrg    vg_line |= (width >> 3) << DC3_LINE_SIZE_VB_SHIFT;
250f29dbc25Smrg
251f29dbc25Smrg    /* WRITE ALL PARAMETERS AT ONCE */
252f29dbc25Smrg
253f29dbc25Smrg    WRITE_REG32(DC3_UNLOCK, DC3_UNLOCK_VALUE);
254f29dbc25Smrg    WRITE_VID32(DF_VIDEO_CONFIG, vcfg);
255f29dbc25Smrg    WRITE_VID32(DF_VID_ALPHA_CONTROL, ctrl);
256f29dbc25Smrg    WRITE_VID32(DF_VIDEO_SCALER, scale);
257f29dbc25Smrg    WRITE_REG32(DC3_GENERAL_CFG, gcfg);
258f29dbc25Smrg    WRITE_REG32(DC3_LINE_SIZE, vg_line);
259f29dbc25Smrg    WRITE_REG32(DC3_VID_YUV_PITCH, pitch);
260f29dbc25Smrg
261f29dbc25Smrg    /* WRITE EVEN OR ODD BUFFER OFFSETS                            */
262f29dbc25Smrg    /* The even buffer is only valid inside an interlaced display. */
263f29dbc25Smrg
264f29dbc25Smrg    if (READ_REG32(DC3_IRQ_FILT_CTL) & DC3_IRQFILT_INTL_EN) {
265f29dbc25Smrg        WRITE_REG32(DC3_VID_EVEN_Y_ST_OFFSET, video_source_even->y_offset);
266f29dbc25Smrg        WRITE_REG32(DC3_VID_EVEN_U_ST_OFFSET, video_source_even->u_offset);
267f29dbc25Smrg        WRITE_REG32(DC3_VID_EVEN_V_ST_OFFSET, video_source_even->v_offset);
268f29dbc25Smrg    }
269f29dbc25Smrg
270f29dbc25Smrg    WRITE_REG32(DC3_VID_Y_ST_OFFSET, video_source_odd->y_offset);
271f29dbc25Smrg    WRITE_REG32(DC3_VID_U_ST_OFFSET, video_source_odd->u_offset);
272f29dbc25Smrg    WRITE_REG32(DC3_VID_V_ST_OFFSET, video_source_odd->v_offset);
273f29dbc25Smrg
274f29dbc25Smrg    WRITE_REG32(DC3_UNLOCK, lock);
275f29dbc25Smrg
276f29dbc25Smrg    return CIM_STATUS_OK;
277f29dbc25Smrg}
278f29dbc25Smrg
279f29dbc25Smrg/*---------------------------------------------------------------------------
280f29dbc25Smrg * df_set_video_offsets
281f29dbc25Smrg *
282f29dbc25Smrg * This routine sets the starting offset for the video buffer(s).  The buffers
283f29dbc25Smrg * can also be configured inside df_configure_video_source, but a separate
284f29dbc25Smrg * routine is provided here to allow quick buffer flipping.
285f29dbc25Smrg *--------------------------------------------------------------------------*/
286f29dbc25Smrg
287f29dbc25Smrgint
288f29dbc25Smrgdf_set_video_offsets(int even, unsigned long y_offset,
28904007ebaSmrg                     unsigned long u_offset, unsigned long v_offset)
290f29dbc25Smrg{
291f29dbc25Smrg    unsigned long lock = READ_REG32(DC3_UNLOCK);
292f29dbc25Smrg
293f29dbc25Smrg    WRITE_REG32(DC3_UNLOCK, DC3_UNLOCK_VALUE);
294f29dbc25Smrg
295f29dbc25Smrg    if (even) {
296f29dbc25Smrg        WRITE_REG32(DC3_VID_EVEN_Y_ST_OFFSET, y_offset);
297f29dbc25Smrg        WRITE_REG32(DC3_VID_EVEN_U_ST_OFFSET, u_offset);
298f29dbc25Smrg        WRITE_REG32(DC3_VID_EVEN_V_ST_OFFSET, v_offset);
29904007ebaSmrg    }
30004007ebaSmrg    else {
301f29dbc25Smrg        WRITE_REG32(DC3_VID_Y_ST_OFFSET, y_offset);
302f29dbc25Smrg        WRITE_REG32(DC3_VID_U_ST_OFFSET, u_offset);
303f29dbc25Smrg        WRITE_REG32(DC3_VID_V_ST_OFFSET, v_offset);
304f29dbc25Smrg    }
305f29dbc25Smrg
306f29dbc25Smrg    WRITE_REG32(DC3_UNLOCK, lock);
307f29dbc25Smrg
308f29dbc25Smrg    return CIM_STATUS_OK;
309f29dbc25Smrg}
310f29dbc25Smrg
311f29dbc25Smrg/*---------------------------------------------------------------------------
312f29dbc25Smrg * df_set_video_scale
313f29dbc25Smrg *
314f29dbc25Smrg * This routine programs the horizontal/vertical scale factors for video.  To
315f29dbc25Smrg * disable scaling/filtering, this routine should be called with identical source
316f29dbc25Smrg * and destination dimensions.
317f29dbc25Smrg *--------------------------------------------------------------------------*/
318f29dbc25Smrg
319f29dbc25Smrgint
320f29dbc25Smrgdf_set_video_scale(unsigned long src_width, unsigned long src_height,
32104007ebaSmrg                   unsigned long dst_width, unsigned long dst_height,
32204007ebaSmrg                   unsigned long flags)
323f29dbc25Smrg{
324f29dbc25Smrg    unsigned long temp, misc;
325f29dbc25Smrg    unsigned long scale, gfxscale;
326f29dbc25Smrg    unsigned long fbactive, src;
327f29dbc25Smrg    unsigned long size, downscale;
328f29dbc25Smrg    unsigned long vcfg, gcfg, unlock;
329f29dbc25Smrg
330f29dbc25Smrg    /* APPLY THE GRAPHICS SCALE */
331f29dbc25Smrg    /* When requested by the user, we will adjust the video scale by the  */
332f29dbc25Smrg    /* current graphics scale factor.  This allows video to be programmed */
333f29dbc25Smrg    /* in terms of the graphics source resolution.                        */
334f29dbc25Smrg
335f29dbc25Smrg    misc = READ_VID32(DF_VID_MISC);
336f29dbc25Smrg    if (misc & DF_USER_IMPLICIT_SCALING) {
337f29dbc25Smrg        gfxscale = READ_REG32(DC3_GFX_SCALE);
338f29dbc25Smrg        fbactive = READ_REG32(DC3_FB_ACTIVE);
339f29dbc25Smrg
340f29dbc25Smrg        /* REVERSE ENGINEER THE SCALE FACTOR */
341f29dbc25Smrg        /* The graphics scale factor is (source / (dst - 1)), so a little */
342f29dbc25Smrg        /* math is performed to reverse engineer the correct scale for    */
343f29dbc25Smrg        /* video.                                                         */
344f29dbc25Smrg        /*                                                                */
345f29dbc25Smrg        /* F = (0x4000*S)/(D-1)  ->  (D/S) = (((0x4000*S)/F)+1)/S         */
346f29dbc25Smrg
347f29dbc25Smrg        scale = gfxscale & 0xFFFF;
348f29dbc25Smrg        src = (fbactive >> 16) + 1;
349f29dbc25Smrg        if (scale != 0x4000) {
350f29dbc25Smrg            dst_width = dst_width * (((0x4000 * src) / scale) + 1);
351f29dbc25Smrg            dst_width /= src;
352f29dbc25Smrg        }
353f29dbc25Smrg
354f29dbc25Smrg        scale = gfxscale >> 16;
355f29dbc25Smrg        src = (fbactive & 0xFFFF) + 1;
356f29dbc25Smrg        if (scale != 0x4000) {
357f29dbc25Smrg            dst_height = dst_height * (((0x4000 * src) / scale) + 1);
358f29dbc25Smrg            dst_height /= src;
359f29dbc25Smrg        }
360f29dbc25Smrg    }
361f29dbc25Smrg
362f29dbc25Smrg    /* CHECK FOR VALID SCALING FACTOR */
363f29dbc25Smrg    /* The display filter/video generator can support up to 8:1  */
364f29dbc25Smrg    /* horizontal downscale and up to 4:1 vertical downscale.    */
365f29dbc25Smrg    /* Scale factors above 4:1 horizontal and 2:1 horizontal     */
366f29dbc25Smrg    /* will have a quality impact.  However, at such large scale */
367f29dbc25Smrg    /* factors, it might not matter,                             */
368f29dbc25Smrg
369f29dbc25Smrg    if (((flags & DF_SCALEFLAG_CHANGEX) && dst_width < (src_width >> 3)) ||
370f29dbc25Smrg        ((flags & DF_SCALEFLAG_CHANGEY) && dst_height < (src_height >> 2))) {
371f29dbc25Smrg        return CIM_STATUS_INVALIDSCALE;
372f29dbc25Smrg    }
373f29dbc25Smrg
374f29dbc25Smrg    /* ENABLE OR DISABLE ADVANCED SCALING FEATURES          */
375f29dbc25Smrg    /* Scaling above 2:1 vertical and 4:1 horizontal relies */
376f29dbc25Smrg    /* on mechanisms beside the line filter.                */
377f29dbc25Smrg
378f29dbc25Smrg    if (flags & DF_SCALEFLAG_CHANGEX) {
379f29dbc25Smrg        scale = READ_VID32(DF_VIDEO_SCALER);
380f29dbc25Smrg        vcfg = READ_VID32(DF_VIDEO_CONFIG);
381f29dbc25Smrg        vcfg &= ~(DF_VCFG_LINE_SIZE_LOWER_MASK | DF_VCFG_LINE_SIZE_BIT8 |
38204007ebaSmrg                  DF_VCFG_LINE_SIZE_BIT9);
383f29dbc25Smrg
384f29dbc25Smrg        if (dst_width < (src_width >> 2)) {
385f29dbc25Smrg            src_width >>= 1;
386f29dbc25Smrg            WRITE_VID32(DF_VIDEO_SCALER, scale | DF_SCALE_DOUBLE_H_DOWNSCALE);
38704007ebaSmrg        }
38804007ebaSmrg        else {
38904007ebaSmrg            WRITE_VID32(DF_VIDEO_SCALER, scale & ~DF_SCALE_DOUBLE_H_DOWNSCALE);
390f29dbc25Smrg        }
391f29dbc25Smrg
392f29dbc25Smrg        /* PROGRAM A NEW LINE SIZE */
393f29dbc25Smrg        /* The line size must be updated when using the Double Horizontal  */
394f29dbc25Smrg        /* Downscale (DHD) bit.  This is because the amount of VFIFO space */
395f29dbc25Smrg        /* consumed is effectively half in this mode.                      */
396f29dbc25Smrg
397f29dbc25Smrg        size = ((src_width >> 1) + 7) & 0xFFF8;
398f29dbc25Smrg        vcfg |= (size & 0x00FF) << 8;
399f29dbc25Smrg        if (size & 0x0100)
400f29dbc25Smrg            vcfg |= DF_VCFG_LINE_SIZE_BIT8;
401f29dbc25Smrg        if (size & 0x0200)
402f29dbc25Smrg            vcfg |= DF_VCFG_LINE_SIZE_BIT9;
403f29dbc25Smrg        WRITE_VID32(DF_VIDEO_CONFIG, vcfg);
404f29dbc25Smrg        WRITE_VID32(DF_VIDEO_XSCALE, ((0x10000 * src_width) / dst_width));
405f29dbc25Smrg    }
406f29dbc25Smrg
407f29dbc25Smrg    if (flags & DF_SCALEFLAG_CHANGEY) {
408f29dbc25Smrg        unlock = READ_REG32(DC3_UNLOCK);
409f29dbc25Smrg        gcfg = READ_REG32(DC3_GENERAL_CFG) & ~DC3_GCFG_VDSE;
410f29dbc25Smrg        WRITE_REG32(DC3_UNLOCK, DC3_UNLOCK_VALUE);
411f29dbc25Smrg        if (dst_height < (src_height >> 1)) {
412f29dbc25Smrg            gcfg |= DC3_GCFG_VDSE;
413f29dbc25Smrg            downscale = READ_REG32(DC3_VID_DS_DELTA) & ~DC3_DS_DELTA_MASK;
414f29dbc25Smrg            if (dst_height == (src_height >> 2))
415f29dbc25Smrg                downscale |= (0x3FFF << 18);
416f29dbc25Smrg            else
417f29dbc25Smrg                downscale |= (((src_height >> 1) << 14) / dst_height) << 18;
418f29dbc25Smrg
419f29dbc25Smrg            WRITE_REG32(DC3_VID_DS_DELTA, downscale);
420f29dbc25Smrg            WRITE_VID32(DF_VIDEO_YSCALE, 0x20000);
42104007ebaSmrg        }
42204007ebaSmrg        else {
42304007ebaSmrg            WRITE_VID32(DF_VIDEO_YSCALE, ((0x10000 * src_height) / dst_height));
424f29dbc25Smrg        }
425f29dbc25Smrg        WRITE_REG32(DC3_GENERAL_CFG, gcfg);
426f29dbc25Smrg        WRITE_REG32(DC3_UNLOCK, unlock);
427f29dbc25Smrg    }
428f29dbc25Smrg
429f29dbc25Smrg    /* CHECK IF SCALING IS DISABLED */
430f29dbc25Smrg    /* If no scaling occurs, we disable the hardware filter. */
431f29dbc25Smrg
432f29dbc25Smrg    temp = READ_VID32(DF_VIDEO_CONFIG);
433f29dbc25Smrg    if ((READ_VID32(DF_VIDEO_XSCALE) == 0x10000) &&
434f29dbc25Smrg        (READ_VID32(DF_VIDEO_YSCALE) == 0x10000)) {
435f29dbc25Smrg        WRITE_VID32(DF_VIDEO_CONFIG, (temp | DF_VCFG_SC_BYP));
43604007ebaSmrg    }
43704007ebaSmrg    else
438f29dbc25Smrg        WRITE_VID32(DF_VIDEO_CONFIG, (temp & ~DF_VCFG_SC_BYP));
439f29dbc25Smrg
440f29dbc25Smrg    return CIM_STATUS_OK;
441f29dbc25Smrg}
442f29dbc25Smrg
443f29dbc25Smrg/*---------------------------------------------------------------------------
444f29dbc25Smrg * df_set_video_position
445f29dbc25Smrg *
446f29dbc25Smrg * This routine programs the position of the video window on the display.
447f29dbc25Smrg * An indent parameter is also passed to this program to prevent artifacts
448f29dbc25Smrg * when the video window is moved beyond the left edge of the screen.
449f29dbc25Smrg *--------------------------------------------------------------------------*/
450f29dbc25Smrg
451f29dbc25Smrgint
452f29dbc25Smrgdf_set_video_position(DF_VIDEO_POSITION * video_window)
453f29dbc25Smrg{
454f29dbc25Smrg    unsigned long vblankstart_even, vblankend_even, vsyncend_even,
455f29dbc25Smrg        vtotal_even, vactive_even;
456f29dbc25Smrg    unsigned long hblankstart, hblankend, hsyncend, htotal, hactive;
457f29dbc25Smrg    unsigned long vblankstart, vblankend, vsyncend, vtotal, vactive;
458f29dbc25Smrg    unsigned long width, height, height_even;
459f29dbc25Smrg    unsigned long adjust, border_x, border_y, border_y_even;
460f29dbc25Smrg    unsigned long xstart, xend;
461f29dbc25Smrg    unsigned long ystart, yend;
462f29dbc25Smrg    unsigned long ckey_x, ckey_y;
463f29dbc25Smrg    unsigned long x_copy, y_copy;
464f29dbc25Smrg    unsigned long width_copy, height_copy;
465f29dbc25Smrg    unsigned long vcfg, initread;
466f29dbc25Smrg    unsigned long xscale, dst_clip;
467f29dbc25Smrg    unsigned long ypos, ypos_even;
468f29dbc25Smrg    unsigned long y, gfxscale;
469f29dbc25Smrg    unsigned long misc, fbactive;
470f29dbc25Smrg    unsigned long scale, src;
471f29dbc25Smrg    unsigned long irq_ctl;
472f29dbc25Smrg    unsigned long unlock;
473f29dbc25Smrg
474f29dbc25Smrg    hsyncend = ((READ_REG32(DC3_H_SYNC_TIMING) >> 16) & 0xFFF) + 1;
475f29dbc25Smrg    vsyncend = ((READ_REG32(DC3_V_SYNC_TIMING) >> 16) & 0xFFF) + 1;
476f29dbc25Smrg    vblankend = ((READ_REG32(DC3_V_BLANK_TIMING) >> 16) & 0xFFF) + 1;
477f29dbc25Smrg    hblankend = ((READ_REG32(DC3_H_BLANK_TIMING) >> 16) & 0xFFF) + 1;
478f29dbc25Smrg    htotal = ((READ_REG32(DC3_H_ACTIVE_TIMING) >> 16) & 0xFFF) + 1;
479f29dbc25Smrg    vtotal = ((READ_REG32(DC3_V_ACTIVE_TIMING) >> 16) & 0xFFF) + 1;
480f29dbc25Smrg    vblankstart = (READ_REG32(DC3_V_BLANK_TIMING) & 0xFFF) + 1;
481f29dbc25Smrg    hblankstart = (READ_REG32(DC3_H_BLANK_TIMING) & 0xFFF) + 1;
482f29dbc25Smrg    hactive = (READ_REG32(DC3_H_ACTIVE_TIMING) & 0xFFF) + 1;
483f29dbc25Smrg    vactive = (READ_REG32(DC3_V_ACTIVE_TIMING) & 0xFFF) + 1;
484f29dbc25Smrg    unlock = READ_REG32(DC3_UNLOCK);
485f29dbc25Smrg
486f29dbc25Smrg    /* INCLUDE BORDER IF REQUESTED */
487f29dbc25Smrg
488f29dbc25Smrg    if (video_window->flags & DF_POSFLAG_INCLUDEBORDER) {
489f29dbc25Smrg        border_x = htotal - hblankend;
490f29dbc25Smrg        border_y = vtotal - vblankend;
491f29dbc25Smrg        hactive = hblankstart + htotal - hblankend;
492f29dbc25Smrg        vactive = vblankstart + vtotal - vblankend;
49304007ebaSmrg    }
49404007ebaSmrg    else {
495f29dbc25Smrg        border_x = border_y = 0;
496f29dbc25Smrg    }
497f29dbc25Smrg
498f29dbc25Smrg    /* APPLY THE GRAPHICS SCALE     */
499f29dbc25Smrg    /* Do not alter the input data. */
500f29dbc25Smrg
501f29dbc25Smrg    width_copy = video_window->width;
502f29dbc25Smrg    height_copy = video_window->height;
503f29dbc25Smrg    x_copy = video_window->x;
504f29dbc25Smrg    y_copy = video_window->y;
505f29dbc25Smrg
506f29dbc25Smrg    misc = READ_VID32(DF_VID_MISC);
507f29dbc25Smrg    if (misc & DF_USER_IMPLICIT_SCALING) {
508f29dbc25Smrg        gfxscale = READ_REG32(DC3_GFX_SCALE);
509f29dbc25Smrg        fbactive = READ_REG32(DC3_FB_ACTIVE);
510f29dbc25Smrg
511f29dbc25Smrg        /* REVERSE ENGINEER THE SCALE FACTOR */
512f29dbc25Smrg
513f29dbc25Smrg        scale = gfxscale & 0xFFFF;
514f29dbc25Smrg        src = (fbactive >> 16) + 1;
515f29dbc25Smrg        if (scale != 0x4000) {
516f29dbc25Smrg            width_copy = width_copy * (((0x4000 * src) / scale) + 1);
517f29dbc25Smrg            width_copy /= src;
518f29dbc25Smrg            x_copy = x_copy * (((0x4000 * src) / scale) + 1);
519f29dbc25Smrg            x_copy /= src;
520f29dbc25Smrg        }
521f29dbc25Smrg
522f29dbc25Smrg        scale = gfxscale >> 16;
523f29dbc25Smrg        src = (fbactive & 0xFFFF) + 1;
524f29dbc25Smrg        if (scale != 0x4000) {
525f29dbc25Smrg            height_copy = height_copy * (((0x4000 * src) / scale) + 1);
526f29dbc25Smrg            height_copy /= src;
527f29dbc25Smrg            y_copy = y_copy * (((0x4000 * src) / scale) + 1);
528f29dbc25Smrg            y_copy /= src;
529f29dbc25Smrg        }
530f29dbc25Smrg    }
531f29dbc25Smrg
532f29dbc25Smrg    /* HANDLE INTERLACING */
533f29dbc25Smrg    /* When the output is interlaced, we must set the position and height */
534f29dbc25Smrg    /* on the fields and not on the composite image.                      */
535f29dbc25Smrg
536f29dbc25Smrg    if ((irq_ctl = READ_REG32(DC3_IRQ_FILT_CTL)) & DC3_IRQFILT_INTL_EN) {
537f29dbc25Smrg        vsyncend_even = ((READ_REG32(DC3_V_SYNC_EVEN) >> 16) & 0xFFF) + 1;
538f29dbc25Smrg        vtotal_even = ((READ_REG32(DC3_V_ACTIVE_EVEN) >> 16) & 0xFFF) + 1;
539f29dbc25Smrg        vblankend_even = ((READ_REG32(DC3_V_BLANK_EVEN) >> 16) & 0xFFF) + 1;
540f29dbc25Smrg        vactive_even = (READ_REG32(DC3_V_ACTIVE_EVEN) & 0xFFF) + 1;
541f29dbc25Smrg        vblankstart_even = (READ_REG32(DC3_V_BLANK_EVEN) & 0xFFF) + 1;
542f29dbc25Smrg
543f29dbc25Smrg        if (video_window->flags & DF_POSFLAG_INCLUDEBORDER) {
544f29dbc25Smrg            border_y_even = vtotal_even - vblankend_even;
545f29dbc25Smrg            vactive_even = vblankstart_even + vtotal_even - vblankend_even;
54604007ebaSmrg        }
54704007ebaSmrg        else
548f29dbc25Smrg            border_y_even = 0;
549f29dbc25Smrg
550f29dbc25Smrg        /*
551f29dbc25Smrg         * THE ODD FIELD MUST ALWAYS PRECEDE THE EVEN FIELD
552f29dbc25Smrg         * This implies that we can never start video on an odd y position
553f29dbc25Smrg         * in the composite image.  This is required because the only way
554f29dbc25Smrg         * to accomplish an odd y start would be to switch the buffer
555f29dbc25Smrg         * which could have serious repercussions for genlocked VIP.
556f29dbc25Smrg         */
557f29dbc25Smrg
558f29dbc25Smrg        y = y_copy >> 1;
559f29dbc25Smrg
560f29dbc25Smrg        /* CALCULATE Y POSITION FOR ODD FIELD */
561f29dbc25Smrg        /* Clip the video window to the odd field timings. Note that the */
562f29dbc25Smrg        /* height in the odd field may be greater if the video height is */
563f29dbc25Smrg        /* odd.                                                          */
564f29dbc25Smrg
565f29dbc25Smrg        height = (height_copy + 1) >> 1;
566f29dbc25Smrg        if ((y + height) > vactive)
567f29dbc25Smrg            height = vactive - y;
568f29dbc25Smrg
569f29dbc25Smrg        ystart = y + vtotal_even - vsyncend_even + 1;
570f29dbc25Smrg        if (video_window->flags & DF_POSFLAG_INCLUDEBORDER)
571f29dbc25Smrg            ystart -= border_y_even;
572f29dbc25Smrg
573f29dbc25Smrg        yend = ystart + height;
574f29dbc25Smrg        ypos = (yend << 16) | ystart;
575f29dbc25Smrg
576f29dbc25Smrg        /* CALCULATE Y POSITION FOR EVEN FIELD */
577f29dbc25Smrg
578f29dbc25Smrg        height_even = height_copy >> 1;
579f29dbc25Smrg        if ((y + height_even) > vactive_even)
580f29dbc25Smrg            height_even = vactive_even - y;
581f29dbc25Smrg
582f29dbc25Smrg        ystart = y + vtotal - vsyncend + 1;
583f29dbc25Smrg        if (video_window->flags & DF_POSFLAG_INCLUDEBORDER)
584f29dbc25Smrg            ystart -= border_y;
585f29dbc25Smrg
586f29dbc25Smrg        yend = ystart + height_even;
587f29dbc25Smrg        ypos_even = (yend << 16) | ystart;
588f29dbc25Smrg
589f29dbc25Smrg        /* CALCULATE ACTUAL FRAME BUFFER HEIGHT */
590f29dbc25Smrg        /* The y position and height are used to determine the actual    */
591f29dbc25Smrg        /* placement of the color key region.  The region will either be */
592f29dbc25Smrg        /* the sum of the even and odd fields (for interlaced addressing */
593f29dbc25Smrg        /* or flicker filtering) or it will be the union of the two (for */
594f29dbc25Smrg        /* line doubling).  We must also adjust the region such that the */
595f29dbc25Smrg        /* origin (0, 0) is centered on the beginning of graphics data.  */
596f29dbc25Smrg        /* This is only a problem if video is being displayed over the   */
597f29dbc25Smrg        /* overscan area.                                                */
598f29dbc25Smrg
599f29dbc25Smrg        if ((READ_REG32(DC3_GENLK_CTL) & DC3_GC_FLICKER_FILTER_ENABLE) ||
600f29dbc25Smrg            (irq_ctl & DC3_IRQFILT_INTL_ADDR)) {
601f29dbc25Smrg            y <<= 1;
602f29dbc25Smrg            height += height_even;
603f29dbc25Smrg            adjust = border_y + border_y_even;
60404007ebaSmrg        }
60504007ebaSmrg        else {
606f29dbc25Smrg            adjust = border_y;
607f29dbc25Smrg            if (height_even > height)
608f29dbc25Smrg                height = height_even;
609f29dbc25Smrg        }
610f29dbc25Smrg        if (video_window->flags & DF_POSFLAG_INCLUDEBORDER) {
611f29dbc25Smrg            if (y > adjust) {
612f29dbc25Smrg                y -= adjust;
613f29dbc25Smrg                adjust = 0;
61404007ebaSmrg            }
61504007ebaSmrg            else {
616f29dbc25Smrg                adjust -= y;
617f29dbc25Smrg                if (height > adjust)
618f29dbc25Smrg                    height -= adjust;
619f29dbc25Smrg                else
620f29dbc25Smrg                    height = 0;
621f29dbc25Smrg            }
622f29dbc25Smrg        }
623f29dbc25Smrg
62404007ebaSmrg    }
62504007ebaSmrg    else {
626f29dbc25Smrg        y = y_copy;
627f29dbc25Smrg
628f29dbc25Smrg        height = height_copy;
629f29dbc25Smrg        if ((y + height) > vactive)
630f29dbc25Smrg            height = vactive - y;
631f29dbc25Smrg
632f29dbc25Smrg        ystart = y + vtotal - vsyncend + 1;
633f29dbc25Smrg        if (video_window->flags & DF_POSFLAG_INCLUDEBORDER)
634f29dbc25Smrg            ystart -= border_y;
635f29dbc25Smrg
636f29dbc25Smrg        yend = ystart + height;
637f29dbc25Smrg        ypos = (yend << 16) | ystart;
638f29dbc25Smrg        ypos_even = 0;
639f29dbc25Smrg    }
640f29dbc25Smrg
641f29dbc25Smrg    /* HORIZONTAL POSITION */
642f29dbc25Smrg    /* The horizontal values are identical for the even and odd field. */
643f29dbc25Smrg
644f29dbc25Smrg    width = width_copy;
645f29dbc25Smrg    xstart = x_copy + htotal - hsyncend - 14;
646f29dbc25Smrg    if (video_window->flags & DF_POSFLAG_INCLUDEBORDER)
647f29dbc25Smrg        xstart -= border_x;
648f29dbc25Smrg
649f29dbc25Smrg    /* RIGHT CLIPPING */
650f29dbc25Smrg
651f29dbc25Smrg    if ((x_copy + width) > hactive)
652f29dbc25Smrg        width = hactive - x_copy;
653f29dbc25Smrg
654f29dbc25Smrg    xend = xstart + width;
655f29dbc25Smrg
656f29dbc25Smrg    /*
657f29dbc25Smrg     * CALCULATE LEFT CLIPPING PARAMETER
658f29dbc25Smrg     * The value passed in can be interpreted as destination pixels, in
659f29dbc25Smrg     * which case the video scale is factored in, or as source pixels, in
660f29dbc25Smrg     * which case the value is written directly.  Also, the display filter's
661f29dbc25Smrg     * initial read address value is only programmable on 4-pixel increments.
662f29dbc25Smrg     * However, we can achieve an arbitrary left clip by adjusting the
663f29dbc25Smrg     * xstart value, as there is a 14-clock delay in which to play.  Also,
664f29dbc25Smrg     * according to the designers, 4:2:0 and 4:2:2 behave identically when
665f29dbc25Smrg     * setting the initial read address.  The addition of scaling further
666f29dbc25Smrg     * complicates the algorithm.  When setting the initial read address, it
667f29dbc25Smrg     * is in terms of source pixels, while adjusting the xstart value is in
668f29dbc25Smrg     * destination pixels We may thus not be able to achieve a perfect
669f29dbc25Smrg     * clipping fit for scaled video.  We compensate by including two
670f29dbc25Smrg     * clipping parameters in our structure.  This allows us the user
671f29dbc25Smrg     * additional control and it allows us to accurately convey to the user
672f29dbc25Smrg     * the state of clipping on the machine.
673f29dbc25Smrg     */
674f29dbc25Smrg
675f29dbc25Smrg    initread = video_window->left_clip;
676f29dbc25Smrg    dst_clip = 0;
677f29dbc25Smrg    if (!(video_window->flags & DF_POSFLAG_DIRECTCLIP)) {
678f29dbc25Smrg        xscale = READ_VID32(DF_VIDEO_XSCALE) & 0xFFFFF;
679f29dbc25Smrg        initread = (initread * xscale) / 0x10000;
680f29dbc25Smrg        if (xscale)
681f29dbc25Smrg            dst_clip = ((initread & 3) * 0x10000) / xscale;
68204007ebaSmrg    }
68304007ebaSmrg    else
684f29dbc25Smrg        dst_clip = video_window->dst_clip;
685f29dbc25Smrg
686f29dbc25Smrg    /*
687f29dbc25Smrg     * LIMIT THE CLIP
688f29dbc25Smrg     * We technically have a 14 pixel window in which to play.  However,
689f29dbc25Smrg     * taking the entire 14 pixels makes the video timing a little hairy...
690f29dbc25Smrg     * Also note that we cannot do this when performing panel centering, as
691f29dbc25Smrg     * the video would then exceed the mode size.
692f29dbc25Smrg     */
693f29dbc25Smrg
694f29dbc25Smrg    if (dst_clip > 4)
695f29dbc25Smrg        dst_clip = 4;
696f29dbc25Smrg    if (READ_REG32(DC3_DISPLAY_CFG) & DC3_DCFG_DCEN)
697f29dbc25Smrg        dst_clip = 0;
698f29dbc25Smrg
699f29dbc25Smrg    xstart -= dst_clip;
700f29dbc25Smrg
701f29dbc25Smrg    vcfg = READ_VID32(DF_VIDEO_CONFIG);
702f29dbc25Smrg    vcfg &= ~DF_VCFG_INIT_READ_MASK;
703f29dbc25Smrg    vcfg |= (initread >> 2) << 16;
704f29dbc25Smrg
705f29dbc25Smrg    /* SET COLOR KEY REGION */
706f29dbc25Smrg    /* We are assuming that color keying will never be desired outside   */
707f29dbc25Smrg    /* of the video region.  We adjust the color key region for graphics */
708f29dbc25Smrg    /* scaling.                                                          */
709f29dbc25Smrg
710f29dbc25Smrg    gfxscale = READ_REG32(DC3_GFX_SCALE);
711f29dbc25Smrg
712f29dbc25Smrg    ckey_x = ((x_copy * (gfxscale & 0xFFFF)) / 0x4000) |
713f29dbc25Smrg        ((((x_copy + width) * (gfxscale & 0xFFFF)) / 0x4000) << 16);
714f29dbc25Smrg    ckey_y = ((y * (gfxscale >> 16)) / 0x4000) |
715f29dbc25Smrg        ((((y + height) * (gfxscale >> 16)) / 0x4000) << 16);
716f29dbc25Smrg
717f29dbc25Smrg    /* WRITE ALL PARAMETERS AT ONCE */
718f29dbc25Smrg
719f29dbc25Smrg    WRITE_REG32(DC3_UNLOCK, DC3_UNLOCK_VALUE);
720f29dbc25Smrg    WRITE_REG32(DC3_CLR_KEY_X, ckey_x);
721f29dbc25Smrg    WRITE_REG32(DC3_CLR_KEY_Y, ckey_y);
722f29dbc25Smrg    WRITE_VID32(DF_VIDEO_X_POS, (xend << 16) | xstart);
723f29dbc25Smrg    WRITE_VID32(DF_VIDEO_Y_POS, ypos);
724f29dbc25Smrg    WRITE_VID32(DF_VID_YPOS_EVEN, ypos_even);
725f29dbc25Smrg    WRITE_VID32(DF_VIDEO_CONFIG, vcfg);
726f29dbc25Smrg    WRITE_REG32(DC3_UNLOCK, unlock);
727f29dbc25Smrg
728f29dbc25Smrg    return CIM_STATUS_OK;
729f29dbc25Smrg}
730f29dbc25Smrg
731f29dbc25Smrg/*---------------------------------------------------------------------------
732f29dbc25Smrg * df_set_video_filter_coefficients
733f29dbc25Smrg *
734f29dbc25Smrg * This routine sets the horizontal and vertical filter coefficients for video
735f29dbc25Smrg * scaling.  These coefficients are used for upscaling and downscaling video.
736f29dbc25Smrg * If the phase256 parameter is 1, the coefficient arrays are used as single
737f29dbc25Smrg * arrays of 256 phases for both vertical and horizontal scaling.  If the
738f29dbc25Smrg * phase256 parameter is clear, the coefficient arrays are used as two
739f29dbc25Smrg * 128-phase arrays.  The first 128 entries represent the phases for
740f29dbc25Smrg * vertical scaling.  The last 128 entries represent the phases for
741f29dbc25Smrg * horizontal scaling.
742f29dbc25Smrg *--------------------------------------------------------------------------*/
743f29dbc25Smrg
744f29dbc25Smrgint
745f29dbc25Smrgdf_set_video_filter_coefficients(long taps[][4], int phase256)
746f29dbc25Smrg{
747f29dbc25Smrg    unsigned long scale, coeff0, coeff1;
748f29dbc25Smrg    unsigned long i;
749f29dbc25Smrg    long (*defaults)[2];
750f29dbc25Smrg
751f29dbc25Smrg    /* SET PHASE COUNT AND CHOOSE COEFFICIENT ARRAY */
752f29dbc25Smrg
753f29dbc25Smrg    scale = READ_VID32(DF_VIDEO_SCALER);
754f29dbc25Smrg    if (phase256) {
755f29dbc25Smrg        WRITE_VID32(DF_VIDEO_SCALER, (scale & ~DF_SCALE_128_PHASES));
756f29dbc25Smrg        defaults = CimarronVideoFilter256;
75704007ebaSmrg    }
75804007ebaSmrg    else {
759f29dbc25Smrg        WRITE_VID32(DF_VIDEO_SCALER, (scale | DF_SCALE_128_PHASES));
760f29dbc25Smrg        defaults = CimarronVideoFilter128;
761f29dbc25Smrg    }
762f29dbc25Smrg
763f29dbc25Smrg    /* PROGRAM COEFFICIENTS */
764f29dbc25Smrg
765f29dbc25Smrg    for (i = 0; i < 256; i++) {
766f29dbc25Smrg        if (!taps) {
767f29dbc25Smrg            coeff0 = defaults[i][0];
768f29dbc25Smrg            coeff1 = defaults[i][1];
76904007ebaSmrg        }
77004007ebaSmrg        else {
771f29dbc25Smrg            if (taps[i][1] < 0)
772f29dbc25Smrg                coeff0 = -taps[i][1] | 0x8000;
773f29dbc25Smrg            else
774f29dbc25Smrg                coeff0 = taps[i][1];
775f29dbc25Smrg
776f29dbc25Smrg            coeff0 <<= 16;
777f29dbc25Smrg
778f29dbc25Smrg            if (taps[i][0] < 0)
779f29dbc25Smrg                coeff0 |= -taps[i][0] | 0x8000;
780f29dbc25Smrg            else
781f29dbc25Smrg                coeff0 |= taps[i][0];
782f29dbc25Smrg
783f29dbc25Smrg            if (taps[i][3] < 0)
784f29dbc25Smrg                coeff1 = -taps[i][3] | 0x8000;
785f29dbc25Smrg            else
786f29dbc25Smrg                coeff1 = taps[i][3];
787f29dbc25Smrg
788f29dbc25Smrg            coeff1 <<= 16;
789f29dbc25Smrg
790f29dbc25Smrg            if (taps[i][2] < 0)
791f29dbc25Smrg                coeff1 |= -taps[i][2] | 0x8000;
792f29dbc25Smrg            else
793f29dbc25Smrg                coeff1 |= taps[i][2];
794f29dbc25Smrg        }
795f29dbc25Smrg
796f29dbc25Smrg        WRITE_VID32((DF_COEFFICIENT_BASE + (i << 3)), coeff0);
797f29dbc25Smrg        WRITE_VID32((DF_COEFFICIENT_BASE + (i << 3) + 4), coeff1);
798f29dbc25Smrg    }
799f29dbc25Smrg
800f29dbc25Smrg    return CIM_STATUS_OK;
801f29dbc25Smrg}
802f29dbc25Smrg
803f29dbc25Smrg/*---------------------------------------------------------------------------
804f29dbc25Smrg * df_set_video_enable
805f29dbc25Smrg *
806f29dbc25Smrg * This routine enables or disables the video overlay.
807f29dbc25Smrg *--------------------------------------------------------------------------*/
808f29dbc25Smrg
809f29dbc25Smrgint
810f29dbc25Smrgdf_set_video_enable(int enable, unsigned long flags)
811f29dbc25Smrg{
812f29dbc25Smrg    unsigned long vcfg, lock, gcfg;
813f29dbc25Smrg    unsigned long dcfg, vg_ckey, fifo = 0;
814f29dbc25Smrg
815f29dbc25Smrg    vcfg = READ_VID32(DF_VIDEO_CONFIG);
816f29dbc25Smrg    lock = READ_REG32(DC3_UNLOCK);
817f29dbc25Smrg    gcfg = READ_REG32(DC3_GENERAL_CFG);
818f29dbc25Smrg
819f29dbc25Smrg    /* SET VIDEO FIFO END WATERMARK */
820f29dbc25Smrg    /* The video FIFO end watermark is set to 0 when video is disabled  */
821f29dbc25Smrg    /* to allow low priority transactions in the VG.  Otherwise, the    */
822f29dbc25Smrg    /* priority will be forced high until the VG fills the video FIFO   */
823f29dbc25Smrg    /* by not fetching video.  That could take a while...  Note that    */
824f29dbc25Smrg    /* we set the end priority to be 4 greater than the start.  We      */
825f29dbc25Smrg    /* assume that the start priority has been configured by a modeset. */
826f29dbc25Smrg
827f29dbc25Smrg    dcfg = READ_REG32(DC3_DISPLAY_CFG) & ~DC3_DCFG_VFHPEL_MASK;
828f29dbc25Smrg    if (enable) {
829f29dbc25Smrg        fifo = ((dcfg >> 12) & 0x0000000F) + 4;
830f29dbc25Smrg        if (fifo > 0xF)
831f29dbc25Smrg            fifo = 0xF;
832f29dbc25Smrg    }
833f29dbc25Smrg    WRITE_REG32(DC3_UNLOCK, DC3_UNLOCK_VALUE);
834f29dbc25Smrg    WRITE_REG32(DC3_DISPLAY_CFG, dcfg | (fifo << 16));
835f29dbc25Smrg
836f29dbc25Smrg    /* ENABLE OR DISABLE VIDEO */
837f29dbc25Smrg    /* The mechanism to fetch video data is enabled first and */
838f29dbc25Smrg    /* disabled last.                                         */
839f29dbc25Smrg
840f29dbc25Smrg    if (enable) {
841f29dbc25Smrg        WRITE_REG32(DC3_GENERAL_CFG, (gcfg | DC3_GCFG_VIDE));
842f29dbc25Smrg        WRITE_VID32(DF_VIDEO_CONFIG, (vcfg | DF_VCFG_VID_EN));
843f29dbc25Smrg
844f29dbc25Smrg        /* DISABLE COLOR KEYING IF REQUESTED BY THE USER */
845f29dbc25Smrg
846f29dbc25Smrg        if (flags & DF_ENABLEFLAG_NOCOLORKEY) {
847f29dbc25Smrg            /* OVERRIDE THE MODE TO COLOR KEYING */
848f29dbc25Smrg
849f29dbc25Smrg            dcfg = READ_VID32(DF_DISPLAY_CONFIG);
850f29dbc25Smrg            WRITE_VID32(DF_DISPLAY_CONFIG, (dcfg & ~DF_DCFG_VG_CK));
851f29dbc25Smrg
852f29dbc25Smrg            /* DISABLE COLOR KEYING IN THE VG */
853f29dbc25Smrg
854f29dbc25Smrg            vg_ckey = READ_REG32(DC3_COLOR_KEY);
855f29dbc25Smrg            WRITE_REG32(DC3_COLOR_KEY, (vg_ckey & ~DC3_CLR_KEY_ENABLE));
85604007ebaSmrg        }
85704007ebaSmrg        else if (!(READ_VID32(DF_DISPLAY_CONFIG) & DF_DCFG_VG_CK)) {
858f29dbc25Smrg            /* OTHERWISE RE-ENABLE COLOR KEYING */
859f29dbc25Smrg
860f29dbc25Smrg            vg_ckey = READ_REG32(DC3_COLOR_KEY);
861f29dbc25Smrg            WRITE_REG32(DC3_COLOR_KEY, (vg_ckey | DC3_CLR_KEY_ENABLE));
862f29dbc25Smrg        }
86304007ebaSmrg    }
86404007ebaSmrg    else {
865f29dbc25Smrg        WRITE_VID32(DF_VIDEO_CONFIG, (vcfg & ~DF_VCFG_VID_EN));
866f29dbc25Smrg        WRITE_REG32(DC3_GENERAL_CFG, (gcfg & ~DC3_GCFG_VIDE));
867f29dbc25Smrg
868f29dbc25Smrg        /* DISABLE COLOR KEY WINDOW WHEN VIDEO IS INACTIVE         */
86979d5fcd7Smrg        /* To mimic legacy functionality, we disable color keying  */
870f29dbc25Smrg        /* when the video window is not active.  We will restore   */
871f29dbc25Smrg        /* the enable when video is re-enabled if the appropriate  */
872f29dbc25Smrg        /* bit is set in display config.                           */
873f29dbc25Smrg
874f29dbc25Smrg        vg_ckey = READ_REG32(DC3_COLOR_KEY);
875f29dbc25Smrg        WRITE_REG32(DC3_COLOR_KEY, (vg_ckey & ~DC3_CLR_KEY_ENABLE));
876f29dbc25Smrg    }
877f29dbc25Smrg    WRITE_REG32(DC3_UNLOCK, lock);
878f29dbc25Smrg
879f29dbc25Smrg    return CIM_STATUS_OK;
880f29dbc25Smrg}
881f29dbc25Smrg
882f29dbc25Smrg/*---------------------------------------------------------------------------
883f29dbc25Smrg * df_set_video_color_key
884f29dbc25Smrg *
885f29dbc25Smrg * This routine configures the video color/chroma key mechanism.
886f29dbc25Smrg *--------------------------------------------------------------------------*/
887f29dbc25Smrg
888f29dbc25Smrgint
889f29dbc25Smrgdf_set_video_color_key(unsigned long key, unsigned long mask, int graphics)
890f29dbc25Smrg{
891f29dbc25Smrg    unsigned long lock, vg_ckey, df_dcfg;
892f29dbc25Smrg
893f29dbc25Smrg    vg_ckey = READ_REG32(DC3_COLOR_KEY);
894f29dbc25Smrg    lock = READ_REG32(DC3_UNLOCK);
895f29dbc25Smrg    df_dcfg = READ_VID32(DF_DISPLAY_CONFIG);
896f29dbc25Smrg
897f29dbc25Smrg    WRITE_REG32(DC3_UNLOCK, DC3_UNLOCK_VALUE);
898f29dbc25Smrg
899f29dbc25Smrg    if (graphics) {
900f29dbc25Smrg        /* COLOR KEY - USE VG HARDWARE */
901f29dbc25Smrg        /* Note that color key is never enabled unless a video window */
902f29dbc25Smrg        /* is active.  This is to match legacy behavior.              */
903f29dbc25Smrg
904f29dbc25Smrg        df_dcfg &= ~DF_DCFG_VG_CK;
905f29dbc25Smrg        vg_ckey = (vg_ckey & 0xFF000000) | (key & 0xFFFFFF);
906f29dbc25Smrg        if (READ_VID32(DF_VIDEO_CONFIG) & DF_VCFG_VID_EN)
907f29dbc25Smrg            vg_ckey |= DC3_CLR_KEY_ENABLE;
908f29dbc25Smrg        else
909f29dbc25Smrg            vg_ckey &= ~DC3_CLR_KEY_ENABLE;
910f29dbc25Smrg
911f29dbc25Smrg        WRITE_VID32(DF_DISPLAY_CONFIG, df_dcfg);
912f29dbc25Smrg        WRITE_REG32(DC3_COLOR_KEY, vg_ckey);
913f29dbc25Smrg        WRITE_REG32(DC3_COLOR_MASK, (mask & 0xFFFFFF));
91404007ebaSmrg    }
91504007ebaSmrg    else {
916f29dbc25Smrg        /* CHROMA KEY - USE DF HARDWARE */
917f29dbc25Smrg
918f29dbc25Smrg        df_dcfg |= DF_DCFG_VG_CK;
919f29dbc25Smrg        vg_ckey &= ~DC3_CLR_KEY_ENABLE;
920f29dbc25Smrg
921f29dbc25Smrg        WRITE_REG32(DC3_COLOR_KEY, vg_ckey);
922f29dbc25Smrg        WRITE_VID32(DF_DISPLAY_CONFIG, df_dcfg);
923f29dbc25Smrg        WRITE_VID32(DF_VIDEO_COLOR_KEY, (key & 0xFFFFFF));
924f29dbc25Smrg        WRITE_VID32(DF_VIDEO_COLOR_MASK, (mask & 0xFFFFFF));
925f29dbc25Smrg    }
926f29dbc25Smrg
927f29dbc25Smrg    WRITE_REG32(DC3_UNLOCK, lock);
928f29dbc25Smrg
929f29dbc25Smrg    return CIM_STATUS_OK;
930f29dbc25Smrg}
931f29dbc25Smrg
932f29dbc25Smrg/*---------------------------------------------------------------------------
933f29dbc25Smrg * df_set_video_palette
934f29dbc25Smrg *
935f29dbc25Smrg * This routine loads the video hardware palette.  If a NULL pointer is
936f29dbc25Smrg * specified, the palette is bypassed.
937f29dbc25Smrg *-------------------------------------------------------------------------*/
938f29dbc25Smrg
939f29dbc25Smrgint
940f29dbc25Smrgdf_set_video_palette(unsigned long *palette)
941f29dbc25Smrg{
942f29dbc25Smrg    unsigned long i, entry;
943f29dbc25Smrg    unsigned long misc, dcfg;
944f29dbc25Smrg
945f29dbc25Smrg    /* LOAD GEODE LX VIDEO PALETTE */
946f29dbc25Smrg
947f29dbc25Smrg    WRITE_VID32(DF_PALETTE_ADDRESS, 0);
948f29dbc25Smrg    for (i = 0; i < 256; i++) {
949f29dbc25Smrg        if (palette)
950f29dbc25Smrg            entry = palette[i];
951f29dbc25Smrg        else
952f29dbc25Smrg            entry = i | (i << 8) | (i << 16);
953f29dbc25Smrg        WRITE_VID32(DF_PALETTE_DATA, entry);
954f29dbc25Smrg    }
955f29dbc25Smrg
956f29dbc25Smrg    /* ENABLE THE VIDEO PALETTE */
957f29dbc25Smrg    /* Ensure that the video palette has an effect by routing video data */
958f29dbc25Smrg    /* through the palette RAM and clearing the 'Bypass Both' bit.       */
959f29dbc25Smrg
960f29dbc25Smrg    dcfg = READ_VID32(DF_DISPLAY_CONFIG);
961f29dbc25Smrg    misc = READ_VID32(DF_VID_MISC);
962f29dbc25Smrg
963f29dbc25Smrg    dcfg |= DF_DCFG_GV_PAL_BYP;
964f29dbc25Smrg    misc &= ~DF_GAMMA_BYPASS_BOTH;
965f29dbc25Smrg
966f29dbc25Smrg    WRITE_VID32(DF_DISPLAY_CONFIG, dcfg);
967f29dbc25Smrg    WRITE_VID32(DF_VID_MISC, misc);
968f29dbc25Smrg
969f29dbc25Smrg    return CIM_STATUS_OK;
970f29dbc25Smrg}
971f29dbc25Smrg
972f29dbc25Smrg/*---------------------------------------------------------------------------
973f29dbc25Smrg * df_set_video_palette_entry
974f29dbc25Smrg *
975f29dbc25Smrg * This routine loads a single entry of the video hardware palette.
976f29dbc25Smrg *--------------------------------------------------------------------------*/
977f29dbc25Smrg
978f29dbc25Smrgint
979f29dbc25Smrgdf_set_video_palette_entry(unsigned long index, unsigned long palette)
980f29dbc25Smrg{
981f29dbc25Smrg    unsigned long misc, dcfg;
982f29dbc25Smrg
983f29dbc25Smrg    if (index > 0xFF)
984f29dbc25Smrg        return CIM_STATUS_INVALIDPARAMS;
985f29dbc25Smrg
986f29dbc25Smrg    /* SET A SINGLE ENTRY */
987f29dbc25Smrg
988f29dbc25Smrg    WRITE_VID32(DF_PALETTE_ADDRESS, index);
989f29dbc25Smrg    WRITE_VID32(DF_PALETTE_DATA, palette);
990f29dbc25Smrg
991f29dbc25Smrg    /* ENABLE THE VIDEO PALETTE */
992f29dbc25Smrg    /* Ensure that the video palette has an effect by routing video data */
993f29dbc25Smrg    /* through the palette RAM and clearing the 'Bypass Both' bit.       */
994f29dbc25Smrg
995f29dbc25Smrg    dcfg = READ_VID32(DF_DISPLAY_CONFIG);
996f29dbc25Smrg    misc = READ_VID32(DF_VID_MISC);
997f29dbc25Smrg
998170d5fdcSmrg    /* Ensure that the Graphic data passes through the Gamma
999170d5fdcSmrg     * Correction RAM
10007aef237fSmrg     *
10017aef237fSmrg     * XXX is this a bug? perhaps it should be setting the bit so that video
10027aef237fSmrg     * data is routed, according to the description above.
10037aef237fSmrg     * it also mismatches df_set_video_palette().
1004170d5fdcSmrg     */
1005170d5fdcSmrg    dcfg &= ~DF_DCFG_GV_PAL_BYP;
1006170d5fdcSmrg
10077aef237fSmrg    /* Unset the "bypass both" bit to make sure the above selection (gfx/video
10087aef237fSmrg     * data through gamma correction RAM) takes effect.
1009170d5fdcSmrg     */
1010f29dbc25Smrg    misc &= ~DF_GAMMA_BYPASS_BOTH;
1011f29dbc25Smrg
1012f29dbc25Smrg    WRITE_VID32(DF_DISPLAY_CONFIG, dcfg);
1013f29dbc25Smrg    WRITE_VID32(DF_VID_MISC, misc);
1014f29dbc25Smrg
1015f29dbc25Smrg    return CIM_STATUS_OK;
1016f29dbc25Smrg}
1017f29dbc25Smrg
1018f29dbc25Smrg/*---------------------------------------------------------------------------
1019f29dbc25Smrg * df_configure_video_cursor_color_key
1020f29dbc25Smrg *
1021f29dbc25Smrg * This routine configures the hardware video cursor color key mechanism.
1022f29dbc25Smrg *--------------------------------------------------------------------------*/
1023f29dbc25Smrg
1024f29dbc25Smrgint
1025f29dbc25Smrgdf_configure_video_cursor_color_key(DF_VIDEO_CURSOR_PARAMS * cursor_color_key)
1026f29dbc25Smrg{
1027f29dbc25Smrg    unsigned long key;
1028f29dbc25Smrg
1029f29dbc25Smrg    if (cursor_color_key->select_color2 >= 24)
1030f29dbc25Smrg        return CIM_STATUS_INVALIDPARAMS;
1031f29dbc25Smrg
1032f29dbc25Smrg    key = READ_VID32(DF_CURSOR_COLOR_KEY) & DF_CURSOR_COLOR_KEY_ENABLE;
103304007ebaSmrg    key =
103404007ebaSmrg        key | (cursor_color_key->key & 0xFFFFFF) | (cursor_color_key->
103504007ebaSmrg                                                    select_color2 << 24);
1036f29dbc25Smrg
1037f29dbc25Smrg    WRITE_VID32(DF_CURSOR_COLOR_KEY, key);
1038f29dbc25Smrg    WRITE_VID32(DF_CURSOR_COLOR_MASK, (cursor_color_key->mask & 0xFFFFFF));
1039f29dbc25Smrg    WRITE_VID32(DF_CURSOR_COLOR_1, (cursor_color_key->color1 & 0xFFFFFF));
1040f29dbc25Smrg    WRITE_VID32(DF_CURSOR_COLOR_2, (cursor_color_key->color2 & 0xFFFFFF));
1041f29dbc25Smrg
1042f29dbc25Smrg    return CIM_STATUS_OK;
1043f29dbc25Smrg}
1044f29dbc25Smrg
1045f29dbc25Smrg/*---------------------------------------------------------------------------
1046f29dbc25Smrg * df_set_video_cursor_color_key_enable
1047f29dbc25Smrg *
1048f29dbc25Smrg * This routine enables or disables the video cursor color key.
1049f29dbc25Smrg *--------------------------------------------------------------------------*/
1050f29dbc25Smrg
1051f29dbc25Smrgint
1052f29dbc25Smrgdf_set_video_cursor_color_key_enable(int enable)
1053f29dbc25Smrg{
1054f29dbc25Smrg    unsigned long temp = READ_VID32(DF_CURSOR_COLOR_KEY);
1055f29dbc25Smrg
1056f29dbc25Smrg    if (enable)
1057f29dbc25Smrg        temp |= DF_CURSOR_COLOR_KEY_ENABLE;
1058f29dbc25Smrg    else
1059f29dbc25Smrg        temp &= ~DF_CURSOR_COLOR_KEY_ENABLE;
1060f29dbc25Smrg
1061f29dbc25Smrg    WRITE_VID32(DF_CURSOR_COLOR_KEY, temp);
1062f29dbc25Smrg
1063f29dbc25Smrg    return CIM_STATUS_OK;
1064f29dbc25Smrg}
1065f29dbc25Smrg
1066f29dbc25Smrg/*---------------------------------------------------------------------------
1067f29dbc25Smrg * df_configure_alpha_window
1068f29dbc25Smrg *
1069f29dbc25Smrg * This routine configures one of the three hardware alpha regions.
1070f29dbc25Smrg *--------------------------------------------------------------------------*/
1071f29dbc25Smrg
1072f29dbc25Smrgint
1073f29dbc25Smrgdf_configure_alpha_window(int window, DF_ALPHA_REGION_PARAMS * alpha_data)
1074f29dbc25Smrg{
1075f29dbc25Smrg    unsigned long vsyncend_even, vtotal_even, vactive_even;
1076f29dbc25Smrg    unsigned long hsyncend, htotal, hactive;
1077f29dbc25Smrg    unsigned long vsyncend, vtotal, vactive;
1078f29dbc25Smrg    unsigned long alpha_ctl, pos;
1079f29dbc25Smrg    unsigned long hadjust, vadjust;
1080f29dbc25Smrg    unsigned long y, height;
1081f29dbc25Smrg    unsigned long xstart, xend;
1082f29dbc25Smrg    unsigned long ystart, yend;
1083f29dbc25Smrg    unsigned long x_copy, width_copy;
1084f29dbc25Smrg    unsigned long y_copy, height_copy;
1085f29dbc25Smrg    unsigned long scale, src, misc;
1086f29dbc25Smrg    unsigned long gfxscale, fbactive;
1087f29dbc25Smrg    unsigned long color;
1088f29dbc25Smrg
1089f29dbc25Smrg    if (window > 2)
1090f29dbc25Smrg        return CIM_STATUS_INVALIDPARAMS;
1091f29dbc25Smrg
1092f29dbc25Smrg    hsyncend = ((READ_REG32(DC3_H_SYNC_TIMING) >> 16) & 0xFFF) + 1;
1093f29dbc25Smrg    vsyncend = ((READ_REG32(DC3_V_SYNC_TIMING) >> 16) & 0xFFF) + 1;
1094f29dbc25Smrg    htotal = ((READ_REG32(DC3_H_ACTIVE_TIMING) >> 16) & 0xFFF) + 1;
1095f29dbc25Smrg    vtotal = ((READ_REG32(DC3_V_ACTIVE_TIMING) >> 16) & 0xFFF) + 1;
1096f29dbc25Smrg    hactive = (READ_REG32(DC3_H_ACTIVE_TIMING) & 0xFFF) + 1;
1097f29dbc25Smrg    vactive = (READ_REG32(DC3_V_ACTIVE_TIMING) & 0xFFF) + 1;
1098f29dbc25Smrg
1099f29dbc25Smrg    /* APPLY THE GRAPHICS SCALE */
1100f29dbc25Smrg
1101f29dbc25Smrg    width_copy = alpha_data->width;
1102f29dbc25Smrg    height_copy = alpha_data->height;
1103f29dbc25Smrg    x_copy = alpha_data->x;
1104f29dbc25Smrg    y_copy = alpha_data->y;
1105f29dbc25Smrg
1106f29dbc25Smrg    misc = READ_VID32(DF_VID_MISC);
1107f29dbc25Smrg    if (misc & DF_USER_IMPLICIT_SCALING) {
1108f29dbc25Smrg        gfxscale = READ_REG32(DC3_GFX_SCALE);
1109f29dbc25Smrg        fbactive = READ_REG32(DC3_FB_ACTIVE);
1110f29dbc25Smrg
1111f29dbc25Smrg        /* REVERSE ENGINEER THE SCALE FACTOR */
1112f29dbc25Smrg
1113f29dbc25Smrg        scale = gfxscale & 0xFFFF;
1114f29dbc25Smrg        src = (fbactive >> 16) + 1;
1115f29dbc25Smrg        if (scale != 0x4000) {
1116f29dbc25Smrg            width_copy = width_copy * (((0x4000 * src) / scale) + 1);
1117f29dbc25Smrg            width_copy /= src;
1118f29dbc25Smrg            x_copy = x_copy * (((0x4000 * src) / scale) + 1);
1119f29dbc25Smrg            x_copy /= src;
1120f29dbc25Smrg        }
1121f29dbc25Smrg
1122f29dbc25Smrg        scale = gfxscale >> 16;
1123f29dbc25Smrg        src = (fbactive & 0xFFFF) + 1;
1124f29dbc25Smrg        if (scale != 0x4000) {
1125f29dbc25Smrg            height_copy = height_copy * (((0x4000 * src) / scale) + 1);
1126f29dbc25Smrg            height_copy /= src;
1127f29dbc25Smrg            y_copy = y_copy * (((0x4000 * src) / scale) + 1);
1128f29dbc25Smrg            y_copy /= src;
1129f29dbc25Smrg        }
1130f29dbc25Smrg    }
1131f29dbc25Smrg
1132f29dbc25Smrg    /* SET PRIORITY */
1133f29dbc25Smrg    /* Priority is the only alpha parameter that is not in a register that */
1134f29dbc25Smrg    /* can be indexed based on the alpha window number.                    */
1135f29dbc25Smrg
1136f29dbc25Smrg    pos = 16 + (window << 1);
1137f29dbc25Smrg    alpha_ctl = READ_VID32(DF_VID_ALPHA_CONTROL) & ~(3L << pos);
1138f29dbc25Smrg    alpha_ctl |= (alpha_data->priority & 3) << pos;
1139f29dbc25Smrg    WRITE_VID32(DF_VID_ALPHA_CONTROL, alpha_ctl);
1140f29dbc25Smrg
1141f29dbc25Smrg    /* HANDLE INTERLACED MODES */
1142f29dbc25Smrg
1143f29dbc25Smrg    if (READ_REG32(DC3_IRQ_FILT_CTL) & DC3_IRQFILT_INTL_EN) {
1144f29dbc25Smrg        vsyncend_even = ((READ_REG32(DC3_V_SYNC_EVEN) >> 16) & 0xFFF) + 1;
1145f29dbc25Smrg        vtotal_even = ((READ_REG32(DC3_V_ACTIVE_EVEN) >> 16) & 0xFFF) + 1;
1146f29dbc25Smrg        vactive_even = (READ_REG32(DC3_V_ACTIVE_EVEN) & 0xFFF) + 1;
1147f29dbc25Smrg
1148f29dbc25Smrg        y = y_copy >> 1;
1149f29dbc25Smrg
1150f29dbc25Smrg        /* SET Y POSITION FOR ODD FIELD */
1151f29dbc25Smrg
1152f29dbc25Smrg        height = (height_copy + 1) >> 1;
1153f29dbc25Smrg        vadjust = vtotal_even - vsyncend_even + 1;
1154f29dbc25Smrg
1155f29dbc25Smrg        ystart = y + vadjust;
1156f29dbc25Smrg        yend = y + vadjust + height;
1157f29dbc25Smrg
1158f29dbc25Smrg        if (yend > (vactive + vadjust))
1159f29dbc25Smrg            yend = vactive + vadjust;
1160f29dbc25Smrg
116104007ebaSmrg        WRITE_VID32((DF_ALPHA_YPOS_1 + (window << 5)), (ystart | (yend << 16)));
1162f29dbc25Smrg
1163f29dbc25Smrg        /* SET Y POSITION FOR EVEN FIELD */
1164f29dbc25Smrg
1165f29dbc25Smrg        height = height_copy >> 1;
1166f29dbc25Smrg        vadjust = vtotal - vsyncend + 1;
1167f29dbc25Smrg
1168f29dbc25Smrg        ystart = y + vadjust;
1169f29dbc25Smrg        yend = y + vadjust + height;
1170f29dbc25Smrg
1171f29dbc25Smrg        if (yend > (vactive_even + vadjust))
1172f29dbc25Smrg            yend = vactive_even + vadjust;
1173f29dbc25Smrg
1174f29dbc25Smrg        WRITE_VID32((DF_VID_ALPHA_Y_EVEN_1 + (window << 3)),
117504007ebaSmrg                    (ystart | (yend << 16)));
117604007ebaSmrg    }
117704007ebaSmrg    else {
1178f29dbc25Smrg        y = y_copy;
1179f29dbc25Smrg        height = height_copy;
1180f29dbc25Smrg        vadjust = vtotal - vsyncend + 1;
1181f29dbc25Smrg
1182f29dbc25Smrg        ystart = y + vadjust;
1183f29dbc25Smrg        yend = y + vadjust + height;
1184f29dbc25Smrg
1185f29dbc25Smrg        if (yend > (vactive + vadjust))
1186f29dbc25Smrg            yend = vactive + vadjust;
1187f29dbc25Smrg
118804007ebaSmrg        WRITE_VID32((DF_ALPHA_YPOS_1 + (window << 5)), (ystart | (yend << 16)));
1189f29dbc25Smrg    }
1190f29dbc25Smrg
1191f29dbc25Smrg    /* SET ALPHA X POSITION */
1192f29dbc25Smrg    /* The x position is the same for both the odd and even fields. */
1193f29dbc25Smrg
1194f29dbc25Smrg    hadjust = htotal - hsyncend - 2;
1195f29dbc25Smrg
1196f29dbc25Smrg    xstart = x_copy + hadjust;
1197f29dbc25Smrg    xend = x_copy + hadjust + width_copy;
1198f29dbc25Smrg
1199f29dbc25Smrg    if (xend > (hactive + hadjust))
1200f29dbc25Smrg        xend = hactive + hadjust;
1201f29dbc25Smrg
1202f29dbc25Smrg    WRITE_VID32((DF_ALPHA_XPOS_1 + (window << 5)), (xstart | (xend << 16)));
1203f29dbc25Smrg
1204f29dbc25Smrg    /* SET COLOR REGISTER */
1205f29dbc25Smrg
1206f29dbc25Smrg    color = alpha_data->color & 0xFFFFFF;
1207f29dbc25Smrg    if (alpha_data->flags & DF_ALPHAFLAG_COLORENABLED)
1208f29dbc25Smrg        color |= DF_ALPHA_COLOR_ENABLE;
1209f29dbc25Smrg
1210f29dbc25Smrg    WRITE_VID32((DF_ALPHA_COLOR_1 + (window << 5)), color);
1211f29dbc25Smrg
1212f29dbc25Smrg    /* SET ALPHA VALUE, DELTA AND PER PIXEL */
1213f29dbc25Smrg
1214f29dbc25Smrg    alpha_ctl = READ_VID32(DF_ALPHA_CONTROL_1 + (window << 5)) &
1215f29dbc25Smrg        DF_ACTRL_WIN_ENABLE;
1216f29dbc25Smrg    alpha_ctl |= (alpha_data->alpha_value & 0xFF) | DF_ACTRL_LOAD_ALPHA |
121704007ebaSmrg        (((unsigned long) alpha_data->delta & 0xFF) << 8);
1218f29dbc25Smrg    if (alpha_data->flags & DF_ALPHAFLAG_PERPIXELENABLED)
1219f29dbc25Smrg        alpha_ctl |= DF_ACTRL_PERPIXEL_EN;
1220f29dbc25Smrg
1221f29dbc25Smrg    WRITE_VID32((DF_ALPHA_CONTROL_1 + (window << 5)), alpha_ctl);
1222f29dbc25Smrg
1223f29dbc25Smrg    return CIM_STATUS_OK;
1224f29dbc25Smrg}
1225f29dbc25Smrg
1226f29dbc25Smrg/*---------------------------------------------------------------------------
1227f29dbc25Smrg * df_set_alpha_window_enable
1228f29dbc25Smrg *
1229f29dbc25Smrg * This routine enables or disables one of the three hardware alpha regions.
1230f29dbc25Smrg *--------------------------------------------------------------------------*/
1231f29dbc25Smrg
1232f29dbc25Smrgint
1233f29dbc25Smrgdf_set_alpha_window_enable(int window, int enable)
1234f29dbc25Smrg{
1235f29dbc25Smrg    unsigned long alpha_ctl;
1236f29dbc25Smrg
1237f29dbc25Smrg    if (window > 2)
1238f29dbc25Smrg        return CIM_STATUS_INVALIDPARAMS;
1239f29dbc25Smrg
1240f29dbc25Smrg    alpha_ctl = READ_VID32(DF_ALPHA_CONTROL_1 + (window << 5));
1241f29dbc25Smrg    if (enable)
1242f29dbc25Smrg        alpha_ctl |= DF_ACTRL_WIN_ENABLE;
1243f29dbc25Smrg    else
1244f29dbc25Smrg        alpha_ctl &= ~DF_ACTRL_WIN_ENABLE;
1245f29dbc25Smrg    WRITE_VID32((DF_ALPHA_CONTROL_1 + (window << 5)), alpha_ctl);
1246f29dbc25Smrg
1247f29dbc25Smrg    return CIM_STATUS_OK;
1248f29dbc25Smrg}
1249f29dbc25Smrg
1250f29dbc25Smrg/*---------------------------------------------------------------------------
1251f29dbc25Smrg * df_set_no_ck_outside_alpha
1252f29dbc25Smrg *
1253f29dbc25Smrg * This function affects how color/chroma keying is performed inside the video
1254f29dbc25Smrg * window.
1255f29dbc25Smrg *
1256f29dbc25Smrg * If enable is 1, color/chroma key comparison is performed only inside
1257f29dbc25Smrg * the enabled alpha windows. Outside the enabled alpha windows, video
1258f29dbc25Smrg * is displayed if color keying is enabled, or graphics is displayed if
1259f29dbc25Smrg * chroma keying is enabled.
1260f29dbc25Smrg * If enable is 0, color/chroma key comparison is performed inside the
1261f29dbc25Smrg * entire video window.
1262f29dbc25Smrg *--------------------------------------------------------------------------*/
1263f29dbc25Smrg
1264f29dbc25Smrgint
1265f29dbc25Smrgdf_set_no_ck_outside_alpha(int enable)
1266f29dbc25Smrg{
1267f29dbc25Smrg    unsigned long value;
1268f29dbc25Smrg
1269f29dbc25Smrg    value = READ_VID32(DF_VID_ALPHA_CONTROL);
1270f29dbc25Smrg    if (enable)
1271f29dbc25Smrg        value |= DF_NO_CK_OUTSIDE_ALPHA;
1272f29dbc25Smrg    else
1273f29dbc25Smrg        value &= ~DF_NO_CK_OUTSIDE_ALPHA;
1274f29dbc25Smrg    WRITE_VID32(DF_VID_ALPHA_CONTROL, value);
1275f29dbc25Smrg
1276f29dbc25Smrg    return CIM_STATUS_OK;
1277f29dbc25Smrg}
1278f29dbc25Smrg
1279f29dbc25Smrg/*---------------------------------------------------------------------------
1280f29dbc25Smrg * df_set_video_request
1281f29dbc25Smrg *
1282f29dbc25Smrg * This routine sets the horizontal (pixel) and vertical (line) video request
1283f29dbc25Smrg * values.
1284f29dbc25Smrg *--------------------------------------------------------------------------*/
1285f29dbc25Smrg
1286f29dbc25Smrgint
1287f29dbc25Smrgdf_set_video_request(unsigned long x, unsigned long y)
1288f29dbc25Smrg{
1289f29dbc25Smrg    unsigned long htotal, hsyncend;
1290f29dbc25Smrg    unsigned long vtotal, vsyncend;
1291f29dbc25Smrg
1292f29dbc25Smrg    hsyncend = ((READ_REG32(DC3_H_SYNC_TIMING) >> 16) & 0xFFF) + 1;
1293f29dbc25Smrg    vsyncend = ((READ_REG32(DC3_V_SYNC_TIMING) >> 16) & 0xFFF) + 1;
1294f29dbc25Smrg    htotal = ((READ_REG32(DC3_H_ACTIVE_TIMING) >> 16) & 0xFFF) + 1;
1295f29dbc25Smrg    vtotal = ((READ_REG32(DC3_V_ACTIVE_TIMING) >> 16) & 0xFFF) + 1;
1296f29dbc25Smrg
1297f29dbc25Smrg    /* SET DISPLAY FILTER VIDEO REQUEST */
1298f29dbc25Smrg
1299f29dbc25Smrg    x += htotal - hsyncend - 2;
1300f29dbc25Smrg    y += vtotal - vsyncend + 1;
1301f29dbc25Smrg
1302f29dbc25Smrg    if (x >= 0x1000 || y >= 0x800)
1303f29dbc25Smrg        return CIM_STATUS_INVALIDPARAMS;
1304f29dbc25Smrg
1305f29dbc25Smrg    WRITE_VID32(DF_VIDEO_REQUEST, (y | (x << 16)));
1306f29dbc25Smrg    return CIM_STATUS_OK;
1307f29dbc25Smrg}
1308f29dbc25Smrg
1309f29dbc25Smrg/*---------------------------------------------------------------------------
1310f29dbc25Smrg * df_set_output_color_space
1311f29dbc25Smrg *
1312f29dbc25Smrg * This routine sets the color space used when combining graphics and video.
1313f29dbc25Smrg *--------------------------------------------------------------------------*/
1314f29dbc25Smrg
1315f29dbc25Smrgint
1316f29dbc25Smrgdf_set_output_color_space(int color_space)
1317f29dbc25Smrg{
1318f29dbc25Smrg    unsigned long alpha_ctl;
1319f29dbc25Smrg
1320f29dbc25Smrg    alpha_ctl = READ_VID32(DF_VID_ALPHA_CONTROL);
1321f29dbc25Smrg
1322f29dbc25Smrg    alpha_ctl &= ~(DF_CSC_GRAPHICS_RGB_TO_YUV | DF_CSC_VIDEO_YUV_TO_RGB |
132304007ebaSmrg                   DF_HD_GRAPHICS | DF_YUV_CSC_EN | DF_ALPHA_DRGB);
1324f29dbc25Smrg
1325f29dbc25Smrg    /* OUTPUT IS RGB */
1326f29dbc25Smrg    /* Enable YUV->RGB CSC if necessary and enable alpha output if  */
1327f29dbc25Smrg    /* requested.                                                   */
1328f29dbc25Smrg
1329f29dbc25Smrg    if (color_space == DF_OUTPUT_RGB || color_space == DF_OUTPUT_ARGB) {
1330f29dbc25Smrg        if (!(alpha_ctl & DF_VIDEO_INPUT_IS_RGB))
1331f29dbc25Smrg            alpha_ctl |= DF_CSC_VIDEO_YUV_TO_RGB;
1332f29dbc25Smrg
1333f29dbc25Smrg        if (color_space == DF_OUTPUT_ARGB)
1334f29dbc25Smrg            alpha_ctl |= DF_ALPHA_DRGB;
1335f29dbc25Smrg    }
1336f29dbc25Smrg
1337f29dbc25Smrg    /* OUTPUT IS YUV */
1338f29dbc25Smrg    /* Enable YUV->YUV CSC if necessary and enable RGB->YUV CSC. */
1339f29dbc25Smrg
1340f29dbc25Smrg    else if (color_space == DF_OUTPUT_SDTV || color_space == DF_OUTPUT_HDTV) {
1341f29dbc25Smrg        alpha_ctl |= DF_CSC_GRAPHICS_RGB_TO_YUV;
1342f29dbc25Smrg
1343f29dbc25Smrg        if (((alpha_ctl & DF_HD_VIDEO) && color_space == DF_OUTPUT_SDTV) ||
1344f29dbc25Smrg            (!(alpha_ctl & DF_HD_VIDEO) && color_space == DF_OUTPUT_HDTV)) {
1345f29dbc25Smrg            alpha_ctl |= DF_YUV_CSC_EN;
1346f29dbc25Smrg        }
1347f29dbc25Smrg
1348f29dbc25Smrg        if (color_space == DF_OUTPUT_HDTV)
1349f29dbc25Smrg            alpha_ctl |= DF_HD_GRAPHICS;
135004007ebaSmrg    }
135104007ebaSmrg    else
1352f29dbc25Smrg        return CIM_STATUS_INVALIDPARAMS;
1353f29dbc25Smrg
1354f29dbc25Smrg    WRITE_VID32(DF_VID_ALPHA_CONTROL, alpha_ctl);
1355f29dbc25Smrg
1356f29dbc25Smrg    return CIM_STATUS_OK;
1357f29dbc25Smrg}
1358f29dbc25Smrg
1359f29dbc25Smrg/*---------------------------------------------------------------------------
1360f29dbc25Smrg * df_set_output_path
1361f29dbc25Smrg *
1362f29dbc25Smrg * This routine changes the current output path in the display filter.
1363f29dbc25Smrg *--------------------------------------------------------------------------*/
1364f29dbc25Smrg
1365f29dbc25Smrgint
1366f29dbc25Smrgdf_set_output_path(int format)
1367f29dbc25Smrg{
1368f29dbc25Smrg    unsigned long panel_tim2, panel_pm;
1369f29dbc25Smrg    unsigned long output = 0;
1370f29dbc25Smrg    Q_WORD msr_value;
1371f29dbc25Smrg
1372f29dbc25Smrg    msr_read64(MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_CONFIG, &msr_value);
1373f29dbc25Smrg    msr_value.low &= ~(DF_SIMULTANEOUS_CRT_FP | DF_CONFIG_OUTPUT_MASK);
1374f29dbc25Smrg    panel_tim2 = READ_VID32(DF_VIDEO_PANEL_TIM2);
1375f29dbc25Smrg    panel_pm = READ_VID32(DF_POWER_MANAGEMENT);
1376f29dbc25Smrg
1377f29dbc25Smrg    if (format == DF_DISPLAY_CRT) {
1378f29dbc25Smrg        /* SiBZ #4188 */
1379f29dbc25Smrg        /* When CRT output is selected, the DF drives the DISP_EN signal   */
1380f29dbc25Smrg        /* with the CRT display enable.  As a consequence, systems that    */
1381f29dbc25Smrg        /* wire the DISP_EN signal to the TFT backlight control will not   */
1382f29dbc25Smrg        /* be able to set CRT-only output without leaving the backlight    */
1383f29dbc25Smrg        /* enabled.  To workaround this issue, we are setting simultaneous */
1384f29dbc25Smrg        /* TFT/CRT and disabling the TFT logic.  The only caveat to this   */
1385f29dbc25Smrg        /* is that some TFT pins are shared with VIP 601 pins.  VIP 601    */
1386f29dbc25Smrg        /* will thus not work when in this pseudo-CRT mode.  To address    */
1387f29dbc25Smrg        /* THAT issue, normal CRT mode sets (in cim_vg.c) will set CRT     */
1388f29dbc25Smrg        /* as the DF output format.  This will allow VIP 601 on CRT-only   */
1389f29dbc25Smrg        /* systems without a TFT attached.                                 */
1390f29dbc25Smrg
1391f29dbc25Smrg        panel_pm &= ~DF_PM_PANEL_ON;
1392f29dbc25Smrg        panel_tim2 |= DF_PMTIM2_TFT_PASSHTHROUGH;
1393f29dbc25Smrg        output = DF_OUTPUT_PANEL | DF_SIMULTANEOUS_CRT_FP;
139404007ebaSmrg    }
139504007ebaSmrg    else if (format == DF_DISPLAY_FP || format == DF_DISPLAY_CRT_FP) {
1396f29dbc25Smrg        panel_pm |= DF_PM_PANEL_ON;
1397f29dbc25Smrg        panel_tim2 &= ~DF_PMTIM2_TFT_PASSHTHROUGH;
1398f29dbc25Smrg
1399f29dbc25Smrg        if (format == DF_DISPLAY_FP)
1400f29dbc25Smrg            output = DF_OUTPUT_PANEL;
1401f29dbc25Smrg        else if (format == DF_DISPLAY_CRT_FP)
1402f29dbc25Smrg            output = DF_OUTPUT_PANEL | DF_SIMULTANEOUS_CRT_FP;
140304007ebaSmrg    }
140404007ebaSmrg    else {
1405f29dbc25Smrg        switch (format) {
1406f29dbc25Smrg        case DF_DISPLAY_VOP:
1407f29dbc25Smrg            output = DF_OUTPUT_VOP;
1408f29dbc25Smrg            break;
1409f29dbc25Smrg        case DF_DISPLAY_DRGB:
1410f29dbc25Smrg            output = DF_OUTPUT_DRGB;
1411f29dbc25Smrg            break;
1412f29dbc25Smrg        case DF_DISPLAY_CRT_DRGB:
1413f29dbc25Smrg            output = DF_OUTPUT_DRGB | DF_SIMULTANEOUS_CRT_FP;
1414f29dbc25Smrg            break;
1415f29dbc25Smrg        default:
1416f29dbc25Smrg            return CIM_STATUS_INVALIDPARAMS;
1417f29dbc25Smrg        }
1418f29dbc25Smrg    }
1419f29dbc25Smrg    msr_value.low |= output;
1420f29dbc25Smrg    msr_write64(MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_CONFIG, &msr_value);
1421f29dbc25Smrg    WRITE_VID32(DF_VIDEO_PANEL_TIM2, panel_tim2);
1422f29dbc25Smrg    WRITE_VID32(DF_POWER_MANAGEMENT, panel_pm);
1423f29dbc25Smrg
1424f29dbc25Smrg    return CIM_STATUS_OK;
1425f29dbc25Smrg}
1426f29dbc25Smrg
1427f29dbc25Smrg/*---------------------------------------------------------------------------
1428f29dbc25Smrg * df_test_video_flip_status
1429f29dbc25Smrg *
1430f29dbc25Smrg * This routine tests if a new video offset has been latched.
1431f29dbc25Smrg *--------------------------------------------------------------------------*/
1432f29dbc25Smrg
1433f29dbc25Smrgunsigned long
1434f29dbc25Smrgdf_test_video_flip_status(void)
1435f29dbc25Smrg{
1436f29dbc25Smrg    return (READ_REG32(DC3_LINE_CNT_STATUS) & DC3_LNCNT_VFLIP);
1437f29dbc25Smrg}
1438f29dbc25Smrg
1439f29dbc25Smrg/*---------------------------------------------------------------------------
1440f29dbc25Smrg * df_save_state
1441f29dbc25Smrg *
1442f29dbc25Smrg * This routine saves all persistent DF state information.
1443f29dbc25Smrg *--------------------------------------------------------------------------*/
1444f29dbc25Smrg
1445f29dbc25Smrgint
1446f29dbc25Smrgdf_save_state(DF_SAVE_RESTORE * df_state)
1447f29dbc25Smrg{
1448f29dbc25Smrg    unsigned long i;
1449f29dbc25Smrg
1450f29dbc25Smrg    /* READ ALL DF REGISTERS */
1451f29dbc25Smrg
1452f29dbc25Smrg    df_state->vcfg = READ_VID32(DF_VIDEO_CONFIG);
1453f29dbc25Smrg    df_state->dcfg = READ_VID32(DF_DISPLAY_CONFIG);
1454f29dbc25Smrg    df_state->video_x = READ_VID32(DF_VIDEO_X_POS);
1455f29dbc25Smrg    df_state->video_y = READ_VID32(DF_VIDEO_Y_POS);
1456f29dbc25Smrg    df_state->video_scaler = READ_VID32(DF_VIDEO_SCALER);
1457f29dbc25Smrg    df_state->video_color_key = READ_VID32(DF_VIDEO_COLOR_KEY);
1458f29dbc25Smrg    df_state->video_color_mask = READ_VID32(DF_VIDEO_COLOR_MASK);
1459f29dbc25Smrg    df_state->sat_limit = READ_VID32(DF_SATURATION_LIMIT);
1460f29dbc25Smrg    df_state->vid_misc = READ_VID32(DF_VID_MISC);
1461f29dbc25Smrg    df_state->video_yscale = READ_VID32(DF_VIDEO_YSCALE);
1462f29dbc25Smrg    df_state->video_xscale = READ_VID32(DF_VIDEO_XSCALE);
1463f29dbc25Smrg    df_state->vid_alpha_control = READ_VID32(DF_VID_ALPHA_CONTROL);
1464f29dbc25Smrg    df_state->cursor_key = READ_VID32(DF_CURSOR_COLOR_KEY);
1465f29dbc25Smrg    df_state->cursor_mask = READ_VID32(DF_CURSOR_COLOR_MASK);
1466f29dbc25Smrg    df_state->cursor_color1 = READ_VID32(DF_CURSOR_COLOR_1);
1467f29dbc25Smrg    df_state->cursor_color2 = READ_VID32(DF_CURSOR_COLOR_2);
1468f29dbc25Smrg    df_state->alpha_xpos1 = READ_VID32(DF_ALPHA_XPOS_1);
1469f29dbc25Smrg    df_state->alpha_ypos1 = READ_VID32(DF_ALPHA_YPOS_1);
1470f29dbc25Smrg    df_state->alpha_color1 = READ_VID32(DF_ALPHA_COLOR_1);
1471f29dbc25Smrg    df_state->alpha_control1 = READ_VID32(DF_ALPHA_CONTROL_1);
1472f29dbc25Smrg    df_state->alpha_xpos2 = READ_VID32(DF_ALPHA_XPOS_2);
1473f29dbc25Smrg    df_state->alpha_ypos2 = READ_VID32(DF_ALPHA_YPOS_2);
1474f29dbc25Smrg    df_state->alpha_color2 = READ_VID32(DF_ALPHA_COLOR_2);
1475f29dbc25Smrg    df_state->alpha_control2 = READ_VID32(DF_ALPHA_CONTROL_2);
1476f29dbc25Smrg    df_state->alpha_xpos3 = READ_VID32(DF_ALPHA_XPOS_3);
1477f29dbc25Smrg    df_state->alpha_ypos3 = READ_VID32(DF_ALPHA_YPOS_3);
1478f29dbc25Smrg    df_state->alpha_color3 = READ_VID32(DF_ALPHA_COLOR_3);
1479f29dbc25Smrg    df_state->alpha_control3 = READ_VID32(DF_ALPHA_CONTROL_3);
1480f29dbc25Smrg    df_state->vid_request = READ_VID32(DF_VIDEO_REQUEST);
1481f29dbc25Smrg    df_state->vid_ypos_even = READ_VID32(DF_VID_YPOS_EVEN);
1482f29dbc25Smrg    df_state->alpha_ypos_even1 = READ_VID32(DF_VID_ALPHA_Y_EVEN_1);
1483f29dbc25Smrg    df_state->alpha_ypos_even2 = READ_VID32(DF_VID_ALPHA_Y_EVEN_2);
1484f29dbc25Smrg    df_state->alpha_ypos_even3 = READ_VID32(DF_VID_ALPHA_Y_EVEN_3);
1485f29dbc25Smrg    df_state->panel_tim1 = READ_VID32(DF_VIDEO_PANEL_TIM1);
1486f29dbc25Smrg    df_state->panel_tim2 = READ_VID32(DF_VIDEO_PANEL_TIM2);
1487f29dbc25Smrg    df_state->panel_pm = READ_VID32(DF_POWER_MANAGEMENT);
1488f29dbc25Smrg    df_state->panel_dither = READ_VID32(DF_DITHER_CONTROL);
1489f29dbc25Smrg
1490f29dbc25Smrg    /* READ DF PALETTE */
1491f29dbc25Smrg
1492f29dbc25Smrg    WRITE_VID32(DF_PALETTE_ADDRESS, 0);
1493f29dbc25Smrg    for (i = 0; i < 256; i++)
1494f29dbc25Smrg        df_state->palette[i] = READ_VID32(DF_PALETTE_DATA);
1495f29dbc25Smrg
1496f29dbc25Smrg    /* READ FILTER COEFFICIENTS */
1497f29dbc25Smrg
1498f29dbc25Smrg    for (i = 0; i < 512; i++)
149904007ebaSmrg        df_state->coefficients[i] = READ_VID32(DF_COEFFICIENT_BASE + (i << 2));
1500f29dbc25Smrg
1501f29dbc25Smrg    /* READ ALL DF MSRS */
1502f29dbc25Smrg
150304007ebaSmrg    msr_read64(MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_CAP, &(df_state->msr_cap));
1504f29dbc25Smrg    msr_read64(MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_CONFIG,
150504007ebaSmrg               &(df_state->msr_config));
150604007ebaSmrg    msr_read64(MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_SMI, &(df_state->msr_smi));
1507f29dbc25Smrg    msr_read64(MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_ERROR,
150804007ebaSmrg               &(df_state->msr_error));
1509f29dbc25Smrg    msr_read64(MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_PM, &(df_state->msr_pm));
1510f29dbc25Smrg    msr_read64(MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_DIAG,
151104007ebaSmrg               &(df_state->msr_diag));
1512f29dbc25Smrg    msr_read64(MSR_DEVICE_GEODELX_DF, DF_MBD_MSR_DIAG_DF,
151304007ebaSmrg               &(df_state->msr_df_diag));
151404007ebaSmrg    msr_read64(MSR_DEVICE_GEODELX_DF, DF_MSR_PAD_SEL, &(df_state->msr_pad_sel));
1515f29dbc25Smrg
1516f29dbc25Smrg    return CIM_STATUS_OK;
1517f29dbc25Smrg}
1518f29dbc25Smrg
1519f29dbc25Smrg/*---------------------------------------------------------------------------
1520f29dbc25Smrg * df_restore_state
1521f29dbc25Smrg *
1522f29dbc25Smrg * This routine restores all persistent DF state information.
1523f29dbc25Smrg *--------------------------------------------------------------------------*/
1524f29dbc25Smrg
1525f29dbc25Smrgint
1526f29dbc25Smrgdf_restore_state(DF_SAVE_RESTORE * df_state)
1527f29dbc25Smrg{
1528f29dbc25Smrg    unsigned long i;
1529f29dbc25Smrg
1530f29dbc25Smrg    /* CLEAR VCFG AND DCFG */
1531f29dbc25Smrg
1532f29dbc25Smrg    WRITE_VID32(DF_VIDEO_CONFIG, 0);
1533f29dbc25Smrg    WRITE_VID32(DF_DISPLAY_CONFIG, 0);
1534f29dbc25Smrg
1535f29dbc25Smrg    /* RESTORE DF MSRS */
1536f29dbc25Smrg
153704007ebaSmrg    msr_write64(MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_CAP, &(df_state->msr_cap));
1538f29dbc25Smrg    msr_write64(MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_CONFIG,
153904007ebaSmrg                &(df_state->msr_config));
154004007ebaSmrg    msr_write64(MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_SMI, &(df_state->msr_smi));
1541f29dbc25Smrg    msr_write64(MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_ERROR,
154204007ebaSmrg                &(df_state->msr_error));
1543f29dbc25Smrg    msr_write64(MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_PM, &(df_state->msr_pm));
1544f29dbc25Smrg    msr_write64(MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_DIAG,
154504007ebaSmrg                &(df_state->msr_diag));
1546f29dbc25Smrg    msr_write64(MSR_DEVICE_GEODELX_DF, DF_MBD_MSR_DIAG_DF,
154704007ebaSmrg                &(df_state->msr_df_diag));
1548f29dbc25Smrg    msr_write64(MSR_DEVICE_GEODELX_DF, DF_MSR_PAD_SEL,
154904007ebaSmrg                &(df_state->msr_pad_sel));
1550f29dbc25Smrg
1551f29dbc25Smrg    /* RESTORE ALL DF REGISTERS */
1552f29dbc25Smrg
1553f29dbc25Smrg    WRITE_VID32(DF_VIDEO_X_POS, df_state->video_x);
1554f29dbc25Smrg    WRITE_VID32(DF_VIDEO_Y_POS, df_state->video_y);
1555f29dbc25Smrg    WRITE_VID32(DF_VIDEO_SCALER, df_state->video_scaler);
1556f29dbc25Smrg    WRITE_VID32(DF_VIDEO_COLOR_KEY, df_state->video_color_key);
1557f29dbc25Smrg    WRITE_VID32(DF_VIDEO_COLOR_MASK, df_state->video_color_mask);
1558f29dbc25Smrg    WRITE_VID32(DF_SATURATION_LIMIT, df_state->sat_limit);
1559f29dbc25Smrg    WRITE_VID32(DF_VID_MISC, df_state->vid_misc);
1560f29dbc25Smrg    WRITE_VID32(DF_VIDEO_YSCALE, df_state->video_yscale);
1561f29dbc25Smrg    WRITE_VID32(DF_VIDEO_XSCALE, df_state->video_xscale);
1562f29dbc25Smrg    WRITE_VID32(DF_VID_ALPHA_CONTROL, df_state->vid_alpha_control);
1563f29dbc25Smrg    WRITE_VID32(DF_CURSOR_COLOR_KEY, df_state->cursor_key);
1564f29dbc25Smrg    WRITE_VID32(DF_CURSOR_COLOR_MASK, df_state->cursor_mask);
1565f29dbc25Smrg    WRITE_VID32(DF_CURSOR_COLOR_1, df_state->cursor_color1);
1566f29dbc25Smrg    WRITE_VID32(DF_CURSOR_COLOR_2, df_state->cursor_color2);
1567f29dbc25Smrg    WRITE_VID32(DF_ALPHA_XPOS_1, df_state->alpha_xpos1);
1568f29dbc25Smrg    WRITE_VID32(DF_ALPHA_YPOS_1, df_state->alpha_ypos1);
1569f29dbc25Smrg    WRITE_VID32(DF_ALPHA_COLOR_1, df_state->alpha_color1);
1570f29dbc25Smrg    WRITE_VID32(DF_ALPHA_CONTROL_1, df_state->alpha_control1);
1571f29dbc25Smrg    WRITE_VID32(DF_ALPHA_XPOS_2, df_state->alpha_xpos2);
1572f29dbc25Smrg    WRITE_VID32(DF_ALPHA_YPOS_2, df_state->alpha_ypos2);
1573f29dbc25Smrg    WRITE_VID32(DF_ALPHA_COLOR_2, df_state->alpha_color2);
1574f29dbc25Smrg    WRITE_VID32(DF_ALPHA_CONTROL_2, df_state->alpha_control1);
1575f29dbc25Smrg    WRITE_VID32(DF_ALPHA_XPOS_3, df_state->alpha_xpos3);
1576f29dbc25Smrg    WRITE_VID32(DF_ALPHA_YPOS_3, df_state->alpha_ypos3);
1577f29dbc25Smrg    WRITE_VID32(DF_ALPHA_COLOR_3, df_state->alpha_color3);
1578f29dbc25Smrg    WRITE_VID32(DF_ALPHA_CONTROL_3, df_state->alpha_control3);
1579f29dbc25Smrg    WRITE_VID32(DF_VIDEO_REQUEST, df_state->vid_request);
1580f29dbc25Smrg    WRITE_VID32(DF_VID_YPOS_EVEN, df_state->vid_ypos_even);
1581f29dbc25Smrg    WRITE_VID32(DF_VID_ALPHA_Y_EVEN_1, df_state->alpha_ypos_even1);
1582f29dbc25Smrg    WRITE_VID32(DF_VID_ALPHA_Y_EVEN_2, df_state->alpha_ypos_even2);
1583f29dbc25Smrg    WRITE_VID32(DF_VID_ALPHA_Y_EVEN_3, df_state->alpha_ypos_even3);
1584f29dbc25Smrg    WRITE_VID32(DF_VIDEO_PANEL_TIM1, df_state->panel_tim1);
1585f29dbc25Smrg    WRITE_VID32(DF_VIDEO_PANEL_TIM2, df_state->panel_tim2);
1586f29dbc25Smrg    WRITE_VID32(DF_POWER_MANAGEMENT, df_state->panel_pm);
1587f29dbc25Smrg    WRITE_VID32(DF_DITHER_CONTROL, df_state->panel_dither);
1588f29dbc25Smrg
1589f29dbc25Smrg    /* RESTORE DF PALETTE */
1590f29dbc25Smrg
1591f29dbc25Smrg    WRITE_VID32(DF_PALETTE_ADDRESS, 0);
1592f29dbc25Smrg    for (i = 0; i < 256; i++)
1593f29dbc25Smrg        WRITE_VID32(DF_PALETTE_DATA, df_state->palette[i]);
1594f29dbc25Smrg
1595f29dbc25Smrg    /* RESTORE FILTER COEFFICIENTS */
1596f29dbc25Smrg
1597f29dbc25Smrg    for (i = 0; i < 512; i++)
159804007ebaSmrg        WRITE_VID32(DF_COEFFICIENT_BASE + (i << 2), df_state->coefficients[i]);
1599f29dbc25Smrg
1600f29dbc25Smrg    /* RESTORE DCFG AND VCFG */
1601f29dbc25Smrg
1602f29dbc25Smrg    WRITE_VID32(DF_DISPLAY_CONFIG, df_state->dcfg);
1603f29dbc25Smrg    WRITE_VID32(DF_VIDEO_CONFIG, df_state->vcfg);
1604f29dbc25Smrg
1605f29dbc25Smrg    return CIM_STATUS_OK;
1606f29dbc25Smrg}
1607f29dbc25Smrg
1608f29dbc25Smrg/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1609f29dbc25Smrg * CIMARRON DF READ ROUTINES
1610f29dbc25Smrg * These routines are included for use in diagnostics or when debugging.  They
1611f29dbc25Smrg * can be optionally excluded from a project.
1612f29dbc25Smrg *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
1613f29dbc25Smrg
1614f29dbc25Smrg#if CIMARRON_INCLUDE_DF_READ_ROUTINES
1615f29dbc25Smrg
1616f29dbc25Smrg/*---------------------------------------------------------------------------
1617f29dbc25Smrg * df_read_composite_crc
1618f29dbc25Smrg *
1619f29dbc25Smrg * This routine reads the CRC of the combination of graphics/video data.  This
1620f29dbc25Smrg * CRC checks data immediately before the CRT DACs.
1621f29dbc25Smrg *--------------------------------------------------------------------------*/
1622f29dbc25Smrg
1623f29dbc25Smrgunsigned long
1624f29dbc25Smrgdf_read_composite_crc(int crc_source)
1625f29dbc25Smrg{
1626f29dbc25Smrg    Q_WORD msr_value;
1627f29dbc25Smrg    unsigned long crc;
1628f29dbc25Smrg    unsigned long interlaced;
1629f29dbc25Smrg    unsigned long line, field;
1630f29dbc25Smrg    unsigned long timeout = 1000;
1631f29dbc25Smrg
1632f29dbc25Smrg    if (!(READ_REG32(DC3_DISPLAY_CFG) & DC3_DCFG_TGEN))
1633f29dbc25Smrg        return 0xFFFFFFFF;
1634f29dbc25Smrg
1635f29dbc25Smrg    /* ENABLE 32-BIT CRCS */
1636f29dbc25Smrg
1637f29dbc25Smrg    msr_read64(MSR_DEVICE_GEODELX_DF, DF_MBD_MSR_DIAG_DF, &msr_value);
1638f29dbc25Smrg    msr_value.low |= DF_DIAG_32BIT_CRC;
1639f29dbc25Smrg    msr_write64(MSR_DEVICE_GEODELX_DF, DF_MBD_MSR_DIAG_DF, &msr_value);
1640f29dbc25Smrg
1641f29dbc25Smrg    /* RESET THE CRC */
1642f29dbc25Smrg
1643f29dbc25Smrg    WRITE_VID32(DF_VID_CRC, 0);
1644f29dbc25Smrg
1645f29dbc25Smrg    /* WAIT FOR THE RESET TO BE LATCHED */
1646f29dbc25Smrg
1647f29dbc25Smrg    while ((READ_VID32(DF_VID_CRC32) != 0x00000001) && timeout)
1648f29dbc25Smrg        timeout--;
1649f29dbc25Smrg
1650f29dbc25Smrg    /* WAIT FOR THE CORRECT FIELD */
1651f29dbc25Smrg    /* We use the VG line count and field indicator to determine when */
1652f29dbc25Smrg    /* to kick off a CRC.                                             */
1653f29dbc25Smrg
1654f29dbc25Smrg    if (crc_source & DF_CRC_SOURCE_EVEN)
1655f29dbc25Smrg        field = 0;
1656f29dbc25Smrg    else
1657f29dbc25Smrg        field = DC3_LNCNT_EVEN_FIELD;
1658f29dbc25Smrg
1659f29dbc25Smrg    if ((interlaced = (READ_REG32(DC3_IRQ_FILT_CTL) & DC3_IRQFILT_INTL_EN))) {
1660f29dbc25Smrg        /* WAIT FOR THE BEGINNING OF THE FIELD (LINE 1-5) */
1661f29dbc25Smrg        /* Note that we wait for the field to be odd when CRCing the even */
1662f29dbc25Smrg        /* field and vice versa.  This is because the CRC will not begin  */
1663f29dbc25Smrg        /* until the following field.                                     */
1664f29dbc25Smrg
1665f29dbc25Smrg        do {
1666f29dbc25Smrg            line = READ_REG32(DC3_LINE_CNT_STATUS);
1667f29dbc25Smrg        } while ((line & DC3_LNCNT_EVEN_FIELD) != field ||
166804007ebaSmrg                 ((line & DC3_LNCNT_V_LINE_CNT) >> 16) < 10 ||
166904007ebaSmrg                 ((line & DC3_LNCNT_V_LINE_CNT) >> 16) > 15);
167004007ebaSmrg    }
167104007ebaSmrg    else {
1672f29dbc25Smrg        /* NON-INTERLACED - EVEN FIELD CRCS ARE INVALID */
1673f29dbc25Smrg
1674f29dbc25Smrg        if (crc_source & DF_CRC_SOURCE_EVEN)
1675f29dbc25Smrg            return 0xFFFFFFFF;
1676f29dbc25Smrg    }
1677f29dbc25Smrg
1678f29dbc25Smrg    /* ENABLE THE CRC */
1679f29dbc25Smrg
1680f29dbc25Smrg    WRITE_VID32(DF_VID_CRC, 1);
1681f29dbc25Smrg
1682f29dbc25Smrg    /* WAIT FOR THE CRC TO BE COMPLETED */
1683f29dbc25Smrg
168404007ebaSmrg    while (!(READ_VID32(DF_VID_CRC) & 4));
1685f29dbc25Smrg
1686f29dbc25Smrg    crc = READ_VID32(DF_VID_CRC32);
1687f29dbc25Smrg
1688f29dbc25Smrg    return crc;
1689f29dbc25Smrg}
1690f29dbc25Smrg
1691f29dbc25Smrg/*---------------------------------------------------------------------------
1692f29dbc25Smrg * df_read_composite_window_crc
1693f29dbc25Smrg *
1694f29dbc25Smrg * This routine reads the CRC of a rectangular subsection of the combination
1695f29dbc25Smrg * of graphics/video data.
1696f29dbc25Smrg *--------------------------------------------------------------------------*/
1697f29dbc25Smrg
1698f29dbc25Smrgunsigned long
1699f29dbc25Smrgdf_read_composite_window_crc(unsigned long x, unsigned long y,
170004007ebaSmrg                             unsigned long width, unsigned long height,
170104007ebaSmrg                             int source)
1702f29dbc25Smrg{
1703f29dbc25Smrg    Q_WORD msr_value;
1704f29dbc25Smrg    unsigned long interlaced;
1705f29dbc25Smrg    unsigned long line, field;
1706f29dbc25Smrg    unsigned long crc = 0;
1707f29dbc25Smrg    unsigned long hsyncend, htotal, hsyncstart;
1708f29dbc25Smrg    unsigned long vsyncend, vtotal, vsyncstart;
1709f29dbc25Smrg    unsigned long hblankstart, hactive;
1710f29dbc25Smrg    unsigned long vblankstart, vactive;
1711f29dbc25Smrg
1712f29dbc25Smrg    hsyncend = ((READ_REG32(DC3_H_SYNC_TIMING) >> 16) & 0xFFF) + 1;
1713f29dbc25Smrg    htotal = ((READ_REG32(DC3_H_ACTIVE_TIMING) >> 16) & 0xFFF) + 1;
1714f29dbc25Smrg    hsyncstart = (READ_REG32(DC3_H_SYNC_TIMING) & 0xFFF) + 1;
1715f29dbc25Smrg    hactive = (READ_REG32(DC3_H_ACTIVE_TIMING) & 0xFFF) + 1;
1716f29dbc25Smrg    hblankstart = (READ_REG32(DC3_H_BLANK_TIMING) & 0xFFF) + 1;
1717f29dbc25Smrg    if ((interlaced = (READ_REG32(DC3_IRQ_FILT_CTL) & DC3_IRQFILT_INTL_EN)) &&
1718f29dbc25Smrg        !(source & DF_CRC_SOURCE_EVEN)) {
1719f29dbc25Smrg        vsyncend = ((READ_REG32(DC3_V_SYNC_EVEN) >> 16) & 0xFFF) + 1;
1720f29dbc25Smrg        vtotal = ((READ_REG32(DC3_V_ACTIVE_EVEN) >> 16) & 0xFFF) + 1;
1721f29dbc25Smrg        vsyncstart = (READ_REG32(DC3_V_SYNC_EVEN) & 0xFFF) + 1;
1722f29dbc25Smrg        vactive = (READ_REG32(DC3_V_ACTIVE_EVEN) & 0xFFF) + 1;
1723f29dbc25Smrg        vblankstart = (READ_REG32(DC3_V_BLANK_EVEN) & 0xFFF) + 1;
172404007ebaSmrg    }
172504007ebaSmrg    else {
1726f29dbc25Smrg        vsyncend = ((READ_REG32(DC3_V_SYNC_TIMING) >> 16) & 0xFFF) + 1;
1727f29dbc25Smrg        vtotal = ((READ_REG32(DC3_V_ACTIVE_TIMING) >> 16) & 0xFFF) + 1;
1728f29dbc25Smrg        vsyncstart = (READ_REG32(DC3_V_SYNC_TIMING) & 0xFFF) + 1;
1729f29dbc25Smrg        vactive = (READ_REG32(DC3_V_ACTIVE_TIMING) & 0xFFF) + 1;
1730f29dbc25Smrg        vblankstart = (READ_REG32(DC3_V_BLANK_TIMING) & 0xFFF) + 1;
1731f29dbc25Smrg    }
1732f29dbc25Smrg
1733f29dbc25Smrg    /* TIMINGS MUST BE ACTIVE */
1734f29dbc25Smrg
1735f29dbc25Smrg    if (!(READ_REG32(DC3_DISPLAY_CFG) & DC3_DCFG_TGEN))
1736f29dbc25Smrg        return 0xFFFFFFFF;
1737f29dbc25Smrg
1738f29dbc25Smrg    /* DISABLE GLCP ACTIONS */
1739f29dbc25Smrg
1740f29dbc25Smrg    msr_value.low = 0;
1741f29dbc25Smrg    msr_value.high = 0;
1742f29dbc25Smrg    msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_DIAGCTL, &msr_value);
1743f29dbc25Smrg
1744f29dbc25Smrg    /* ENABLE HW CLOCK GATING AND SET GLCP CLOCK TO DOT CLOCK */
1745f29dbc25Smrg
1746f29dbc25Smrg    msr_value.low = 5;
1747f29dbc25Smrg    msr_write64(MSR_DEVICE_GEODELX_GLCP, MSR_GEODELINK_PM, &msr_value);
1748f29dbc25Smrg    msr_value.low = 0;
1749f29dbc25Smrg    msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_DBGCLKCTL, &msr_value);
1750f29dbc25Smrg    msr_value.low = 3;
1751f29dbc25Smrg    msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_DBGCLKCTL, &msr_value);
1752f29dbc25Smrg
1753f29dbc25Smrg    /* USE H4 FUNCTION A FOR HSYNC AND H4 FUNCTION B FOR NOT HSYNC */
1754f29dbc25Smrg    /* HSYNC is bit 30 for the DF                                  */
1755f29dbc25Smrg
1756f29dbc25Smrg    msr_value.high = 0x00000001;
1757f29dbc25Smrg    msr_value.low = 0xE0000FF0;
1758f29dbc25Smrg    msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_H0CTL + 4, &msr_value);
1759f29dbc25Smrg
1760f29dbc25Smrg    /* USE H3 FUNCTION A FOR VSYNC AND H3 FUNCTION B FOR NOT VSYNC */
1761f29dbc25Smrg    /* VSYNC is bit 54 for VG and bit 29 for DF                    */
1762f29dbc25Smrg
1763f29dbc25Smrg    msr_value.high = 0x00000000;
1764f29dbc25Smrg    msr_value.low = 0x001D55AA;
1765f29dbc25Smrg    msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_H0CTL + 3, &msr_value);
1766f29dbc25Smrg
1767f29dbc25Smrg    /* M4 (XSTATE = 00 AND VSYNC HIGH) */
1768f29dbc25Smrg    /* Goto state 01                   */
1769f29dbc25Smrg    /* Note: VSync = H3A               */
1770f29dbc25Smrg
1771f29dbc25Smrg    msr_value.high = 0x00000001;
1772f29dbc25Smrg    msr_value.low = 0x000000A0;
1773f29dbc25Smrg    msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_SETM0CTL + 4, &msr_value);
1774f29dbc25Smrg
1775f29dbc25Smrg    /* N0 (XSTATE = 01 AND VSYNC LOW) */
1776f29dbc25Smrg    /* Goto state 02                  */
1777f29dbc25Smrg    /* Note: VSync low = H3B          */
1778f29dbc25Smrg
1779f29dbc25Smrg    msr_value.high = 0x00040000;
1780f29dbc25Smrg    msr_value.low = 0x000000C0;
1781f29dbc25Smrg    msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_SETN0CTL, &msr_value);
1782f29dbc25Smrg
1783f29dbc25Smrg    /* M5 (XSTATE = 10 AND VSYNC HIGH) */
1784f29dbc25Smrg    /* Goto state 11                   */
1785f29dbc25Smrg
1786f29dbc25Smrg    msr_value.high = 0x00000001;
1787f29dbc25Smrg    msr_value.low = 0x00000120;
1788f29dbc25Smrg    msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_SETM0CTL + 5, &msr_value);
1789f29dbc25Smrg
1790f29dbc25Smrg    /* N1 (XSTATE = 10 and HSYNC LOW) */
1791f29dbc25Smrg    /* Increment H. Counter           */
1792f29dbc25Smrg    /* Note: HSync = H4               */
1793f29dbc25Smrg
1794f29dbc25Smrg    msr_value.high = 0x00080000;
1795f29dbc25Smrg    msr_value.low = 0x00000120;
1796f29dbc25Smrg    msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_SETN0CTL + 1, &msr_value);
1797f29dbc25Smrg
1798f29dbc25Smrg    /* M0 (XSTATE = 10 and H. COUNTER == LIMIT)  */
1799f29dbc25Smrg    /* Clear H. Counter and increment V. Counter */
1800f29dbc25Smrg
1801f29dbc25Smrg    msr_value.high = 0x00000000;
1802f29dbc25Smrg    msr_value.low = 0x00000122;
1803f29dbc25Smrg    msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_SETM0CTL, &msr_value);
1804f29dbc25Smrg
1805f29dbc25Smrg    /* N4 (XSTATE = 10 && CMP0 <= H. COUNTER <= CMP1 && CMP2 <= V. COUNTER
1806f29dbc25Smrg     * <= CMP3)
1807f29dbc25Smrg     * CRC into REGB
1808f29dbc25Smrg     */
1809f29dbc25Smrg
1810f29dbc25Smrg    msr_value.high = 0x00000000;
1811f29dbc25Smrg    msr_value.low = 0x10C20120;
1812f29dbc25Smrg    msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_SETN0CTL + 4, &msr_value);
1813f29dbc25Smrg
1814f29dbc25Smrg    /* COMPARATOR 0 VALUE                                   */
1815f29dbc25Smrg    /* Value = xstart + (htotal - hsync_end) - 1            */
1816f29dbc25Smrg    /* The value will be adjusted for a border if necessary */
1817f29dbc25Smrg
1818f29dbc25Smrg    msr_value.low = x + htotal - hsyncend - 1;
1819f29dbc25Smrg    if (READ_REG32(DC3_DISPLAY_CFG) & DC3_DCFG_DCEN)
1820f29dbc25Smrg        msr_value.low -= hblankstart - hactive;
1821f29dbc25Smrg    msr_value.low--;
1822f29dbc25Smrg    msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_CMPVAL0, &msr_value);
1823f29dbc25Smrg
1824f29dbc25Smrg    /* COMPARATOR 1 VALUE                                    */
1825f29dbc25Smrg    /* Value = xstart + (htotal - hsync_end - 1) - 1 + width */
1826f29dbc25Smrg
1827f29dbc25Smrg    msr_value.low += width - 1;
1828f29dbc25Smrg    msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_CMPVAL0 + 2, &msr_value);
1829f29dbc25Smrg
1830f29dbc25Smrg    /* COMPARATOR 2 VALUE                 */
1831f29dbc25Smrg    /* Value = ystart + vtotal - vsyncend */
1832f29dbc25Smrg
1833f29dbc25Smrg    msr_value.low = (y + vtotal - vsyncend) << 16;
1834f29dbc25Smrg    if (READ_REG32(DC3_DISPLAY_CFG) & DC3_DCFG_DCEN)
1835f29dbc25Smrg        msr_value.low -= (vblankstart - vactive) << 16;
1836f29dbc25Smrg    msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_CMPVAL0 + 4, &msr_value);
1837f29dbc25Smrg
1838f29dbc25Smrg    /* COMPARATOR 3 VALUE                              */
1839f29dbc25Smrg    /* Value = ystart + vtotal - vsyncend + height - 1 */
1840f29dbc25Smrg
1841f29dbc25Smrg    msr_value.low += (height - 1) << 16;
1842f29dbc25Smrg    msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_CMPVAL0 + 6, &msr_value);
1843f29dbc25Smrg
1844f29dbc25Smrg    /* COMPARATOR MASKS */
1845f29dbc25Smrg    /* Comparators 0 and 1 refer to lower 16 bits of RegB */
1846f29dbc25Smrg
1847f29dbc25Smrg    msr_value.low = 0x0000FFFF;
1848f29dbc25Smrg    msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_CMPMASK0, &msr_value);
1849f29dbc25Smrg    msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_CMPMASK0 + 2, &msr_value);
1850f29dbc25Smrg
1851f29dbc25Smrg    /* Comparators 2 and 3 refer to upper 16 bits of RegB */
1852f29dbc25Smrg
1853f29dbc25Smrg    msr_value.low = 0xFFFF0000;
1854f29dbc25Smrg    msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_CMPMASK0 + 4, &msr_value);
1855f29dbc25Smrg    msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_CMPMASK0 + 6, &msr_value);
1856f29dbc25Smrg
1857f29dbc25Smrg    /* SET REGB MASK                                                */
1858f29dbc25Smrg    /* We set the mask such that all only 24 bits of data are CRCed */
1859f29dbc25Smrg
1860f29dbc25Smrg    msr_value.low = 0x00FFFFFF;
1861f29dbc25Smrg    msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_REGBMASK, &msr_value);
1862f29dbc25Smrg
1863f29dbc25Smrg    /* SET REGA LIMITS                              */
1864f29dbc25Smrg    /* Lower counter uses htotal - sync_time - 1.   */
1865f29dbc25Smrg    /* Upper counter is 0xFFFF to prevent rollover. */
1866f29dbc25Smrg
1867f29dbc25Smrg    msr_value.low = 0xFFFF0000 | (htotal - (hsyncend - hsyncstart) - 1);
1868f29dbc25Smrg    msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_REGAVAL, &msr_value);
1869f29dbc25Smrg
1870f29dbc25Smrg    /* ACTIONS */
1871f29dbc25Smrg
1872f29dbc25Smrg    /* STATE 00->01 (SET 4M) */
1873f29dbc25Smrg
1874f29dbc25Smrg    msr_value.low = 0x000C0000;
1875f29dbc25Smrg    msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 14, &msr_value);
1876f29dbc25Smrg
1877f29dbc25Smrg    /* STATE 01->10 (SET 0N) */
1878f29dbc25Smrg
1879f29dbc25Smrg    msr_value.low = 0x0000000A;
1880f29dbc25Smrg    msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 15, &msr_value);
1881f29dbc25Smrg
1882f29dbc25Smrg    /* STATE 10->11 (SET 5M) */
1883f29dbc25Smrg
1884f29dbc25Smrg    msr_value.low = 0x00C00000;
1885f29dbc25Smrg    msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 16, &msr_value);
1886f29dbc25Smrg
1887f29dbc25Smrg    /* CLEAR REGA WHEN TRANSITIONING TO STATE 10                 */
1888f29dbc25Smrg    /* Do not clear RegB as the initial value must be 0x00000001 */
1889f29dbc25Smrg
1890f29dbc25Smrg    msr_value.low = 0x0000000A;
1891f29dbc25Smrg    msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0, &msr_value);
1892f29dbc25Smrg
1893f29dbc25Smrg    /* REGISTER ACTION 1 */
1894f29dbc25Smrg    /* CRC into RegB if cmp0 <= h.counter <= cmp1 && cmp2 <= v. counter <
1895f29dbc25Smrg     * cmp3 && 7 xstate = 10 8
1896f29dbc25Smrg     * Increment h.counter if xstate = 10 and HSync is low.
1897f29dbc25Smrg     */
1898f29dbc25Smrg
1899f29dbc25Smrg    msr_value.low = 0x000A00A0;
1900f29dbc25Smrg    msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 1, &msr_value);
1901f29dbc25Smrg
1902f29dbc25Smrg    /* REGISTER ACTION 2            */
1903f29dbc25Smrg    /* Increment V. Counter in REGA */
1904f29dbc25Smrg
1905f29dbc25Smrg    msr_value.low = 0x0000000C;
1906f29dbc25Smrg    msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 2, &msr_value);
1907f29dbc25Smrg
1908f29dbc25Smrg    /* SET REGB TO 0x00000001 */
1909f29dbc25Smrg
1910f29dbc25Smrg    msr_value.low = 0x00000001;
1911f29dbc25Smrg    msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_REGB, &msr_value);
1912f29dbc25Smrg
1913f29dbc25Smrg    /* SET XSTATE TO 0 */
1914f29dbc25Smrg
1915f29dbc25Smrg    msr_value.low = 0x00000000;
1916f29dbc25Smrg    msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_XSTATE, &msr_value);
1917f29dbc25Smrg
1918f29dbc25Smrg    /* CLEAR ALL OTHER ACTIONS */
1919f29dbc25Smrg    /* This prevents side-effects from previous accesses to the GLCP */
1920f29dbc25Smrg    /* debug logic.                                                  */
1921f29dbc25Smrg
1922f29dbc25Smrg    msr_value.low = 0x00000000;
1923f29dbc25Smrg    msr_value.high = 0x00000000;
1924f29dbc25Smrg    msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 3, &msr_value);
1925f29dbc25Smrg    msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 4, &msr_value);
1926f29dbc25Smrg    msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 5, &msr_value);
1927f29dbc25Smrg    msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 6, &msr_value);
1928f29dbc25Smrg    msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 7, &msr_value);
1929f29dbc25Smrg    msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 8, &msr_value);
1930f29dbc25Smrg    msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 9, &msr_value);
1931f29dbc25Smrg    msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 10, &msr_value);
1932f29dbc25Smrg    msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 11, &msr_value);
1933f29dbc25Smrg    msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 12, &msr_value);
1934f29dbc25Smrg    msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 13, &msr_value);
1935f29dbc25Smrg    msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 17, &msr_value);
1936f29dbc25Smrg    msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 18, &msr_value);
1937f29dbc25Smrg    msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 19, &msr_value);
1938f29dbc25Smrg    msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 20, &msr_value);
1939f29dbc25Smrg
1940f29dbc25Smrg    /* WAIT FOR THE CORRECT FIELD */
1941f29dbc25Smrg    /* We use the VG line count and field indicator to determine when */
1942f29dbc25Smrg    /* to kick off a CRC.                                             */
1943f29dbc25Smrg
1944f29dbc25Smrg    if (source & DF_CRC_SOURCE_EVEN)
1945f29dbc25Smrg        field = 0;
1946f29dbc25Smrg    else
1947f29dbc25Smrg        field = DC3_LNCNT_EVEN_FIELD;
1948f29dbc25Smrg
1949f29dbc25Smrg    if (interlaced) {
1950f29dbc25Smrg        /* WAIT FOR THE BEGINNING OF THE FIELD (LINE 1-5) */
1951f29dbc25Smrg        /* Note that we wait for the field to be odd when CRCing the even */
1952f29dbc25Smrg        /* field and vice versa.  This is because the CRC will not begin  */
1953f29dbc25Smrg        /* until the following field.                                     */
1954f29dbc25Smrg
1955f29dbc25Smrg        do {
1956f29dbc25Smrg            line = READ_REG32(DC3_LINE_CNT_STATUS);
1957f29dbc25Smrg        } while ((line & DC3_LNCNT_EVEN_FIELD) != field ||
195804007ebaSmrg                 ((line & DC3_LNCNT_V_LINE_CNT) >> 16) < 1 ||
195904007ebaSmrg                 ((line & DC3_LNCNT_V_LINE_CNT) >> 16) > 5);
196004007ebaSmrg    }
196104007ebaSmrg    else {
1962f29dbc25Smrg        /* NON-INTERLACED - EVEN FIELD CRCS ARE INVALID */
1963f29dbc25Smrg
1964f29dbc25Smrg        if (source & DF_CRC_SOURCE_EVEN)
1965f29dbc25Smrg            return 0xFFFFFFFF;
1966f29dbc25Smrg    }
1967f29dbc25Smrg
1968f29dbc25Smrg    /* CONFIGURE DISPLAY FILTER TO LOAD DATA ONTO LOWER 32-BITS */
1969f29dbc25Smrg
1970f29dbc25Smrg    msr_value.high = 0;
1971f29dbc25Smrg    msr_value.low = 0x0000800B;
1972f29dbc25Smrg    msr_write64(MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_DIAG, &msr_value);
1973f29dbc25Smrg
1974f29dbc25Smrg    /* CONFIGURE DIAG CONTROL */
1975f29dbc25Smrg    /* Set RegA action1 to increment lower 16 bits and clear at limit. (5)
1976f29dbc25Smrg     * Set RegA action2 to increment upper 16 bits. (6)
1977f29dbc25Smrg     * Set RegB action1 to CRC32 (1)
1978f29dbc25Smrg     * Set all comparators to REGA override (0,1 lower mbus, 2,3 upper mbus)
1979f29dbc25Smrg     * Enable all actions
1980f29dbc25Smrg     */
1981f29dbc25Smrg
1982f29dbc25Smrg    msr_value.low = 0x80EA20A0;
1983f29dbc25Smrg    msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_DIAGCTL, &msr_value);
1984f29dbc25Smrg
1985f29dbc25Smrg    /* DELAY TWO FRAMES */
1986f29dbc25Smrg
198704007ebaSmrg    while (READ_REG32(DC3_LINE_CNT_STATUS) & DC3_LNCNT_VNA);
198804007ebaSmrg    while (!(READ_REG32(DC3_LINE_CNT_STATUS) & DC3_LNCNT_VNA));
198904007ebaSmrg    while (READ_REG32(DC3_LINE_CNT_STATUS) & DC3_LNCNT_VNA);
199004007ebaSmrg    while (!(READ_REG32(DC3_LINE_CNT_STATUS) & DC3_LNCNT_VNA));
199104007ebaSmrg    while (READ_REG32(DC3_LINE_CNT_STATUS) & DC3_LNCNT_VNA);
1992f29dbc25Smrg
1993f29dbc25Smrg    /* VERIFY THAT XSTATE = 11 */
1994f29dbc25Smrg
1995f29dbc25Smrg    msr_read64(MSR_DEVICE_GEODELX_GLCP, GLCP_XSTATE, &msr_value);
1996f29dbc25Smrg    if ((msr_value.low & 3) == 3) {
1997f29dbc25Smrg        msr_read64(MSR_DEVICE_GEODELX_GLCP, GLCP_REGB, &msr_value);
1998f29dbc25Smrg
1999f29dbc25Smrg        crc = msr_value.low;
2000f29dbc25Smrg    }
2001f29dbc25Smrg
2002f29dbc25Smrg    /* DISABLE DF DIAG BUS OUTPUTS */
2003f29dbc25Smrg
2004f29dbc25Smrg    msr_value.low = 0x00000000;
2005f29dbc25Smrg    msr_value.high = 0x00000000;
2006f29dbc25Smrg    msr_write64(MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_DIAG, &msr_value);
2007f29dbc25Smrg
2008f29dbc25Smrg    /* DISABLE GLCP ACTIONS */
2009f29dbc25Smrg
2010f29dbc25Smrg    msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_DIAGCTL, &msr_value);
2011f29dbc25Smrg
2012f29dbc25Smrg    return crc;
2013f29dbc25Smrg}
2014f29dbc25Smrg
2015f29dbc25Smrg/*---------------------------------------------------------------------------
2016f29dbc25Smrg * df_read_panel_crc
2017f29dbc25Smrg *
2018f29dbc25Smrg * This routine reads the CRC for a frame of data after the panel dithering
2019f29dbc25Smrg * logic.
2020f29dbc25Smrg *--------------------------------------------------------------------------*/
2021f29dbc25Smrg
2022f29dbc25Smrgunsigned long
2023f29dbc25Smrgdf_read_panel_crc(void)
2024f29dbc25Smrg{
2025f29dbc25Smrg    Q_WORD msr_value;
2026f29dbc25Smrg    unsigned long timeout = 1000;
2027f29dbc25Smrg
2028f29dbc25Smrg    if (!(READ_REG32(DC3_DISPLAY_CFG) & DC3_DCFG_TGEN))
2029f29dbc25Smrg        return 0xFFFFFFFF;
2030f29dbc25Smrg
2031f29dbc25Smrg    /* ENABLE 32-BIT CRCS */
2032f29dbc25Smrg
2033f29dbc25Smrg    msr_read64(MSR_DEVICE_GEODELX_DF, DF_MBD_MSR_DIAG_DF, &msr_value);
2034f29dbc25Smrg    msr_value.low |= DF_DIAG_32BIT_CRC;
2035f29dbc25Smrg    msr_write64(MSR_DEVICE_GEODELX_DF, DF_MBD_MSR_DIAG_DF, &msr_value);
2036f29dbc25Smrg
2037f29dbc25Smrg    /* RESET CRC */
2038f29dbc25Smrg
2039f29dbc25Smrg    WRITE_VID32(DF_PANEL_CRC, 0);
2040f29dbc25Smrg
2041f29dbc25Smrg    /* WAIT FOR THE RESET TO BE LATCHED */
2042f29dbc25Smrg
2043f29dbc25Smrg    while ((READ_VID32(DF_PANEL_CRC32) != 0x00000001) && timeout)
2044f29dbc25Smrg        timeout--;
2045f29dbc25Smrg
2046f29dbc25Smrg    WRITE_VID32(DF_PANEL_CRC, 1);
2047f29dbc25Smrg
2048f29dbc25Smrg    /* WAIT FOR THE CRC TO BE COMPLETED */
2049f29dbc25Smrg
205004007ebaSmrg    while (!(READ_VID32(DF_PANEL_CRC) & 4));
2051f29dbc25Smrg
2052f29dbc25Smrg    return READ_VID32(DF_PANEL_CRC32);
2053f29dbc25Smrg}
2054f29dbc25Smrg
2055f29dbc25Smrg/*---------------------------------------------------------------------------
2056f29dbc25Smrg * df_get_video_enable
2057f29dbc25Smrg *
2058f29dbc25Smrg * This routine reads the enable status of the video overlay.
2059f29dbc25Smrg *--------------------------------------------------------------------------*/
2060f29dbc25Smrg
2061f29dbc25Smrgint
2062f29dbc25Smrgdf_get_video_enable(int *enable, unsigned long *flags)
2063f29dbc25Smrg{
2064f29dbc25Smrg    *enable = 0;
2065f29dbc25Smrg    *flags = 0;
2066f29dbc25Smrg    if (READ_VID32(DF_VIDEO_CONFIG) & DF_VCFG_VID_EN) {
2067f29dbc25Smrg        *enable = 1;
2068f29dbc25Smrg
2069f29dbc25Smrg        /* CHECK FOR COLOR KEY DISABLED */
2070f29dbc25Smrg        /* Color keying can be completely disabled when video is enabled to */
2071f29dbc25Smrg        /* allow unhindered per-pixel alpha blending.  As color keying is   */
2072f29dbc25Smrg        /* always disabled when video is disabled, it is only possible to   */
2073f29dbc25Smrg        /* test for this condition when video is enabled.                   */
2074f29dbc25Smrg
2075f29dbc25Smrg        if (!(READ_VID32(DF_DISPLAY_CONFIG) & DF_DCFG_VG_CK) &&
2076f29dbc25Smrg            !(READ_REG32(DC3_COLOR_KEY) & DC3_CLR_KEY_ENABLE)) {
2077f29dbc25Smrg            *flags = DF_ENABLEFLAG_NOCOLORKEY;
2078f29dbc25Smrg        }
2079f29dbc25Smrg    }
2080f29dbc25Smrg
2081f29dbc25Smrg    return CIM_STATUS_OK;
2082f29dbc25Smrg}
2083f29dbc25Smrg
2084f29dbc25Smrg/*---------------------------------------------------------------------------
2085f29dbc25Smrg * df_get_video_source_configuration
2086f29dbc25Smrg *
2087f29dbc25Smrg * This routine reads the current configuration of the source buffers for the
2088f29dbc25Smrg * video overlay.
2089f29dbc25Smrg *--------------------------------------------------------------------------*/
2090f29dbc25Smrg
2091f29dbc25Smrgint
2092f29dbc25Smrgdf_get_video_source_configuration(DF_VIDEO_SOURCE_PARAMS * video_source_odd,
209304007ebaSmrg                                  DF_VIDEO_SOURCE_PARAMS * video_source_even)
2094f29dbc25Smrg{
2095f29dbc25Smrg    unsigned long format, temp;
2096f29dbc25Smrg    unsigned long size;
2097f29dbc25Smrg
2098f29dbc25Smrg    /* READ VIDEO FORMAT */
2099f29dbc25Smrg
2100f29dbc25Smrg    temp = READ_VID32(DF_VIDEO_CONFIG);
2101f29dbc25Smrg
2102f29dbc25Smrg    format = (temp >> 2) & 3;
2103f29dbc25Smrg    if (temp & DF_VCFG_4_2_0_MODE)
2104f29dbc25Smrg        format |= 4;
2105f29dbc25Smrg    else if (READ_VID32(DF_VID_ALPHA_CONTROL) & DF_VIDEO_INPUT_IS_RGB)
2106f29dbc25Smrg        format |= 8;
2107f29dbc25Smrg    video_source_odd->video_format = format;
2108f29dbc25Smrg
2109f29dbc25Smrg    /* CHECK IF SOURCE IS HD VIDEO */
2110f29dbc25Smrg
2111f29dbc25Smrg    if (READ_VID32(DF_VID_ALPHA_CONTROL) & DF_HD_VIDEO)
2112f29dbc25Smrg        video_source_odd->flags = DF_SOURCEFLAG_HDTVSOURCE;
2113f29dbc25Smrg    else
2114f29dbc25Smrg        video_source_odd->flags = 0;
2115f29dbc25Smrg
2116f29dbc25Smrg    /* READ SCALING ALGORITHM */
2117f29dbc25Smrg
2118f29dbc25Smrg    if (READ_VID32(DF_VID_MISC) & DF_USER_IMPLICIT_SCALING)
2119f29dbc25Smrg        video_source_odd->flags |= DF_SOURCEFLAG_IMPLICITSCALING;
2120f29dbc25Smrg
2121f29dbc25Smrg    /* READ VIDEO PITCH */
2122f29dbc25Smrg
2123f29dbc25Smrg    temp = READ_REG32(DC3_VID_YUV_PITCH);
2124f29dbc25Smrg    video_source_odd->y_pitch = (temp & 0xFFFF) << 3;
2125f29dbc25Smrg    video_source_odd->uv_pitch = (temp >> 16) << 3;
2126f29dbc25Smrg
2127f29dbc25Smrg    /* READ VIDEO SIZE */
2128f29dbc25Smrg
2129f29dbc25Smrg    temp = READ_VID32(DF_VIDEO_CONFIG);
2130f29dbc25Smrg    size = (temp >> 8) & 0xFF;
2131f29dbc25Smrg    if (temp & DF_VCFG_LINE_SIZE_BIT8)
2132f29dbc25Smrg        size |= 0x100;
2133f29dbc25Smrg    if (temp & DF_VCFG_LINE_SIZE_BIT9)
2134f29dbc25Smrg        size |= 0x200;
2135f29dbc25Smrg
2136f29dbc25Smrg    video_source_odd->width = size << 1;
2137f29dbc25Smrg    video_source_odd->height = READ_VID32(DF_VIDEO_SCALER) & 0x7FF;
2138f29dbc25Smrg
2139f29dbc25Smrg    /* READ VIDEO OFFSETS */
2140f29dbc25Smrg
2141f29dbc25Smrg    video_source_odd->y_offset = READ_REG32(DC3_VID_Y_ST_OFFSET) & 0xFFFFFFF;
2142f29dbc25Smrg    video_source_odd->u_offset = READ_REG32(DC3_VID_U_ST_OFFSET) & 0xFFFFFFF;
2143f29dbc25Smrg    video_source_odd->v_offset = READ_REG32(DC3_VID_V_ST_OFFSET) & 0xFFFFFFF;
2144f29dbc25Smrg
2145f29dbc25Smrg    if (READ_REG32(DC3_IRQ_FILT_CTL) & DC3_IRQFILT_INTL_EN) {
2146f29dbc25Smrg        video_source_even->y_offset =
2147f29dbc25Smrg            READ_REG32(DC3_VID_EVEN_Y_ST_OFFSET) & 0xFFFFFFF;
2148f29dbc25Smrg        video_source_even->u_offset =
2149f29dbc25Smrg            READ_REG32(DC3_VID_EVEN_U_ST_OFFSET) & 0xFFFFFFF;
2150f29dbc25Smrg        video_source_even->v_offset =
2151f29dbc25Smrg            READ_REG32(DC3_VID_EVEN_V_ST_OFFSET) & 0xFFFFFFF;
2152f29dbc25Smrg    }
2153f29dbc25Smrg
2154f29dbc25Smrg    return CIM_STATUS_OK;
2155f29dbc25Smrg}
2156f29dbc25Smrg
2157f29dbc25Smrg/*---------------------------------------------------------------------------
2158f29dbc25Smrg * df_get_video_position
2159f29dbc25Smrg *
2160f29dbc25Smrg * This routine reads the current position of the video overlay.
2161f29dbc25Smrg *--------------------------------------------------------------------------*/
2162f29dbc25Smrg
2163f29dbc25Smrgint
2164f29dbc25Smrgdf_get_video_position(DF_VIDEO_POSITION * video_window)
2165f29dbc25Smrg{
2166f29dbc25Smrg    unsigned long xreg, yreg, dst_clip, clip;
2167f29dbc25Smrg    unsigned long height;
2168f29dbc25Smrg    unsigned long xend, yend;
2169f29dbc25Smrg    unsigned long hsyncend, htotal;
2170f29dbc25Smrg    unsigned long vsyncend, vtotal;
2171f29dbc25Smrg    unsigned long hadjust, vadjust;
2172f29dbc25Smrg    unsigned long misc, gfxscale;
2173f29dbc25Smrg    unsigned long temp;
2174f29dbc25Smrg    long xstart, ystart;
2175f29dbc25Smrg
2176f29dbc25Smrg    video_window->flags = DF_POSFLAG_DIRECTCLIP;
2177f29dbc25Smrg
2178f29dbc25Smrg    hsyncend = ((READ_REG32(DC3_H_SYNC_TIMING) >> 16) & 0xFFF) + 1;
2179f29dbc25Smrg    htotal = ((READ_REG32(DC3_H_ACTIVE_TIMING) >> 16) & 0xFFF) + 1;
2180f29dbc25Smrg
2181f29dbc25Smrg    /* ODD FIELD START COUNTS FROM THE EVEN FIELD TIMINGS */
2182f29dbc25Smrg    /* We assume that the even field y position is always programmed */
2183f29dbc25Smrg    /* to be just after the odd field.                               */
2184f29dbc25Smrg
2185f29dbc25Smrg    if (READ_REG32(DC3_IRQ_FILT_CTL) & DC3_IRQFILT_INTL_EN) {
2186f29dbc25Smrg        vsyncend = ((READ_REG32(DC3_V_SYNC_EVEN) >> 16) & 0xFFF) + 1;
2187f29dbc25Smrg        vtotal = ((READ_REG32(DC3_V_ACTIVE_EVEN) >> 16) & 0xFFF) + 1;
218804007ebaSmrg    }
218904007ebaSmrg    else {
2190f29dbc25Smrg        vsyncend = ((READ_REG32(DC3_V_SYNC_TIMING) >> 16) & 0xFFF) + 1;
2191f29dbc25Smrg        vtotal = ((READ_REG32(DC3_V_ACTIVE_TIMING) >> 16) & 0xFFF) + 1;
2192f29dbc25Smrg    }
2193f29dbc25Smrg
2194f29dbc25Smrg    hadjust = htotal - hsyncend - 14;
2195f29dbc25Smrg    vadjust = vtotal - vsyncend + 1;
2196f29dbc25Smrg
2197f29dbc25Smrg    xreg = READ_VID32(DF_VIDEO_X_POS);
2198f29dbc25Smrg    yreg = READ_VID32(DF_VIDEO_Y_POS);
2199f29dbc25Smrg
2200f29dbc25Smrg    xstart = (xreg & 0xFFF) - hadjust;
2201f29dbc25Smrg    ystart = (yreg & 0x7FF) - vadjust;
2202f29dbc25Smrg    xend = ((xreg >> 16) & 0xFFF) - hadjust;
2203f29dbc25Smrg    yend = ((yreg >> 16) & 0x7FF) - vadjust;
2204f29dbc25Smrg
2205f29dbc25Smrg    height = yend - ystart;
2206f29dbc25Smrg
2207f29dbc25Smrg    if (READ_REG32(DC3_IRQ_FILT_CTL) & DC3_IRQFILT_INTL_EN) {
2208f29dbc25Smrg        /* Y COORDINATE IS ACTUALLY 2X THE ODD FIELD START */
2209f29dbc25Smrg
2210f29dbc25Smrg        ystart <<= 1;
2211f29dbc25Smrg
2212f29dbc25Smrg        /* CALCULATE THE EXACT VIDEO HEIGHT */
2213f29dbc25Smrg        /* The height of the video window is the sum of the */
2214f29dbc25Smrg        /* odd and even field heights.                      */
2215f29dbc25Smrg
2216f29dbc25Smrg        yreg = READ_VID32(DF_VID_YPOS_EVEN);
2217f29dbc25Smrg        height += ((yreg >> 16) & 0x7FF) - (yreg & 0x7FF);
2218f29dbc25Smrg    }
2219f29dbc25Smrg
2220f29dbc25Smrg    clip = ((READ_VID32(DF_VIDEO_CONFIG) >> 16) & 0x1FF) << 2;
2221f29dbc25Smrg
2222f29dbc25Smrg    /* ADJUST FOR CLIPPING VALUES THAT ARE NOT FOUR-PIXEL ALIGNED */
2223f29dbc25Smrg
2224f29dbc25Smrg    dst_clip = 0;
2225f29dbc25Smrg    if (xstart < 0) {
2226f29dbc25Smrg        dst_clip += -xstart;
2227f29dbc25Smrg        xstart = 0;
2228f29dbc25Smrg    }
2229f29dbc25Smrg
2230f29dbc25Smrg    /* REVERSE THE GRAPHICS SCALE */
2231f29dbc25Smrg
2232f29dbc25Smrg    misc = READ_VID32(DF_VID_MISC);
2233f29dbc25Smrg    if (misc & DF_USER_IMPLICIT_SCALING) {
2234f29dbc25Smrg        gfxscale = READ_REG32(DC3_GFX_SCALE);
2235f29dbc25Smrg
2236f29dbc25Smrg        if (gfxscale != 0x40004000) {
2237f29dbc25Smrg            temp = ystart + height;
2238f29dbc25Smrg            temp = (temp * (gfxscale >> 16)) / 0x4000;
2239f29dbc25Smrg
2240f29dbc25Smrg            xstart = (xstart * (gfxscale & 0xFFFF)) / 0x4000;
2241f29dbc25Smrg            xend = (xend * (gfxscale & 0xFFFF)) / 0x4000;
2242f29dbc25Smrg            ystart = (ystart * (gfxscale >> 16)) / 0x4000;
2243f29dbc25Smrg            height = temp - ystart;
2244f29dbc25Smrg        }
2245f29dbc25Smrg    }
2246f29dbc25Smrg
2247f29dbc25Smrg    video_window->left_clip = clip;
2248f29dbc25Smrg    video_window->dst_clip = dst_clip;
2249f29dbc25Smrg    video_window->x = xstart;
2250f29dbc25Smrg    video_window->y = ystart;
2251f29dbc25Smrg    video_window->width = xend - xstart;
2252f29dbc25Smrg    video_window->height = height;
2253f29dbc25Smrg
2254f29dbc25Smrg    return CIM_STATUS_OK;
2255f29dbc25Smrg}
2256f29dbc25Smrg
2257f29dbc25Smrg/*---------------------------------------------------------------------------
2258f29dbc25Smrg * df_get_video_scale
2259f29dbc25Smrg *
2260f29dbc25Smrg * This routine reads the current scale values for video scaling.
2261f29dbc25Smrg *--------------------------------------------------------------------------*/
2262f29dbc25Smrg
2263f29dbc25Smrgint
2264f29dbc25Smrgdf_get_video_scale(unsigned long *x_scale, unsigned long *y_scale)
2265f29dbc25Smrg{
2266f29dbc25Smrg    *x_scale = READ_VID32(DF_VIDEO_XSCALE) & 0x000FFFFF;
2267f29dbc25Smrg    *y_scale = READ_VID32(DF_VIDEO_YSCALE) & 0x000FFFFF;
2268f29dbc25Smrg    return CIM_STATUS_OK;
2269f29dbc25Smrg}
2270f29dbc25Smrg
2271f29dbc25Smrg/*---------------------------------------------------------------------------
2272f29dbc25Smrg * df_get_video_filter_coefficients
2273f29dbc25Smrg *
2274f29dbc25Smrg * This routine reads the coefficients for the video scaler/filter.
2275f29dbc25Smrg *--------------------------------------------------------------------------*/
2276f29dbc25Smrg
2277f29dbc25Smrgint
2278f29dbc25Smrgdf_get_video_filter_coefficients(long taps[][4], int *phase256)
2279f29dbc25Smrg{
2280f29dbc25Smrg    unsigned long i, temp;
2281f29dbc25Smrg    long coeff;
2282f29dbc25Smrg
2283f29dbc25Smrg    if (READ_VID32(DF_VIDEO_SCALER) & DF_SCALE_128_PHASES)
2284f29dbc25Smrg        *phase256 = 0;
2285f29dbc25Smrg    else
2286f29dbc25Smrg        *phase256 = 1;
2287f29dbc25Smrg
2288f29dbc25Smrg    for (i = 0; i < 256; i++) {
2289f29dbc25Smrg        temp = READ_VID32(DF_COEFFICIENT_BASE + (i << 3));
2290f29dbc25Smrg
2291f29dbc25Smrg        /* TAP 0 */
2292f29dbc25Smrg
2293f29dbc25Smrg        coeff = temp & 0x7FFF;
2294f29dbc25Smrg        if (temp & 0x8000)
2295f29dbc25Smrg            coeff = -coeff;
2296f29dbc25Smrg        taps[i][0] = coeff;
2297f29dbc25Smrg
2298f29dbc25Smrg        /* TAP 1 */
2299f29dbc25Smrg
2300f29dbc25Smrg        temp >>= 16;
2301f29dbc25Smrg        coeff = temp & 0x7FFF;
2302f29dbc25Smrg        if (temp & 0x8000)
2303f29dbc25Smrg            coeff = -coeff;
2304f29dbc25Smrg        taps[i][1] = coeff;
2305f29dbc25Smrg
2306f29dbc25Smrg        temp = READ_VID32(DF_COEFFICIENT_BASE + (i << 3) + 4);
2307f29dbc25Smrg
2308f29dbc25Smrg        /* TAP 2 */
2309f29dbc25Smrg
2310f29dbc25Smrg        coeff = temp & 0x7FFF;
2311f29dbc25Smrg        if (temp & 0x8000)
2312f29dbc25Smrg            coeff = -coeff;
2313f29dbc25Smrg        taps[i][2] = coeff;
2314f29dbc25Smrg
2315f29dbc25Smrg        /* TAP 3 */
2316f29dbc25Smrg
2317f29dbc25Smrg        temp >>= 16;
2318f29dbc25Smrg        coeff = temp & 0x7FFF;
2319f29dbc25Smrg        if (temp & 0x8000)
2320f29dbc25Smrg            coeff = -coeff;
2321f29dbc25Smrg        taps[i][3] = coeff;
2322f29dbc25Smrg    }
2323f29dbc25Smrg
2324f29dbc25Smrg    return CIM_STATUS_OK;
2325f29dbc25Smrg}
2326f29dbc25Smrg
2327f29dbc25Smrg/*---------------------------------------------------------------------------
2328f29dbc25Smrg * df_get_video_color_key
2329f29dbc25Smrg *
2330f29dbc25Smrg * This routine reads the current settings for hardware color/chroma keying.
2331f29dbc25Smrg *--------------------------------------------------------------------------*/
2332f29dbc25Smrg
2333f29dbc25Smrgint
2334f29dbc25Smrgdf_get_video_color_key(unsigned long *key, unsigned long *mask, int *graphics)
2335f29dbc25Smrg{
2336f29dbc25Smrg    unsigned long chroma = READ_VID32(DF_DISPLAY_CONFIG) & DF_DCFG_VG_CK;
2337f29dbc25Smrg
2338f29dbc25Smrg    if (chroma) {
2339f29dbc25Smrg        /* CHROMA KEY - READ KEY AND MASK FROM DF */
2340f29dbc25Smrg
2341f29dbc25Smrg        *graphics = 0;
2342f29dbc25Smrg        *key = READ_VID32(DF_VIDEO_COLOR_KEY) & 0xFFFFFF;
2343f29dbc25Smrg        *mask = READ_VID32(DF_VIDEO_COLOR_MASK) & 0xFFFFFF;
234404007ebaSmrg    }
234504007ebaSmrg    else {
2346f29dbc25Smrg        *graphics = 1;
2347f29dbc25Smrg
2348f29dbc25Smrg        *key = READ_REG32(DC3_COLOR_KEY) & 0xFFFFFF;
2349f29dbc25Smrg        *mask = READ_REG32(DC3_COLOR_MASK) & 0xFFFFFF;
2350f29dbc25Smrg    }
2351f29dbc25Smrg
2352f29dbc25Smrg    return CIM_STATUS_OK;
2353f29dbc25Smrg}
2354f29dbc25Smrg
2355f29dbc25Smrg/*---------------------------------------------------------------------------
2356f29dbc25Smrg * df_get_video_palette_entry
2357f29dbc25Smrg *
2358f29dbc25Smrg * This routine returns a single palette entry.
2359f29dbc25Smrg *--------------------------------------------------------------------------*/
2360f29dbc25Smrg
2361f29dbc25Smrgint
2362f29dbc25Smrgdf_get_video_palette_entry(unsigned long index, unsigned long *palette)
2363f29dbc25Smrg{
2364f29dbc25Smrg    if (index > 0xFF)
2365f29dbc25Smrg        return CIM_STATUS_INVALIDPARAMS;
2366f29dbc25Smrg
2367f29dbc25Smrg    /* READ A SINGLE ENTRY */
2368f29dbc25Smrg
2369f29dbc25Smrg    WRITE_VID32(DF_PALETTE_ADDRESS, index);
2370f29dbc25Smrg    *palette = READ_VID32(DF_PALETTE_DATA);
2371f29dbc25Smrg
2372f29dbc25Smrg    return CIM_STATUS_OK;
2373f29dbc25Smrg}
2374f29dbc25Smrg
2375f29dbc25Smrg/*---------------------------------------------------------------------------
2376f29dbc25Smrg * df_get_video_palette
2377f29dbc25Smrg *
2378f29dbc25Smrg * This routine returns the entire video palette.
2379f29dbc25Smrg *--------------------------------------------------------------------------*/
2380f29dbc25Smrg
2381f29dbc25Smrgint
2382f29dbc25Smrgdf_get_video_palette(unsigned long *palette)
2383f29dbc25Smrg{
2384f29dbc25Smrg    unsigned long i;
2385f29dbc25Smrg
2386f29dbc25Smrg    WRITE_VID32(DF_PALETTE_ADDRESS, 0);
2387f29dbc25Smrg    for (i = 0; i < 256; i++)
2388f29dbc25Smrg        palette[i] = READ_VID32(DF_PALETTE_DATA);
2389f29dbc25Smrg
2390f29dbc25Smrg    return CIM_STATUS_OK;
2391f29dbc25Smrg}
2392f29dbc25Smrg
2393f29dbc25Smrg/*---------------------------------------------------------------------------
2394f29dbc25Smrg * df_get_video_cursor_color_key
2395f29dbc25Smrg *
2396f29dbc25Smrg * This routine returns the current configuration for the hardware video cursor
2397f29dbc25Smrg * color key.
2398f29dbc25Smrg *--------------------------------------------------------------------------*/
2399f29dbc25Smrg
2400f29dbc25Smrgint
2401f29dbc25Smrgdf_get_video_cursor_color_key(DF_VIDEO_CURSOR_PARAMS * cursor_color_key)
2402f29dbc25Smrg{
2403f29dbc25Smrg    unsigned long key;
2404f29dbc25Smrg
2405f29dbc25Smrg    cursor_color_key->flags = 0;
2406f29dbc25Smrg    cursor_color_key->color1 = READ_VID32(DF_CURSOR_COLOR_1) & 0xFFFFFF;
2407f29dbc25Smrg    cursor_color_key->color2 = READ_VID32(DF_CURSOR_COLOR_2) & 0xFFFFFF;
2408f29dbc25Smrg    cursor_color_key->mask = READ_VID32(DF_CURSOR_COLOR_MASK) & 0xFFFFFF;
2409f29dbc25Smrg
2410f29dbc25Smrg    key = READ_VID32(DF_CURSOR_COLOR_KEY);
2411f29dbc25Smrg    cursor_color_key->key = key & 0xFFFFFF;
2412f29dbc25Smrg    cursor_color_key->select_color2 = (key >> 24) & 0x1F;
2413f29dbc25Smrg
2414f29dbc25Smrg    return CIM_STATUS_OK;
2415f29dbc25Smrg}
2416f29dbc25Smrg
2417f29dbc25Smrg/*---------------------------------------------------------------------------
2418f29dbc25Smrg * df_get_video_cursor_color_key_enable
2419f29dbc25Smrg *
2420f29dbc25Smrg * This routine returns the current enable status of the hardware video cursor
2421f29dbc25Smrg * color key.
2422f29dbc25Smrg *--------------------------------------------------------------------------*/
2423f29dbc25Smrg
2424f29dbc25Smrgint
2425f29dbc25Smrgdf_get_video_cursor_color_key_enable(void)
2426f29dbc25Smrg{
2427f29dbc25Smrg    if (READ_VID32(DF_CURSOR_COLOR_KEY) & DF_CURSOR_COLOR_KEY_ENABLE)
2428f29dbc25Smrg        return 1;
2429f29dbc25Smrg
2430f29dbc25Smrg    return 0;
2431f29dbc25Smrg}
2432f29dbc25Smrg
2433f29dbc25Smrg/*---------------------------------------------------------------------------
2434f29dbc25Smrg * df_get_alpha_window_configuration
2435f29dbc25Smrg *
2436f29dbc25Smrg * This routine reads the current configuration for one of the three hardware
2437f29dbc25Smrg * alpha regions.
2438f29dbc25Smrg *--------------------------------------------------------------------------*/
2439f29dbc25Smrg
2440f29dbc25Smrgint
2441f29dbc25Smrgdf_get_alpha_window_configuration(int window,
244204007ebaSmrg                                  DF_ALPHA_REGION_PARAMS * alpha_data)
2443f29dbc25Smrg{
2444f29dbc25Smrg    unsigned long pos, color, alpha_ctl;
2445f29dbc25Smrg    unsigned long hsyncend, htotal;
2446f29dbc25Smrg    unsigned long vsyncend, vtotal;
2447f29dbc25Smrg    unsigned long hadjust, vadjust;
2448f29dbc25Smrg    unsigned long xreg, yreg;
2449f29dbc25Smrg    unsigned long misc, gfxscale;
2450f29dbc25Smrg    unsigned long temp;
2451f29dbc25Smrg    char delta;
2452f29dbc25Smrg
2453f29dbc25Smrg    if (window > 2)
2454f29dbc25Smrg        return CIM_STATUS_INVALIDPARAMS;
2455f29dbc25Smrg
2456f29dbc25Smrg    hsyncend = ((READ_REG32(DC3_H_SYNC_TIMING) >> 16) & 0xFFF) + 1;
2457f29dbc25Smrg    htotal = ((READ_REG32(DC3_H_ACTIVE_TIMING) >> 16) & 0xFFF) + 1;
2458f29dbc25Smrg    if (READ_REG32(DC3_IRQ_FILT_CTL) & DC3_IRQFILT_INTL_EN) {
2459f29dbc25Smrg        vtotal = ((READ_REG32(DC3_V_ACTIVE_EVEN) >> 16) & 0xFFF) + 1;
2460f29dbc25Smrg        vsyncend = ((READ_REG32(DC3_V_SYNC_EVEN) >> 16) & 0xFFF) + 1;
246104007ebaSmrg    }
246204007ebaSmrg    else {
2463f29dbc25Smrg        vtotal = ((READ_REG32(DC3_V_ACTIVE_TIMING) >> 16) & 0xFFF) + 1;
2464f29dbc25Smrg        vsyncend = ((READ_REG32(DC3_V_SYNC_TIMING) >> 16) & 0xFFF) + 1;
2465f29dbc25Smrg    }
2466f29dbc25Smrg
2467f29dbc25Smrg    /* GET PRIORITY */
2468f29dbc25Smrg
2469f29dbc25Smrg    pos = 16 + (window << 1);
2470f29dbc25Smrg    alpha_data->priority = (READ_VID32(DF_VID_ALPHA_CONTROL) >> pos) & 3L;
2471f29dbc25Smrg
2472f29dbc25Smrg    /* GET ALPHA WINDOW */
2473f29dbc25Smrg
2474f29dbc25Smrg    hadjust = htotal - hsyncend - 2;
2475f29dbc25Smrg    vadjust = vtotal - vsyncend + 1;
2476f29dbc25Smrg
2477f29dbc25Smrg    xreg = READ_VID32(DF_ALPHA_XPOS_1 + (window << 5));
2478f29dbc25Smrg    yreg = READ_VID32(DF_ALPHA_YPOS_1 + (window << 5));
2479f29dbc25Smrg    alpha_data->width = ((xreg >> 16) & 0xFFF) - (xreg & 0xFFF);
2480f29dbc25Smrg    alpha_data->height = ((yreg >> 16) & 0x7FF) - (yreg & 0x7FF);
2481f29dbc25Smrg    alpha_data->x = (xreg & 0xFFF) - hadjust;
2482f29dbc25Smrg    alpha_data->y = (yreg & 0x7FF) - vadjust;
2483f29dbc25Smrg
2484f29dbc25Smrg    /* REVERSE THE GRAPHICS SCALE */
2485f29dbc25Smrg
2486f29dbc25Smrg    misc = READ_VID32(DF_VID_MISC);
2487f29dbc25Smrg    if (misc & DF_USER_IMPLICIT_SCALING) {
2488f29dbc25Smrg        gfxscale = READ_REG32(DC3_GFX_SCALE);
2489f29dbc25Smrg        if (gfxscale != 0x40004000) {
2490f29dbc25Smrg            temp = alpha_data->y + alpha_data->height;
2491f29dbc25Smrg            temp = (temp * (gfxscale >> 16)) / 0x4000;
2492f29dbc25Smrg
2493f29dbc25Smrg            alpha_data->x = (alpha_data->x * (gfxscale & 0xFFFF)) / 0x4000;
2494f29dbc25Smrg            alpha_data->width =
2495f29dbc25Smrg                (alpha_data->width * (gfxscale & 0xFFFF)) / 0x4000;
2496f29dbc25Smrg            alpha_data->y = (alpha_data->y * (gfxscale >> 16)) / 0x4000;
2497f29dbc25Smrg            alpha_data->height = temp - alpha_data->y;
2498f29dbc25Smrg        }
2499f29dbc25Smrg    }
2500f29dbc25Smrg
2501f29dbc25Smrg    if (READ_REG32(DC3_IRQ_FILT_CTL) & DC3_IRQFILT_INTL_EN) {
2502f29dbc25Smrg        /* Y COORDINATE IS ACTUALLY 2X THE ODD FIELD START */
2503f29dbc25Smrg
2504f29dbc25Smrg        alpha_data->y <<= 1;
2505f29dbc25Smrg
2506f29dbc25Smrg        /* CALCULATE THE EXACT VIDEO HEIGHT */
2507f29dbc25Smrg        /* The height of the video window is the sum of the */
2508f29dbc25Smrg        /* odd and even field heights.                      */
2509f29dbc25Smrg
2510f29dbc25Smrg        yreg = READ_VID32(DF_VID_ALPHA_Y_EVEN_1 + (window << 3));
2511f29dbc25Smrg        alpha_data->height += ((yreg >> 16) & 0x7FF) - (yreg & 0x7FF);
2512f29dbc25Smrg    }
2513f29dbc25Smrg
2514f29dbc25Smrg    /* GET COLOR REGISTER */
2515f29dbc25Smrg
2516f29dbc25Smrg    color = READ_VID32(DF_ALPHA_COLOR_1 + (window << 5));
2517f29dbc25Smrg    alpha_data->color = color & 0xFFFFFF;
2518f29dbc25Smrg    if (color & DF_ALPHA_COLOR_ENABLE)
2519f29dbc25Smrg        alpha_data->flags = DF_ALPHAFLAG_COLORENABLED;
2520f29dbc25Smrg    else
2521f29dbc25Smrg        alpha_data->flags = 0;
2522f29dbc25Smrg
2523f29dbc25Smrg    /* GET ALPHA VALUE, DELTA AND PER PIXEL */
2524f29dbc25Smrg
2525f29dbc25Smrg    alpha_ctl = READ_VID32(DF_ALPHA_CONTROL_1 + (window << 5));
2526f29dbc25Smrg    alpha_data->alpha_value = alpha_ctl & 0xFF;
2527f29dbc25Smrg    if (alpha_ctl & DF_ACTRL_PERPIXEL_EN)
2528f29dbc25Smrg        alpha_data->flags |= DF_ALPHAFLAG_PERPIXELENABLED;
2529f29dbc25Smrg
253004007ebaSmrg    delta = (char) ((alpha_ctl >> 8) & 0xFF);
253104007ebaSmrg    alpha_data->delta = (long) delta;
2532f29dbc25Smrg    return CIM_STATUS_OK;
2533f29dbc25Smrg}
2534f29dbc25Smrg
2535f29dbc25Smrg/*---------------------------------------------------------------------------
2536f29dbc25Smrg * df_get_alpha_window_enable
2537f29dbc25Smrg *
2538f29dbc25Smrg * This routine reads the current enable status of one of the three hardware
2539f29dbc25Smrg * alpha regions.
2540f29dbc25Smrg *--------------------------------------------------------------------------*/
2541f29dbc25Smrg
2542f29dbc25Smrgint
2543f29dbc25Smrgdf_get_alpha_window_enable(int window)
2544f29dbc25Smrg{
2545f29dbc25Smrg    if (window > 2)
2546f29dbc25Smrg        return 0;
2547f29dbc25Smrg
2548f29dbc25Smrg    if (READ_VID32(DF_ALPHA_CONTROL_1 + (window << 5)) & DF_ACTRL_WIN_ENABLE)
2549f29dbc25Smrg        return 1;
2550f29dbc25Smrg
2551f29dbc25Smrg    return 0;
2552f29dbc25Smrg}
2553f29dbc25Smrg
2554f29dbc25Smrg/*---------------------------------------------------------------------------
2555f29dbc25Smrg * df_get_video_request
2556f29dbc25Smrg *
2557f29dbc25Smrg * This routine reads the horizontal (pixel) and vertical (line) video request
2558f29dbc25Smrg * values.
2559f29dbc25Smrg *--------------------------------------------------------------------------*/
2560f29dbc25Smrg
2561f29dbc25Smrgint
2562f29dbc25Smrgdf_get_video_request(unsigned long *x, unsigned long *y)
2563f29dbc25Smrg{
2564f29dbc25Smrg    unsigned long request;
2565f29dbc25Smrg    unsigned long hsyncend, htotal;
2566f29dbc25Smrg    unsigned long vsyncend, vtotal;
2567f29dbc25Smrg
2568f29dbc25Smrg    hsyncend = ((READ_REG32(DC3_H_SYNC_TIMING) >> 16) & 0xFFF) + 1;
2569f29dbc25Smrg    vsyncend = ((READ_REG32(DC3_V_SYNC_TIMING) >> 16) & 0xFFF) + 1;
2570f29dbc25Smrg    htotal = ((READ_REG32(DC3_H_ACTIVE_TIMING) >> 16) & 0xFFF) + 1;
2571f29dbc25Smrg    vtotal = ((READ_REG32(DC3_V_ACTIVE_TIMING) >> 16) & 0xFFF) + 1;
2572f29dbc25Smrg
2573f29dbc25Smrg    request = READ_VID32(DF_VIDEO_REQUEST);
2574f29dbc25Smrg    *x = ((request >> 16) & 0xFFF) - (htotal - hsyncend - 2);
2575f29dbc25Smrg    *y = (request & 0x7FF) - (vtotal - vsyncend + 1);
2576f29dbc25Smrg
2577f29dbc25Smrg    return CIM_STATUS_OK;
2578f29dbc25Smrg}
2579f29dbc25Smrg
2580f29dbc25Smrg/*---------------------------------------------------------------------------
2581f29dbc25Smrg * df_get_output_color_space
2582f29dbc25Smrg *
2583f29dbc25Smrg * This routine sets the color space used when combining graphics and video.
2584f29dbc25Smrg *--------------------------------------------------------------------------*/
2585f29dbc25Smrg
2586f29dbc25Smrgint
2587f29dbc25Smrgdf_get_output_color_space(int *color_space)
2588f29dbc25Smrg{
2589f29dbc25Smrg    unsigned long alpha_ctl;
2590f29dbc25Smrg
2591f29dbc25Smrg    alpha_ctl = READ_VID32(DF_VID_ALPHA_CONTROL);
2592f29dbc25Smrg
2593f29dbc25Smrg    if ((alpha_ctl & DF_CSC_VIDEO_YUV_TO_RGB) ||
2594f29dbc25Smrg        !(alpha_ctl & DF_CSC_GRAPHICS_RGB_TO_YUV)) {
2595f29dbc25Smrg        if (alpha_ctl & DF_ALPHA_DRGB)
2596f29dbc25Smrg            *color_space = DF_OUTPUT_ARGB;
2597f29dbc25Smrg        else
2598f29dbc25Smrg            *color_space = DF_OUTPUT_RGB;
259904007ebaSmrg    }
260004007ebaSmrg    else {
2601f29dbc25Smrg        *color_space = DF_OUTPUT_SDTV;
2602f29dbc25Smrg
2603f29dbc25Smrg        if (alpha_ctl & DF_HD_GRAPHICS)
2604f29dbc25Smrg            *color_space = DF_OUTPUT_HDTV;
2605f29dbc25Smrg    }
2606f29dbc25Smrg
2607f29dbc25Smrg    return CIM_STATUS_OK;
2608f29dbc25Smrg}
2609f29dbc25Smrg
2610f29dbc25Smrg#endif
2611