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 VOP configuration routines. 29 */ 30 31/*--------------------------------------------------------------------------- 32 * vop_set_vbi_window 33 * 34 * This routine configures the output position and location in memory of 35 * VBI data. 36 *--------------------------------------------------------------------------*/ 37 38int 39vop_set_vbi_window(VOPVBIWINDOWBUFFER * buffer) 40{ 41 unsigned long unlock, temp; 42 unsigned long hstart, hstop; 43 unsigned long htotal, hsyncstart; 44 45 if (!buffer) 46 return CIM_STATUS_INVALIDPARAMS; 47 48 unlock = READ_REG32(DC3_UNLOCK); 49 WRITE_REG32(DC3_UNLOCK, DC3_UNLOCK_VALUE); 50 51 /* PROGRAM HORIZONTAL POSITION 52 * The horizontal position is a little tricky. The counter for the 53 * horizontal timings is reused for the VBI counter. Consequently, the 54 * horizontal start and stop values are based off the beginning of active 55 * data. However, the VG has a quirk. If the counter start position is 56 * before the beginning of HSync, it applies to the previous line. If 57 * the counter is after the beginning of HSync it applies to the current 58 * line. So, for one line the real range can be thought of as 59 * HSync_start to (HSync_start + htotal - 1). However, the counters 60 * must be between 0 and htotal - 1. When placing VBI data before the 61 * start of active data, the horizontal end position will thus be *less* 62 * than the horizontal start. 63 */ 64 65 htotal = ((READ_REG32(DC3_H_ACTIVE_TIMING) >> 16) & 0xFFF) + 1; 66 hsyncstart = (READ_REG32(DC3_H_SYNC_TIMING) & 0xFFF) + 1; 67 68 if (buffer->horz_from_hsync) { 69 /* VERIFY THAT THE INPUT IS VALID */ 70 71 if (buffer->horz_start < 0 72 || (buffer->horz_start + buffer->vbi_width) > htotal) 73 return CIM_STATUS_INVALIDPARAMS; 74 75 hstart = buffer->horz_start + hsyncstart; 76 } 77 else { 78 /* VERIFY THAT THE INPUT IS VALID */ 79 80 if (buffer->horz_start < ((long) hsyncstart - (long) htotal) || 81 buffer->horz_start > (long) hsyncstart || 82 buffer->vbi_width > htotal) { 83 return CIM_STATUS_INVALIDPARAMS; 84 } 85 86 hstart = buffer->horz_start + htotal; 87 } 88 89 hstop = hstart + buffer->vbi_width; 90 if (hstart > htotal) 91 hstart -= htotal; 92 if (hstop > htotal) 93 hstop -= htotal; 94 hstart--; 95 hstop--; 96 WRITE_REG32(DC3_VBI_HOR, ((hstop << DC3_VBI_HOR_END_SHIFT) & 97 DC3_VBI_HOR_END_MASK) | (hstart & 98 DC3_VBI_HOR_START_MASK)); 99 100 /* WRITE LINE CAPTURE MASKS */ 101 102 WRITE_REG32(DC3_VBI_LN_ODD, ((buffer->odd_line_offset << 103 DC3_VBI_ODD_LINE_SHIFT) & 104 DC3_VBI_ODD_LINE_MASK) | 105 (buffer->odd_line_capture_mask & DC3_VBI_ODD_ENABLE_MASK)); 106 107 WRITE_REG32(DC3_VBI_LN_EVEN, ((buffer->even_line_offset << 108 DC3_VBI_EVEN_LINE_SHIFT) & 109 DC3_VBI_EVEN_LINE_MASK) | 110 (buffer->even_line_capture_mask & DC3_VBI_EVEN_ENABLE_MASK)); 111 112 /* PROGRAM SOURCE OFFSETS 113 * Start with the even offsets. Note that we always enable 16-bit VBI, 114 * as this is the only way to get VBI data on each VOP clock. 115 */ 116 117 temp = READ_REG32(DC3_VBI_EVEN_CTL) & ~DC3_VBI_EVEN_CTL_OFFSET_MASK; 118 temp |= DC3_VBI_EVEN_CTL_ENABLE_16; 119 if (buffer->enable_upscale) 120 temp |= DC3_VBI_EVEN_CTL_UPSCALE; 121 WRITE_REG32(DC3_VBI_EVEN_CTL, temp | 122 (buffer->even_address_offset & DC3_VBI_EVEN_CTL_OFFSET_MASK)); 123 124 /* ODD OFFSET */ 125 126 temp = READ_REG32(DC3_VBI_ODD_CTL) & ~DC3_VBI_ODD_CTL_OFFSET_MASK; 127 WRITE_REG32(DC3_VBI_ODD_CTL, temp | 128 (buffer->odd_address_offset & DC3_VBI_ODD_CTL_OFFSET_MASK)); 129 130 /* PITCH */ 131 132 temp = ((buffer->data_size >> 3) << 16) | ((buffer->data_pitch >> 3) & 133 0x0000FFFF); 134 WRITE_REG32(DC3_VBI_PITCH, temp); 135 136 WRITE_REG32(DC3_UNLOCK, unlock); 137 138 return CIM_STATUS_OK; 139} 140 141/*--------------------------------------------------------------------------- 142 * vop_enable_vbi_output 143 * 144 * This routine enables/disables VBI fetching inside the video generator. 145 *--------------------------------------------------------------------------*/ 146 147int 148vop_enable_vbi_output(int enable) 149{ 150 unsigned long unlock, temp; 151 152 unlock = READ_REG32(DC3_UNLOCK); 153 temp = READ_REG32(DC3_VBI_EVEN_CTL); 154 155 if (enable) 156 temp |= DC3_VBI_ENABLE; 157 else 158 temp &= ~DC3_VBI_ENABLE; 159 160 WRITE_REG32(DC3_UNLOCK, DC3_UNLOCK_VALUE); 161 WRITE_REG32(DC3_VBI_EVEN_CTL, temp); 162 WRITE_REG32(DC3_UNLOCK, unlock); 163 164 return CIM_STATUS_OK; 165} 166 167/*--------------------------------------------------------------------------- 168 * vop_set_configuration 169 * 170 * This routine is passed a VOP_CONFIGURATION structure that contains all 171 * the necessary information to configure VOP output. 172 *--------------------------------------------------------------------------*/ 173 174int 175vop_set_configuration(VOPCONFIGURATIONBUFFER * config) 176{ 177 unsigned long vop_config = 0; 178 unsigned long alpha, control2; 179 unsigned long unlock; 180 unsigned long delta; 181 Q_WORD msr_value; 182 int rgb = 0; 183 184 if (!config) 185 return CIM_STATUS_INVALIDPARAMS; 186 187 unlock = READ_REG32(DC3_UNLOCK); 188 delta = READ_REG32(DC3_VID_DS_DELTA) & DC3_DS_DELTA_MASK; 189 190 /* OVERRIDE THE OUTPUT SETTINGS TO ENABLE VOP OUTPUT */ 191 192 if (config->mode != VOP_MODE_DISABLED) { 193 msr_read64(MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_CONFIG, &msr_value); 194 msr_value.low &= ~DF_CONFIG_OUTPUT_MASK; 195 msr_value.low |= DF_OUTPUT_VOP; 196 msr_write64(MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_CONFIG, &msr_value); 197 } 198 199 /* SET THE UNIVERSAL VOP OPTIONS */ 200 201 if (config->flags & VOP_FLAG_SWAP_UV) 202 vop_config |= VOP_CONFIG_SWAPUV; 203 if (config->flags & VOP_FLAG_SWAP_VBI) 204 vop_config |= VOP_CONFIG_SWAPVBI; 205 206 /* SET THE MODE SPECIFIC PARAMETERS */ 207 208 if (config->mode == VOP_MODE_601) { 209 vop_config |= config->vop601.flags; 210 vop_config |= config->vop601.vsync_shift; 211 vop_config |= VOP_CONFIG_ENABLE_601 | VOP_CONFIG_VIP2_0; 212 213 switch (config->vop601.output_mode) { 214 case VOP_601_YUV_16BIT: 215 vop_config |= VOP_CONFIG_VIP2_16BIT; 216 break; 217 case VOP_601_YUV_4_4_4: 218 vop_config |= VOP_CONFIG_DISABLE_DECIMATE; 219 break; 220 case VOP_601_RGB_8_8_8: 221 vop_config |= VOP_CONFIG_DISABLE_DECIMATE | VOP_CONFIG_RGBMODE; 222 rgb = 1; 223 break; 224 } 225 226 if (config->vop601.vsync_shift == VOP_VSYNC_LATER_BY_X) { 227 delta |= (config->vop601.vsync_shift_count & 228 DC3_601_VSYNC_SHIFT_MASK); 229 delta |= DC3_601_VSYNC_SHIFT_ENABLE; 230 } 231 } 232 else { 233 if (config->flags & VOP_FLAG_VBI) 234 vop_config |= VOP_CONFIG_VBI; 235 if (config->flags & VOP_FLAG_TASK) 236 vop_config |= VOP_CONFIG_TASK; 237 if (config->flags & VOP_FLAG_SINGLECHIPCOMPAT) 238 vop_config |= VOP_CONFIG_SC_COMPATIBLE; 239 if (config->flags & VOP_FLAG_EXTENDEDSAV) 240 vop_config |= VOP_CONFIG_EXTENDED_SAV; 241 242 switch (config->mode) { 243 case VOP_MODE_DISABLED: 244 vop_config |= VOP_CONFIG_DISABLED; 245 break; 246 case VOP_MODE_VIP11: 247 vop_config |= VOP_CONFIG_VIP1_1; 248 break; 249 case VOP_MODE_CCIR656: 250 vop_config |= VOP_CONFIG_CCIR656; 251 break; 252 case VOP_MODE_VIP20_8BIT: 253 vop_config |= VOP_CONFIG_VIP2_0; 254 break; 255 case VOP_MODE_VIP20_16BIT: 256 vop_config |= VOP_CONFIG_VIP2_0 | VOP_CONFIG_VIP2_16BIT; 257 break; 258 } 259 } 260 261 /* SET THE 4:4:4 TO 4:2:2 DECIMATION ALGORITHM */ 262 263 vop_config |= (config->conversion_mode); 264 265 /* SET THE VSYNC OUT OPTIONS */ 266 267 control2 = READ_VIP32(VIP_CONTROL2) & ~VIP_CONTROL2_SYNC2PIN_MASK; 268 control2 |= config->vsync_out; 269 WRITE_VIP32(VIP_CONTROL2, control2); 270 271 /* FORCE THE CORRECT VOP COLOR SPACE */ 272 /* The output of the mixer will be either RGB or YUV. We must enable */ 273 /* or disable the VOP CSC based on the desired output format. */ 274 275 alpha = READ_VID32(DF_VID_ALPHA_CONTROL); 276 if (!(alpha & DF_CSC_GRAPHICS_RGB_TO_YUV)) { 277 /* RGB OUTPUT FROM THE MIXER */ 278 279 if (!rgb) 280 alpha |= DF_CSC_VOP_RGB_TO_YUV; 281 else 282 alpha &= ~DF_CSC_VOP_RGB_TO_YUV; 283 } 284 else { 285 /* YUV OUTPUT FROM THE MIXER */ 286 /* As there is no YUV->RGB VOP conversion, we simply disable the */ 287 /* VOP CSC and trust that the user is competent. */ 288 289 alpha &= ~DF_CSC_VOP_RGB_TO_YUV; 290 } 291 292 /* AND WRITE THE CONFIGURATION */ 293 294 WRITE_VID32(DF_VID_ALPHA_CONTROL, alpha); 295 WRITE_VOP32(VOP_CONFIGURATION, vop_config); 296 WRITE_REG32(DC3_UNLOCK, DC3_UNLOCK_VALUE); 297 WRITE_REG32(DC3_VID_DS_DELTA, delta); 298 WRITE_REG32(DC3_UNLOCK, unlock); 299 300 return CIM_STATUS_OK; 301} 302 303/*--------------------------------------------------------------------------- 304 * vop_save_state 305 * 306 * This routine saves the necessary register contents in order to restore 307 * at a later point to the same state. Note that the capture state is 308 * forced to OFF in this routine. 309 *--------------------------------------------------------------------------*/ 310 311int 312vop_save_state(VOPSTATEBUFFER * save_buffer) 313{ 314 if (!save_buffer) 315 return CIM_STATUS_INVALIDPARAMS; 316 317 save_buffer->config = READ_VOP32(VOP_CONFIGURATION); 318 319 return CIM_STATUS_OK; 320} 321 322/*--------------------------------------------------------------------------- 323 * vop_restore_state 324 * 325 * This routine restores the state of the vop registers - which were 326 * previously saved using vop_save_state. 327 *--------------------------------------------------------------------------*/ 328 329int 330vop_restore_state(VOPSTATEBUFFER * restore_buffer) 331{ 332 if (!restore_buffer) 333 return CIM_STATUS_INVALIDPARAMS; 334 335 WRITE_VOP32(VOP_CONFIGURATION, restore_buffer->config); 336 337 return CIM_STATUS_OK; 338} 339 340/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 341 * CIMARRON VOP READ ROUTINES 342 * These routines are included for use in diagnostics or when debugging. They 343 * can be optionally excluded from a project. 344 *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 345 346#if CIMARRON_INCLUDE_VOP_READ_ROUTINES 347 348/*--------------------------------------------------------------------------- 349 * vop_get_current_mode 350 * 351 * This routine reads the current VIP operating mode and stores it in the 352 * passed VOP_CONFIGURATION structure. 353 *--------------------------------------------------------------------------*/ 354 355int 356vop_get_current_mode(VOPCONFIGURATIONBUFFER * config) 357{ 358 unsigned long vop_config = 0; 359 unsigned long alpha; 360 361 if (!config) 362 return CIM_STATUS_INVALIDPARAMS; 363 364 vop_config = READ_VOP32(VOP_CONFIGURATION); 365 alpha = READ_VID32(DF_VID_ALPHA_CONTROL); 366 367 /* READ THE CURRENT MODE */ 368 369 switch (vop_config & VOP_CONFIG_MODE_MASK) { 370 case VOP_CONFIG_DISABLED: 371 config->mode = VOP_MODE_DISABLED; 372 break; 373 case VOP_CONFIG_VIP1_1: 374 config->mode = VOP_MODE_VIP11; 375 break; 376 case VOP_CONFIG_CCIR656: 377 config->mode = VOP_MODE_CCIR656; 378 break; 379 case VOP_CONFIG_VIP2_0: 380 381 if (vop_config & VOP_CONFIG_ENABLE_601) 382 config->mode = VOP_MODE_601; 383 else if (vop_config & VOP_CONFIG_VIP2_16BIT) 384 config->mode = VOP_MODE_VIP20_16BIT; 385 else 386 config->mode = VOP_MODE_VIP20_8BIT; 387 break; 388 } 389 390 /* READ 601 SETTINGS */ 391 392 config->vop601.flags = vop_config & (VOP_CONFIG_INVERT_DISPE | 393 VOP_CONFIG_INVERT_HSYNC | 394 VOP_CONFIG_INVERT_VSYNC); 395 396 config->vop601.vsync_shift = vop_config & VOP_CONFIG_VSYNC_MASK; 397 config->vop601.vsync_shift_count = 398 READ_REG32(DC3_VID_DS_DELTA) & DC3_601_VSYNC_SHIFT_MASK; 399 400 if ((alpha & DF_CSC_GRAPHICS_RGB_TO_YUV) || (alpha & DF_CSC_VOP_RGB_TO_YUV)) { 401 /* YUV OUTPUT */ 402 403 if (vop_config & VOP_CONFIG_DISABLE_DECIMATE) 404 config->vop601.output_mode = VOP_601_YUV_4_4_4; 405 else if (vop_config & VOP_CONFIG_VIP2_16BIT) 406 config->vop601.output_mode = VOP_601_YUV_16BIT; 407 else 408 config->vop601.output_mode = VOP_601_YUV_8BIT; 409 } 410 else { 411 config->vop601.output_mode = VOP_601_RGB_8_8_8; 412 } 413 414 config->flags = 0; 415 416 /* READ THE UNIVERSAL VOP OPTIONS */ 417 418 if (vop_config & VOP_CONFIG_SWAPUV) 419 config->flags |= VOP_FLAG_SWAP_UV; 420 if (vop_config & VOP_CONFIG_SWAPVBI) 421 config->flags |= VOP_FLAG_SWAP_VBI; 422 if (vop_config & VOP_CONFIG_VBI) 423 config->flags |= VOP_FLAG_VBI; 424 if (vop_config & VOP_CONFIG_TASK) 425 config->flags |= VOP_FLAG_TASK; 426 if (vop_config & VOP_CONFIG_SC_COMPATIBLE) 427 config->flags |= VOP_FLAG_SINGLECHIPCOMPAT; 428 if (vop_config & VOP_CONFIG_EXTENDED_SAV) 429 config->flags |= VOP_FLAG_EXTENDEDSAV; 430 431 config->conversion_mode = vop_config & VOP_CONFIG_422_MASK; 432 433 config->vsync_out = READ_VIP32(VIP_CONTROL2) & VIP_CONTROL2_SYNC2PIN_MASK; 434 435 return CIM_STATUS_OK; 436} 437 438/*--------------------------------------------------------------------------- 439 * vop_get_vbi_window 440 * 441 * This routine reads the current VBI configuration for VOP output. 442 *--------------------------------------------------------------------------*/ 443 444int 445vop_get_vbi_configuration(VOPVBIWINDOWBUFFER * buffer) 446{ 447 unsigned long temp; 448 unsigned long hstart, hstop; 449 unsigned long htotal, hsyncstart; 450 451 if (!buffer) 452 return CIM_STATUS_INVALIDPARAMS; 453 454 htotal = ((READ_REG32(DC3_H_ACTIVE_TIMING) >> 16) & 0xFFF) + 1; 455 hsyncstart = (READ_REG32(DC3_H_SYNC_TIMING) & 0xFFF) + 1; 456 457 /* DECODE HORIZONTAL POSITION */ 458 /* This is done according to the requested horizontal origin */ 459 460 temp = READ_REG32(DC3_VBI_HOR); 461 hstart = (temp & DC3_VBI_HOR_START_MASK) + 1; 462 hstop = ((temp & DC3_VBI_HOR_END_MASK) >> DC3_VBI_HOR_END_SHIFT) + 1; 463 if (buffer->horz_from_hsync) { 464 buffer->horz_start = hstart + htotal - hsyncstart; 465 if (buffer->horz_start >= (long) htotal) 466 buffer->horz_start -= htotal; 467 } 468 else { 469 if (hstart > hsyncstart) 470 buffer->horz_start = (long) hstart - (long) htotal; 471 else 472 buffer->horz_start = hstart; 473 } 474 475 if (hstop > hstart) 476 buffer->vbi_width = hstop - hstart; 477 else 478 buffer->vbi_width = (htotal - hstart) + hstop; 479 480 /* READ LINE MASKS */ 481 482 temp = READ_REG32(DC3_VBI_LN_ODD); 483 buffer->odd_line_offset = (temp & DC3_VBI_ODD_LINE_MASK) >> 484 DC3_VBI_ODD_LINE_SHIFT; 485 buffer->odd_line_capture_mask = (temp & DC3_VBI_ODD_ENABLE_MASK); 486 487 temp = READ_REG32(DC3_VBI_LN_EVEN); 488 buffer->even_line_offset = (temp & DC3_VBI_EVEN_LINE_MASK) >> 489 DC3_VBI_EVEN_LINE_SHIFT; 490 buffer->even_line_capture_mask = (temp & DC3_VBI_EVEN_ENABLE_MASK); 491 492 /* READ VBI UPSCALE SETTINGS */ 493 494 buffer->enable_upscale = 0; 495 temp = READ_REG32(DC3_VBI_EVEN_CTL); 496 if (temp & DC3_VBI_EVEN_CTL_UPSCALE) 497 buffer->enable_upscale = 1; 498 499 /* READ SOURCE OFFSETS */ 500 501 buffer->even_address_offset = temp & DC3_VBI_EVEN_CTL_OFFSET_MASK; 502 buffer->odd_address_offset = 503 READ_REG32(DC3_VBI_ODD_CTL) & DC3_VBI_ODD_CTL_OFFSET_MASK; 504 505 /* PITCH AND SIZE */ 506 507 temp = READ_REG32(DC3_VBI_PITCH); 508 buffer->data_size = (temp >> 16) << 3; 509 buffer->data_pitch = (temp & 0xFFFF); 510 511 return CIM_STATUS_OK; 512} 513 514/*--------------------------------------------------------------------------- 515 * vop_get_vbi_enable 516 * 517 * This routine reads the current enable status of VBI output. 518 *--------------------------------------------------------------------------*/ 519 520int 521vop_get_vbi_enable(void) 522{ 523 if (READ_REG32(DC3_VBI_EVEN_CTL) & DC3_VBI_ENABLE) 524 return 1; 525 526 return 0; 527} 528 529/*--------------------------------------------------------------------------- 530 * vop_get_crc 531 * 532 * This routine returns a CRC of the current VOP data 533 --------------------------------------------------------------------------*/ 534 535unsigned long 536vop_get_crc(void) 537{ 538 unsigned long crc; 539 unsigned long config = READ_VOP32(VOP_CONFIGURATION); 540 unsigned long timeout = 1000; 541 542 if (!(READ_REG32(DC3_DISPLAY_CFG) & DC3_DCFG_TGEN)) 543 return 0xFFFFFFFF; 544 545 /* RESET CRC */ 546 547 WRITE_VOP32(VOP_CONFIGURATION, config & ~VOP_CONFIG_ENABLE_SIGNATURE); 548 549 /* WAIT FOR THE RESET TO BE LATCHED */ 550 551 while ((READ_VOP32(VOP_SIGNATURE) != 0x00000001) && timeout) 552 timeout--; 553 554 WRITE_VOP32(VOP_CONFIGURATION, config | VOP_CONFIG_ENABLE_SIGNATURE); 555 556 /* WAIT UNTIL NOT ACTIVE, THEN ACTIVE, NOT ACTIVE, THEN ACTIVE */ 557 558 while (!(READ_VOP32(VOP_CONFIGURATION) & VOP_CONFIG_SIGVAL)); 559 560 crc = READ_VOP32(VOP_SIGNATURE); 561 562 return crc; 563} 564 565/*--------------------------------------------------------------------------- 566 * vop_read_vbi_crc 567 * 568 * This routine returns a CRC of the current VBI data 569 ---------------------------------------------------------------------------*/ 570 571unsigned long 572vop_read_vbi_crc(void) 573{ 574 unsigned long gcfg, unlock, vbi_even; 575 unsigned long crc; 576 577 if (!(READ_REG32(DC3_DISPLAY_CFG) & DC3_DCFG_TGEN) || 578 !(READ_REG32(DC3_VBI_EVEN_CTL) & DC3_VBI_ENABLE)) { 579 return 0xFFFFFFFF; 580 } 581 582 unlock = READ_REG32(DC3_UNLOCK); 583 gcfg = READ_REG32(DC3_GENERAL_CFG); 584 vbi_even = READ_REG32(DC3_VBI_EVEN_CTL); 585 586 gcfg |= DC3_GCFG_SGRE | DC3_GCFG_CRC_MODE; 587 gcfg &= ~(DC3_GCFG_SGFR | DC3_GCFG_SIG_SEL); 588 vbi_even |= DC3_VBI_EVEN_ENABLE_CRC; 589 590 WRITE_REG32(DC3_UNLOCK, DC3_UNLOCK_VALUE); 591 WRITE_REG32(DC3_VBI_EVEN_CTL, vbi_even); 592 WRITE_REG32(DC3_GENERAL_CFG, gcfg & ~DC3_GCFG_SIGE); 593 WRITE_REG32(DC3_GENERAL_CFG, gcfg | DC3_GCFG_SIGE); 594 595 /* WAIT FOR THE CRC TO BE COMPLETED */ 596 597 while (!(READ_REG32(DC3_LINE_CNT_STATUS) & DC3_LNCNT_SIGC)); 598 599 /* READ THE COMPLETED CRC */ 600 601 crc = READ_REG32(DC3_PAL_DATA); 602 603 /* RESTORE THE PALETTE SETTINGS */ 604 605 gcfg &= ~DC3_GCFG_SGRE; 606 WRITE_REG32(DC3_GENERAL_CFG, gcfg); 607 WRITE_REG32(DC3_UNLOCK, unlock); 608 609 return crc; 610} 611 612#endif 613