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