cim_vip.c revision f29dbc25
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 VIP configuration routines.
29f29dbc25Smrg  */
30f29dbc25Smrg
31f29dbc25Smrg/*---------------------------------------------------------------------------
32f29dbc25Smrg * vip_initialize
33f29dbc25Smrg *
34f29dbc25Smrg * This routine initializes the internal module state and prepares the
35f29dbc25Smrg * module for subsequent VIP orientated activities.
36f29dbc25Smrg *--------------------------------------------------------------------------*/
37f29dbc25Smrg
38f29dbc25Smrgint
39f29dbc25Smrgvip_initialize(VIPSETMODEBUFFER * buffer)
40f29dbc25Smrg{
41f29dbc25Smrg    unsigned long vip_control1, vip_control2, vip_control3;
42f29dbc25Smrg
43f29dbc25Smrg    if (!buffer)
44f29dbc25Smrg        return CIM_STATUS_INVALIDPARAMS;
45f29dbc25Smrg
46f29dbc25Smrg    vip_control1 = 0;
47f29dbc25Smrg    vip_control2 = 0;
48f29dbc25Smrg    vip_control3 = 0;
49f29dbc25Smrg
50f29dbc25Smrg    /* CONFIGURE CONTROL WORDS BASED ON MODE STRUCTURE                  */
51f29dbc25Smrg    /* Note that some of the input parameters match the register fields */
52f29dbc25Smrg    /* they represent.                                                  */
53f29dbc25Smrg
54f29dbc25Smrg    /* STREAM ENABLES */
55f29dbc25Smrg
56f29dbc25Smrg    vip_control1 |= buffer->stream_enables;
57f29dbc25Smrg
58f29dbc25Smrg    /* VIP CAPTURE MODE */
59f29dbc25Smrg
60f29dbc25Smrg    vip_control1 |= buffer->operating_mode;
61f29dbc25Smrg
62f29dbc25Smrg    /* HANDLE PLANAR CAPTURE */
63f29dbc25Smrg
64f29dbc25Smrg    if (buffer->flags & VIP_MODEFLAG_PLANARCAPTURE) {
65f29dbc25Smrg        vip_control1 |= VIP_CONTROL1_PLANAR;
66f29dbc25Smrg
67f29dbc25Smrg        if (buffer->planar_capture == VIP_420CAPTURE_EVERYLINE) {
68f29dbc25Smrg            vip_control1 |= VIP_CONTROL1_DISABLE_DECIMATION;
69f29dbc25Smrg        } else if (buffer->planar_capture == VIP_420CAPTURE_ALTERNATINGFIELDS) {
70f29dbc25Smrg            if (buffer->flags & VIP_MODEFLAG_PROGRESSIVE)
71f29dbc25Smrg                return CIM_STATUS_INVALIDPARAMS;
72f29dbc25Smrg
73f29dbc25Smrg            vip_control1 |= VIP_CONTROL1_DISABLE_DECIMATION;
74f29dbc25Smrg            vip_control3 |= VIP_CONTROL3_DECIMATE_EVEN;
75f29dbc25Smrg        } else if (buffer->planar_capture != VIP_420CAPTURE_ALTERNATINGLINES)
76f29dbc25Smrg            return CIM_STATUS_INVALIDPARAMS;
77f29dbc25Smrg
78f29dbc25Smrg        /* CONFIGURE THE VIDEO FIFO THRESHOLD BASED ON THE FIFO DEPTH */
79f29dbc25Smrg
80f29dbc25Smrg        vip_control2 |= VIP_CONTROL2_DEFAULT_VIDTH_420 <<
81f29dbc25Smrg            VIP_CONTROL2_VIDTH_SHIFT;
82f29dbc25Smrg
83f29dbc25Smrg    } else {
84f29dbc25Smrg        vip_control2 |= VIP_CONTROL2_DEFAULT_VIDTH_422 <<
85f29dbc25Smrg            VIP_CONTROL2_VIDTH_SHIFT;
86f29dbc25Smrg    }
87f29dbc25Smrg
88f29dbc25Smrg    /* CONFIGURE DEFAULT ANCILARRY THRESHOLD AND VIDEO FLUSH VALUES */
89f29dbc25Smrg
90f29dbc25Smrg    vip_control2 |= VIP_CONTROL2_DEFAULT_ANCTH << VIP_CONTROL2_ANCTH_SHIFT;
91f29dbc25Smrg    vip_control1 |= VIP_CONTROL1_DEFAULT_ANC_FF << VIP_CONTROL1_ANC_FF_SHIFT;
92f29dbc25Smrg    vip_control1 |= VIP_CONTROL1_DEFAULT_VID_FF << VIP_CONTROL1_VID_FF_SHIFT;
93f29dbc25Smrg
94f29dbc25Smrg    /* PROGRAM VIP OPTIONS */
95f29dbc25Smrg    /* The options are sanitized based on the current configuration. */
96f29dbc25Smrg
97f29dbc25Smrg    if (buffer->flags & VIP_MODEFLAG_PROGRESSIVE)
98f29dbc25Smrg        vip_control1 |= VIP_CONTROL1_NON_INTERLACED;
99f29dbc25Smrg    else {
100f29dbc25Smrg        if (buffer->flags & VIP_MODEFLAG_TOGGLEEACHFIELD)
101f29dbc25Smrg            vip_control3 |= VIP_CONTROL3_BASE_UPDATE;
102f29dbc25Smrg        if (buffer->flags & VIP_MODEFLAG_INVERTPOLARITY)
103f29dbc25Smrg            vip_control2 |= VIP_CONTROL2_INVERT_POLARITY;
104f29dbc25Smrg    }
105f29dbc25Smrg
106f29dbc25Smrg    if ((buffer->operating_mode == VIP_MODE_MSG ||
107f29dbc25Smrg            buffer->operating_mode == VIP_MODE_DATA) &&
108f29dbc25Smrg        (buffer->flags & VIP_MODEFLAG_FLIPMESSAGEWHENFULL)) {
109f29dbc25Smrg        vip_control1 |= VIP_CONTROL1_MSG_STRM_CTRL;
110f29dbc25Smrg    }
111f29dbc25Smrg
112f29dbc25Smrg    else if (buffer->operating_mode == VIP_MODE_VIP2_8BIT ||
113f29dbc25Smrg        buffer->operating_mode == VIP_MODE_VIP2_16BIT) {
114f29dbc25Smrg        if (buffer->flags & VIP_MODEFLAG_ENABLEREPEATFLAG)
115f29dbc25Smrg            vip_control2 |= VIP_CONTROL2_REPEAT_ENABLE;
116f29dbc25Smrg        if (buffer->flags & VIP_MODEFLAG_INVERTTASKPOLARITY)
117f29dbc25Smrg            vip_control3 |= VIP_CONTROL3_TASK_POLARITY;
118f29dbc25Smrg    }
119f29dbc25Smrg
120f29dbc25Smrg    if (buffer->flags & VIP_MODEFLAG_DISABLEZERODETECT)
121f29dbc25Smrg        vip_control1 |= VIP_CONTROL1_DISABLE_ZERO_DETECT;
122f29dbc25Smrg    if (buffer->flags & VIP_MODEFLAG_10BITANCILLARY)
123f29dbc25Smrg        vip_control2 |= VIP_CONTROL2_ANC10;
124f29dbc25Smrg
125f29dbc25Smrg    /* WRITE THE CONTROL REGISTERS */
126f29dbc25Smrg    /* The control registers are kept 'live' to allow separate instances of */
127f29dbc25Smrg    /* Cimarron to control the VIP hardware.                                */
128f29dbc25Smrg
129f29dbc25Smrg    WRITE_VIP32(VIP_CONTROL1, vip_control1);
130f29dbc25Smrg    WRITE_VIP32(VIP_CONTROL2, vip_control2);
131f29dbc25Smrg    WRITE_VIP32(VIP_CONTROL3, vip_control3);
132f29dbc25Smrg
133f29dbc25Smrg    /* CONFIGURE 601 PARAMETERS */
134f29dbc25Smrg
135f29dbc25Smrg    if (buffer->operating_mode == VIP_MODE_8BIT601 ||
136f29dbc25Smrg        buffer->operating_mode == VIP_MODE_16BIT601) {
137f29dbc25Smrg        vip_update_601_params(&buffer->vip601_settings);
138f29dbc25Smrg    }
139f29dbc25Smrg
140f29dbc25Smrg    return CIM_STATUS_OK;
141f29dbc25Smrg}
142f29dbc25Smrg
143f29dbc25Smrg/*---------------------------------------------------------------------------
144f29dbc25Smrg * vip_update_601_params
145f29dbc25Smrg *
146f29dbc25Smrg * This routine configures all aspects of 601 VIP data capture, including
147f29dbc25Smrg * start and stop timings and input polarities.
148f29dbc25Smrg *--------------------------------------------------------------------------*/
149f29dbc25Smrg
150f29dbc25Smrgint
151f29dbc25Smrgvip_update_601_params(VIP_601PARAMS * buffer)
152f29dbc25Smrg{
153f29dbc25Smrg    unsigned long vip_control3, vip_control1;
154f29dbc25Smrg
155f29dbc25Smrg    if (!buffer)
156f29dbc25Smrg        return CIM_STATUS_INVALIDPARAMS;
157f29dbc25Smrg
158f29dbc25Smrg    vip_control1 = READ_VIP32(VIP_CONTROL3);
159f29dbc25Smrg    vip_control3 = READ_VIP32(VIP_CONTROL3);
160f29dbc25Smrg
161f29dbc25Smrg    if (buffer->flags & VIP_MODEFLAG_VSYNCACTIVEHIGH)
162f29dbc25Smrg        vip_control3 |= VIP_CONTROL3_VSYNC_POLARITY;
163f29dbc25Smrg    else
164f29dbc25Smrg        vip_control3 &= ~VIP_CONTROL3_VSYNC_POLARITY;
165f29dbc25Smrg    if (buffer->flags & VIP_MODEFLAG_HSYNCACTIVEHIGH)
166f29dbc25Smrg        vip_control3 |= VIP_CONTROL3_HSYNC_POLARITY;
167f29dbc25Smrg    else
168f29dbc25Smrg        vip_control3 &= ~VIP_CONTROL3_HSYNC_POLARITY;
169f29dbc25Smrg
170f29dbc25Smrg    WRITE_VIP32(VIP_CONTROL3, vip_control3);
171f29dbc25Smrg    WRITE_VIP32(VIP_601_HORZ_START, buffer->horz_start);
172f29dbc25Smrg    WRITE_VIP32(VIP_601_VBI_START, buffer->vbi_start);
173f29dbc25Smrg    WRITE_VIP32(VIP_601_VBI_END, buffer->vbi_start + buffer->vbi_height - 1);
174f29dbc25Smrg    WRITE_VIP32(VIP_601_EVEN_START_STOP,
175f29dbc25Smrg        buffer->vert_start_even | ((buffer->vert_start_even +
176f29dbc25Smrg                buffer->even_height - 1) << 16));
177f29dbc25Smrg    WRITE_VIP32(VIP_601_ODD_START_STOP,
178f29dbc25Smrg        buffer->vert_start_odd | ((buffer->vert_start_odd +
179f29dbc25Smrg                buffer->odd_height - 1) << 16));
180f29dbc25Smrg    WRITE_VIP32(VIP_ODD_FIELD_DETECT,
181f29dbc25Smrg        buffer->odd_detect_start | (buffer->odd_detect_end << 16));
182f29dbc25Smrg
183f29dbc25Smrg    /* SPECIAL CASE FOR HORIZONTAL DATA
184f29dbc25Smrg     * 601 horizontal parameters are based on the number of clocks and not
185f29dbc25Smrg     * the number of pixels.
186f29dbc25Smrg     */
187f29dbc25Smrg
188f29dbc25Smrg    if ((vip_control1 & VIP_CONTROL1_MODE_MASK) == VIP_MODE_16BIT601)
189f29dbc25Smrg        WRITE_VIP32(VIP_601_HORZ_END,
190f29dbc25Smrg            buffer->horz_start + (buffer->width << 1) + 3);
191f29dbc25Smrg    else
192f29dbc25Smrg        WRITE_VIP32(VIP_601_HORZ_END, buffer->horz_start + buffer->width + 3);
193f29dbc25Smrg
194f29dbc25Smrg    return CIM_STATUS_OK;
195f29dbc25Smrg}
196f29dbc25Smrg
197f29dbc25Smrg/*---------------------------------------------------------------------------
198f29dbc25Smrg * vip_configure_capture_buffers
199f29dbc25Smrg *
200f29dbc25Smrg * This routine configures the base offsets for video, ancillary or message
201f29dbc25Smrg * mode capture.  The input structure can also contain multiple offsets, such
202f29dbc25Smrg * that the calling application can avoid updating the structure for each
203f29dbc25Smrg * flip.
204f29dbc25Smrg *
205f29dbc25Smrg * The new buffer addresses are written to the hardware registers although
206f29dbc25Smrg * they may not be latched immediately. Calling vip_is_buffer_update_latched
207f29dbc25Smrg * allows the determination of whether the update has occured.
208f29dbc25Smrg *
209f29dbc25Smrg * Review the Cimarron VIP API documentation to determine which buffer
210f29dbc25Smrg * addresses are latched immediately.
211f29dbc25Smrg *--------------------------------------------------------------------------*/
212f29dbc25Smrg
213f29dbc25Smrgint
214f29dbc25Smrgvip_configure_capture_buffers(int buffer_type, VIPINPUTBUFFER * buffer)
215f29dbc25Smrg{
216f29dbc25Smrg    VIPINPUTBUFFER_ADDR *offsets;
217f29dbc25Smrg    unsigned long cur_buffer = buffer->current_buffer;
218f29dbc25Smrg
219f29dbc25Smrg    if (!buffer)
220f29dbc25Smrg        return CIM_STATUS_INVALIDPARAMS;
221f29dbc25Smrg
222f29dbc25Smrg    if (buffer_type == VIP_BUFFER_A || buffer_type == VIP_BUFFER_601) {
223f29dbc25Smrg        offsets = &buffer->offsets[VIP_BUFFER_TASK_A];
224f29dbc25Smrg
225f29dbc25Smrg        /* SET VIDEO PITCH */
226f29dbc25Smrg
227f29dbc25Smrg        WRITE_VIP32(VIP_TASKA_VID_PITCH,
228f29dbc25Smrg            offsets->y_pitch | (offsets->uv_pitch << 16));
229f29dbc25Smrg
230f29dbc25Smrg        /* SET BASE OFFSETS */
231f29dbc25Smrg
232f29dbc25Smrg        if (buffer->flags & VIP_INPUTFLAG_INVERTPOLARITY) {
233f29dbc25Smrg            WRITE_VIP32(VIP_TASKA_VID_ODD_BASE,
234f29dbc25Smrg                offsets->even_base[cur_buffer]);
235f29dbc25Smrg            WRITE_VIP32(VIP_TASKA_VID_EVEN_BASE,
236f29dbc25Smrg                offsets->odd_base[cur_buffer]);
237f29dbc25Smrg            if (buffer->flags & VIP_INPUTFLAG_VBI) {
238f29dbc25Smrg                WRITE_VIP32(VIP_TASKA_VBI_ODD_BASE, offsets->vbi_even_base);
239f29dbc25Smrg                WRITE_VIP32(VIP_TASKA_VBI_EVEN_BASE, offsets->vbi_odd_base);
240f29dbc25Smrg            }
241f29dbc25Smrg        } else {
242f29dbc25Smrg            WRITE_VIP32(VIP_TASKA_VID_ODD_BASE,
243f29dbc25Smrg                offsets->odd_base[cur_buffer]);
244f29dbc25Smrg            WRITE_VIP32(VIP_TASKA_VID_EVEN_BASE,
245f29dbc25Smrg                offsets->even_base[cur_buffer]);
246f29dbc25Smrg            if (buffer->flags & VIP_INPUTFLAG_VBI) {
247f29dbc25Smrg                WRITE_VIP32(VIP_TASKA_VBI_ODD_BASE, offsets->vbi_odd_base);
248f29dbc25Smrg                WRITE_VIP32(VIP_TASKA_VBI_EVEN_BASE, offsets->vbi_even_base);
249f29dbc25Smrg            }
250f29dbc25Smrg        }
251f29dbc25Smrg
252f29dbc25Smrg        /* SET 4:2:0 OFFSETS */
253f29dbc25Smrg
254f29dbc25Smrg        if (buffer->flags & VIP_INPUTFLAG_PLANAR) {
255f29dbc25Smrg            WRITE_VIP32(VIP_TASKA_U_OFFSET, offsets->odd_uoffset);
256f29dbc25Smrg            WRITE_VIP32(VIP_TASKA_V_OFFSET, offsets->odd_voffset);
257f29dbc25Smrg            WRITE_VIP32(VIP_TASKA_U_EVEN_OFFSET, offsets->even_uoffset);
258f29dbc25Smrg            WRITE_VIP32(VIP_TASKA_V_EVEN_OFFSET, offsets->even_voffset);
259f29dbc25Smrg        }
260f29dbc25Smrg    } else if (buffer_type == VIP_BUFFER_B) {
261f29dbc25Smrg        offsets = &buffer->offsets[VIP_BUFFER_TASK_B];
262f29dbc25Smrg
263f29dbc25Smrg        /* SET VIDEO PITCH */
264f29dbc25Smrg
265f29dbc25Smrg        WRITE_VIP32(VIP_TASKB_VID_PITCH,
266f29dbc25Smrg            offsets->y_pitch | (offsets->uv_pitch << 16));
267f29dbc25Smrg
268f29dbc25Smrg        /* SET BASE OFFSETS */
269f29dbc25Smrg
270f29dbc25Smrg        if (buffer->flags & VIP_INPUTFLAG_INVERTPOLARITY) {
271f29dbc25Smrg            WRITE_VIP32(VIP_TASKB_VID_ODD_BASE,
272f29dbc25Smrg                offsets->even_base[cur_buffer]);
273f29dbc25Smrg            WRITE_VIP32(VIP_TASKB_VID_EVEN_BASE,
274f29dbc25Smrg                offsets->odd_base[cur_buffer]);
275f29dbc25Smrg            if (buffer->flags & VIP_INPUTFLAG_VBI) {
276f29dbc25Smrg                WRITE_VIP32(VIP_TASKB_VBI_ODD_BASE, offsets->vbi_even_base);
277f29dbc25Smrg                WRITE_VIP32(VIP_TASKB_VBI_EVEN_BASE, offsets->vbi_odd_base);
278f29dbc25Smrg            }
279f29dbc25Smrg        } else {
280f29dbc25Smrg            WRITE_VIP32(VIP_TASKB_VID_ODD_BASE,
281f29dbc25Smrg                offsets->odd_base[cur_buffer]);
282f29dbc25Smrg            WRITE_VIP32(VIP_TASKB_VID_EVEN_BASE,
283f29dbc25Smrg                offsets->even_base[cur_buffer]);
284f29dbc25Smrg            if (buffer->flags & VIP_INPUTFLAG_VBI) {
285f29dbc25Smrg                WRITE_VIP32(VIP_TASKB_VBI_ODD_BASE, offsets->vbi_odd_base);
286f29dbc25Smrg                WRITE_VIP32(VIP_TASKB_VBI_EVEN_BASE, offsets->vbi_even_base);
287f29dbc25Smrg            }
288f29dbc25Smrg        }
289f29dbc25Smrg
290f29dbc25Smrg        /* SET 4:2:0 OFFSETS */
291f29dbc25Smrg
292f29dbc25Smrg        if (buffer->flags & VIP_INPUTFLAG_PLANAR) {
293f29dbc25Smrg            WRITE_VIP32(VIP_TASKB_U_OFFSET, offsets->odd_uoffset);
294f29dbc25Smrg            WRITE_VIP32(VIP_TASKB_V_OFFSET, offsets->odd_voffset);
295f29dbc25Smrg        }
296f29dbc25Smrg    } else if (buffer_type == VIP_BUFFER_ANC || buffer_type == VIP_BUFFER_MSG) {
297f29dbc25Smrg        WRITE_VIP32(VIP_ANC_MSG1_BASE, buffer->ancillaryData.msg1_base);
298f29dbc25Smrg        WRITE_VIP32(VIP_ANC_MSG2_BASE, buffer->ancillaryData.msg2_base);
299f29dbc25Smrg        WRITE_VIP32(VIP_ANC_MSG_SIZE, buffer->ancillaryData.msg_size);
300f29dbc25Smrg    } else {
301f29dbc25Smrg        return CIM_STATUS_INVALIDPARAMS;
302f29dbc25Smrg    }
303f29dbc25Smrg
304f29dbc25Smrg    return CIM_STATUS_OK;
305f29dbc25Smrg}
306f29dbc25Smrg
307f29dbc25Smrg/*---------------------------------------------------------------------------
308f29dbc25Smrg * vip_toggle_vip_video_offsets
309f29dbc25Smrg *
310f29dbc25Smrg * This routine updates the offsets for video capture.  It is a simplified
311f29dbc25Smrg * version of vip_configure_capture_buffers that is designed to be called from
312f29dbc25Smrg * interrupt service routines or other buffer flipping applications that
313f29dbc25Smrg * require low latency.
314f29dbc25Smrg *--------------------------------------------------------------------------*/
315f29dbc25Smrg
316f29dbc25Smrgint
317f29dbc25Smrgvip_toggle_video_offsets(int buffer_type, VIPINPUTBUFFER * buffer)
318f29dbc25Smrg{
319f29dbc25Smrg    unsigned long cur_buffer = buffer->current_buffer;
320f29dbc25Smrg    VIPINPUTBUFFER_ADDR *offsets;
321f29dbc25Smrg
322f29dbc25Smrg    if (buffer_type == VIP_BUFFER_A) {
323f29dbc25Smrg        offsets = &buffer->offsets[VIP_BUFFER_TASK_A];
324f29dbc25Smrg
325f29dbc25Smrg        /* SET BASE OFFSETS */
326f29dbc25Smrg
327f29dbc25Smrg        if (buffer->flags & VIP_INPUTFLAG_INVERTPOLARITY) {
328f29dbc25Smrg            WRITE_VIP32(VIP_TASKA_VID_ODD_BASE,
329f29dbc25Smrg                offsets->even_base[cur_buffer]);
330f29dbc25Smrg            WRITE_VIP32(VIP_TASKA_VID_EVEN_BASE,
331f29dbc25Smrg                offsets->odd_base[cur_buffer]);
332f29dbc25Smrg        } else {
333f29dbc25Smrg            WRITE_VIP32(VIP_TASKA_VID_ODD_BASE,
334f29dbc25Smrg                offsets->odd_base[cur_buffer]);
335f29dbc25Smrg            WRITE_VIP32(VIP_TASKA_VID_EVEN_BASE,
336f29dbc25Smrg                offsets->even_base[cur_buffer]);
337f29dbc25Smrg        }
338f29dbc25Smrg    } else if (buffer_type == VIP_BUFFER_B) {
339f29dbc25Smrg        offsets = &buffer->offsets[VIP_BUFFER_TASK_B];
340f29dbc25Smrg
341f29dbc25Smrg        /* SET BASE OFFSETS */
342f29dbc25Smrg
343f29dbc25Smrg        if (buffer->flags & VIP_INPUTFLAG_INVERTPOLARITY) {
344f29dbc25Smrg            WRITE_VIP32(VIP_TASKB_VID_ODD_BASE,
345f29dbc25Smrg                offsets->even_base[cur_buffer]);
346f29dbc25Smrg            WRITE_VIP32(VIP_TASKB_VID_EVEN_BASE,
347f29dbc25Smrg                offsets->odd_base[cur_buffer]);
348f29dbc25Smrg        } else {
349f29dbc25Smrg            WRITE_VIP32(VIP_TASKB_VID_ODD_BASE,
350f29dbc25Smrg                offsets->odd_base[cur_buffer]);
351f29dbc25Smrg            WRITE_VIP32(VIP_TASKB_VID_EVEN_BASE,
352f29dbc25Smrg                offsets->even_base[cur_buffer]);
353f29dbc25Smrg        }
354f29dbc25Smrg    } else if (buffer_type == VIP_BUFFER_A_ODD) {
355f29dbc25Smrg        offsets = &buffer->offsets[VIP_BUFFER_TASK_A];
356f29dbc25Smrg
357f29dbc25Smrg        /* SET BASE OFFSETS */
358f29dbc25Smrg
359f29dbc25Smrg        if (buffer->flags & VIP_INPUTFLAG_INVERTPOLARITY)
360f29dbc25Smrg            WRITE_VIP32(VIP_TASKA_VID_ODD_BASE,
361f29dbc25Smrg                offsets->even_base[cur_buffer]);
362f29dbc25Smrg        else
363f29dbc25Smrg            WRITE_VIP32(VIP_TASKA_VID_ODD_BASE,
364f29dbc25Smrg                offsets->odd_base[cur_buffer]);
365f29dbc25Smrg    } else if (buffer_type == VIP_BUFFER_A_EVEN) {
366f29dbc25Smrg        offsets = &buffer->offsets[VIP_BUFFER_TASK_A];
367f29dbc25Smrg
368f29dbc25Smrg        /* SET BASE OFFSETS */
369f29dbc25Smrg
370f29dbc25Smrg        if (buffer->flags & VIP_INPUTFLAG_INVERTPOLARITY)
371f29dbc25Smrg            WRITE_VIP32(VIP_TASKA_VID_EVEN_BASE,
372f29dbc25Smrg                offsets->odd_base[cur_buffer]);
373f29dbc25Smrg        else
374f29dbc25Smrg            WRITE_VIP32(VIP_TASKA_VID_EVEN_BASE,
375f29dbc25Smrg                offsets->even_base[cur_buffer]);
376f29dbc25Smrg    } else if (buffer_type == VIP_BUFFER_B_ODD) {
377f29dbc25Smrg        offsets = &buffer->offsets[VIP_BUFFER_TASK_B];
378f29dbc25Smrg
379f29dbc25Smrg        /* SET BASE OFFSETS */
380f29dbc25Smrg
381f29dbc25Smrg        if (buffer->flags & VIP_INPUTFLAG_INVERTPOLARITY)
382f29dbc25Smrg            WRITE_VIP32(VIP_TASKB_VID_ODD_BASE,
383f29dbc25Smrg                offsets->even_base[cur_buffer]);
384f29dbc25Smrg        else
385f29dbc25Smrg            WRITE_VIP32(VIP_TASKB_VID_ODD_BASE,
386f29dbc25Smrg                offsets->odd_base[cur_buffer]);
387f29dbc25Smrg    } else if (buffer_type == VIP_BUFFER_B_EVEN) {
388f29dbc25Smrg        offsets = &buffer->offsets[VIP_BUFFER_TASK_B];
389f29dbc25Smrg
390f29dbc25Smrg        /* SET BASE OFFSETS */
391f29dbc25Smrg
392f29dbc25Smrg        if (buffer->flags & VIP_INPUTFLAG_INVERTPOLARITY)
393f29dbc25Smrg            WRITE_VIP32(VIP_TASKB_VID_EVEN_BASE,
394f29dbc25Smrg                offsets->odd_base[cur_buffer]);
395f29dbc25Smrg        else
396f29dbc25Smrg            WRITE_VIP32(VIP_TASKB_VID_EVEN_BASE,
397f29dbc25Smrg                offsets->even_base[cur_buffer]);
398f29dbc25Smrg    } else
399f29dbc25Smrg        return CIM_STATUS_INVALIDPARAMS;
400f29dbc25Smrg
401f29dbc25Smrg    return CIM_STATUS_OK;
402f29dbc25Smrg}
403f29dbc25Smrg
404f29dbc25Smrg/*---------------------------------------------------------------------------
405f29dbc25Smrg * vip_set_capture_state
406f29dbc25Smrg *
407f29dbc25Smrg * This routine takes the current control word definition ( stored in locals )
408f29dbc25Smrg * adds in the specified state, and writes the control word.
409f29dbc25Smrg *--------------------------------------------------------------------------*/
410f29dbc25Smrg
411f29dbc25Smrgint
412f29dbc25Smrgvip_set_capture_state(unsigned long state)
413f29dbc25Smrg{
414f29dbc25Smrg    unsigned long vip_control1, vip_control3;
415f29dbc25Smrg
416f29dbc25Smrg    /* UPDATE THE CURRENT CAPTURE MODE */
417f29dbc25Smrg
418f29dbc25Smrg    vip_control1 = READ_VIP32(VIP_CONTROL1);
419f29dbc25Smrg    vip_control3 = READ_VIP32(VIP_CONTROL3);
420f29dbc25Smrg    vip_control1 &= ~VIP_CONTROL1_RUNMODE_MASK;
421f29dbc25Smrg    vip_control1 |= (state << VIP_CONTROL1_RUNMODE_SHIFT);
422f29dbc25Smrg
423f29dbc25Smrg    WRITE_VIP32(VIP_CONTROL1, vip_control1);
424f29dbc25Smrg
425f29dbc25Smrg    if (state >= VIP_STARTCAPTUREATNEXTLINE) {
426f29dbc25Smrg        /* WHACK VIP RESET
427f29dbc25Smrg         * The VIP can get confused when switching between capture settings,
428f29dbc25Smrg         * such as between linear and planar.  We will thus whack VIP reset
429f29dbc25Smrg         * when enabling capture to ensure a pristine VIP state.
430f29dbc25Smrg         */
431f29dbc25Smrg
432f29dbc25Smrg        WRITE_VIP32(VIP_CONTROL1, vip_control1 | VIP_CONTROL1_RESET);
433f29dbc25Smrg        WRITE_VIP32(VIP_CONTROL1, vip_control1 & ~VIP_CONTROL1_RESET);
434f29dbc25Smrg        WRITE_VIP32(VIP_CONTROL3, vip_control3 | VIP_CONTROL3_FIFO_RESET);
435f29dbc25Smrg    }
436f29dbc25Smrg
437f29dbc25Smrg    return CIM_STATUS_OK;
438f29dbc25Smrg}
439f29dbc25Smrg
440f29dbc25Smrg/*---------------------------------------------------------------------------
441f29dbc25Smrg * vip_terminate
442f29dbc25Smrg *
443f29dbc25Smrg * This routine stops VIP capture and resets the VIP internal state.
444f29dbc25Smrg *--------------------------------------------------------------------------*/
445f29dbc25Smrg
446f29dbc25Smrgint
447f29dbc25Smrgvip_terminate(void)
448f29dbc25Smrg{
449f29dbc25Smrg    unsigned long timeout = 50000;
450f29dbc25Smrg
451f29dbc25Smrg    /* DISABLE AND CLEAR ALL VIP INTERRUPTS */
452f29dbc25Smrg
453f29dbc25Smrg    WRITE_VIP32(VIP_INTERRUPT, VIP_ALL_INTERRUPTS |
454f29dbc25Smrg        (VIP_ALL_INTERRUPTS >> 16));
455f29dbc25Smrg
456f29dbc25Smrg    /* DISABLE VIP CAPTURE */
457f29dbc25Smrg    /* We will try to let the VIP FIFO flush before shutting it down. */
458f29dbc25Smrg
459f29dbc25Smrg    WRITE_VIP32(VIP_CONTROL1, 0);
460f29dbc25Smrg    while (timeout) {
461f29dbc25Smrg        timeout--;
462f29dbc25Smrg        if (READ_VIP32(VIP_STATUS) & VIP_STATUS_WRITES_COMPLETE)
463f29dbc25Smrg            break;
464f29dbc25Smrg    }
465f29dbc25Smrg
466f29dbc25Smrg    /* RESET THE HARDWARE REGISTERS */
467f29dbc25Smrg    /* Note that we enable VIP reset to allow clock gating to lower VIP */
468f29dbc25Smrg    /* power consumption.                                               */
469f29dbc25Smrg
470f29dbc25Smrg    WRITE_VIP32(VIP_CONTROL1, VIP_CONTROL1_RESET);
471f29dbc25Smrg    WRITE_VIP32(VIP_CONTROL3, VIP_CONTROL3_FIFO_RESET);
472f29dbc25Smrg    WRITE_VIP32(VIP_CONTROL2, 0);
473f29dbc25Smrg
474f29dbc25Smrg    return CIM_STATUS_OK;
475f29dbc25Smrg}
476f29dbc25Smrg
477f29dbc25Smrg/*---------------------------------------------------------------------------
478f29dbc25Smrg * vip_configure_fifo
479f29dbc25Smrg *
480f29dbc25Smrg * This routine sets the desired threshold or flush for the specified fifo.
481f29dbc25Smrg *--------------------------------------------------------------------------*/
482f29dbc25Smrg
483f29dbc25Smrgint
484f29dbc25Smrgvip_configure_fifo(unsigned long fifo_type, unsigned long fifo_size)
485f29dbc25Smrg{
486f29dbc25Smrg    unsigned long vip_control1, vip_control2;
487f29dbc25Smrg
488f29dbc25Smrg    vip_control1 = READ_VIP32(VIP_CONTROL1);
489f29dbc25Smrg    vip_control2 = READ_VIP32(VIP_CONTROL2);
490f29dbc25Smrg
491f29dbc25Smrg    switch (fifo_type) {
492f29dbc25Smrg    case VIP_VIDEOTHRESHOLD:
493f29dbc25Smrg        vip_control2 &= ~VIP_CONTROL2_VIDTH_MASK;
494f29dbc25Smrg        vip_control2 |=
495f29dbc25Smrg            (fifo_size << VIP_CONTROL2_VIDTH_SHIFT) & VIP_CONTROL2_VIDTH_MASK;
496f29dbc25Smrg        break;
497f29dbc25Smrg
498f29dbc25Smrg    case VIP_ANCILLARYTHRESHOLD:
499f29dbc25Smrg        vip_control2 &= ~VIP_CONTROL2_ANCTH_MASK;
500f29dbc25Smrg        vip_control2 |=
501f29dbc25Smrg            (fifo_size << VIP_CONTROL2_ANCTH_SHIFT) & VIP_CONTROL2_ANCTH_MASK;
502f29dbc25Smrg        break;
503f29dbc25Smrg
504f29dbc25Smrg    case VIP_VIDEOFLUSH:
505f29dbc25Smrg        vip_control1 &= ~VIP_CONTROL1_VID_FF_MASK;
506f29dbc25Smrg        vip_control1 |=
507f29dbc25Smrg            ((fifo_size >> 2) << VIP_CONTROL1_VID_FF_SHIFT) &
508f29dbc25Smrg            VIP_CONTROL1_VID_FF_MASK;
509f29dbc25Smrg        break;
510f29dbc25Smrg
511f29dbc25Smrg    case VIP_ANCILLARYFLUSH:
512f29dbc25Smrg        vip_control1 &= ~VIP_CONTROL1_ANC_FF_MASK;
513f29dbc25Smrg        vip_control1 |=
514f29dbc25Smrg            ((fifo_size >> 2) << VIP_CONTROL1_ANC_FF_SHIFT) &
515f29dbc25Smrg            VIP_CONTROL1_ANC_FF_MASK;
516f29dbc25Smrg        break;
517f29dbc25Smrg
518f29dbc25Smrg    default:
519f29dbc25Smrg        return CIM_STATUS_INVALIDPARAMS;
520f29dbc25Smrg    }
521f29dbc25Smrg
522f29dbc25Smrg    WRITE_VIP32(VIP_CONTROL1, vip_control1);
523f29dbc25Smrg    WRITE_VIP32(VIP_CONTROL2, vip_control2);
524f29dbc25Smrg
525f29dbc25Smrg    return CIM_STATUS_OK;
526f29dbc25Smrg}
527f29dbc25Smrg
528f29dbc25Smrg/*---------------------------------------------------------------------------
529f29dbc25Smrg * vip_set_interrupt_enable
530f29dbc25Smrg *
531f29dbc25Smrg * This routine accepts a mask of interrupts to be enabled/disabled and
532f29dbc25Smrg * an enable flag.
533f29dbc25Smrg *
534f29dbc25Smrg * For each mask match, the interrupt will be enabled or disabled based on
535f29dbc25Smrg * enable
536f29dbc25Smrg *--------------------------------------------------------------------------*/
537f29dbc25Smrg
538f29dbc25Smrgint
539f29dbc25Smrgvip_set_interrupt_enable(unsigned long mask, int enable)
540f29dbc25Smrg{
541f29dbc25Smrg    /* CHECK IF ANY VALID INTERRUPTS ARE BEING CHANGED */
542f29dbc25Smrg
543f29dbc25Smrg    if (mask & VIP_ALL_INTERRUPTS) {
544f29dbc25Smrg        unsigned long int_enable = READ_VIP32(VIP_INTERRUPT) & 0xFFFF;
545f29dbc25Smrg
546f29dbc25Smrg        /* SET OR CLEAR THE MASK BITS */
547f29dbc25Smrg        /* Note that the upper 16-bits of the register are 0 after this */
548f29dbc25Smrg        /* operation.  This prevents us from indadvertently clearing a  */
549f29dbc25Smrg        /* pending interrupt by enabling/disabling another one.         */
550f29dbc25Smrg
551f29dbc25Smrg        if (enable)
552f29dbc25Smrg            int_enable &= ~(mask >> 16);
553f29dbc25Smrg        else
554f29dbc25Smrg            int_enable |= (mask >> 16);
555f29dbc25Smrg
556f29dbc25Smrg        WRITE_VIP32(VIP_INTERRUPT, int_enable);
557f29dbc25Smrg    }
558f29dbc25Smrg
559f29dbc25Smrg    return CIM_STATUS_OK;
560f29dbc25Smrg}
561f29dbc25Smrg
562f29dbc25Smrg/*---------------------------------------------------------------------------
563f29dbc25Smrg * vip_set_vsync_error
564f29dbc25Smrg *
565f29dbc25Smrg * This routine defines a region that is used to determine if the vsync is
566f29dbc25Smrg * within an acceptable range. This definition is accomplished using
567f29dbc25Smrg * a count and a vertical window.  The count specifies the exact number
568f29dbc25Smrg * of clocks expected for one field.  The window parameters specify the number
569f29dbc25Smrg * of clocks variation allowed before and after the expected vsync.  For
570f29dbc25Smrg * example, if vertical_count is 1000, window_before is 5 and window_after
571f29dbc25Smrg * is 12, VSync will be considered valid if it occurs between 995 and 1012
572f29dbc25Smrg * clocks after the last VSync.  The total window size (window_before +
573f29dbc25Smrg * window_after) cannot exceed 255.
574f29dbc25Smrg *--------------------------------------------------------------------------*/
575f29dbc25Smrg
576f29dbc25Smrgint
577f29dbc25Smrgvip_set_vsync_error(unsigned long vertical_count, unsigned long window_before,
578f29dbc25Smrg    unsigned long window_after, int enable)
579f29dbc25Smrg{
580f29dbc25Smrg    unsigned long vip_control2 = READ_VIP32(VIP_CONTROL2);
581f29dbc25Smrg    unsigned long temp;
582f29dbc25Smrg
583f29dbc25Smrg    if (enable) {
584f29dbc25Smrg        /* CREATE THE VERTICAL WINDOW
585f29dbc25Smrg         * The VIP uses two counters.  The first counter defines the minimum
586f29dbc25Smrg         * clock count before a valid VSync can occur.  The second counter
587f29dbc25Smrg         * starts after the first completes and defines the acceptable
588f29dbc25Smrg         * region of variation.
589f29dbc25Smrg         */
590f29dbc25Smrg
591f29dbc25Smrg        temp = ((window_before +
592f29dbc25Smrg                window_after) << VIP_VSYNC_ERR_WINDOW_SHIFT) &
593f29dbc25Smrg            VIP_VSYNC_ERR_WINDOW_MASK;
594f29dbc25Smrg        temp |= (vertical_count - window_before) & VIP_VSYNC_ERR_COUNT_MASK;
595f29dbc25Smrg
596f29dbc25Smrg        vip_control2 |= VIP_CONTROL2_VERTERROR_ENABLE;
597f29dbc25Smrg
598f29dbc25Smrg        WRITE_VIP32(VIP_VSYNC_ERR_COUNT, temp);
599f29dbc25Smrg    } else {
600f29dbc25Smrg        vip_control2 &= ~VIP_CONTROL2_VERTERROR_ENABLE;
601f29dbc25Smrg    }
602f29dbc25Smrg    WRITE_VIP32(VIP_CONTROL2, vip_control2);
603f29dbc25Smrg
604f29dbc25Smrg    return CIM_STATUS_OK;
605f29dbc25Smrg}
606f29dbc25Smrg
607f29dbc25Smrg/*---------------------------------------------------------------------------
608f29dbc25Smrg * vip_max_address_enable
609f29dbc25Smrg *
610f29dbc25Smrg * This routine specifies the maximum address to which the the hardware should
611f29dbc25Smrg * write during data storage. If this value is exceeded an error is generated,
612f29dbc25Smrg * (this may be monitored using the appropriate interrupt flags - see
613f29dbc25Smrg * vip_set_interrupt_enable)
614f29dbc25Smrg *--------------------------------------------------------------------------*/
615f29dbc25Smrg
616f29dbc25Smrgint
617f29dbc25Smrgvip_max_address_enable(unsigned long max_address, int enable)
618f29dbc25Smrg{
619f29dbc25Smrg    unsigned long vip_control2 = READ_VIP32(VIP_CONTROL2);
620f29dbc25Smrg
621f29dbc25Smrg    if (enable) {
622f29dbc25Smrg        /* ENABLE THE CONTROL BIT */
623f29dbc25Smrg
624f29dbc25Smrg        vip_control2 |= VIP_CONTROL2_ADD_ERROR_ENABLE;
625f29dbc25Smrg
626f29dbc25Smrg        WRITE_VIP32(VIP_MAX_ADDRESS, max_address & VIP_MAXADDR_MASK);
627f29dbc25Smrg    } else {
628f29dbc25Smrg        /* DISABLE DETECTION */
629f29dbc25Smrg
630f29dbc25Smrg        vip_control2 &= ~VIP_CONTROL2_ADD_ERROR_ENABLE;
631f29dbc25Smrg    }
632f29dbc25Smrg    WRITE_VIP32(VIP_CONTROL2, vip_control2);
633f29dbc25Smrg
634f29dbc25Smrg    return CIM_STATUS_OK;
635f29dbc25Smrg}
636f29dbc25Smrg
637f29dbc25Smrg/*---------------------------------------------------------------------------
638f29dbc25Smrg * vip_set_loopback_enable
639f29dbc25Smrg *
640f29dbc25Smrg * This routine enables/disables internal loopback functionality.  When
641f29dbc25Smrg * loopback is enabled, the VOP outputs are rerouted to the VIP inputs
642f29dbc25Smrg * internal to the chip.  No loopback connector is required.
643f29dbc25Smrg *--------------------------------------------------------------------------*/
644f29dbc25Smrg
645f29dbc25Smrgint
646f29dbc25Smrgvip_set_loopback_enable(int enable)
647f29dbc25Smrg{
648f29dbc25Smrg    unsigned long vip_control2 = READ_VIP32(VIP_CONTROL2);
649f29dbc25Smrg
650f29dbc25Smrg    if (enable)
651f29dbc25Smrg        vip_control2 |= VIP_CONTROL2_LOOPBACK_ENABLE;
652f29dbc25Smrg    else
653f29dbc25Smrg        vip_control2 &= ~VIP_CONTROL2_LOOPBACK_ENABLE;
654f29dbc25Smrg
655f29dbc25Smrg    WRITE_VIP32(VIP_CONTROL2, vip_control2);
656f29dbc25Smrg
657f29dbc25Smrg    return CIM_STATUS_OK;
658f29dbc25Smrg}
659f29dbc25Smrg
660f29dbc25Smrg/*---------------------------------------------------------------------------
661f29dbc25Smrg * vip_configure_genlock
662f29dbc25Smrg *
663f29dbc25Smrg * This routine configures genlock functionality.
664f29dbc25Smrg *---------------------------------------------------------------------------*/
665f29dbc25Smrg
666f29dbc25Smrgint
667f29dbc25Smrgvip_configure_genlock(VIPGENLOCKBUFFER * buffer)
668f29dbc25Smrg{
669f29dbc25Smrg    unsigned long vip_control1, vip_control2;
670f29dbc25Smrg    unsigned long unlock, genlk_ctl;
671f29dbc25Smrg
672f29dbc25Smrg    if (!buffer)
673f29dbc25Smrg        return CIM_STATUS_INVALIDPARAMS;
674f29dbc25Smrg
675f29dbc25Smrg    unlock = READ_REG32(DC3_UNLOCK);
676f29dbc25Smrg    genlk_ctl = READ_REG32(DC3_GENLK_CTL);
677f29dbc25Smrg    vip_control1 = READ_VIP32(VIP_CONTROL1);
678f29dbc25Smrg    vip_control2 = READ_VIP32(VIP_CONTROL2);
679f29dbc25Smrg
680f29dbc25Smrg    /* UPDATE VIDEO DETECTION */
681f29dbc25Smrg    /* These flags are used to indicate the ways in which the VIP signal */
682f29dbc25Smrg    /* can be considered 'lost'.                                         */
683f29dbc25Smrg
684f29dbc25Smrg    vip_control1 &= ~VIP_CONTROL1_VDE_FF_MASK;
685f29dbc25Smrg    vip_control2 &= ~(VIP_CONTROL2_FIELD2VG_MASK | VIP_CONTROL2_SYNC2VG_MASK);
686f29dbc25Smrg    vip_control1 |= buffer->vip_signal_loss;
687f29dbc25Smrg
688f29dbc25Smrg    /* UPDATE FIELD AND VSYNC INFORMATION */
689f29dbc25Smrg    /* These flags control how and when the even/odd field and Vsync */
690f29dbc25Smrg    /* information is communicated to the VG.                        */
691f29dbc25Smrg
692f29dbc25Smrg    vip_control2 |= buffer->field_to_vg;
693f29dbc25Smrg    vip_control2 |= buffer->vsync_to_vg;
694f29dbc25Smrg
695f29dbc25Smrg    /* ENABLE OR DISABLE GENLOCK TIMEOUT */
696f29dbc25Smrg    /* Enabling genlock timeout allows the VG to revert to its own sync */
697f29dbc25Smrg    /* timings when the VIP input is lost.  Note that the VIP will not  */
698f29dbc25Smrg    /* know the signal is lost unless the appropriate error detection   */
699f29dbc25Smrg    /* flags have been enabled inside vip_initialize.                   */
700f29dbc25Smrg
701f29dbc25Smrg    if (buffer->enable_timeout)
702f29dbc25Smrg        genlk_ctl |= DC3_GC_GENLOCK_TO_ENABLE;
703f29dbc25Smrg    else
704f29dbc25Smrg        genlk_ctl &= ~DC3_GC_GENLOCK_TO_ENABLE;
705f29dbc25Smrg
706f29dbc25Smrg    genlk_ctl &= ~DC3_GC_GENLOCK_SKEW_MASK;
707f29dbc25Smrg    genlk_ctl |= buffer->genlock_skew & DC3_GC_GENLOCK_SKEW_MASK;
708f29dbc25Smrg
709f29dbc25Smrg    WRITE_REG32(DC3_UNLOCK, DC3_UNLOCK_VALUE);
710f29dbc25Smrg    WRITE_REG32(DC3_GENLK_CTL, genlk_ctl);
711f29dbc25Smrg    WRITE_VIP32(VIP_CONTROL1, vip_control1);
712f29dbc25Smrg    WRITE_VIP32(VIP_CONTROL2, vip_control2);
713f29dbc25Smrg    WRITE_REG32(DC3_UNLOCK, unlock);
714f29dbc25Smrg
715f29dbc25Smrg    return CIM_STATUS_OK;
716f29dbc25Smrg}
717f29dbc25Smrg
718f29dbc25Smrg/*---------------------------------------------------------------------------
719f29dbc25Smrg * vip_set_genlock_enable
720f29dbc25Smrg *
721f29dbc25Smrg * This routine enables/disables genlock inside the VG.
722f29dbc25Smrg *--------------------------------------------------------------------------*/
723f29dbc25Smrg
724f29dbc25Smrgint
725f29dbc25Smrgvip_set_genlock_enable(int enable)
726f29dbc25Smrg{
727f29dbc25Smrg    unsigned long unlock, temp;
728f29dbc25Smrg
729f29dbc25Smrg    unlock = READ_REG32(DC3_UNLOCK);
730f29dbc25Smrg    temp = READ_REG32(DC3_GENLK_CTL);
731f29dbc25Smrg
732f29dbc25Smrg    if (enable)
733f29dbc25Smrg        temp |= DC3_GC_GENLOCK_ENABLE;
734f29dbc25Smrg    else
735f29dbc25Smrg        temp &= ~DC3_GC_GENLOCK_ENABLE;
736f29dbc25Smrg
737f29dbc25Smrg    WRITE_REG32(DC3_UNLOCK, DC3_UNLOCK_VALUE);
738f29dbc25Smrg    WRITE_REG32(DC3_GENLK_CTL, temp);
739f29dbc25Smrg    WRITE_REG32(DC3_UNLOCK, unlock);
740f29dbc25Smrg
741f29dbc25Smrg    return CIM_STATUS_OK;
742f29dbc25Smrg}
743f29dbc25Smrg
744f29dbc25Smrg/*---------------------------------------------------------------------------
745f29dbc25Smrg * vip_set_power_characteristics
746f29dbc25Smrg *
747f29dbc25Smrg * This routine takes a VIPPOWERBUFFER structure, and selectively sets the
748f29dbc25Smrg * GeodeLink power and/or Vip clock power states.
749f29dbc25Smrg *--------------------------------------------------------------------------*/
750f29dbc25Smrg
751f29dbc25Smrgint
752f29dbc25Smrgvip_set_power_characteristics(VIPPOWERBUFFER * buffer)
753f29dbc25Smrg{
754f29dbc25Smrg    Q_WORD q_word;
755f29dbc25Smrg
756f29dbc25Smrg    if (!buffer)
757f29dbc25Smrg        return CIM_STATUS_INVALIDPARAMS;
758f29dbc25Smrg
759f29dbc25Smrg    q_word.low = q_word.high = 0;
760f29dbc25Smrg
761f29dbc25Smrg    /* ENABLE GEODELINK CLOCK GATING */
762f29dbc25Smrg
763f29dbc25Smrg    if (buffer->glink_clock_mode)
764f29dbc25Smrg        q_word.low |= VIP_MSR_POWER_GLINK;
765f29dbc25Smrg
766f29dbc25Smrg    /* ENABLE VIP CLOCK GATING */
767f29dbc25Smrg
768f29dbc25Smrg    if (buffer->vip_clock_mode)
769f29dbc25Smrg        q_word.low |= VIP_MSR_POWER_CLOCK;
770f29dbc25Smrg
771f29dbc25Smrg    /* WRITE THE NEW VALUE */
772f29dbc25Smrg
773f29dbc25Smrg    msr_write64(MSR_DEVICE_GEODELX_VIP, MSR_GEODELINK_PM, &q_word);
774f29dbc25Smrg
775f29dbc25Smrg    return CIM_STATUS_OK;
776f29dbc25Smrg}
777f29dbc25Smrg
778f29dbc25Smrg/*---------------------------------------------------------------------------
779f29dbc25Smrg * vip_set_priority_characteristics
780f29dbc25Smrg *
781f29dbc25Smrg * This routine programs the VIP GeodeLink priority characteristics
782f29dbc25Smrg *--------------------------------------------------------------------------*/
783f29dbc25Smrg
784f29dbc25Smrgint
785f29dbc25Smrgvip_set_priority_characteristics(VIPPRIORITYBUFFER * buffer)
786f29dbc25Smrg{
787f29dbc25Smrg    Q_WORD q_word;
788f29dbc25Smrg
789f29dbc25Smrg    if (!buffer)
790f29dbc25Smrg        return CIM_STATUS_INVALIDPARAMS;
791f29dbc25Smrg
792f29dbc25Smrg    q_word.low = q_word.high = 0;
793f29dbc25Smrg
794f29dbc25Smrg    q_word.low |= (buffer->secondary <<
795f29dbc25Smrg        VIP_MSR_MCR_SECOND_PRIORITY_SHIFT) & VIP_MSR_MCR_SECOND_PRIORITY_MASK;
796f29dbc25Smrg    q_word.low |= (buffer->primary <<
797f29dbc25Smrg        VIP_MSR_MCR_PRIMARY_PRIORITY_SHIFT) &
798f29dbc25Smrg        VIP_MSR_MCR_PRIMARY_PRIORITY_MASK;
799f29dbc25Smrg    q_word.low |= (buffer->pid << VIP_MSR_MCR_PID_SHIFT) &
800f29dbc25Smrg        VIP_MSR_MCR_PID_MASK;
801f29dbc25Smrg
802f29dbc25Smrg    msr_write64(MSR_DEVICE_GEODELX_VIP, MSR_GEODELINK_CONFIG, &q_word);
803f29dbc25Smrg
804f29dbc25Smrg    return CIM_STATUS_OK;
805f29dbc25Smrg}
806f29dbc25Smrg
807f29dbc25Smrg/*---------------------------------------------------------------------------
808f29dbc25Smrg * vip_set_debug_characteristics
809f29dbc25Smrg *
810f29dbc25Smrg * This routine configures the debug data that is exposed over the diag bus.
811f29dbc25Smrg *--------------------------------------------------------------------------*/
812f29dbc25Smrg
813f29dbc25Smrgint
814f29dbc25Smrgvip_set_debug_characteristics(VIPDEBUGBUFFER * buffer)
815f29dbc25Smrg{
816f29dbc25Smrg    Q_WORD q_word;
817f29dbc25Smrg
818f29dbc25Smrg    if (!buffer)
819f29dbc25Smrg        return CIM_STATUS_INVALIDPARAMS;
820f29dbc25Smrg
821f29dbc25Smrg    q_word.low = q_word.high = 0;
822f29dbc25Smrg
823f29dbc25Smrg    q_word.high |= (buffer->bist << VIP_MSR_DIAG_BIST_SHIFT) &
824f29dbc25Smrg        VIP_MSR_DIAG_BIST_WMASK;
825f29dbc25Smrg    q_word.low |= (buffer->enable_upper ?
826f29dbc25Smrg        VIP_MSR_DIAG_MSB_ENABLE : 0x00000000);
827f29dbc25Smrg    q_word.low |= (buffer->select_upper << VIP_MSR_DIAG_SEL_UPPER_SHIFT) &
828f29dbc25Smrg        VIP_MSR_DIAG_SEL_UPPER_MASK;
829f29dbc25Smrg    q_word.low |= (buffer->enable_lower ?
830f29dbc25Smrg        VIP_MSR_DIAG_LSB_ENABLE : 0x00000000);
831f29dbc25Smrg    q_word.low |= (buffer->select_lower << VIP_MSR_DIAG_SEL_LOWER_SHIFT) &
832f29dbc25Smrg        VIP_MSR_DIAG_SEL_LOWER_MASK;
833f29dbc25Smrg
834f29dbc25Smrg    msr_write64(MSR_DEVICE_GEODELX_VIP, MSR_GEODELINK_DIAG, &q_word);
835f29dbc25Smrg
836f29dbc25Smrg    return CIM_STATUS_OK;
837f29dbc25Smrg}
838f29dbc25Smrg
839f29dbc25Smrg/*---------------------------------------------------------------------------
840f29dbc25Smrg * vip_configure_pages
841f29dbc25Smrg *
842f29dbc25Smrg * This routine sets the number of pages, and their offset from each other.
843f29dbc25Smrg *--------------------------------------------------------------------------*/
844f29dbc25Smrg
845f29dbc25Smrgint
846f29dbc25Smrgvip_configure_pages(int page_count, unsigned long page_offset)
847f29dbc25Smrg{
848f29dbc25Smrg    unsigned long vip_control2 = READ_VIP32(VIP_CONTROL2);
849f29dbc25Smrg
850f29dbc25Smrg    /* SET THE NEW PAGE COUNT */
851f29dbc25Smrg
852f29dbc25Smrg    vip_control2 &= ~VIP_CONTROL2_PAGECNT_MASK;
853f29dbc25Smrg    vip_control2 |= (page_count << VIP_CONTROL2_PAGECNT_SHIFT) &
854f29dbc25Smrg        VIP_CONTROL2_PAGECNT_MASK;
855f29dbc25Smrg
856f29dbc25Smrg    /* WRITE THE PAGE OFFSET */
857f29dbc25Smrg
858f29dbc25Smrg    WRITE_VIP32(VIP_CONTROL2, vip_control2);
859f29dbc25Smrg    WRITE_VIP32(VIP_PAGE_OFFSET, page_offset);
860f29dbc25Smrg
861f29dbc25Smrg    return CIM_STATUS_OK;
862f29dbc25Smrg}
863f29dbc25Smrg
864f29dbc25Smrg/*---------------------------------------------------------------------------
865f29dbc25Smrg * vip_set_interrupt_line
866f29dbc25Smrg *
867f29dbc25Smrg * This routine sets the line at which a line interrupt should be generated.
868f29dbc25Smrg *--------------------------------------------------------------------------*/
869f29dbc25Smrg
870f29dbc25Smrgint
871f29dbc25Smrgvip_set_interrupt_line(int line)
872f29dbc25Smrg{
873f29dbc25Smrg    WRITE_VIP32(VIP_CURRENT_TARGET,
874f29dbc25Smrg        (line << VIP_CTARGET_TLINE_SHIFT) & VIP_CTARGET_TLINE_MASK);
875f29dbc25Smrg
876f29dbc25Smrg    return CIM_STATUS_OK;
877f29dbc25Smrg}
878f29dbc25Smrg
879f29dbc25Smrg/*---------------------------------------------------------------------------
880f29dbc25Smrg * vip_reset
881f29dbc25Smrg *
882f29dbc25Smrg * This routine does a one-shot enable of the VIP hardware.  It is useful
883f29dbc25Smrg * for handling unrecoverable VIP errors.
884f29dbc25Smrg *--------------------------------------------------------------------------*/
885f29dbc25Smrg
886f29dbc25Smrgint
887f29dbc25Smrgvip_reset(void)
888f29dbc25Smrg{
889f29dbc25Smrg    unsigned long vip_control1, vip_control3;
890f29dbc25Smrg
891f29dbc25Smrg    /* INVERT THE PAUSE BIT */
892f29dbc25Smrg
893f29dbc25Smrg    vip_control1 = READ_VIP32(VIP_CONTROL1);
894f29dbc25Smrg    vip_control3 = READ_VIP32(VIP_CONTROL3);
895f29dbc25Smrg
896f29dbc25Smrg    WRITE_VIP32(VIP_CONTROL1, vip_control1 | VIP_CONTROL1_RESET);
897f29dbc25Smrg    WRITE_VIP32(VIP_CONTROL1, vip_control1 & ~VIP_CONTROL1_RESET);
898f29dbc25Smrg    WRITE_VIP32(VIP_CONTROL3, vip_control3 | VIP_CONTROL3_FIFO_RESET);
899f29dbc25Smrg
900f29dbc25Smrg    return CIM_STATUS_OK;
901f29dbc25Smrg}
902f29dbc25Smrg
903f29dbc25Smrg/*---------------------------------------------------------------------------
904f29dbc25Smrg * vip_set_subwindow_enable
905f29dbc25Smrg *
906f29dbc25Smrg * This routine turns on SubWindow capture, that is a portion of the incoming
907f29dbc25Smrg * signal is captured rather than the entire frame. The window always has
908f29dbc25Smrg * the same width as the frame, only the vertical component can be
909f29dbc25Smrg * modified.
910f29dbc25Smrg *--------------------------------------------------------------------------*/
911f29dbc25Smrg
912f29dbc25Smrgint
913f29dbc25Smrgvip_set_subwindow_enable(VIPSUBWINDOWBUFFER * buffer)
914f29dbc25Smrg{
915f29dbc25Smrg    unsigned long vip_control2;
916f29dbc25Smrg
917f29dbc25Smrg    if (!buffer)
918f29dbc25Smrg        return CIM_STATUS_INVALIDPARAMS;
919f29dbc25Smrg
920f29dbc25Smrg    vip_control2 = READ_VIP32(VIP_CONTROL2);
921f29dbc25Smrg    if (buffer->enable) {
922f29dbc25Smrg        /* WRITE THE WINDOW VALUE */
923f29dbc25Smrg
924f29dbc25Smrg        WRITE_VIP32(VIP_VERTICAL_START_STOP, ((buffer->stop <<
925f29dbc25Smrg                    VIP_VSTART_VERTEND_SHIFT) &
926f29dbc25Smrg                VIP_VSTART_VERTEND_MASK) | ((buffer->start <<
927f29dbc25Smrg                    VIP_VSTART_VERTSTART_SHIFT) & VIP_VSTART_VERTSTART_MASK));
928f29dbc25Smrg
929f29dbc25Smrg        /* ENABLE IN THE CONTROL REGISTER */
930f29dbc25Smrg
931f29dbc25Smrg        vip_control2 |= VIP_CONTROL2_SWC_ENABLE;
932f29dbc25Smrg    } else {
933f29dbc25Smrg        /* DISABLE SUBWINDOW CAPTURE IN THE CONTROL REGISTER */
934f29dbc25Smrg
935f29dbc25Smrg        vip_control2 &= ~VIP_CONTROL2_SWC_ENABLE;
936f29dbc25Smrg    }
937f29dbc25Smrg    WRITE_VIP32(VIP_CONTROL2, vip_control2);
938f29dbc25Smrg
939f29dbc25Smrg    return CIM_STATUS_OK;
940f29dbc25Smrg}
941f29dbc25Smrg
942f29dbc25Smrg/*---------------------------------------------------------------------------
943f29dbc25Smrg * vip_reset_interrupt_state
944f29dbc25Smrg *
945f29dbc25Smrg * This routine resets the state of one or more interrupts.
946f29dbc25Smrg *--------------------------------------------------------------------------*/
947f29dbc25Smrg
948f29dbc25Smrgint
949f29dbc25Smrgvip_reset_interrupt_state(unsigned long interrupt_mask)
950f29dbc25Smrg{
951f29dbc25Smrg    unsigned long temp;
952f29dbc25Smrg
953f29dbc25Smrg    temp = READ_VIP32(VIP_INTERRUPT);
954f29dbc25Smrg    WRITE_VIP32(VIP_INTERRUPT, temp | (interrupt_mask & VIP_ALL_INTERRUPTS));
955f29dbc25Smrg
956f29dbc25Smrg    return CIM_STATUS_OK;
957f29dbc25Smrg}
958f29dbc25Smrg
959f29dbc25Smrg/*---------------------------------------------------------------------------
960f29dbc25Smrg * vip_save_state
961f29dbc25Smrg *
962f29dbc25Smrg * This routine saves the necessary register contents in order to restore
963f29dbc25Smrg * at a later point to the same state.
964f29dbc25Smrg *
965f29dbc25Smrg * NOTE: Capture state is forced to OFF in this routine
966f29dbc25Smrg *--------------------------------------------------------------------------*/
967f29dbc25Smrg
968f29dbc25Smrgint
969f29dbc25Smrgvip_save_state(VIPSTATEBUFFER * save_buffer)
970f29dbc25Smrg{
971f29dbc25Smrg    if (!save_buffer)
972f29dbc25Smrg        return CIM_STATUS_INVALIDPARAMS;
973f29dbc25Smrg
974f29dbc25Smrg    /* FORCE CAPTURE TO BE DISABLED */
975f29dbc25Smrg
976f29dbc25Smrg    vip_set_capture_state(VIP_STOPCAPTURE);
977f29dbc25Smrg
978f29dbc25Smrg    /* READ AND SAVE THE REGISTER CONTENTS */
979f29dbc25Smrg
980f29dbc25Smrg    save_buffer->control1 = READ_VIP32(VIP_CONTROL1);
981f29dbc25Smrg    save_buffer->control2 = READ_VIP32(VIP_CONTROL2);
982f29dbc25Smrg    save_buffer->vip_int = READ_VIP32(VIP_INTERRUPT);
983f29dbc25Smrg    save_buffer->current_target = READ_VIP32(VIP_CURRENT_TARGET);
984f29dbc25Smrg    save_buffer->max_address = READ_VIP32(VIP_MAX_ADDRESS);
985f29dbc25Smrg    save_buffer->taska_evenbase = READ_VIP32(VIP_TASKA_VID_EVEN_BASE);
986f29dbc25Smrg    save_buffer->taska_oddbase = READ_VIP32(VIP_TASKA_VID_ODD_BASE);
987f29dbc25Smrg    save_buffer->taska_vbi_evenbase = READ_VIP32(VIP_TASKA_VBI_EVEN_BASE);
988f29dbc25Smrg    save_buffer->taska_vbi_oddbase = READ_VIP32(VIP_TASKA_VBI_ODD_BASE);
989f29dbc25Smrg    save_buffer->taska_data_pitch = READ_VIP32(VIP_TASKA_VID_PITCH);
990f29dbc25Smrg    save_buffer->control3 = READ_VIP32(VIP_CONTROL3);
991f29dbc25Smrg    save_buffer->taska_v_oddoffset = READ_VIP32(VIP_TASKA_U_OFFSET);
992f29dbc25Smrg    save_buffer->taska_u_oddoffset = READ_VIP32(VIP_TASKA_V_OFFSET);
993f29dbc25Smrg    save_buffer->taskb_evenbase = READ_VIP32(VIP_TASKB_VID_EVEN_BASE);
994f29dbc25Smrg    save_buffer->taskb_oddbase = READ_VIP32(VIP_TASKB_VID_ODD_BASE);
995f29dbc25Smrg    save_buffer->taskb_vbi_evenbase = READ_VIP32(VIP_TASKB_VBI_EVEN_BASE);
996f29dbc25Smrg    save_buffer->taskb_vbi_oddbase = READ_VIP32(VIP_TASKB_VBI_ODD_BASE);
997f29dbc25Smrg    save_buffer->taskb_pitch = READ_VIP32(VIP_TASKB_VID_PITCH);
998f29dbc25Smrg    save_buffer->taskb_voffset = READ_VIP32(VIP_TASKB_U_OFFSET);
999f29dbc25Smrg    save_buffer->taskb_uoffset = READ_VIP32(VIP_TASKB_V_OFFSET);
1000f29dbc25Smrg    save_buffer->msg1_base = READ_VIP32(VIP_ANC_MSG1_BASE);
1001f29dbc25Smrg    save_buffer->msg2_base = READ_VIP32(VIP_ANC_MSG2_BASE);
1002f29dbc25Smrg    save_buffer->msg_size = READ_VIP32(VIP_ANC_MSG_SIZE);
1003f29dbc25Smrg    save_buffer->page_offset = READ_VIP32(VIP_PAGE_OFFSET);
1004f29dbc25Smrg    save_buffer->vert_start_stop = READ_VIP32(VIP_VERTICAL_START_STOP);
1005f29dbc25Smrg    save_buffer->vsync_err_count = READ_VIP32(VIP_VSYNC_ERR_COUNT);
1006f29dbc25Smrg    save_buffer->taska_u_evenoffset = READ_VIP32(VIP_TASKA_U_EVEN_OFFSET);
1007f29dbc25Smrg    save_buffer->taska_v_evenoffset = READ_VIP32(VIP_TASKA_V_EVEN_OFFSET);
1008f29dbc25Smrg
1009f29dbc25Smrg    /* READ ALL VIP MSRS */
1010f29dbc25Smrg
1011f29dbc25Smrg    msr_read64(MSR_DEVICE_GEODELX_VIP, MSR_GEODELINK_CONFIG,
1012f29dbc25Smrg        &(save_buffer->msr_config));
1013f29dbc25Smrg    msr_read64(MSR_DEVICE_GEODELX_VIP, MSR_GEODELINK_SMI,
1014f29dbc25Smrg        &(save_buffer->msr_smi));
1015f29dbc25Smrg    msr_read64(MSR_DEVICE_GEODELX_VIP, MSR_GEODELINK_PM,
1016f29dbc25Smrg        &(save_buffer->msr_pm));
1017f29dbc25Smrg    msr_read64(MSR_DEVICE_GEODELX_VIP, MSR_GEODELINK_DIAG,
1018f29dbc25Smrg        &(save_buffer->msr_diag));
1019f29dbc25Smrg
1020f29dbc25Smrg    return CIM_STATUS_OK;
1021f29dbc25Smrg}
1022f29dbc25Smrg
1023f29dbc25Smrg/*---------------------------------------------------------------------------
1024f29dbc25Smrg * vip_restore_state
1025f29dbc25Smrg *
1026f29dbc25Smrg * This routine restores the state of the vip registers - which were
1027f29dbc25Smrg * previously saved using vip_save_state.
1028f29dbc25Smrg *--------------------------------------------------------------------------*/
1029f29dbc25Smrg
1030f29dbc25Smrgint
1031f29dbc25Smrgvip_restore_state(VIPSTATEBUFFER * restore_buffer)
1032f29dbc25Smrg{
1033f29dbc25Smrg    if (!restore_buffer)
1034f29dbc25Smrg        return CIM_STATUS_OK;
1035f29dbc25Smrg
1036f29dbc25Smrg    /* RESTORE THE REGISTERS */
1037f29dbc25Smrg
1038f29dbc25Smrg    WRITE_VIP32(VIP_CURRENT_TARGET, restore_buffer->current_target);
1039f29dbc25Smrg    WRITE_VIP32(VIP_MAX_ADDRESS, restore_buffer->max_address);
1040f29dbc25Smrg    WRITE_VIP32(VIP_TASKA_VID_EVEN_BASE, restore_buffer->taska_evenbase);
1041f29dbc25Smrg    WRITE_VIP32(VIP_TASKA_VID_ODD_BASE, restore_buffer->taska_oddbase);
1042f29dbc25Smrg    WRITE_VIP32(VIP_TASKA_VBI_EVEN_BASE, restore_buffer->taska_vbi_evenbase);
1043f29dbc25Smrg    WRITE_VIP32(VIP_TASKA_VBI_ODD_BASE, restore_buffer->taska_vbi_oddbase);
1044f29dbc25Smrg    WRITE_VIP32(VIP_TASKA_VID_PITCH, restore_buffer->taska_data_pitch);
1045f29dbc25Smrg    WRITE_VIP32(VIP_CONTROL3, restore_buffer->control3);
1046f29dbc25Smrg    WRITE_VIP32(VIP_TASKA_U_OFFSET, restore_buffer->taska_v_oddoffset);
1047f29dbc25Smrg    WRITE_VIP32(VIP_TASKA_V_OFFSET, restore_buffer->taska_u_oddoffset);
1048f29dbc25Smrg    WRITE_VIP32(VIP_TASKB_VID_EVEN_BASE, restore_buffer->taskb_evenbase);
1049f29dbc25Smrg    WRITE_VIP32(VIP_TASKB_VID_ODD_BASE, restore_buffer->taskb_oddbase);
1050f29dbc25Smrg    WRITE_VIP32(VIP_TASKB_VBI_EVEN_BASE, restore_buffer->taskb_vbi_evenbase);
1051f29dbc25Smrg    WRITE_VIP32(VIP_TASKB_VBI_ODD_BASE, restore_buffer->taskb_vbi_oddbase);
1052f29dbc25Smrg    WRITE_VIP32(VIP_TASKB_VID_PITCH, restore_buffer->taskb_pitch);
1053f29dbc25Smrg    WRITE_VIP32(VIP_TASKB_U_OFFSET, restore_buffer->taskb_voffset);
1054f29dbc25Smrg    WRITE_VIP32(VIP_TASKB_V_OFFSET, restore_buffer->taskb_uoffset);
1055f29dbc25Smrg    WRITE_VIP32(VIP_ANC_MSG1_BASE, restore_buffer->msg1_base);
1056f29dbc25Smrg    WRITE_VIP32(VIP_ANC_MSG2_BASE, restore_buffer->msg2_base);
1057f29dbc25Smrg    WRITE_VIP32(VIP_ANC_MSG_SIZE, restore_buffer->msg_size);
1058f29dbc25Smrg    WRITE_VIP32(VIP_PAGE_OFFSET, restore_buffer->page_offset);
1059f29dbc25Smrg    WRITE_VIP32(VIP_VERTICAL_START_STOP, restore_buffer->vert_start_stop);
1060f29dbc25Smrg    WRITE_VIP32(VIP_VSYNC_ERR_COUNT, restore_buffer->vsync_err_count);
1061f29dbc25Smrg    WRITE_VIP32(VIP_TASKA_U_EVEN_OFFSET, restore_buffer->taska_u_evenoffset);
1062f29dbc25Smrg    WRITE_VIP32(VIP_TASKA_V_EVEN_OFFSET, restore_buffer->taska_v_evenoffset);
1063f29dbc25Smrg
1064f29dbc25Smrg    /* RESTORE THE VIP MSRS */
1065f29dbc25Smrg
1066f29dbc25Smrg    msr_write64(MSR_DEVICE_GEODELX_VIP, MSR_GEODELINK_CONFIG,
1067f29dbc25Smrg        &(restore_buffer->msr_config));
1068f29dbc25Smrg    msr_write64(MSR_DEVICE_GEODELX_VIP, MSR_GEODELINK_SMI,
1069f29dbc25Smrg        &(restore_buffer->msr_smi));
1070f29dbc25Smrg    msr_write64(MSR_DEVICE_GEODELX_VIP, MSR_GEODELINK_PM,
1071f29dbc25Smrg        &(restore_buffer->msr_pm));
1072f29dbc25Smrg    msr_write64(MSR_DEVICE_GEODELX_VIP, MSR_GEODELINK_DIAG,
1073f29dbc25Smrg        &(restore_buffer->msr_diag));
1074f29dbc25Smrg
1075f29dbc25Smrg    /* RESTORE THE CONTROL WORDS LAST */
1076f29dbc25Smrg
1077f29dbc25Smrg    WRITE_VIP32(VIP_CONTROL1, restore_buffer->control1);
1078f29dbc25Smrg    WRITE_VIP32(VIP_CONTROL2, restore_buffer->control2);
1079f29dbc25Smrg    WRITE_VIP32(VIP_CONTROL3, restore_buffer->control3);
1080f29dbc25Smrg
1081f29dbc25Smrg    return CIM_STATUS_OK;
1082f29dbc25Smrg}
1083f29dbc25Smrg
1084f29dbc25Smrg/*---------------------------------------------------------------------------
1085f29dbc25Smrg * vip_get_interrupt_state
1086f29dbc25Smrg *
1087f29dbc25Smrg * This routine returns the current interrupt state of the system. The
1088f29dbc25Smrg * rv can be tested with the following flags to determine if the appropriate
1089f29dbc25Smrg * event has occured.
1090f29dbc25Smrg *--------------------------------------------------------------------------*/
1091f29dbc25Smrg
1092f29dbc25Smrgunsigned long
1093f29dbc25Smrgvip_get_interrupt_state(void)
1094f29dbc25Smrg{
1095f29dbc25Smrg    unsigned long interrupt_mask = READ_VIP32(VIP_INTERRUPT);
1096f29dbc25Smrg
1097f29dbc25Smrg    return (~(interrupt_mask << 16) & interrupt_mask & VIP_ALL_INTERRUPTS);
1098f29dbc25Smrg}
1099f29dbc25Smrg
1100f29dbc25Smrg/*---------------------------------------------------------------------------
1101f29dbc25Smrg * vip_test_genlock_active
1102f29dbc25Smrg *
1103f29dbc25Smrg * This routine reads the live status of the genlock connection between the
1104f29dbc25Smrg * VIP and VG blocks.
1105f29dbc25Smrg *--------------------------------------------------------------------------*/
1106f29dbc25Smrg
1107f29dbc25Smrgint
1108f29dbc25Smrgvip_test_genlock_active(void)
1109f29dbc25Smrg{
1110f29dbc25Smrg    if (READ_REG32(DC3_GENLK_CTL) & DC3_GC_GENLK_ACTIVE)
1111f29dbc25Smrg        return 1;
1112f29dbc25Smrg
1113f29dbc25Smrg    return 0;
1114f29dbc25Smrg}
1115f29dbc25Smrg
1116f29dbc25Smrg/*---------------------------------------------------------------------------
1117f29dbc25Smrg * vip_test_signal_status
1118f29dbc25Smrg *
1119f29dbc25Smrg * This routine reads the live signal status coming into the VIP block.
1120f29dbc25Smrg *--------------------------------------------------------------------------*/
1121f29dbc25Smrg
1122f29dbc25Smrgint
1123f29dbc25Smrgvip_test_signal_status(void)
1124f29dbc25Smrg{
1125f29dbc25Smrg    if (READ_REG32(DC3_GENLK_CTL) & DC3_GC_VIP_VID_OK)
1126f29dbc25Smrg        return 1;
1127f29dbc25Smrg
1128f29dbc25Smrg    return 0;
1129f29dbc25Smrg}
1130f29dbc25Smrg
1131f29dbc25Smrg/*---------------------------------------------------------------------------
1132f29dbc25Smrg * vip_get_current_field
1133f29dbc25Smrg *
1134f29dbc25Smrg * This routine returns the current field being received.
1135f29dbc25Smrg *--------------------------------------------------------------------------*/
1136f29dbc25Smrg
1137f29dbc25Smrgunsigned long
1138f29dbc25Smrgvip_get_current_field(void)
1139f29dbc25Smrg{
1140f29dbc25Smrg    if (READ_VIP32(VIP_STATUS) & VIP_STATUS_FIELD)
1141f29dbc25Smrg        return VIP_EVEN_FIELD;
1142f29dbc25Smrg
1143f29dbc25Smrg    return VIP_ODD_FIELD;
1144f29dbc25Smrg}
1145f29dbc25Smrg
1146f29dbc25Smrg/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1147f29dbc25Smrg * CIMARRON VIP READ ROUTINES
1148f29dbc25Smrg * These routines are included for use in diagnostics or when debugging.  They
1149f29dbc25Smrg * can be optionally excluded from a project.
1150f29dbc25Smrg *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
1151f29dbc25Smrg
1152f29dbc25Smrg#if CIMARRON_INCLUDE_VIP_READ_ROUTINES
1153f29dbc25Smrg
1154f29dbc25Smrg/*---------------------------------------------------------------------------
1155f29dbc25Smrg * vip_get_current_mode
1156f29dbc25Smrg *
1157f29dbc25Smrg * This routine reads the current VIP operating mode.
1158f29dbc25Smrg *--------------------------------------------------------------------------*/
1159f29dbc25Smrg
1160f29dbc25Smrgint
1161f29dbc25Smrgvip_get_current_mode(VIPSETMODEBUFFER * buffer)
1162f29dbc25Smrg{
1163f29dbc25Smrg    unsigned long vip_control1, vip_control2, vip_control3;
1164f29dbc25Smrg
1165f29dbc25Smrg    if (!buffer)
1166f29dbc25Smrg        return CIM_STATUS_INVALIDPARAMS;
1167f29dbc25Smrg
1168f29dbc25Smrg    vip_control1 = READ_VIP32(VIP_CONTROL1);
1169f29dbc25Smrg    vip_control2 = READ_VIP32(VIP_CONTROL2);
1170f29dbc25Smrg    vip_control3 = READ_VIP32(VIP_CONTROL3);
1171f29dbc25Smrg
1172f29dbc25Smrg    /* READ CURRENT OPERATING MODE AND ENABLES */
1173f29dbc25Smrg
1174f29dbc25Smrg    buffer->stream_enables = vip_control1 & VIP_ENABLE_ALL;
1175f29dbc25Smrg    buffer->operating_mode = vip_control1 & VIP_CONTROL1_MODE_MASK;
1176f29dbc25Smrg
1177f29dbc25Smrg    /* READ CURRENT PLANAR CAPTURE SETTINGS */
1178f29dbc25Smrg
1179f29dbc25Smrg    buffer->flags = 0;
1180f29dbc25Smrg    buffer->planar_capture = 0;
1181f29dbc25Smrg    if (vip_control1 & VIP_CONTROL1_PLANAR) {
1182f29dbc25Smrg        buffer->flags |= VIP_MODEFLAG_PLANARCAPTURE;
1183f29dbc25Smrg        if (vip_control1 & VIP_CONTROL1_DISABLE_DECIMATION) {
1184f29dbc25Smrg            if (vip_control3 & VIP_CONTROL3_DECIMATE_EVEN)
1185f29dbc25Smrg                buffer->planar_capture = VIP_420CAPTURE_ALTERNATINGFIELDS;
1186f29dbc25Smrg            else
1187f29dbc25Smrg                buffer->planar_capture = VIP_420CAPTURE_EVERYLINE;
1188f29dbc25Smrg        } else
1189f29dbc25Smrg            buffer->planar_capture = VIP_420CAPTURE_ALTERNATINGLINES;
1190f29dbc25Smrg    }
1191f29dbc25Smrg
1192f29dbc25Smrg    /* READ MISCELLANEOUS FLAGS */
1193f29dbc25Smrg
1194f29dbc25Smrg    if (vip_control1 & VIP_CONTROL1_NON_INTERLACED)
1195f29dbc25Smrg        buffer->flags |= VIP_MODEFLAG_PROGRESSIVE;
1196f29dbc25Smrg    if (vip_control3 & VIP_CONTROL3_BASE_UPDATE)
1197f29dbc25Smrg        buffer->flags |= VIP_MODEFLAG_TOGGLEEACHFIELD;
1198f29dbc25Smrg    if (vip_control2 & VIP_CONTROL2_INVERT_POLARITY)
1199f29dbc25Smrg        buffer->flags |= VIP_MODEFLAG_INVERTPOLARITY;
1200f29dbc25Smrg    if (vip_control1 & VIP_CONTROL1_MSG_STRM_CTRL)
1201f29dbc25Smrg        buffer->flags |= VIP_MODEFLAG_FLIPMESSAGEWHENFULL;
1202f29dbc25Smrg    if (vip_control2 & VIP_CONTROL2_REPEAT_ENABLE)
1203f29dbc25Smrg        buffer->flags |= VIP_MODEFLAG_ENABLEREPEATFLAG;
1204f29dbc25Smrg    if (vip_control3 & VIP_CONTROL3_TASK_POLARITY)
1205f29dbc25Smrg        buffer->flags |= VIP_MODEFLAG_INVERTTASKPOLARITY;
1206f29dbc25Smrg    if (vip_control1 & VIP_CONTROL1_DISABLE_ZERO_DETECT)
1207f29dbc25Smrg        buffer->flags |= VIP_MODEFLAG_DISABLEZERODETECT;
1208f29dbc25Smrg    if (vip_control2 & VIP_CONTROL2_ANC10)
1209f29dbc25Smrg        buffer->flags |= VIP_MODEFLAG_10BITANCILLARY;
1210f29dbc25Smrg
1211f29dbc25Smrg    /* READ THE CURRENT VIP 601 SETTINGS */
1212f29dbc25Smrg
1213f29dbc25Smrg    vip_get_601_configuration(&buffer->vip601_settings);
1214f29dbc25Smrg
1215f29dbc25Smrg    return CIM_STATUS_OK;
1216f29dbc25Smrg}
1217f29dbc25Smrg
1218f29dbc25Smrg/*---------------------------------------------------------------------------
1219f29dbc25Smrg * vip_get_601_configuration
1220f29dbc25Smrg *
1221f29dbc25Smrg * This routine returns the current 601 configuration information.
1222f29dbc25Smrg *--------------------------------------------------------------------------*/
1223f29dbc25Smrg
1224f29dbc25Smrgint
1225f29dbc25Smrgvip_get_601_configuration(VIP_601PARAMS * buffer)
1226f29dbc25Smrg{
1227f29dbc25Smrg    unsigned long vip_control3, vip_control1;
1228f29dbc25Smrg
1229f29dbc25Smrg    if (!buffer)
1230f29dbc25Smrg        return CIM_STATUS_INVALIDPARAMS;
1231f29dbc25Smrg
1232f29dbc25Smrg    vip_control1 = READ_VIP32(VIP_CONTROL3);
1233f29dbc25Smrg    vip_control3 = READ_VIP32(VIP_CONTROL3);
1234f29dbc25Smrg
1235f29dbc25Smrg    buffer->flags = 0;
1236f29dbc25Smrg    if (vip_control3 & VIP_CONTROL3_VSYNC_POLARITY)
1237f29dbc25Smrg        buffer->flags |= VIP_MODEFLAG_VSYNCACTIVEHIGH;
1238f29dbc25Smrg    if (vip_control3 & VIP_CONTROL3_HSYNC_POLARITY)
1239f29dbc25Smrg        buffer->flags |= VIP_MODEFLAG_HSYNCACTIVEHIGH;
1240f29dbc25Smrg
1241f29dbc25Smrg    buffer->horz_start = READ_VIP32(VIP_601_HORZ_START);
1242f29dbc25Smrg    buffer->vbi_start = READ_VIP32(VIP_601_VBI_START);
1243f29dbc25Smrg    buffer->vbi_height = READ_VIP32(VIP_601_VBI_END) - buffer->vbi_start + 1;
1244f29dbc25Smrg    buffer->vert_start_even = READ_VIP32(VIP_601_EVEN_START_STOP) & 0xFFFF;
1245f29dbc25Smrg    buffer->even_height = (READ_VIP32(VIP_601_EVEN_START_STOP) >> 16) -
1246f29dbc25Smrg        buffer->vert_start_even + 1;
1247f29dbc25Smrg    buffer->vert_start_odd = READ_VIP32(VIP_601_ODD_START_STOP) & 0xFFFF;
1248f29dbc25Smrg    buffer->odd_height = (READ_VIP32(VIP_601_ODD_START_STOP) >> 16) -
1249f29dbc25Smrg        buffer->vert_start_odd + 1;
1250f29dbc25Smrg    buffer->odd_detect_start = READ_VIP32(VIP_ODD_FIELD_DETECT) & 0xFFFF;
1251f29dbc25Smrg    buffer->odd_detect_end = READ_VIP32(VIP_ODD_FIELD_DETECT) >> 16;
1252f29dbc25Smrg
1253f29dbc25Smrg    /* SPECIAL CASE FOR HORIZONTAL DATA
1254f29dbc25Smrg     * 601 horizontal parameters are based on the number of clocks and not
1255f29dbc25Smrg     * the number of pixels.
1256f29dbc25Smrg     */
1257f29dbc25Smrg
1258f29dbc25Smrg    if ((vip_control1 & VIP_CONTROL1_MODE_MASK) == VIP_MODE_16BIT601)
1259f29dbc25Smrg        buffer->width = (READ_VIP32(VIP_601_HORZ_END) -
1260f29dbc25Smrg            buffer->horz_start - 3) >> 1;
1261f29dbc25Smrg    else
1262f29dbc25Smrg        buffer->width = (READ_VIP32(VIP_601_HORZ_END) -
1263f29dbc25Smrg            buffer->horz_start - 3);
1264f29dbc25Smrg
1265f29dbc25Smrg    return CIM_STATUS_OK;
1266f29dbc25Smrg}
1267f29dbc25Smrg
1268f29dbc25Smrg/*---------------------------------------------------------------------------
1269f29dbc25Smrg * vip_get_buffer_configuration
1270f29dbc25Smrg *
1271f29dbc25Smrg * This routine reads the current buffer configuration for Task A, Task B,
1272f29dbc25Smrg * ancillary or message data.  The current_buffer member indicates which
1273f29dbc25Smrg * array index should hold the new values for Task A or Task B data.
1274f29dbc25Smrg *--------------------------------------------------------------------------*/
1275f29dbc25Smrg
1276f29dbc25Smrgint
1277f29dbc25Smrgvip_get_buffer_configuration(int buffer_type, VIPINPUTBUFFER * buffer)
1278f29dbc25Smrg{
1279f29dbc25Smrg    unsigned long cur_buffer = buffer->current_buffer;
1280f29dbc25Smrg    VIPINPUTBUFFER_ADDR *offsets;
1281f29dbc25Smrg
1282f29dbc25Smrg    if (!buffer)
1283f29dbc25Smrg        return CIM_STATUS_INVALIDPARAMS;
1284f29dbc25Smrg
1285f29dbc25Smrg    if (buffer_type == VIP_BUFFER_A) {
1286f29dbc25Smrg        offsets = &buffer->offsets[VIP_BUFFER_TASK_A];
1287f29dbc25Smrg
1288f29dbc25Smrg        /* READ VIDEO PITCH */
1289f29dbc25Smrg
1290f29dbc25Smrg        offsets->y_pitch = READ_VIP32(VIP_TASKA_VID_PITCH) & 0xFFFF;
1291f29dbc25Smrg        offsets->uv_pitch = READ_VIP32(VIP_TASKA_VID_PITCH) >> 16;
1292f29dbc25Smrg
1293f29dbc25Smrg        /* READ BASE OFFSETS */
1294f29dbc25Smrg
1295f29dbc25Smrg        if (buffer->flags & VIP_INPUTFLAG_INVERTPOLARITY) {
1296f29dbc25Smrg            offsets->even_base[cur_buffer] =
1297f29dbc25Smrg                READ_VIP32(VIP_TASKA_VID_ODD_BASE);
1298f29dbc25Smrg            offsets->odd_base[cur_buffer] =
1299f29dbc25Smrg                READ_VIP32(VIP_TASKA_VID_EVEN_BASE);
1300f29dbc25Smrg
1301f29dbc25Smrg            if (buffer->flags & VIP_INPUTFLAG_VBI) {
1302f29dbc25Smrg                offsets->vbi_even_base = READ_VIP32(VIP_TASKA_VBI_ODD_BASE);
1303f29dbc25Smrg                offsets->vbi_odd_base = READ_VIP32(VIP_TASKA_VBI_EVEN_BASE);
1304f29dbc25Smrg            }
1305f29dbc25Smrg        } else {
1306f29dbc25Smrg            offsets->even_base[cur_buffer] =
1307f29dbc25Smrg                READ_VIP32(VIP_TASKA_VID_EVEN_BASE);
1308f29dbc25Smrg            offsets->odd_base[cur_buffer] =
1309f29dbc25Smrg                READ_VIP32(VIP_TASKA_VID_ODD_BASE);
1310f29dbc25Smrg
1311f29dbc25Smrg            if (buffer->flags & VIP_INPUTFLAG_VBI) {
1312f29dbc25Smrg                offsets->vbi_even_base = READ_VIP32(VIP_TASKA_VBI_EVEN_BASE);
1313f29dbc25Smrg                offsets->vbi_odd_base = READ_VIP32(VIP_TASKA_VBI_ODD_BASE);
1314f29dbc25Smrg            }
1315f29dbc25Smrg        }
1316f29dbc25Smrg
1317f29dbc25Smrg        /* READ 4:2:0 OFFSETS */
1318f29dbc25Smrg
1319f29dbc25Smrg        if (buffer->flags & VIP_INPUTFLAG_PLANAR) {
1320f29dbc25Smrg            offsets->odd_uoffset = READ_VIP32(VIP_TASKA_U_OFFSET);
1321f29dbc25Smrg            offsets->odd_voffset = READ_VIP32(VIP_TASKA_V_OFFSET);
1322f29dbc25Smrg            offsets->even_uoffset = READ_VIP32(VIP_TASKA_U_EVEN_OFFSET);
1323f29dbc25Smrg            offsets->even_voffset = READ_VIP32(VIP_TASKA_V_EVEN_OFFSET);
1324f29dbc25Smrg        }
1325f29dbc25Smrg    } else if (buffer_type == VIP_BUFFER_B) {
1326f29dbc25Smrg        offsets = &buffer->offsets[VIP_BUFFER_TASK_B];
1327f29dbc25Smrg
1328f29dbc25Smrg        /* READ VIDEO PITCH */
1329f29dbc25Smrg
1330f29dbc25Smrg        offsets->y_pitch = READ_VIP32(VIP_TASKB_VID_PITCH) & 0xFFFF;
1331f29dbc25Smrg        offsets->uv_pitch = READ_VIP32(VIP_TASKB_VID_PITCH) >> 16;
1332f29dbc25Smrg
1333f29dbc25Smrg        /* READ BASE OFFSETS */
1334f29dbc25Smrg
1335f29dbc25Smrg        if (buffer->flags & VIP_INPUTFLAG_INVERTPOLARITY) {
1336f29dbc25Smrg            offsets->even_base[cur_buffer] =
1337f29dbc25Smrg                READ_VIP32(VIP_TASKB_VID_ODD_BASE);
1338f29dbc25Smrg            offsets->odd_base[cur_buffer] =
1339f29dbc25Smrg                READ_VIP32(VIP_TASKB_VID_EVEN_BASE);
1340f29dbc25Smrg
1341f29dbc25Smrg            if (buffer->flags & VIP_INPUTFLAG_VBI) {
1342f29dbc25Smrg                offsets->vbi_even_base = READ_VIP32(VIP_TASKB_VBI_ODD_BASE);
1343f29dbc25Smrg                offsets->vbi_odd_base = READ_VIP32(VIP_TASKB_VBI_EVEN_BASE);
1344f29dbc25Smrg            }
1345f29dbc25Smrg        } else {
1346f29dbc25Smrg            offsets->even_base[cur_buffer] =
1347f29dbc25Smrg                READ_VIP32(VIP_TASKB_VID_EVEN_BASE);
1348f29dbc25Smrg            offsets->odd_base[cur_buffer] =
1349f29dbc25Smrg                READ_VIP32(VIP_TASKB_VID_ODD_BASE);
1350f29dbc25Smrg
1351f29dbc25Smrg            if (buffer->flags & VIP_INPUTFLAG_VBI) {
1352f29dbc25Smrg                offsets->vbi_even_base = READ_VIP32(VIP_TASKB_VBI_EVEN_BASE);
1353f29dbc25Smrg                offsets->vbi_odd_base = READ_VIP32(VIP_TASKB_VBI_ODD_BASE);
1354f29dbc25Smrg            }
1355f29dbc25Smrg        }
1356f29dbc25Smrg
1357f29dbc25Smrg        /* READ 4:2:0 OFFSETS */
1358f29dbc25Smrg
1359f29dbc25Smrg        if (buffer->flags & VIP_INPUTFLAG_PLANAR) {
1360f29dbc25Smrg            offsets->odd_uoffset = READ_VIP32(VIP_TASKB_U_OFFSET);
1361f29dbc25Smrg            offsets->odd_voffset = READ_VIP32(VIP_TASKB_V_OFFSET);
1362f29dbc25Smrg        }
1363f29dbc25Smrg    } else if (buffer_type == VIP_BUFFER_ANC || buffer_type == VIP_BUFFER_MSG) {
1364f29dbc25Smrg        buffer->ancillaryData.msg1_base = READ_VIP32(VIP_ANC_MSG1_BASE);
1365f29dbc25Smrg        buffer->ancillaryData.msg2_base = READ_VIP32(VIP_ANC_MSG2_BASE);
1366f29dbc25Smrg        buffer->ancillaryData.msg_size = READ_VIP32(VIP_ANC_MSG_SIZE);
1367f29dbc25Smrg    } else {
1368f29dbc25Smrg        return CIM_STATUS_INVALIDPARAMS;
1369f29dbc25Smrg    }
1370f29dbc25Smrg
1371f29dbc25Smrg    return CIM_STATUS_OK;
1372f29dbc25Smrg}
1373f29dbc25Smrg
1374f29dbc25Smrg/*---------------------------------------------------------------------------
1375f29dbc25Smrg * vip_get_genlock_configuration
1376f29dbc25Smrg *
1377f29dbc25Smrg * This routine reads the current genlock configuration.
1378f29dbc25Smrg *--------------------------------------------------------------------------*/
1379f29dbc25Smrg
1380f29dbc25Smrgint
1381f29dbc25Smrgvip_get_genlock_configuration(VIPGENLOCKBUFFER * buffer)
1382f29dbc25Smrg{
1383f29dbc25Smrg    unsigned long vip_control1, vip_control2;
1384f29dbc25Smrg    unsigned long genlk_ctl;
1385f29dbc25Smrg
1386f29dbc25Smrg    if (!buffer)
1387f29dbc25Smrg        return CIM_STATUS_INVALIDPARAMS;
1388f29dbc25Smrg
1389f29dbc25Smrg    genlk_ctl = READ_REG32(DC3_GENLK_CTL);
1390f29dbc25Smrg    vip_control1 = READ_VIP32(VIP_CONTROL1);
1391f29dbc25Smrg    vip_control2 = READ_VIP32(VIP_CONTROL2);
1392f29dbc25Smrg
1393f29dbc25Smrg    /* READ ERROR DETECTION, CURRENT FIELD AND CURRENT VSYNC
1394f29dbc25Smrg     * These flags are used to indicate the ways in which the VIP signal can
1395f29dbc25Smrg     * be considered 'lost'.
1396f29dbc25Smrg     */
1397f29dbc25Smrg
1398f29dbc25Smrg    buffer->vip_signal_loss = vip_control1 & VIP_CONTROL1_VDE_FF_MASK;
1399f29dbc25Smrg    buffer->field_to_vg = vip_control2 & VIP_CONTROL2_FIELD2VG_MASK;
1400f29dbc25Smrg    buffer->vsync_to_vg = vip_control2 & VIP_CONTROL2_SYNC2VG_MASK;
1401f29dbc25Smrg
1402f29dbc25Smrg    /* GENLOCK TIMEOUT ENABLE */
1403f29dbc25Smrg
1404f29dbc25Smrg    buffer->enable_timeout = 0;
1405f29dbc25Smrg    if (genlk_ctl & DC3_GC_GENLOCK_TO_ENABLE)
1406f29dbc25Smrg        buffer->enable_timeout = 1;
1407f29dbc25Smrg
1408f29dbc25Smrg    /* GENLOCK SKEW */
1409f29dbc25Smrg
1410f29dbc25Smrg    buffer->genlock_skew = genlk_ctl & DC3_GC_GENLOCK_SKEW_MASK;
1411f29dbc25Smrg
1412f29dbc25Smrg    return CIM_STATUS_OK;
1413f29dbc25Smrg}
1414f29dbc25Smrg
1415f29dbc25Smrg/*---------------------------------------------------------------------------
1416f29dbc25Smrg * vip_get_genlock_enable
1417f29dbc25Smrg *
1418f29dbc25Smrg * This routine returns the current enable status of genlock in the VG.
1419f29dbc25Smrg *--------------------------------------------------------------------------*/
1420f29dbc25Smrg
1421f29dbc25Smrgint
1422f29dbc25Smrgvip_get_genlock_enable(void)
1423f29dbc25Smrg{
1424f29dbc25Smrg    if (READ_REG32(DC3_GENLK_CTL) & DC3_GC_GENLOCK_ENABLE)
1425f29dbc25Smrg        return 1;
1426f29dbc25Smrg
1427f29dbc25Smrg    return 0;
1428f29dbc25Smrg}
1429f29dbc25Smrg
1430f29dbc25Smrg/*---------------------------------------------------------------------------
1431f29dbc25Smrg * vip_is_buffer_update_latched
1432f29dbc25Smrg *
1433f29dbc25Smrg * This routine indicates whether changes to the VIP offsets have been
1434f29dbc25Smrg * latched by the hardware.
1435f29dbc25Smrg *--------------------------------------------------------------------------*/
1436f29dbc25Smrg
1437f29dbc25Smrgint
1438f29dbc25Smrgvip_is_buffer_update_latched(void)
1439f29dbc25Smrg{
1440f29dbc25Smrg    return (!(READ_VIP32(VIP_STATUS) & VIP_STATUS_BASEREG_NOTUPDT));
1441f29dbc25Smrg}
1442f29dbc25Smrg
1443f29dbc25Smrg/*---------------------------------------------------------------------------
1444f29dbc25Smrg * vip_get_capture_state
1445f29dbc25Smrg *
1446f29dbc25Smrg * This routine reads the current capture status of the VIP hardware.
1447f29dbc25Smrg *--------------------------------------------------------------------------*/
1448f29dbc25Smrg
1449f29dbc25Smrgunsigned long
1450f29dbc25Smrgvip_get_capture_state(void)
1451f29dbc25Smrg{
1452f29dbc25Smrg    return ((READ_VIP32(VIP_CONTROL1) & VIP_CONTROL1_RUNMODE_MASK) >>
1453f29dbc25Smrg        VIP_CONTROL1_RUNMODE_SHIFT);
1454f29dbc25Smrg}
1455f29dbc25Smrg
1456f29dbc25Smrg/*---------------------------------------------------------------------------
1457f29dbc25Smrg * vip_get_current_line
1458f29dbc25Smrg *
1459f29dbc25Smrg * This routine returns the current line that is being processed.
1460f29dbc25Smrg *--------------------------------------------------------------------------*/
1461f29dbc25Smrg
1462f29dbc25Smrgunsigned long
1463f29dbc25Smrgvip_get_current_line(void)
1464f29dbc25Smrg{
1465f29dbc25Smrg    return (READ_VIP32(VIP_CURRENT_TARGET) & VIP_CTARGET_CLINE_MASK);
1466f29dbc25Smrg}
1467f29dbc25Smrg
1468f29dbc25Smrg/*---------------------------------------------------------------------------
1469f29dbc25Smrg * vip_read_fifo
1470f29dbc25Smrg *
1471f29dbc25Smrg * This routine reads from the specified fifo address. As the fifo access
1472f29dbc25Smrg * enable should be disabled when running in normal vip mode, this routine
1473f29dbc25Smrg * enables and disables access around the read.
1474f29dbc25Smrg * DIAGNOSTIC USE ONLY
1475f29dbc25Smrg *--------------------------------------------------------------------------*/
1476f29dbc25Smrg
1477f29dbc25Smrgunsigned long
1478f29dbc25Smrgvip_read_fifo(unsigned long dwFifoAddress)
1479f29dbc25Smrg{
1480f29dbc25Smrg    unsigned long fifo_data;
1481f29dbc25Smrg
1482f29dbc25Smrg    /* ENABLE FIFO ACCESS */
1483f29dbc25Smrg
1484f29dbc25Smrg    vip_enable_fifo_access(1);
1485f29dbc25Smrg
1486f29dbc25Smrg    /* NOW READ THE DATA */
1487f29dbc25Smrg
1488f29dbc25Smrg    WRITE_VIP32(VIP_FIFO_ADDRESS, dwFifoAddress);
1489f29dbc25Smrg    fifo_data = READ_VIP32(VIP_FIFO_DATA);
1490f29dbc25Smrg
1491f29dbc25Smrg    /* DISABLE FIFO ACCESS */
1492f29dbc25Smrg
1493f29dbc25Smrg    vip_enable_fifo_access(0);
1494f29dbc25Smrg
1495f29dbc25Smrg    return fifo_data;
1496f29dbc25Smrg}
1497f29dbc25Smrg
1498f29dbc25Smrg/*---------------------------------------------------------------------------
1499f29dbc25Smrg * vip_write_fifo
1500f29dbc25Smrg *
1501f29dbc25Smrg * SYNOPSIS:
1502f29dbc25Smrg * This routine writes to the specified fifo address. As the fifo access
1503f29dbc25Smrg * enable should be disabled when running in normal vip mode, this routine
1504f29dbc25Smrg * enables and disables access around the write.
1505f29dbc25Smrg * DIAGNOSTIC USE ONLY
1506f29dbc25Smrg *--------------------------------------------------------------------------*/
1507f29dbc25Smrg
1508f29dbc25Smrgint
1509f29dbc25Smrgvip_write_fifo(unsigned long dwFifoAddress, unsigned long dwFifoData)
1510f29dbc25Smrg{
1511f29dbc25Smrg    /* ENABLE FIFO ACCESS */
1512f29dbc25Smrg
1513f29dbc25Smrg    vip_enable_fifo_access(1);
1514f29dbc25Smrg
1515f29dbc25Smrg    /* WRITE THE FIFO DATA */
1516f29dbc25Smrg
1517f29dbc25Smrg    WRITE_VIP32(VIP_FIFO_ADDRESS, dwFifoAddress);
1518f29dbc25Smrg    WRITE_VIP32(VIP_FIFO_DATA, dwFifoData);
1519f29dbc25Smrg
1520f29dbc25Smrg    /* DISABLE FIFO ACCESS */
1521f29dbc25Smrg
1522f29dbc25Smrg    vip_enable_fifo_access(0);
1523f29dbc25Smrg
1524f29dbc25Smrg    return CIM_STATUS_OK;
1525f29dbc25Smrg}
1526f29dbc25Smrg
1527f29dbc25Smrg/*---------------------------------------------------------------------------
1528f29dbc25Smrg * vip_enable_fifo_access
1529f29dbc25Smrg *
1530f29dbc25Smrg * This routine enables/disables access to the vip fifo.
1531f29dbc25Smrg * DIAGNOSTIC USE ONLY
1532f29dbc25Smrg *--------------------------------------------------------------------------*/
1533f29dbc25Smrg
1534f29dbc25Smrgint
1535f29dbc25Smrgvip_enable_fifo_access(int enable)
1536f29dbc25Smrg{
1537f29dbc25Smrg    unsigned long cw2;
1538f29dbc25Smrg
1539f29dbc25Smrg    cw2 = READ_VIP32(VIP_CONTROL2);
1540f29dbc25Smrg
1541f29dbc25Smrg    if (enable)
1542f29dbc25Smrg        cw2 |= VIP_CONTROL2_FIFO_ACCESS;
1543f29dbc25Smrg    else
1544f29dbc25Smrg        cw2 &= ~VIP_CONTROL2_FIFO_ACCESS;
1545f29dbc25Smrg
1546f29dbc25Smrg    WRITE_VIP32(VIP_CONTROL2, cw2);
1547f29dbc25Smrg
1548f29dbc25Smrg    return CIM_STATUS_OK;
1549f29dbc25Smrg}
1550f29dbc25Smrg
1551f29dbc25Smrg/*---------------------------------------------------------------------------
1552f29dbc25Smrg * vip_get_power_characteristics
1553f29dbc25Smrg *
1554f29dbc25Smrg * This routine returns the current VIP clock gating state in a
1555f29dbc25Smrg * VIPPOWERBUFFER.
1556f29dbc25Smrg *--------------------------------------------------------------------------*/
1557f29dbc25Smrg
1558f29dbc25Smrgint
1559f29dbc25Smrgvip_get_power_characteristics(VIPPOWERBUFFER * buffer)
1560f29dbc25Smrg{
1561f29dbc25Smrg    Q_WORD q_word;
1562f29dbc25Smrg
1563f29dbc25Smrg    if (!buffer)
1564f29dbc25Smrg        return CIM_STATUS_INVALIDPARAMS;
1565f29dbc25Smrg
1566f29dbc25Smrg    /* READ THE EXISTING STATE */
1567f29dbc25Smrg
1568f29dbc25Smrg    msr_read64(MSR_DEVICE_GEODELX_VIP, MSR_GEODELINK_PM, &q_word);
1569f29dbc25Smrg
1570f29dbc25Smrg    /* DECODE THE CLOCK GATING BITS */
1571f29dbc25Smrg
1572f29dbc25Smrg    buffer->glink_clock_mode = (int)(q_word.low & VIP_MSR_POWER_GLINK);
1573f29dbc25Smrg    buffer->vip_clock_mode = (int)(q_word.low & VIP_MSR_POWER_CLOCK);
1574f29dbc25Smrg
1575f29dbc25Smrg    return CIM_STATUS_OK;
1576f29dbc25Smrg}
1577f29dbc25Smrg
1578f29dbc25Smrg/*---------------------------------------------------------------------------
1579f29dbc25Smrg * vip_get_priority_characteristics
1580f29dbc25Smrg *
1581f29dbc25Smrg * This routine returns the priority characteristics in the supplied
1582f29dbc25Smrg * VIPPRIORITYBUFFER.
1583f29dbc25Smrg *--------------------------------------------------------------------------*/
1584f29dbc25Smrg
1585f29dbc25Smrgint
1586f29dbc25Smrgvip_get_priority_characteristics(VIPPRIORITYBUFFER * buffer)
1587f29dbc25Smrg{
1588f29dbc25Smrg    Q_WORD q_word;
1589f29dbc25Smrg
1590f29dbc25Smrg    if (!buffer)
1591f29dbc25Smrg        return CIM_STATUS_INVALIDPARAMS;
1592f29dbc25Smrg
1593f29dbc25Smrg    /* READ THE CURRENT STATE */
1594f29dbc25Smrg
1595f29dbc25Smrg    msr_read64(MSR_DEVICE_GEODELX_VIP, MSR_GEODELINK_CONFIG, &q_word);
1596f29dbc25Smrg
1597f29dbc25Smrg    /* DECODE THE PRIORITIES */
1598f29dbc25Smrg
1599f29dbc25Smrg    buffer->secondary = (q_word.low & VIP_MSR_MCR_SECOND_PRIORITY_MASK) >>
1600f29dbc25Smrg        VIP_MSR_MCR_SECOND_PRIORITY_SHIFT;
1601f29dbc25Smrg    buffer->primary = (q_word.low & VIP_MSR_MCR_PRIMARY_PRIORITY_MASK) >>
1602f29dbc25Smrg        VIP_MSR_MCR_PRIMARY_PRIORITY_SHIFT;
1603f29dbc25Smrg    buffer->pid = q_word.low & VIP_MSR_MCR_PID_MASK;
1604f29dbc25Smrg
1605f29dbc25Smrg    return CIM_STATUS_OK;
1606f29dbc25Smrg}
1607f29dbc25Smrg
1608f29dbc25Smrg/*---------------------------------------------------------------------------
1609f29dbc25Smrg * vip_get_capability_characteristics
1610f29dbc25Smrg *
1611f29dbc25Smrg * This routine returns revision information for the device.
1612f29dbc25Smrg *--------------------------------------------------------------------------*/
1613f29dbc25Smrg
1614f29dbc25Smrgint
1615f29dbc25Smrgvip_get_capability_characteristics(VIPCAPABILITIESBUFFER * buffer)
1616f29dbc25Smrg{
1617f29dbc25Smrg    Q_WORD q_word;
1618f29dbc25Smrg
1619f29dbc25Smrg    if (!buffer)
1620f29dbc25Smrg        return CIM_STATUS_INVALIDPARAMS;
1621f29dbc25Smrg
1622f29dbc25Smrg    /* READ THE CURRENT MSR CONTENTS */
1623f29dbc25Smrg
1624f29dbc25Smrg    msr_read64(MSR_DEVICE_GEODELX_VIP, MSR_GEODELINK_CAP, &q_word);
1625f29dbc25Smrg
1626f29dbc25Smrg    /* DECODE THE REVISIONS */
1627f29dbc25Smrg
1628f29dbc25Smrg    buffer->revision_id = (q_word.low & VIP_MSR_CAP_REVID_MASK) >>
1629f29dbc25Smrg        VIP_MSR_CAP_REVID_SHIFT;
1630f29dbc25Smrg    buffer->device_id = (q_word.low & VIP_MSR_CAP_DEVID_MASK) >>
1631f29dbc25Smrg        VIP_MSR_CAP_DEVID_SHIFT;
1632f29dbc25Smrg    buffer->n_clock_domains = (q_word.low & VIP_MSR_CAP_NCLK_MASK) >>
1633f29dbc25Smrg        VIP_MSR_CAP_NCLK_SHIFT;
1634f29dbc25Smrg    buffer->n_smi_registers = (q_word.low & VIP_MSR_CAP_NSMI_MASK) >>
1635f29dbc25Smrg        VIP_MSR_CAP_NSMI_SHIFT;
1636f29dbc25Smrg
1637f29dbc25Smrg    return CIM_STATUS_OK;
1638f29dbc25Smrg}
1639f29dbc25Smrg
1640f29dbc25Smrg#endif
1641