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