1/* Copyright (c) 2005 Advanced Micro Devices, Inc. 2 * 3 * Permission is hereby granted, free of charge, to any person obtaining a copy 4 * of this software and associated documentation files (the "Software"), to 5 * deal in the Software without restriction, including without limitation the 6 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 7 * sell copies of the Software, and to permit persons to whom the Software is 8 * furnished to do so, subject to the following conditions: 9 * 10 * The above copyright notice and this permission notice shall be included in 11 * all copies or substantial portions of the Software. 12 * 13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 19 * IN THE SOFTWARE. 20 * 21 * Neither the name of the Advanced Micro Devices, Inc. nor the names of its 22 * contributors may be used to endorse or promote products derived from this 23 * software without specific prior written permission. 24 * */ 25 26/* 27 * This file contains routines to control the SC1200 video input port (VIP) 28 * hardware. 29 * */ 30 31/*---------------------------------------------------------------------------- 32 * gfx_set_vip_enable 33 * 34 * This routine enables or disables the writes to memory from the video port. 35 *---------------------------------------------------------------------------- 36 */ 37#if GFX_VIP_DYNAMIC 38int 39sc1200_set_vip_enable(int enable) 40#else 41int 42gfx_set_vip_enable(int enable) 43#endif 44{ 45 unsigned long value; 46 47 value = READ_VIP32(SC1200_VIP_CONTROL); 48 if (enable) 49 value |= SC1200_VIP_DATA_CAPTURE_EN; 50 else 51 value &= ~SC1200_VIP_DATA_CAPTURE_EN; 52 WRITE_VIP32(SC1200_VIP_CONTROL, value); 53 return (0); 54} 55 56/*---------------------------------------------------------------------------- 57 * gfx_set_vip_capture_run_mode 58 * 59 * This routine selects VIP capture run mode. 60 *---------------------------------------------------------------------------- 61 */ 62#if GFX_VIP_DYNAMIC 63int 64sc1200_set_vip_capture_run_mode(int mode) 65#else 66int 67gfx_set_vip_capture_run_mode(int mode) 68#endif 69{ 70 unsigned long value; 71 72 value = READ_VIP32(SC1200_VIP_CONTROL); 73 value &= ~SC1200_CAPTURE_RUN_MODE_MASK; 74 switch (mode) { 75 case VIP_CAPTURE_STOP_LINE: 76 value |= SC1200_CAPTURE_RUN_MODE_STOP_LINE; 77 break; 78 case VIP_CAPTURE_STOP_FIELD: 79 value |= SC1200_CAPTURE_RUN_MODE_STOP_FIELD; 80 break; 81 case VIP_CAPTURE_START_FIELD: 82 value |= SC1200_CAPTURE_RUN_MODE_START; 83 break; 84 default: 85 return GFX_STATUS_BAD_PARAMETER; 86 } 87 WRITE_VIP32(SC1200_VIP_CONTROL, value); 88 return (0); 89} 90 91/*---------------------------------------------------------------------------- 92 * gfx_set_vip_base 93 * 94 * This routine sets the odd and even base address values for the VIP memory 95 * buffer. 96 *---------------------------------------------------------------------------- 97 */ 98#if GFX_VIP_DYNAMIC 99int 100sc1200_set_vip_base(unsigned long even, unsigned long odd) 101#else 102int 103gfx_set_vip_base(unsigned long even, unsigned long odd) 104#endif 105{ 106 /* TRUE OFFSET IS SPECIFIED, NEED TO SET BIT 23 FOR HARDWARE */ 107 108 if (even) 109 WRITE_VIP32(SC1200_VIP_EVEN_BASE, 110 even + (unsigned long) gfx_phys_fbptr); 111 if (odd) 112 WRITE_VIP32(SC1200_VIP_ODD_BASE, odd + (unsigned long) gfx_phys_fbptr); 113 return (0); 114} 115 116/*---------------------------------------------------------------------------- 117 * gfx_set_vip_pitch 118 * 119 * This routine sets the number of bytes between scanlines for the VIP data. 120 *---------------------------------------------------------------------------- 121 */ 122#if GFX_VIP_DYNAMIC 123int 124sc1200_set_vip_pitch(unsigned long pitch) 125#else 126int 127gfx_set_vip_pitch(unsigned long pitch) 128#endif 129{ 130 WRITE_VIP32(SC1200_VIP_PITCH, pitch & SC1200_VIP_PITCH_MASK); 131 return (0); 132} 133 134/*---------------------------------------------------------------------------- 135 * gfx_set_vip_mode 136 * 137 * This routine sets the VIP operating mode. 138 *---------------------------------------------------------------------------- 139 */ 140#if GFX_VIP_DYNAMIC 141int 142sc1200_set_vip_mode(int mode) 143#else 144int 145gfx_set_vip_mode(int mode) 146#endif 147{ 148 unsigned long config; 149 150 config = READ_VIP32(SC1200_VIP_CONFIG); 151 config &= ~SC1200_VIP_MODE_MASK; 152 switch (mode) { 153 case VIP_MODE_C: 154 WRITE_VIP32(SC1200_VIP_CONFIG, config | SC1200_VIP_MODE_C); 155 break; 156 default: 157 return GFX_STATUS_BAD_PARAMETER; 158 } 159 return (0); 160} 161 162/*---------------------------------------------------------------------------- 163 * gfx_set_vbi_enable 164 * 165 * This routine enables or disables the VBI data capture. 166 *---------------------------------------------------------------------------- 167 */ 168#if GFX_VIP_DYNAMIC 169int 170sc1200_set_vbi_enable(int enable) 171#else 172int 173gfx_set_vbi_enable(int enable) 174#endif 175{ 176 unsigned long value; 177 178 value = READ_VIP32(SC1200_VIP_CONTROL); 179 if (enable) 180 value |= SC1200_VIP_VBI_CAPTURE_EN; 181 else 182 value &= ~SC1200_VIP_VBI_CAPTURE_EN; 183 WRITE_VIP32(SC1200_VIP_CONTROL, value); 184 return (0); 185} 186 187/*---------------------------------------------------------------------------- 188 * gfx_set_vbi_mode 189 * 190 * This routine sets the VBI data types captured to memory. 191 * It receives a mask of all enabled types. 192 *---------------------------------------------------------------------------- 193 */ 194#if GFX_VIP_DYNAMIC 195int 196sc1200_set_vbi_mode(int mode) 197#else 198int 199gfx_set_vbi_mode(int mode) 200#endif 201{ 202 unsigned long config; 203 204 config = READ_VIP32(SC1200_VIP_CONFIG); 205 config &= 206 ~(SC1200_VBI_ANCILLARY_TO_MEMORY | SC1200_VBI_TASK_A_TO_MEMORY | 207 SC1200_VBI_TASK_B_TO_MEMORY); 208 209 if (mode & VBI_ANCILLARY) 210 config |= SC1200_VBI_ANCILLARY_TO_MEMORY; 211 if (mode & VBI_TASK_A) 212 config |= SC1200_VBI_TASK_A_TO_MEMORY; 213 if (mode & VBI_TASK_B) 214 config |= SC1200_VBI_TASK_B_TO_MEMORY; 215 WRITE_VIP32(SC1200_VIP_CONFIG, config); 216 return (0); 217} 218 219/*---------------------------------------------------------------------------- 220 * gfx_set_vbi_base 221 * 222 * This routine sets the odd and even base address values for VBI capture. 223 * 224 * "even" and "odd" should contain 16-byte aligned physical addresses. 225 *---------------------------------------------------------------------------- 226 */ 227#if GFX_VIP_DYNAMIC 228int 229sc1200_set_vbi_base(unsigned long even, unsigned long odd) 230#else 231int 232gfx_set_vbi_base(unsigned long even, unsigned long odd) 233#endif 234{ 235 /* VIP HW REQUIRES THAT BASE ADDRESSES BE 16-BYTE ALIGNED */ 236 237 if (even) 238 WRITE_VIP32(SC1200_VBI_EVEN_BASE, even & ~0xf); 239 if (odd) 240 WRITE_VIP32(SC1200_VBI_ODD_BASE, odd & ~0xf); 241 242 return (0); 243} 244 245/*---------------------------------------------------------------------------- 246 * gfx_set_vbi_pitch 247 * 248 * This routine sets the number of bytes between scanlines for VBI capture. 249 *---------------------------------------------------------------------------- 250 */ 251#if GFX_VIP_DYNAMIC 252int 253sc1200_set_vbi_pitch(unsigned long pitch) 254#else 255int 256gfx_set_vbi_pitch(unsigned long pitch) 257#endif 258{ 259 WRITE_VIP32(SC1200_VBI_PITCH, pitch & SC1200_VBI_PITCH_MASK); 260 return (0); 261} 262 263/*---------------------------------------------------------------------------- 264 * gfx_set_vbi_direct 265 * 266 * This routine sets the VBI lines to be passed to the Direct VIP. 267 *---------------------------------------------------------------------------- 268 */ 269#if GFX_VIP_DYNAMIC 270int 271sc1200_set_vbi_direct(unsigned long even_lines, unsigned long odd_lines) 272#else 273int 274gfx_set_vbi_direct(unsigned long even_lines, unsigned long odd_lines) 275#endif 276{ 277 WRITE_VIP32(SC1200_EVEN_DIRECT_VBI_LINE_ENABLE, 278 even_lines & SC1200_DIRECT_VBI_LINE_ENABLE_MASK); 279 WRITE_VIP32(SC1200_ODD_DIRECT_VBI_LINE_ENABLE, 280 odd_lines & SC1200_DIRECT_VBI_LINE_ENABLE_MASK); 281 return (0); 282} 283 284/*---------------------------------------------------------------------------- 285 * gfx_set_vbi_interrupt 286 * 287 * This routine enables or disables the VBI field interrupt. 288 *---------------------------------------------------------------------------- 289 */ 290#if GFX_VIP_DYNAMIC 291int 292sc1200_set_vbi_interrupt(int enable) 293#else 294int 295gfx_set_vbi_interrupt(int enable) 296#endif 297{ 298 unsigned long value; 299 300 value = READ_VIP32(SC1200_VIP_CONTROL); 301 if (enable) 302 value |= SC1200_VIP_VBI_FIELD_INTERRUPT_EN; 303 else 304 value &= ~SC1200_VIP_VBI_FIELD_INTERRUPT_EN; 305 WRITE_VIP32(SC1200_VIP_CONTROL, value); 306 return (0); 307} 308 309/*---------------------------------------------------------------------------- 310 * gfx_set_vip_bus_request_threshold_high 311 * 312 * This routine sets the VIP FIFO bus request threshold. 313 * If enable is TRUE, VIP FIFO will be set to issue a bus request when it 314 * filled with 64 bytes. If enable is FALSE, VIP FIFO will be set to issue a 315 * bus request when it filled with 32 bytes. 316 *---------------------------------------------------------------------------- 317 */ 318#if GFX_VIP_DYNAMIC 319int 320sc1200_set_vip_bus_request_threshold_high(int enable) 321#else 322int 323gfx_set_vip_bus_request_threshold_high(int enable) 324#endif 325{ 326 unsigned long value; 327 328 value = READ_VIP32(SC1200_VIP_CONFIG); 329 if (enable) 330 value &= ~SC1200_VIP_BUS_REQUEST_THRESHOLD; 331 else 332 value |= SC1200_VIP_BUS_REQUEST_THRESHOLD; 333 WRITE_VIP32(SC1200_VIP_CONFIG, value); 334 return (0); 335} 336 337/*---------------------------------------------------------------------------- 338 * gfx_set_vip_last_line 339 * 340 * This routine sets the maximum number of lines captured in each field. 341 *---------------------------------------------------------------------------- 342 */ 343#if GFX_VIP_DYNAMIC 344int 345sc1200_set_vip_last_line(int last_line) 346#else 347int 348gfx_set_vip_last_line(int last_line) 349#endif 350{ 351 unsigned long value; 352 353 /* This feature is implemented in Rev C1 */ 354 if (gfx_chip_revision < SC1200_REV_C1) 355 return (GFX_STATUS_OK); 356 357 value = READ_VIP32(SC1200_VIP_LINE_TARGET); 358 value &= ~SC1200_VIP_LAST_LINE_MASK; 359 value |= ((last_line & 0x3FF) << 16); 360 WRITE_VIP32(SC1200_VIP_LINE_TARGET, value); 361 return (GFX_STATUS_OK); 362} 363 364/*---------------------------------------------------------------------------- 365 * gfx_test_vip_odd_field 366 * 367 * This routine returns 1 if the current VIP field is odd. Otherwise returns 0 368 *---------------------------------------------------------------------------- 369 */ 370#if GFX_VIP_DYNAMIC 371int 372sc1200_test_vip_odd_field(void) 373#else 374int 375gfx_test_vip_odd_field(void) 376#endif 377{ 378 if (READ_VIP32(SC1200_VIP_STATUS) & SC1200_VIP_CURRENT_FIELD_ODD) 379 return (1); 380 else 381 return (0); 382} 383 384/*---------------------------------------------------------------------------- 385 * gfx_test_vip_bases_updated 386 * 387 * This routine returns 1 if all of the VIP base registers have been updated, 388 * i.e. there is no base register which has been written with a new address, 389 * that VIP has not already captured or started capturing into the new address 390 *---------------------------------------------------------------------------- 391 */ 392#if GFX_VIP_DYNAMIC 393int 394sc1200_test_vip_bases_updated(void) 395#else 396int 397gfx_test_vip_bases_updated(void) 398#endif 399{ 400 if (READ_VIP32(SC1200_VIP_STATUS) & SC1200_VIP_BASE_NOT_UPDATED) 401 return (0); 402 else 403 return (1); 404} 405 406/*---------------------------------------------------------------------------- 407 * gfx_test_vip_fifo_overflow 408 * 409 * This routine returns 1 if an overflow occurred on the FIFO between the VIP 410 * and the fast X-bus, 0 otherwise. 411 * If an overflow occurred, the overflow status indication is reset. 412 *---------------------------------------------------------------------------- 413 */ 414#if GFX_VIP_DYNAMIC 415int 416sc1200_test_vip_fifo_overflow(void) 417#else 418int 419gfx_test_vip_fifo_overflow(void) 420#endif 421{ 422 if (READ_VIP32(SC1200_VIP_STATUS) & SC1200_VIP_FIFO_OVERFLOW) { 423 /* Bits in vip status register are either read only or reset by 424 * writing 1 */ 425 WRITE_VIP32(SC1200_VIP_STATUS, SC1200_VIP_FIFO_OVERFLOW); 426 return (1); 427 } 428 else { 429 return (0); 430 } 431} 432 433/*---------------------------------------------------------------------------- 434 * gfx_get_vip_line 435 * 436 * This routine returns the number of the current video line being 437 * received by the VIP interface. 438 *---------------------------------------------------------------------------- 439 */ 440#if GFX_VIP_DYNAMIC 441int 442sc1200_get_vip_line(void) 443#else 444int 445gfx_get_vip_line(void) 446#endif 447{ 448 return (int) (READ_VIP32(SC1200_VIP_CURRENT_LINE) & 449 SC1200_VIP_CURRENT_LINE_MASK); 450} 451 452/*---------------------------------------------------------------------------- 453 * gfx_get_vip_base 454 *---------------------------------------------------------------------------- 455 */ 456#if GFX_VIP_DYNAMIC 457unsigned long 458sc1200_get_vip_base(int odd) 459#else 460unsigned long 461gfx_get_vip_base(int odd) 462#endif 463{ 464 /* MASK BIT 23 AND ABOVE TO MAKE IT A TRUE OFFSET */ 465 466 if (odd) 467 return (READ_VIP32(SC1200_VIP_ODD_BASE)); 468 return (READ_VIP32(SC1200_VIP_EVEN_BASE)); 469} 470 471/*---------------------------------------------------------------------------- 472 * gfx_get_vbi_pitch 473 *---------------------------------------------------------------------------- 474 */ 475#if GFX_VIP_DYNAMIC 476unsigned long 477sc1200_get_vbi_pitch(void) 478#else 479unsigned long 480gfx_get_vbi_pitch(void) 481#endif 482{ 483 return (READ_VIP32(SC1200_VBI_PITCH) & SC1200_VBI_PITCH_MASK); 484} 485 486/*************************************************************/ 487/* READ ROUTINES | INCLUDED FOR DIAGNOSTIC PURPOSES ONLY */ 488/*************************************************************/ 489 490#if GFX_READ_ROUTINES 491 492/*---------------------------------------------------------------------------- 493 * gfx_get_vip_enable 494 *---------------------------------------------------------------------------- 495 */ 496#if GFX_VIP_DYNAMIC 497int 498sc1200_get_vip_enable(void) 499#else 500int 501gfx_get_vip_enable(void) 502#endif 503{ 504 if (READ_VIP32(SC1200_VIP_CONTROL) & SC1200_VIP_DATA_CAPTURE_EN) 505 return (1); 506 return (0); 507} 508 509/*---------------------------------------------------------------------------- 510 * gfx_get_vip_pitch 511 *---------------------------------------------------------------------------- 512 */ 513#if GFX_VIP_DYNAMIC 514unsigned long 515sc1200_get_vip_pitch(void) 516#else 517unsigned long 518gfx_get_vip_pitch(void) 519#endif 520{ 521 return (READ_VIP32(SC1200_VIP_PITCH) & SC1200_VIP_PITCH_MASK); 522} 523 524/*---------------------------------------------------------------------------- 525 * gfx_get_vip_mode 526 *---------------------------------------------------------------------------- 527 */ 528#if GFX_VIP_DYNAMIC 529int 530sc1200_get_vip_mode(void) 531#else 532int 533gfx_get_vip_mode(void) 534#endif 535{ 536 switch (READ_VIP32(SC1200_VIP_CONFIG) & SC1200_VIP_MODE_MASK) { 537 case SC1200_VIP_MODE_C: 538 return VIP_MODE_C; 539 default: 540 return (0); 541 } 542} 543 544/*---------------------------------------------------------------------------- 545 * gfx_get_vbi_enable 546 *---------------------------------------------------------------------------- 547 */ 548#if GFX_VIP_DYNAMIC 549int 550sc1200_get_vbi_enable(void) 551#else 552int 553gfx_get_vbi_enable(void) 554#endif 555{ 556 if (READ_VIP32(SC1200_VIP_CONTROL) & SC1200_VIP_VBI_CAPTURE_EN) 557 return (1); 558 return (0); 559} 560 561/*---------------------------------------------------------------------------- 562 * gfx_get_vbi_mode 563 *---------------------------------------------------------------------------- 564 */ 565#if GFX_VIP_DYNAMIC 566int 567sc1200_get_vbi_mode(void) 568#else 569int 570gfx_get_vbi_mode(void) 571#endif 572{ 573 int config; 574 int mode = 0; 575 576 config = 577 (int) (READ_VIP32(SC1200_VIP_CONFIG) & (SC1200_VBI_ANCILLARY_TO_MEMORY 578 | SC1200_VBI_TASK_A_TO_MEMORY | 579 SC1200_VBI_TASK_B_TO_MEMORY)); 580 if (config & SC1200_VBI_ANCILLARY_TO_MEMORY) 581 mode |= VBI_ANCILLARY; 582 if (config & SC1200_VBI_TASK_A_TO_MEMORY) 583 mode |= VBI_TASK_A; 584 if (config & SC1200_VBI_TASK_B_TO_MEMORY) 585 mode |= VBI_TASK_B; 586 return mode; 587} 588 589/*---------------------------------------------------------------------------- 590 * gfx_get_vbi_base 591 *---------------------------------------------------------------------------- 592 */ 593#if GFX_VIP_DYNAMIC 594unsigned long 595sc1200_get_vbi_base(int odd) 596#else 597unsigned long 598gfx_get_vbi_base(int odd) 599#endif 600{ 601 /* MASK BIT 23 AND ABOVE TO MAKE IT A TRUE OFFSET */ 602 603 if (odd) 604 return (READ_VIP32(SC1200_VBI_ODD_BASE)); 605 return (READ_VIP32(SC1200_VBI_EVEN_BASE)); 606} 607 608/*---------------------------------------------------------------------------- 609 * gfx_get_vbi_direct 610 *---------------------------------------------------------------------------- 611 */ 612#if GFX_VIP_DYNAMIC 613unsigned long 614sc1200_get_vbi_direct(int odd) 615#else 616unsigned long 617gfx_get_vbi_direct(int odd) 618#endif 619{ 620 /* MASK BIT 23 AND ABOVE TO MAKE IT A TRUE OFFSET */ 621 622 if (odd) 623 return (READ_VIP32(SC1200_ODD_DIRECT_VBI_LINE_ENABLE) & 624 SC1200_DIRECT_VBI_LINE_ENABLE_MASK); 625 return (READ_VIP32(SC1200_EVEN_DIRECT_VBI_LINE_ENABLE) & 626 SC1200_DIRECT_VBI_LINE_ENABLE_MASK); 627} 628 629/*--------------------------------------------------------------------------- 630 * gfx_get_vbi_interrupt 631 *---------------------------------------------------------------------------- 632 */ 633#if GFX_VIP_DYNAMIC 634int 635sc1200_get_vbi_interrupt(void) 636#else 637int 638gfx_get_vbi_interrupt(void) 639#endif 640{ 641 if (READ_VIP32(SC1200_VIP_CONTROL) & SC1200_VIP_VBI_FIELD_INTERRUPT_EN) 642 return (1); 643 return (0); 644} 645 646/*---------------------------------------------------------------------------- 647 * gfx_get_vip_bus_request_threshold_high 648 *---------------------------------------------------------------------------- 649 */ 650#if GFX_VIP_DYNAMIC 651int 652sc1200_get_vip_bus_request_threshold_high(void) 653#else 654int 655gfx_get_vip_bus_request_threshold_high(void) 656#endif 657{ 658 if (READ_VIP32(SC1200_VIP_CONFIG) & SC1200_VIP_BUS_REQUEST_THRESHOLD) 659 return (1); 660 return (0); 661} 662 663#endif /* GFX_READ_ROUTINES */ 664 665/* END OF FILE */ 666