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