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