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