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