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 display filter routines. These routines program the video 29 * hardware. 30 */ 31 32/*--------------------------------------------------------------------------- 33 * df_set_crt_enable 34 * 35 * This routine enables or disables CRT output. 36 *--------------------------------------------------------------------------*/ 37 38int 39df_set_crt_enable(int crt_output) 40{ 41 unsigned long config, misc; 42 43 config = READ_VID32(DF_DISPLAY_CONFIG); 44 misc = READ_VID32(DF_VID_MISC); 45 46 switch (crt_output) { 47 /* DISABLE DISPLAY */ 48 49 case DF_CRT_DISABLE: 50 51 config &= ~(DF_DCFG_DIS_EN | DF_DCFG_HSYNC_EN | 52 DF_DCFG_VSYNC_EN | DF_DCFG_DAC_BL_EN); 53 misc |= DF_DAC_POWER_DOWN; 54 break; 55 56 /* ENABLE THE DISPLAY */ 57 58 case DF_CRT_ENABLE: 59 60 config |= (DF_DCFG_DIS_EN | DF_DCFG_HSYNC_EN | 61 DF_DCFG_VSYNC_EN | DF_DCFG_DAC_BL_EN); 62 misc &= ~(DF_DAC_POWER_DOWN | DF_ANALOG_POWER_DOWN); 63 break; 64 65 /* HSYNC:OFF VSYNC:ON */ 66 67 case DF_CRT_STANDBY: 68 69 config = (config & ~(DF_DCFG_DIS_EN | DF_DCFG_HSYNC_EN | 70 DF_DCFG_DAC_BL_EN)) | DF_DCFG_VSYNC_EN; 71 misc |= DF_DAC_POWER_DOWN; 72 break; 73 74 /* HSYNC:ON VSYNC:OFF */ 75 76 case DF_CRT_SUSPEND: 77 78 config = (config & ~(DF_DCFG_DIS_EN | DF_DCFG_VSYNC_EN | 79 DF_DCFG_DAC_BL_EN)) | DF_DCFG_HSYNC_EN; 80 misc |= DF_DAC_POWER_DOWN; 81 break; 82 83 default: 84 return CIM_STATUS_INVALIDPARAMS; 85 } 86 87 WRITE_VID32(DF_DISPLAY_CONFIG, config); 88 WRITE_VID32(DF_VID_MISC, misc); 89 90 return CIM_STATUS_OK; 91} 92 93/*--------------------------------------------------------------------------- 94 * df_set_panel_enable 95 * 96 * This routine enables or disables panel output. 97 *--------------------------------------------------------------------------*/ 98 99int 100df_set_panel_enable(int enable) 101{ 102 unsigned long pm; 103 104 pm = READ_VID32(DF_POWER_MANAGEMENT); 105 106 if (enable) 107 pm |= DF_PM_PANEL_ON; 108 else 109 pm &= ~DF_PM_PANEL_ON; 110 111 WRITE_VID32(DF_POWER_MANAGEMENT, pm); 112 113 return CIM_STATUS_OK; 114} 115 116/*--------------------------------------------------------------------------- 117 * df_configure_video_source 118 * 119 * This routine initializes all aspects of the source buffer for a video overlay. 120 *--------------------------------------------------------------------------*/ 121 122int 123df_configure_video_source(DF_VIDEO_SOURCE_PARAMS * video_source_odd, 124 DF_VIDEO_SOURCE_PARAMS * video_source_even) 125{ 126 unsigned long pitch, ctrl, vcfg; 127 unsigned long lock, vg_line, gcfg; 128 unsigned long width, size, scale; 129 unsigned long misc; 130 131 lock = READ_REG32(DC3_UNLOCK); 132 vg_line = READ_REG32(DC3_LINE_SIZE); 133 gcfg = READ_REG32(DC3_GENERAL_CFG); 134 vcfg = READ_VID32(DF_VIDEO_CONFIG); 135 ctrl = READ_VID32(DF_VID_ALPHA_CONTROL); 136 scale = READ_VID32(DF_VIDEO_SCALER); 137 138 /* STORE THE DESIRED SCALING PROCEDURE */ 139 /* Cimarron supports two modes when programming the scale and position */ 140 /* of the video window. The first mode is designed to implicitly apply */ 141 /* the graphics scale to any video operations. The second applies the */ 142 /* video unchanged, allowing complete control by the user. To allow */ 143 /* visibility between modules, the current mode is stored in a spare */ 144 /* bit in the DF miscellaneous register. */ 145 146 misc = READ_VID32(DF_VID_MISC); 147 if (video_source_odd->flags & DF_SOURCEFLAG_IMPLICITSCALING) 148 misc |= DF_USER_IMPLICIT_SCALING; 149 else 150 misc &= DF_USER_IMPLICIT_SCALING; 151 WRITE_VID32(DF_VID_MISC, misc); 152 153 /* PARAMETER - VIDEO PITCH */ 154 155 pitch = 156 (video_source_odd->y_pitch >> 3) | ((video_source_odd->uv_pitch >> 3) << 157 16); 158 159 /* PARAMETER - VIDEO FORMAT */ 160 161 gcfg &= ~DC3_GCFG_YUV_420; 162 vcfg &= ~(DF_VCFG_VID_INP_FORMAT | DF_VCFG_4_2_0_MODE); 163 ctrl &= ~(DF_VIDEO_INPUT_IS_RGB | DF_CSC_VIDEO_YUV_TO_RGB | DF_HD_VIDEO | 164 DF_YUV_CSC_EN); 165 166 /* SELECT PIXEL ORDERING */ 167 168 switch (video_source_odd->video_format & 3) { 169 case 0: 170 vcfg |= DF_VCFG_UYVY_FORMAT; 171 break; 172 case 1: 173 vcfg |= DF_VCFG_Y2YU_FORMAT; 174 break; 175 case 2: 176 vcfg |= DF_VCFG_YUYV_FORMAT; 177 break; 178 case 3: 179 vcfg |= DF_VCFG_YVYU_FORMAT; 180 break; 181 } 182 183 /* SELECT SOURCE FORMAT (4:2:2, 4:2:0, RGB) */ 184 185 switch (video_source_odd->video_format >> 2) { 186 case 0: 187 ctrl |= DF_CSC_VIDEO_YUV_TO_RGB; 188 break; 189 190 case 1: 191 ctrl |= DF_CSC_VIDEO_YUV_TO_RGB; 192 vcfg |= DF_VCFG_4_2_0_MODE; 193 gcfg |= DC3_GCFG_YUV_420; 194 break; 195 196 case 2: 197 ctrl |= DF_VIDEO_INPUT_IS_RGB; 198 break; 199 200 default: 201 return CIM_STATUS_INVALIDPARAMS; 202 } 203 204 /* ALIGN TO APPROPRIATE OUTPUT COLOR SPACE */ 205 /* We have assumed until this point that the output color space is RGB */ 206 /* and the input (if YUV) is always SDTV video. */ 207 208 if (video_source_odd->flags & DF_SOURCEFLAG_HDTVSOURCE) 209 ctrl |= DF_HD_VIDEO; 210 211 if (ctrl & DF_CSC_GRAPHICS_RGB_TO_YUV) { 212 /* YUV OUTPUT - DISABLE YUV->RGB AND ENABLE YUV->YUV */ 213 214 ctrl &= ~DF_CSC_VIDEO_YUV_TO_RGB; 215 216 if ((!(ctrl & DF_HD_VIDEO) && (ctrl & DF_HD_GRAPHICS)) || 217 ((ctrl & DF_HD_VIDEO) && !(ctrl & DF_HD_GRAPHICS))) { 218 ctrl |= DF_YUV_CSC_EN; 219 } 220 } 221 222 /* PARAMETER - DISPLAY FILTER BUFFER SIZE */ 223 /* The line size in the video generator must be 32-byte aligned. */ 224 /* However, smaller alignments are managed by setting the */ 225 /* appropriate pitch and clipping the video window. */ 226 227 vcfg &= ~(DF_VCFG_LINE_SIZE_LOWER_MASK | DF_VCFG_LINE_SIZE_BIT8 | 228 DF_VCFG_LINE_SIZE_BIT9); 229 230 size = ((video_source_odd->width >> 1) + 7) & 0xFFF8; 231 232 vcfg |= (size & 0x00FF) << 8; 233 if (size & 0x0100) 234 vcfg |= DF_VCFG_LINE_SIZE_BIT8; 235 if (size & 0x0200) 236 vcfg |= DF_VCFG_LINE_SIZE_BIT9; 237 238 scale = (scale & ~0x7FF) | video_source_odd->height; 239 240 /* PARAMETER - VIDEO GENERATOR BUFFER SIZE */ 241 242 vg_line &= ~DC3_LINE_SIZE_VLS_MASK; 243 244 if (gcfg & DC3_GCFG_YUV_420) 245 width = ((video_source_odd->width >> 1) + 7) & 0xFFF8; 246 else 247 width = ((video_source_odd->width << 1) + 31) & 0xFFE0; 248 249 vg_line |= (width >> 3) << DC3_LINE_SIZE_VB_SHIFT; 250 251 /* WRITE ALL PARAMETERS AT ONCE */ 252 253 WRITE_REG32(DC3_UNLOCK, DC3_UNLOCK_VALUE); 254 WRITE_VID32(DF_VIDEO_CONFIG, vcfg); 255 WRITE_VID32(DF_VID_ALPHA_CONTROL, ctrl); 256 WRITE_VID32(DF_VIDEO_SCALER, scale); 257 WRITE_REG32(DC3_GENERAL_CFG, gcfg); 258 WRITE_REG32(DC3_LINE_SIZE, vg_line); 259 WRITE_REG32(DC3_VID_YUV_PITCH, pitch); 260 261 /* WRITE EVEN OR ODD BUFFER OFFSETS */ 262 /* The even buffer is only valid inside an interlaced display. */ 263 264 if (READ_REG32(DC3_IRQ_FILT_CTL) & DC3_IRQFILT_INTL_EN) { 265 WRITE_REG32(DC3_VID_EVEN_Y_ST_OFFSET, video_source_even->y_offset); 266 WRITE_REG32(DC3_VID_EVEN_U_ST_OFFSET, video_source_even->u_offset); 267 WRITE_REG32(DC3_VID_EVEN_V_ST_OFFSET, video_source_even->v_offset); 268 } 269 270 WRITE_REG32(DC3_VID_Y_ST_OFFSET, video_source_odd->y_offset); 271 WRITE_REG32(DC3_VID_U_ST_OFFSET, video_source_odd->u_offset); 272 WRITE_REG32(DC3_VID_V_ST_OFFSET, video_source_odd->v_offset); 273 274 WRITE_REG32(DC3_UNLOCK, lock); 275 276 return CIM_STATUS_OK; 277} 278 279/*--------------------------------------------------------------------------- 280 * df_set_video_offsets 281 * 282 * This routine sets the starting offset for the video buffer(s). The buffers 283 * can also be configured inside df_configure_video_source, but a separate 284 * routine is provided here to allow quick buffer flipping. 285 *--------------------------------------------------------------------------*/ 286 287int 288df_set_video_offsets(int even, unsigned long y_offset, 289 unsigned long u_offset, unsigned long v_offset) 290{ 291 unsigned long lock = READ_REG32(DC3_UNLOCK); 292 293 WRITE_REG32(DC3_UNLOCK, DC3_UNLOCK_VALUE); 294 295 if (even) { 296 WRITE_REG32(DC3_VID_EVEN_Y_ST_OFFSET, y_offset); 297 WRITE_REG32(DC3_VID_EVEN_U_ST_OFFSET, u_offset); 298 WRITE_REG32(DC3_VID_EVEN_V_ST_OFFSET, v_offset); 299 } 300 else { 301 WRITE_REG32(DC3_VID_Y_ST_OFFSET, y_offset); 302 WRITE_REG32(DC3_VID_U_ST_OFFSET, u_offset); 303 WRITE_REG32(DC3_VID_V_ST_OFFSET, v_offset); 304 } 305 306 WRITE_REG32(DC3_UNLOCK, lock); 307 308 return CIM_STATUS_OK; 309} 310 311/*--------------------------------------------------------------------------- 312 * df_set_video_scale 313 * 314 * This routine programs the horizontal/vertical scale factors for video. To 315 * disable scaling/filtering, this routine should be called with identical source 316 * and destination dimensions. 317 *--------------------------------------------------------------------------*/ 318 319int 320df_set_video_scale(unsigned long src_width, unsigned long src_height, 321 unsigned long dst_width, unsigned long dst_height, 322 unsigned long flags) 323{ 324 unsigned long temp, misc; 325 unsigned long scale, gfxscale; 326 unsigned long fbactive, src; 327 unsigned long size, downscale; 328 unsigned long vcfg, gcfg, unlock; 329 330 /* APPLY THE GRAPHICS SCALE */ 331 /* When requested by the user, we will adjust the video scale by the */ 332 /* current graphics scale factor. This allows video to be programmed */ 333 /* in terms of the graphics source resolution. */ 334 335 misc = READ_VID32(DF_VID_MISC); 336 if (misc & DF_USER_IMPLICIT_SCALING) { 337 gfxscale = READ_REG32(DC3_GFX_SCALE); 338 fbactive = READ_REG32(DC3_FB_ACTIVE); 339 340 /* REVERSE ENGINEER THE SCALE FACTOR */ 341 /* The graphics scale factor is (source / (dst - 1)), so a little */ 342 /* math is performed to reverse engineer the correct scale for */ 343 /* video. */ 344 /* */ 345 /* F = (0x4000*S)/(D-1) -> (D/S) = (((0x4000*S)/F)+1)/S */ 346 347 scale = gfxscale & 0xFFFF; 348 src = (fbactive >> 16) + 1; 349 if (scale != 0x4000) { 350 dst_width = dst_width * (((0x4000 * src) / scale) + 1); 351 dst_width /= src; 352 } 353 354 scale = gfxscale >> 16; 355 src = (fbactive & 0xFFFF) + 1; 356 if (scale != 0x4000) { 357 dst_height = dst_height * (((0x4000 * src) / scale) + 1); 358 dst_height /= src; 359 } 360 } 361 362 /* CHECK FOR VALID SCALING FACTOR */ 363 /* The display filter/video generator can support up to 8:1 */ 364 /* horizontal downscale and up to 4:1 vertical downscale. */ 365 /* Scale factors above 4:1 horizontal and 2:1 horizontal */ 366 /* will have a quality impact. However, at such large scale */ 367 /* factors, it might not matter, */ 368 369 if (((flags & DF_SCALEFLAG_CHANGEX) && dst_width < (src_width >> 3)) || 370 ((flags & DF_SCALEFLAG_CHANGEY) && dst_height < (src_height >> 2))) { 371 return CIM_STATUS_INVALIDSCALE; 372 } 373 374 /* ENABLE OR DISABLE ADVANCED SCALING FEATURES */ 375 /* Scaling above 2:1 vertical and 4:1 horizontal relies */ 376 /* on mechanisms beside the line filter. */ 377 378 if (flags & DF_SCALEFLAG_CHANGEX) { 379 scale = READ_VID32(DF_VIDEO_SCALER); 380 vcfg = READ_VID32(DF_VIDEO_CONFIG); 381 vcfg &= ~(DF_VCFG_LINE_SIZE_LOWER_MASK | DF_VCFG_LINE_SIZE_BIT8 | 382 DF_VCFG_LINE_SIZE_BIT9); 383 384 if (dst_width < (src_width >> 2)) { 385 src_width >>= 1; 386 WRITE_VID32(DF_VIDEO_SCALER, scale | DF_SCALE_DOUBLE_H_DOWNSCALE); 387 } 388 else { 389 WRITE_VID32(DF_VIDEO_SCALER, scale & ~DF_SCALE_DOUBLE_H_DOWNSCALE); 390 } 391 392 /* PROGRAM A NEW LINE SIZE */ 393 /* The line size must be updated when using the Double Horizontal */ 394 /* Downscale (DHD) bit. This is because the amount of VFIFO space */ 395 /* consumed is effectively half in this mode. */ 396 397 size = ((src_width >> 1) + 7) & 0xFFF8; 398 vcfg |= (size & 0x00FF) << 8; 399 if (size & 0x0100) 400 vcfg |= DF_VCFG_LINE_SIZE_BIT8; 401 if (size & 0x0200) 402 vcfg |= DF_VCFG_LINE_SIZE_BIT9; 403 WRITE_VID32(DF_VIDEO_CONFIG, vcfg); 404 WRITE_VID32(DF_VIDEO_XSCALE, ((0x10000 * src_width) / dst_width)); 405 } 406 407 if (flags & DF_SCALEFLAG_CHANGEY) { 408 unlock = READ_REG32(DC3_UNLOCK); 409 gcfg = READ_REG32(DC3_GENERAL_CFG) & ~DC3_GCFG_VDSE; 410 WRITE_REG32(DC3_UNLOCK, DC3_UNLOCK_VALUE); 411 if (dst_height < (src_height >> 1)) { 412 gcfg |= DC3_GCFG_VDSE; 413 downscale = READ_REG32(DC3_VID_DS_DELTA) & ~DC3_DS_DELTA_MASK; 414 if (dst_height == (src_height >> 2)) 415 downscale |= (0x3FFF << 18); 416 else 417 downscale |= (((src_height >> 1) << 14) / dst_height) << 18; 418 419 WRITE_REG32(DC3_VID_DS_DELTA, downscale); 420 WRITE_VID32(DF_VIDEO_YSCALE, 0x20000); 421 } 422 else { 423 WRITE_VID32(DF_VIDEO_YSCALE, ((0x10000 * src_height) / dst_height)); 424 } 425 WRITE_REG32(DC3_GENERAL_CFG, gcfg); 426 WRITE_REG32(DC3_UNLOCK, unlock); 427 } 428 429 /* CHECK IF SCALING IS DISABLED */ 430 /* If no scaling occurs, we disable the hardware filter. */ 431 432 temp = READ_VID32(DF_VIDEO_CONFIG); 433 if ((READ_VID32(DF_VIDEO_XSCALE) == 0x10000) && 434 (READ_VID32(DF_VIDEO_YSCALE) == 0x10000)) { 435 WRITE_VID32(DF_VIDEO_CONFIG, (temp | DF_VCFG_SC_BYP)); 436 } 437 else 438 WRITE_VID32(DF_VIDEO_CONFIG, (temp & ~DF_VCFG_SC_BYP)); 439 440 return CIM_STATUS_OK; 441} 442 443/*--------------------------------------------------------------------------- 444 * df_set_video_position 445 * 446 * This routine programs the position of the video window on the display. 447 * An indent parameter is also passed to this program to prevent artifacts 448 * when the video window is moved beyond the left edge of the screen. 449 *--------------------------------------------------------------------------*/ 450 451int 452df_set_video_position(DF_VIDEO_POSITION * video_window) 453{ 454 unsigned long vblankstart_even, vblankend_even, vsyncend_even, 455 vtotal_even, vactive_even; 456 unsigned long hblankstart, hblankend, hsyncend, htotal, hactive; 457 unsigned long vblankstart, vblankend, vsyncend, vtotal, vactive; 458 unsigned long width, height, height_even; 459 unsigned long adjust, border_x, border_y, border_y_even; 460 unsigned long xstart, xend; 461 unsigned long ystart, yend; 462 unsigned long ckey_x, ckey_y; 463 unsigned long x_copy, y_copy; 464 unsigned long width_copy, height_copy; 465 unsigned long vcfg, initread; 466 unsigned long xscale, dst_clip; 467 unsigned long ypos, ypos_even; 468 unsigned long y, gfxscale; 469 unsigned long misc, fbactive; 470 unsigned long scale, src; 471 unsigned long irq_ctl; 472 unsigned long unlock; 473 474 hsyncend = ((READ_REG32(DC3_H_SYNC_TIMING) >> 16) & 0xFFF) + 1; 475 vsyncend = ((READ_REG32(DC3_V_SYNC_TIMING) >> 16) & 0xFFF) + 1; 476 vblankend = ((READ_REG32(DC3_V_BLANK_TIMING) >> 16) & 0xFFF) + 1; 477 hblankend = ((READ_REG32(DC3_H_BLANK_TIMING) >> 16) & 0xFFF) + 1; 478 htotal = ((READ_REG32(DC3_H_ACTIVE_TIMING) >> 16) & 0xFFF) + 1; 479 vtotal = ((READ_REG32(DC3_V_ACTIVE_TIMING) >> 16) & 0xFFF) + 1; 480 vblankstart = (READ_REG32(DC3_V_BLANK_TIMING) & 0xFFF) + 1; 481 hblankstart = (READ_REG32(DC3_H_BLANK_TIMING) & 0xFFF) + 1; 482 hactive = (READ_REG32(DC3_H_ACTIVE_TIMING) & 0xFFF) + 1; 483 vactive = (READ_REG32(DC3_V_ACTIVE_TIMING) & 0xFFF) + 1; 484 unlock = READ_REG32(DC3_UNLOCK); 485 486 /* INCLUDE BORDER IF REQUESTED */ 487 488 if (video_window->flags & DF_POSFLAG_INCLUDEBORDER) { 489 border_x = htotal - hblankend; 490 border_y = vtotal - vblankend; 491 hactive = hblankstart + htotal - hblankend; 492 vactive = vblankstart + vtotal - vblankend; 493 } 494 else { 495 border_x = border_y = 0; 496 } 497 498 /* APPLY THE GRAPHICS SCALE */ 499 /* Do not alter the input data. */ 500 501 width_copy = video_window->width; 502 height_copy = video_window->height; 503 x_copy = video_window->x; 504 y_copy = video_window->y; 505 506 misc = READ_VID32(DF_VID_MISC); 507 if (misc & DF_USER_IMPLICIT_SCALING) { 508 gfxscale = READ_REG32(DC3_GFX_SCALE); 509 fbactive = READ_REG32(DC3_FB_ACTIVE); 510 511 /* REVERSE ENGINEER THE SCALE FACTOR */ 512 513 scale = gfxscale & 0xFFFF; 514 src = (fbactive >> 16) + 1; 515 if (scale != 0x4000) { 516 width_copy = width_copy * (((0x4000 * src) / scale) + 1); 517 width_copy /= src; 518 x_copy = x_copy * (((0x4000 * src) / scale) + 1); 519 x_copy /= src; 520 } 521 522 scale = gfxscale >> 16; 523 src = (fbactive & 0xFFFF) + 1; 524 if (scale != 0x4000) { 525 height_copy = height_copy * (((0x4000 * src) / scale) + 1); 526 height_copy /= src; 527 y_copy = y_copy * (((0x4000 * src) / scale) + 1); 528 y_copy /= src; 529 } 530 } 531 532 /* HANDLE INTERLACING */ 533 /* When the output is interlaced, we must set the position and height */ 534 /* on the fields and not on the composite image. */ 535 536 if ((irq_ctl = READ_REG32(DC3_IRQ_FILT_CTL)) & DC3_IRQFILT_INTL_EN) { 537 vsyncend_even = ((READ_REG32(DC3_V_SYNC_EVEN) >> 16) & 0xFFF) + 1; 538 vtotal_even = ((READ_REG32(DC3_V_ACTIVE_EVEN) >> 16) & 0xFFF) + 1; 539 vblankend_even = ((READ_REG32(DC3_V_BLANK_EVEN) >> 16) & 0xFFF) + 1; 540 vactive_even = (READ_REG32(DC3_V_ACTIVE_EVEN) & 0xFFF) + 1; 541 vblankstart_even = (READ_REG32(DC3_V_BLANK_EVEN) & 0xFFF) + 1; 542 543 if (video_window->flags & DF_POSFLAG_INCLUDEBORDER) { 544 border_y_even = vtotal_even - vblankend_even; 545 vactive_even = vblankstart_even + vtotal_even - vblankend_even; 546 } 547 else 548 border_y_even = 0; 549 550 /* 551 * THE ODD FIELD MUST ALWAYS PRECEDE THE EVEN FIELD 552 * This implies that we can never start video on an odd y position 553 * in the composite image. This is required because the only way 554 * to accomplish an odd y start would be to switch the buffer 555 * which could have serious repercussions for genlocked VIP. 556 */ 557 558 y = y_copy >> 1; 559 560 /* CALCULATE Y POSITION FOR ODD FIELD */ 561 /* Clip the video window to the odd field timings. Note that the */ 562 /* height in the odd field may be greater if the video height is */ 563 /* odd. */ 564 565 height = (height_copy + 1) >> 1; 566 if ((y + height) > vactive) 567 height = vactive - y; 568 569 ystart = y + vtotal_even - vsyncend_even + 1; 570 if (video_window->flags & DF_POSFLAG_INCLUDEBORDER) 571 ystart -= border_y_even; 572 573 yend = ystart + height; 574 ypos = (yend << 16) | ystart; 575 576 /* CALCULATE Y POSITION FOR EVEN FIELD */ 577 578 height_even = height_copy >> 1; 579 if ((y + height_even) > vactive_even) 580 height_even = vactive_even - y; 581 582 ystart = y + vtotal - vsyncend + 1; 583 if (video_window->flags & DF_POSFLAG_INCLUDEBORDER) 584 ystart -= border_y; 585 586 yend = ystart + height_even; 587 ypos_even = (yend << 16) | ystart; 588 589 /* CALCULATE ACTUAL FRAME BUFFER HEIGHT */ 590 /* The y position and height are used to determine the actual */ 591 /* placement of the color key region. The region will either be */ 592 /* the sum of the even and odd fields (for interlaced addressing */ 593 /* or flicker filtering) or it will be the union of the two (for */ 594 /* line doubling). We must also adjust the region such that the */ 595 /* origin (0, 0) is centered on the beginning of graphics data. */ 596 /* This is only a problem if video is being displayed over the */ 597 /* overscan area. */ 598 599 if ((READ_REG32(DC3_GENLK_CTL) & DC3_GC_FLICKER_FILTER_ENABLE) || 600 (irq_ctl & DC3_IRQFILT_INTL_ADDR)) { 601 y <<= 1; 602 height += height_even; 603 adjust = border_y + border_y_even; 604 } 605 else { 606 adjust = border_y; 607 if (height_even > height) 608 height = height_even; 609 } 610 if (video_window->flags & DF_POSFLAG_INCLUDEBORDER) { 611 if (y > adjust) { 612 y -= adjust; 613 adjust = 0; 614 } 615 else { 616 adjust -= y; 617 if (height > adjust) 618 height -= adjust; 619 else 620 height = 0; 621 } 622 } 623 624 } 625 else { 626 y = y_copy; 627 628 height = height_copy; 629 if ((y + height) > vactive) 630 height = vactive - y; 631 632 ystart = y + vtotal - vsyncend + 1; 633 if (video_window->flags & DF_POSFLAG_INCLUDEBORDER) 634 ystart -= border_y; 635 636 yend = ystart + height; 637 ypos = (yend << 16) | ystart; 638 ypos_even = 0; 639 } 640 641 /* HORIZONTAL POSITION */ 642 /* The horizontal values are identical for the even and odd field. */ 643 644 width = width_copy; 645 xstart = x_copy + htotal - hsyncend - 14; 646 if (video_window->flags & DF_POSFLAG_INCLUDEBORDER) 647 xstart -= border_x; 648 649 /* RIGHT CLIPPING */ 650 651 if ((x_copy + width) > hactive) 652 width = hactive - x_copy; 653 654 xend = xstart + width; 655 656 /* 657 * CALCULATE LEFT CLIPPING PARAMETER 658 * The value passed in can be interpreted as destination pixels, in 659 * which case the video scale is factored in, or as source pixels, in 660 * which case the value is written directly. Also, the display filter's 661 * initial read address value is only programmable on 4-pixel increments. 662 * However, we can achieve an arbitrary left clip by adjusting the 663 * xstart value, as there is a 14-clock delay in which to play. Also, 664 * according to the designers, 4:2:0 and 4:2:2 behave identically when 665 * setting the initial read address. The addition of scaling further 666 * complicates the algorithm. When setting the initial read address, it 667 * is in terms of source pixels, while adjusting the xstart value is in 668 * destination pixels We may thus not be able to achieve a perfect 669 * clipping fit for scaled video. We compensate by including two 670 * clipping parameters in our structure. This allows us the user 671 * additional control and it allows us to accurately convey to the user 672 * the state of clipping on the machine. 673 */ 674 675 initread = video_window->left_clip; 676 dst_clip = 0; 677 if (!(video_window->flags & DF_POSFLAG_DIRECTCLIP)) { 678 xscale = READ_VID32(DF_VIDEO_XSCALE) & 0xFFFFF; 679 initread = (initread * xscale) / 0x10000; 680 if (xscale) 681 dst_clip = ((initread & 3) * 0x10000) / xscale; 682 } 683 else 684 dst_clip = video_window->dst_clip; 685 686 /* 687 * LIMIT THE CLIP 688 * We technically have a 14 pixel window in which to play. However, 689 * taking the entire 14 pixels makes the video timing a little hairy... 690 * Also note that we cannot do this when performing panel centering, as 691 * the video would then exceed the mode size. 692 */ 693 694 if (dst_clip > 4) 695 dst_clip = 4; 696 if (READ_REG32(DC3_DISPLAY_CFG) & DC3_DCFG_DCEN) 697 dst_clip = 0; 698 699 xstart -= dst_clip; 700 701 vcfg = READ_VID32(DF_VIDEO_CONFIG); 702 vcfg &= ~DF_VCFG_INIT_READ_MASK; 703 vcfg |= (initread >> 2) << 16; 704 705 /* SET COLOR KEY REGION */ 706 /* We are assuming that color keying will never be desired outside */ 707 /* of the video region. We adjust the color key region for graphics */ 708 /* scaling. */ 709 710 gfxscale = READ_REG32(DC3_GFX_SCALE); 711 712 ckey_x = ((x_copy * (gfxscale & 0xFFFF)) / 0x4000) | 713 ((((x_copy + width) * (gfxscale & 0xFFFF)) / 0x4000) << 16); 714 ckey_y = ((y * (gfxscale >> 16)) / 0x4000) | 715 ((((y + height) * (gfxscale >> 16)) / 0x4000) << 16); 716 717 /* WRITE ALL PARAMETERS AT ONCE */ 718 719 WRITE_REG32(DC3_UNLOCK, DC3_UNLOCK_VALUE); 720 WRITE_REG32(DC3_CLR_KEY_X, ckey_x); 721 WRITE_REG32(DC3_CLR_KEY_Y, ckey_y); 722 WRITE_VID32(DF_VIDEO_X_POS, (xend << 16) | xstart); 723 WRITE_VID32(DF_VIDEO_Y_POS, ypos); 724 WRITE_VID32(DF_VID_YPOS_EVEN, ypos_even); 725 WRITE_VID32(DF_VIDEO_CONFIG, vcfg); 726 WRITE_REG32(DC3_UNLOCK, unlock); 727 728 return CIM_STATUS_OK; 729} 730 731/*--------------------------------------------------------------------------- 732 * df_set_video_filter_coefficients 733 * 734 * This routine sets the horizontal and vertical filter coefficients for video 735 * scaling. These coefficients are used for upscaling and downscaling video. 736 * If the phase256 parameter is 1, the coefficient arrays are used as single 737 * arrays of 256 phases for both vertical and horizontal scaling. If the 738 * phase256 parameter is clear, the coefficient arrays are used as two 739 * 128-phase arrays. The first 128 entries represent the phases for 740 * vertical scaling. The last 128 entries represent the phases for 741 * horizontal scaling. 742 *--------------------------------------------------------------------------*/ 743 744int 745df_set_video_filter_coefficients(long taps[][4], int phase256) 746{ 747 unsigned long scale, coeff0, coeff1; 748 unsigned long i; 749 long (*defaults)[2]; 750 751 /* SET PHASE COUNT AND CHOOSE COEFFICIENT ARRAY */ 752 753 scale = READ_VID32(DF_VIDEO_SCALER); 754 if (phase256) { 755 WRITE_VID32(DF_VIDEO_SCALER, (scale & ~DF_SCALE_128_PHASES)); 756 defaults = CimarronVideoFilter256; 757 } 758 else { 759 WRITE_VID32(DF_VIDEO_SCALER, (scale | DF_SCALE_128_PHASES)); 760 defaults = CimarronVideoFilter128; 761 } 762 763 /* PROGRAM COEFFICIENTS */ 764 765 for (i = 0; i < 256; i++) { 766 if (!taps) { 767 coeff0 = defaults[i][0]; 768 coeff1 = defaults[i][1]; 769 } 770 else { 771 if (taps[i][1] < 0) 772 coeff0 = -taps[i][1] | 0x8000; 773 else 774 coeff0 = taps[i][1]; 775 776 coeff0 <<= 16; 777 778 if (taps[i][0] < 0) 779 coeff0 |= -taps[i][0] | 0x8000; 780 else 781 coeff0 |= taps[i][0]; 782 783 if (taps[i][3] < 0) 784 coeff1 = -taps[i][3] | 0x8000; 785 else 786 coeff1 = taps[i][3]; 787 788 coeff1 <<= 16; 789 790 if (taps[i][2] < 0) 791 coeff1 |= -taps[i][2] | 0x8000; 792 else 793 coeff1 |= taps[i][2]; 794 } 795 796 WRITE_VID32((DF_COEFFICIENT_BASE + (i << 3)), coeff0); 797 WRITE_VID32((DF_COEFFICIENT_BASE + (i << 3) + 4), coeff1); 798 } 799 800 return CIM_STATUS_OK; 801} 802 803/*--------------------------------------------------------------------------- 804 * df_set_video_enable 805 * 806 * This routine enables or disables the video overlay. 807 *--------------------------------------------------------------------------*/ 808 809int 810df_set_video_enable(int enable, unsigned long flags) 811{ 812 unsigned long vcfg, lock, gcfg; 813 unsigned long dcfg, vg_ckey, fifo = 0; 814 815 vcfg = READ_VID32(DF_VIDEO_CONFIG); 816 lock = READ_REG32(DC3_UNLOCK); 817 gcfg = READ_REG32(DC3_GENERAL_CFG); 818 819 /* SET VIDEO FIFO END WATERMARK */ 820 /* The video FIFO end watermark is set to 0 when video is disabled */ 821 /* to allow low priority transactions in the VG. Otherwise, the */ 822 /* priority will be forced high until the VG fills the video FIFO */ 823 /* by not fetching video. That could take a while... Note that */ 824 /* we set the end priority to be 4 greater than the start. We */ 825 /* assume that the start priority has been configured by a modeset. */ 826 827 dcfg = READ_REG32(DC3_DISPLAY_CFG) & ~DC3_DCFG_VFHPEL_MASK; 828 if (enable) { 829 fifo = ((dcfg >> 12) & 0x0000000F) + 4; 830 if (fifo > 0xF) 831 fifo = 0xF; 832 } 833 WRITE_REG32(DC3_UNLOCK, DC3_UNLOCK_VALUE); 834 WRITE_REG32(DC3_DISPLAY_CFG, dcfg | (fifo << 16)); 835 836 /* ENABLE OR DISABLE VIDEO */ 837 /* The mechanism to fetch video data is enabled first and */ 838 /* disabled last. */ 839 840 if (enable) { 841 WRITE_REG32(DC3_GENERAL_CFG, (gcfg | DC3_GCFG_VIDE)); 842 WRITE_VID32(DF_VIDEO_CONFIG, (vcfg | DF_VCFG_VID_EN)); 843 844 /* DISABLE COLOR KEYING IF REQUESTED BY THE USER */ 845 846 if (flags & DF_ENABLEFLAG_NOCOLORKEY) { 847 /* OVERRIDE THE MODE TO COLOR KEYING */ 848 849 dcfg = READ_VID32(DF_DISPLAY_CONFIG); 850 WRITE_VID32(DF_DISPLAY_CONFIG, (dcfg & ~DF_DCFG_VG_CK)); 851 852 /* DISABLE COLOR KEYING IN THE VG */ 853 854 vg_ckey = READ_REG32(DC3_COLOR_KEY); 855 WRITE_REG32(DC3_COLOR_KEY, (vg_ckey & ~DC3_CLR_KEY_ENABLE)); 856 } 857 else if (!(READ_VID32(DF_DISPLAY_CONFIG) & DF_DCFG_VG_CK)) { 858 /* OTHERWISE RE-ENABLE COLOR KEYING */ 859 860 vg_ckey = READ_REG32(DC3_COLOR_KEY); 861 WRITE_REG32(DC3_COLOR_KEY, (vg_ckey | DC3_CLR_KEY_ENABLE)); 862 } 863 } 864 else { 865 WRITE_VID32(DF_VIDEO_CONFIG, (vcfg & ~DF_VCFG_VID_EN)); 866 WRITE_REG32(DC3_GENERAL_CFG, (gcfg & ~DC3_GCFG_VIDE)); 867 868 /* DISABLE COLOR KEY WINDOW WHEN VIDEO IS INACTIVE */ 869 /* To mimic legacy functionality, we disable color keying */ 870 /* when the video window is not active. We will restore */ 871 /* the enable when video is re-enabled if the appropriate */ 872 /* bit is set in display config. */ 873 874 vg_ckey = READ_REG32(DC3_COLOR_KEY); 875 WRITE_REG32(DC3_COLOR_KEY, (vg_ckey & ~DC3_CLR_KEY_ENABLE)); 876 } 877 WRITE_REG32(DC3_UNLOCK, lock); 878 879 return CIM_STATUS_OK; 880} 881 882/*--------------------------------------------------------------------------- 883 * df_set_video_color_key 884 * 885 * This routine configures the video color/chroma key mechanism. 886 *--------------------------------------------------------------------------*/ 887 888int 889df_set_video_color_key(unsigned long key, unsigned long mask, int graphics) 890{ 891 unsigned long lock, vg_ckey, df_dcfg; 892 893 vg_ckey = READ_REG32(DC3_COLOR_KEY); 894 lock = READ_REG32(DC3_UNLOCK); 895 df_dcfg = READ_VID32(DF_DISPLAY_CONFIG); 896 897 WRITE_REG32(DC3_UNLOCK, DC3_UNLOCK_VALUE); 898 899 if (graphics) { 900 /* COLOR KEY - USE VG HARDWARE */ 901 /* Note that color key is never enabled unless a video window */ 902 /* is active. This is to match legacy behavior. */ 903 904 df_dcfg &= ~DF_DCFG_VG_CK; 905 vg_ckey = (vg_ckey & 0xFF000000) | (key & 0xFFFFFF); 906 if (READ_VID32(DF_VIDEO_CONFIG) & DF_VCFG_VID_EN) 907 vg_ckey |= DC3_CLR_KEY_ENABLE; 908 else 909 vg_ckey &= ~DC3_CLR_KEY_ENABLE; 910 911 WRITE_VID32(DF_DISPLAY_CONFIG, df_dcfg); 912 WRITE_REG32(DC3_COLOR_KEY, vg_ckey); 913 WRITE_REG32(DC3_COLOR_MASK, (mask & 0xFFFFFF)); 914 } 915 else { 916 /* CHROMA KEY - USE DF HARDWARE */ 917 918 df_dcfg |= DF_DCFG_VG_CK; 919 vg_ckey &= ~DC3_CLR_KEY_ENABLE; 920 921 WRITE_REG32(DC3_COLOR_KEY, vg_ckey); 922 WRITE_VID32(DF_DISPLAY_CONFIG, df_dcfg); 923 WRITE_VID32(DF_VIDEO_COLOR_KEY, (key & 0xFFFFFF)); 924 WRITE_VID32(DF_VIDEO_COLOR_MASK, (mask & 0xFFFFFF)); 925 } 926 927 WRITE_REG32(DC3_UNLOCK, lock); 928 929 return CIM_STATUS_OK; 930} 931 932/*--------------------------------------------------------------------------- 933 * df_set_video_palette 934 * 935 * This routine loads the video hardware palette. If a NULL pointer is 936 * specified, the palette is bypassed. 937 *-------------------------------------------------------------------------*/ 938 939int 940df_set_video_palette(unsigned long *palette) 941{ 942 unsigned long i, entry; 943 unsigned long misc, dcfg; 944 945 /* LOAD GEODE LX VIDEO PALETTE */ 946 947 WRITE_VID32(DF_PALETTE_ADDRESS, 0); 948 for (i = 0; i < 256; i++) { 949 if (palette) 950 entry = palette[i]; 951 else 952 entry = i | (i << 8) | (i << 16); 953 WRITE_VID32(DF_PALETTE_DATA, entry); 954 } 955 956 /* ENABLE THE VIDEO PALETTE */ 957 /* Ensure that the video palette has an effect by routing video data */ 958 /* through the palette RAM and clearing the 'Bypass Both' bit. */ 959 960 dcfg = READ_VID32(DF_DISPLAY_CONFIG); 961 misc = READ_VID32(DF_VID_MISC); 962 963 dcfg |= DF_DCFG_GV_PAL_BYP; 964 misc &= ~DF_GAMMA_BYPASS_BOTH; 965 966 WRITE_VID32(DF_DISPLAY_CONFIG, dcfg); 967 WRITE_VID32(DF_VID_MISC, misc); 968 969 return CIM_STATUS_OK; 970} 971 972/*--------------------------------------------------------------------------- 973 * df_set_video_palette_entry 974 * 975 * This routine loads a single entry of the video hardware palette. 976 *--------------------------------------------------------------------------*/ 977 978int 979df_set_video_palette_entry(unsigned long index, unsigned long palette) 980{ 981 unsigned long misc, dcfg; 982 983 if (index > 0xFF) 984 return CIM_STATUS_INVALIDPARAMS; 985 986 /* SET A SINGLE ENTRY */ 987 988 WRITE_VID32(DF_PALETTE_ADDRESS, index); 989 WRITE_VID32(DF_PALETTE_DATA, palette); 990 991 /* ENABLE THE VIDEO PALETTE */ 992 /* Ensure that the video palette has an effect by routing video data */ 993 /* through the palette RAM and clearing the 'Bypass Both' bit. */ 994 995 dcfg = READ_VID32(DF_DISPLAY_CONFIG); 996 misc = READ_VID32(DF_VID_MISC); 997 998 /* Ensure that the Graphic data passes through the Gamma 999 * Correction RAM 1000 * 1001 * XXX is this a bug? perhaps it should be setting the bit so that video 1002 * data is routed, according to the description above. 1003 * it also mismatches df_set_video_palette(). 1004 */ 1005 dcfg &= ~DF_DCFG_GV_PAL_BYP; 1006 1007 /* Unset the "bypass both" bit to make sure the above selection (gfx/video 1008 * data through gamma correction RAM) takes effect. 1009 */ 1010 misc &= ~DF_GAMMA_BYPASS_BOTH; 1011 1012 WRITE_VID32(DF_DISPLAY_CONFIG, dcfg); 1013 WRITE_VID32(DF_VID_MISC, misc); 1014 1015 return CIM_STATUS_OK; 1016} 1017 1018/*--------------------------------------------------------------------------- 1019 * df_configure_video_cursor_color_key 1020 * 1021 * This routine configures the hardware video cursor color key mechanism. 1022 *--------------------------------------------------------------------------*/ 1023 1024int 1025df_configure_video_cursor_color_key(DF_VIDEO_CURSOR_PARAMS * cursor_color_key) 1026{ 1027 unsigned long key; 1028 1029 if (cursor_color_key->select_color2 >= 24) 1030 return CIM_STATUS_INVALIDPARAMS; 1031 1032 key = READ_VID32(DF_CURSOR_COLOR_KEY) & DF_CURSOR_COLOR_KEY_ENABLE; 1033 key = 1034 key | (cursor_color_key->key & 0xFFFFFF) | (cursor_color_key-> 1035 select_color2 << 24); 1036 1037 WRITE_VID32(DF_CURSOR_COLOR_KEY, key); 1038 WRITE_VID32(DF_CURSOR_COLOR_MASK, (cursor_color_key->mask & 0xFFFFFF)); 1039 WRITE_VID32(DF_CURSOR_COLOR_1, (cursor_color_key->color1 & 0xFFFFFF)); 1040 WRITE_VID32(DF_CURSOR_COLOR_2, (cursor_color_key->color2 & 0xFFFFFF)); 1041 1042 return CIM_STATUS_OK; 1043} 1044 1045/*--------------------------------------------------------------------------- 1046 * df_set_video_cursor_color_key_enable 1047 * 1048 * This routine enables or disables the video cursor color key. 1049 *--------------------------------------------------------------------------*/ 1050 1051int 1052df_set_video_cursor_color_key_enable(int enable) 1053{ 1054 unsigned long temp = READ_VID32(DF_CURSOR_COLOR_KEY); 1055 1056 if (enable) 1057 temp |= DF_CURSOR_COLOR_KEY_ENABLE; 1058 else 1059 temp &= ~DF_CURSOR_COLOR_KEY_ENABLE; 1060 1061 WRITE_VID32(DF_CURSOR_COLOR_KEY, temp); 1062 1063 return CIM_STATUS_OK; 1064} 1065 1066/*--------------------------------------------------------------------------- 1067 * df_configure_alpha_window 1068 * 1069 * This routine configures one of the three hardware alpha regions. 1070 *--------------------------------------------------------------------------*/ 1071 1072int 1073df_configure_alpha_window(int window, DF_ALPHA_REGION_PARAMS * alpha_data) 1074{ 1075 unsigned long vsyncend_even, vtotal_even, vactive_even; 1076 unsigned long hsyncend, htotal, hactive; 1077 unsigned long vsyncend, vtotal, vactive; 1078 unsigned long alpha_ctl, pos; 1079 unsigned long hadjust, vadjust; 1080 unsigned long y, height; 1081 unsigned long xstart, xend; 1082 unsigned long ystart, yend; 1083 unsigned long x_copy, width_copy; 1084 unsigned long y_copy, height_copy; 1085 unsigned long scale, src, misc; 1086 unsigned long gfxscale, fbactive; 1087 unsigned long color; 1088 1089 if (window > 2) 1090 return CIM_STATUS_INVALIDPARAMS; 1091 1092 hsyncend = ((READ_REG32(DC3_H_SYNC_TIMING) >> 16) & 0xFFF) + 1; 1093 vsyncend = ((READ_REG32(DC3_V_SYNC_TIMING) >> 16) & 0xFFF) + 1; 1094 htotal = ((READ_REG32(DC3_H_ACTIVE_TIMING) >> 16) & 0xFFF) + 1; 1095 vtotal = ((READ_REG32(DC3_V_ACTIVE_TIMING) >> 16) & 0xFFF) + 1; 1096 hactive = (READ_REG32(DC3_H_ACTIVE_TIMING) & 0xFFF) + 1; 1097 vactive = (READ_REG32(DC3_V_ACTIVE_TIMING) & 0xFFF) + 1; 1098 1099 /* APPLY THE GRAPHICS SCALE */ 1100 1101 width_copy = alpha_data->width; 1102 height_copy = alpha_data->height; 1103 x_copy = alpha_data->x; 1104 y_copy = alpha_data->y; 1105 1106 misc = READ_VID32(DF_VID_MISC); 1107 if (misc & DF_USER_IMPLICIT_SCALING) { 1108 gfxscale = READ_REG32(DC3_GFX_SCALE); 1109 fbactive = READ_REG32(DC3_FB_ACTIVE); 1110 1111 /* REVERSE ENGINEER THE SCALE FACTOR */ 1112 1113 scale = gfxscale & 0xFFFF; 1114 src = (fbactive >> 16) + 1; 1115 if (scale != 0x4000) { 1116 width_copy = width_copy * (((0x4000 * src) / scale) + 1); 1117 width_copy /= src; 1118 x_copy = x_copy * (((0x4000 * src) / scale) + 1); 1119 x_copy /= src; 1120 } 1121 1122 scale = gfxscale >> 16; 1123 src = (fbactive & 0xFFFF) + 1; 1124 if (scale != 0x4000) { 1125 height_copy = height_copy * (((0x4000 * src) / scale) + 1); 1126 height_copy /= src; 1127 y_copy = y_copy * (((0x4000 * src) / scale) + 1); 1128 y_copy /= src; 1129 } 1130 } 1131 1132 /* SET PRIORITY */ 1133 /* Priority is the only alpha parameter that is not in a register that */ 1134 /* can be indexed based on the alpha window number. */ 1135 1136 pos = 16 + (window << 1); 1137 alpha_ctl = READ_VID32(DF_VID_ALPHA_CONTROL) & ~(3L << pos); 1138 alpha_ctl |= (alpha_data->priority & 3) << pos; 1139 WRITE_VID32(DF_VID_ALPHA_CONTROL, alpha_ctl); 1140 1141 /* HANDLE INTERLACED MODES */ 1142 1143 if (READ_REG32(DC3_IRQ_FILT_CTL) & DC3_IRQFILT_INTL_EN) { 1144 vsyncend_even = ((READ_REG32(DC3_V_SYNC_EVEN) >> 16) & 0xFFF) + 1; 1145 vtotal_even = ((READ_REG32(DC3_V_ACTIVE_EVEN) >> 16) & 0xFFF) + 1; 1146 vactive_even = (READ_REG32(DC3_V_ACTIVE_EVEN) & 0xFFF) + 1; 1147 1148 y = y_copy >> 1; 1149 1150 /* SET Y POSITION FOR ODD FIELD */ 1151 1152 height = (height_copy + 1) >> 1; 1153 vadjust = vtotal_even - vsyncend_even + 1; 1154 1155 ystart = y + vadjust; 1156 yend = y + vadjust + height; 1157 1158 if (yend > (vactive + vadjust)) 1159 yend = vactive + vadjust; 1160 1161 WRITE_VID32((DF_ALPHA_YPOS_1 + (window << 5)), (ystart | (yend << 16))); 1162 1163 /* SET Y POSITION FOR EVEN FIELD */ 1164 1165 height = height_copy >> 1; 1166 vadjust = vtotal - vsyncend + 1; 1167 1168 ystart = y + vadjust; 1169 yend = y + vadjust + height; 1170 1171 if (yend > (vactive_even + vadjust)) 1172 yend = vactive_even + vadjust; 1173 1174 WRITE_VID32((DF_VID_ALPHA_Y_EVEN_1 + (window << 3)), 1175 (ystart | (yend << 16))); 1176 } 1177 else { 1178 y = y_copy; 1179 height = height_copy; 1180 vadjust = vtotal - vsyncend + 1; 1181 1182 ystart = y + vadjust; 1183 yend = y + vadjust + height; 1184 1185 if (yend > (vactive + vadjust)) 1186 yend = vactive + vadjust; 1187 1188 WRITE_VID32((DF_ALPHA_YPOS_1 + (window << 5)), (ystart | (yend << 16))); 1189 } 1190 1191 /* SET ALPHA X POSITION */ 1192 /* The x position is the same for both the odd and even fields. */ 1193 1194 hadjust = htotal - hsyncend - 2; 1195 1196 xstart = x_copy + hadjust; 1197 xend = x_copy + hadjust + width_copy; 1198 1199 if (xend > (hactive + hadjust)) 1200 xend = hactive + hadjust; 1201 1202 WRITE_VID32((DF_ALPHA_XPOS_1 + (window << 5)), (xstart | (xend << 16))); 1203 1204 /* SET COLOR REGISTER */ 1205 1206 color = alpha_data->color & 0xFFFFFF; 1207 if (alpha_data->flags & DF_ALPHAFLAG_COLORENABLED) 1208 color |= DF_ALPHA_COLOR_ENABLE; 1209 1210 WRITE_VID32((DF_ALPHA_COLOR_1 + (window << 5)), color); 1211 1212 /* SET ALPHA VALUE, DELTA AND PER PIXEL */ 1213 1214 alpha_ctl = READ_VID32(DF_ALPHA_CONTROL_1 + (window << 5)) & 1215 DF_ACTRL_WIN_ENABLE; 1216 alpha_ctl |= (alpha_data->alpha_value & 0xFF) | DF_ACTRL_LOAD_ALPHA | 1217 (((unsigned long) alpha_data->delta & 0xFF) << 8); 1218 if (alpha_data->flags & DF_ALPHAFLAG_PERPIXELENABLED) 1219 alpha_ctl |= DF_ACTRL_PERPIXEL_EN; 1220 1221 WRITE_VID32((DF_ALPHA_CONTROL_1 + (window << 5)), alpha_ctl); 1222 1223 return CIM_STATUS_OK; 1224} 1225 1226/*--------------------------------------------------------------------------- 1227 * df_set_alpha_window_enable 1228 * 1229 * This routine enables or disables one of the three hardware alpha regions. 1230 *--------------------------------------------------------------------------*/ 1231 1232int 1233df_set_alpha_window_enable(int window, int enable) 1234{ 1235 unsigned long alpha_ctl; 1236 1237 if (window > 2) 1238 return CIM_STATUS_INVALIDPARAMS; 1239 1240 alpha_ctl = READ_VID32(DF_ALPHA_CONTROL_1 + (window << 5)); 1241 if (enable) 1242 alpha_ctl |= DF_ACTRL_WIN_ENABLE; 1243 else 1244 alpha_ctl &= ~DF_ACTRL_WIN_ENABLE; 1245 WRITE_VID32((DF_ALPHA_CONTROL_1 + (window << 5)), alpha_ctl); 1246 1247 return CIM_STATUS_OK; 1248} 1249 1250/*--------------------------------------------------------------------------- 1251 * df_set_no_ck_outside_alpha 1252 * 1253 * This function affects how color/chroma keying is performed inside the video 1254 * window. 1255 * 1256 * If enable is 1, color/chroma key comparison is performed only inside 1257 * the enabled alpha windows. Outside the enabled alpha windows, video 1258 * is displayed if color keying is enabled, or graphics is displayed if 1259 * chroma keying is enabled. 1260 * If enable is 0, color/chroma key comparison is performed inside the 1261 * entire video window. 1262 *--------------------------------------------------------------------------*/ 1263 1264int 1265df_set_no_ck_outside_alpha(int enable) 1266{ 1267 unsigned long value; 1268 1269 value = READ_VID32(DF_VID_ALPHA_CONTROL); 1270 if (enable) 1271 value |= DF_NO_CK_OUTSIDE_ALPHA; 1272 else 1273 value &= ~DF_NO_CK_OUTSIDE_ALPHA; 1274 WRITE_VID32(DF_VID_ALPHA_CONTROL, value); 1275 1276 return CIM_STATUS_OK; 1277} 1278 1279/*--------------------------------------------------------------------------- 1280 * df_set_video_request 1281 * 1282 * This routine sets the horizontal (pixel) and vertical (line) video request 1283 * values. 1284 *--------------------------------------------------------------------------*/ 1285 1286int 1287df_set_video_request(unsigned long x, unsigned long y) 1288{ 1289 unsigned long htotal, hsyncend; 1290 unsigned long vtotal, vsyncend; 1291 1292 hsyncend = ((READ_REG32(DC3_H_SYNC_TIMING) >> 16) & 0xFFF) + 1; 1293 vsyncend = ((READ_REG32(DC3_V_SYNC_TIMING) >> 16) & 0xFFF) + 1; 1294 htotal = ((READ_REG32(DC3_H_ACTIVE_TIMING) >> 16) & 0xFFF) + 1; 1295 vtotal = ((READ_REG32(DC3_V_ACTIVE_TIMING) >> 16) & 0xFFF) + 1; 1296 1297 /* SET DISPLAY FILTER VIDEO REQUEST */ 1298 1299 x += htotal - hsyncend - 2; 1300 y += vtotal - vsyncend + 1; 1301 1302 if (x >= 0x1000 || y >= 0x800) 1303 return CIM_STATUS_INVALIDPARAMS; 1304 1305 WRITE_VID32(DF_VIDEO_REQUEST, (y | (x << 16))); 1306 return CIM_STATUS_OK; 1307} 1308 1309/*--------------------------------------------------------------------------- 1310 * df_set_output_color_space 1311 * 1312 * This routine sets the color space used when combining graphics and video. 1313 *--------------------------------------------------------------------------*/ 1314 1315int 1316df_set_output_color_space(int color_space) 1317{ 1318 unsigned long alpha_ctl; 1319 1320 alpha_ctl = READ_VID32(DF_VID_ALPHA_CONTROL); 1321 1322 alpha_ctl &= ~(DF_CSC_GRAPHICS_RGB_TO_YUV | DF_CSC_VIDEO_YUV_TO_RGB | 1323 DF_HD_GRAPHICS | DF_YUV_CSC_EN | DF_ALPHA_DRGB); 1324 1325 /* OUTPUT IS RGB */ 1326 /* Enable YUV->RGB CSC if necessary and enable alpha output if */ 1327 /* requested. */ 1328 1329 if (color_space == DF_OUTPUT_RGB || color_space == DF_OUTPUT_ARGB) { 1330 if (!(alpha_ctl & DF_VIDEO_INPUT_IS_RGB)) 1331 alpha_ctl |= DF_CSC_VIDEO_YUV_TO_RGB; 1332 1333 if (color_space == DF_OUTPUT_ARGB) 1334 alpha_ctl |= DF_ALPHA_DRGB; 1335 } 1336 1337 /* OUTPUT IS YUV */ 1338 /* Enable YUV->YUV CSC if necessary and enable RGB->YUV CSC. */ 1339 1340 else if (color_space == DF_OUTPUT_SDTV || color_space == DF_OUTPUT_HDTV) { 1341 alpha_ctl |= DF_CSC_GRAPHICS_RGB_TO_YUV; 1342 1343 if (((alpha_ctl & DF_HD_VIDEO) && color_space == DF_OUTPUT_SDTV) || 1344 (!(alpha_ctl & DF_HD_VIDEO) && color_space == DF_OUTPUT_HDTV)) { 1345 alpha_ctl |= DF_YUV_CSC_EN; 1346 } 1347 1348 if (color_space == DF_OUTPUT_HDTV) 1349 alpha_ctl |= DF_HD_GRAPHICS; 1350 } 1351 else 1352 return CIM_STATUS_INVALIDPARAMS; 1353 1354 WRITE_VID32(DF_VID_ALPHA_CONTROL, alpha_ctl); 1355 1356 return CIM_STATUS_OK; 1357} 1358 1359/*--------------------------------------------------------------------------- 1360 * df_set_output_path 1361 * 1362 * This routine changes the current output path in the display filter. 1363 *--------------------------------------------------------------------------*/ 1364 1365int 1366df_set_output_path(int format) 1367{ 1368 unsigned long panel_tim2, panel_pm; 1369 unsigned long output = 0; 1370 Q_WORD msr_value; 1371 1372 msr_read64(MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_CONFIG, &msr_value); 1373 msr_value.low &= ~(DF_SIMULTANEOUS_CRT_FP | DF_CONFIG_OUTPUT_MASK); 1374 panel_tim2 = READ_VID32(DF_VIDEO_PANEL_TIM2); 1375 panel_pm = READ_VID32(DF_POWER_MANAGEMENT); 1376 1377 if (format == DF_DISPLAY_CRT) { 1378 /* SiBZ #4188 */ 1379 /* When CRT output is selected, the DF drives the DISP_EN signal */ 1380 /* with the CRT display enable. As a consequence, systems that */ 1381 /* wire the DISP_EN signal to the TFT backlight control will not */ 1382 /* be able to set CRT-only output without leaving the backlight */ 1383 /* enabled. To workaround this issue, we are setting simultaneous */ 1384 /* TFT/CRT and disabling the TFT logic. The only caveat to this */ 1385 /* is that some TFT pins are shared with VIP 601 pins. VIP 601 */ 1386 /* will thus not work when in this pseudo-CRT mode. To address */ 1387 /* THAT issue, normal CRT mode sets (in cim_vg.c) will set CRT */ 1388 /* as the DF output format. This will allow VIP 601 on CRT-only */ 1389 /* systems without a TFT attached. */ 1390 1391 panel_pm &= ~DF_PM_PANEL_ON; 1392 panel_tim2 |= DF_PMTIM2_TFT_PASSHTHROUGH; 1393 output = DF_OUTPUT_PANEL | DF_SIMULTANEOUS_CRT_FP; 1394 } 1395 else if (format == DF_DISPLAY_FP || format == DF_DISPLAY_CRT_FP) { 1396 panel_pm |= DF_PM_PANEL_ON; 1397 panel_tim2 &= ~DF_PMTIM2_TFT_PASSHTHROUGH; 1398 1399 if (format == DF_DISPLAY_FP) 1400 output = DF_OUTPUT_PANEL; 1401 else if (format == DF_DISPLAY_CRT_FP) 1402 output = DF_OUTPUT_PANEL | DF_SIMULTANEOUS_CRT_FP; 1403 } 1404 else { 1405 switch (format) { 1406 case DF_DISPLAY_VOP: 1407 output = DF_OUTPUT_VOP; 1408 break; 1409 case DF_DISPLAY_DRGB: 1410 output = DF_OUTPUT_DRGB; 1411 break; 1412 case DF_DISPLAY_CRT_DRGB: 1413 output = DF_OUTPUT_DRGB | DF_SIMULTANEOUS_CRT_FP; 1414 break; 1415 default: 1416 return CIM_STATUS_INVALIDPARAMS; 1417 } 1418 } 1419 msr_value.low |= output; 1420 msr_write64(MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_CONFIG, &msr_value); 1421 WRITE_VID32(DF_VIDEO_PANEL_TIM2, panel_tim2); 1422 WRITE_VID32(DF_POWER_MANAGEMENT, panel_pm); 1423 1424 return CIM_STATUS_OK; 1425} 1426 1427/*--------------------------------------------------------------------------- 1428 * df_test_video_flip_status 1429 * 1430 * This routine tests if a new video offset has been latched. 1431 *--------------------------------------------------------------------------*/ 1432 1433unsigned long 1434df_test_video_flip_status(void) 1435{ 1436 return (READ_REG32(DC3_LINE_CNT_STATUS) & DC3_LNCNT_VFLIP); 1437} 1438 1439/*--------------------------------------------------------------------------- 1440 * df_save_state 1441 * 1442 * This routine saves all persistent DF state information. 1443 *--------------------------------------------------------------------------*/ 1444 1445int 1446df_save_state(DF_SAVE_RESTORE * df_state) 1447{ 1448 unsigned long i; 1449 1450 /* READ ALL DF REGISTERS */ 1451 1452 df_state->vcfg = READ_VID32(DF_VIDEO_CONFIG); 1453 df_state->dcfg = READ_VID32(DF_DISPLAY_CONFIG); 1454 df_state->video_x = READ_VID32(DF_VIDEO_X_POS); 1455 df_state->video_y = READ_VID32(DF_VIDEO_Y_POS); 1456 df_state->video_scaler = READ_VID32(DF_VIDEO_SCALER); 1457 df_state->video_color_key = READ_VID32(DF_VIDEO_COLOR_KEY); 1458 df_state->video_color_mask = READ_VID32(DF_VIDEO_COLOR_MASK); 1459 df_state->sat_limit = READ_VID32(DF_SATURATION_LIMIT); 1460 df_state->vid_misc = READ_VID32(DF_VID_MISC); 1461 df_state->video_yscale = READ_VID32(DF_VIDEO_YSCALE); 1462 df_state->video_xscale = READ_VID32(DF_VIDEO_XSCALE); 1463 df_state->vid_alpha_control = READ_VID32(DF_VID_ALPHA_CONTROL); 1464 df_state->cursor_key = READ_VID32(DF_CURSOR_COLOR_KEY); 1465 df_state->cursor_mask = READ_VID32(DF_CURSOR_COLOR_MASK); 1466 df_state->cursor_color1 = READ_VID32(DF_CURSOR_COLOR_1); 1467 df_state->cursor_color2 = READ_VID32(DF_CURSOR_COLOR_2); 1468 df_state->alpha_xpos1 = READ_VID32(DF_ALPHA_XPOS_1); 1469 df_state->alpha_ypos1 = READ_VID32(DF_ALPHA_YPOS_1); 1470 df_state->alpha_color1 = READ_VID32(DF_ALPHA_COLOR_1); 1471 df_state->alpha_control1 = READ_VID32(DF_ALPHA_CONTROL_1); 1472 df_state->alpha_xpos2 = READ_VID32(DF_ALPHA_XPOS_2); 1473 df_state->alpha_ypos2 = READ_VID32(DF_ALPHA_YPOS_2); 1474 df_state->alpha_color2 = READ_VID32(DF_ALPHA_COLOR_2); 1475 df_state->alpha_control2 = READ_VID32(DF_ALPHA_CONTROL_2); 1476 df_state->alpha_xpos3 = READ_VID32(DF_ALPHA_XPOS_3); 1477 df_state->alpha_ypos3 = READ_VID32(DF_ALPHA_YPOS_3); 1478 df_state->alpha_color3 = READ_VID32(DF_ALPHA_COLOR_3); 1479 df_state->alpha_control3 = READ_VID32(DF_ALPHA_CONTROL_3); 1480 df_state->vid_request = READ_VID32(DF_VIDEO_REQUEST); 1481 df_state->vid_ypos_even = READ_VID32(DF_VID_YPOS_EVEN); 1482 df_state->alpha_ypos_even1 = READ_VID32(DF_VID_ALPHA_Y_EVEN_1); 1483 df_state->alpha_ypos_even2 = READ_VID32(DF_VID_ALPHA_Y_EVEN_2); 1484 df_state->alpha_ypos_even3 = READ_VID32(DF_VID_ALPHA_Y_EVEN_3); 1485 df_state->panel_tim1 = READ_VID32(DF_VIDEO_PANEL_TIM1); 1486 df_state->panel_tim2 = READ_VID32(DF_VIDEO_PANEL_TIM2); 1487 df_state->panel_pm = READ_VID32(DF_POWER_MANAGEMENT); 1488 df_state->panel_dither = READ_VID32(DF_DITHER_CONTROL); 1489 1490 /* READ DF PALETTE */ 1491 1492 WRITE_VID32(DF_PALETTE_ADDRESS, 0); 1493 for (i = 0; i < 256; i++) 1494 df_state->palette[i] = READ_VID32(DF_PALETTE_DATA); 1495 1496 /* READ FILTER COEFFICIENTS */ 1497 1498 for (i = 0; i < 512; i++) 1499 df_state->coefficients[i] = READ_VID32(DF_COEFFICIENT_BASE + (i << 2)); 1500 1501 /* READ ALL DF MSRS */ 1502 1503 msr_read64(MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_CAP, &(df_state->msr_cap)); 1504 msr_read64(MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_CONFIG, 1505 &(df_state->msr_config)); 1506 msr_read64(MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_SMI, &(df_state->msr_smi)); 1507 msr_read64(MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_ERROR, 1508 &(df_state->msr_error)); 1509 msr_read64(MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_PM, &(df_state->msr_pm)); 1510 msr_read64(MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_DIAG, 1511 &(df_state->msr_diag)); 1512 msr_read64(MSR_DEVICE_GEODELX_DF, DF_MBD_MSR_DIAG_DF, 1513 &(df_state->msr_df_diag)); 1514 msr_read64(MSR_DEVICE_GEODELX_DF, DF_MSR_PAD_SEL, &(df_state->msr_pad_sel)); 1515 1516 return CIM_STATUS_OK; 1517} 1518 1519/*--------------------------------------------------------------------------- 1520 * df_restore_state 1521 * 1522 * This routine restores all persistent DF state information. 1523 *--------------------------------------------------------------------------*/ 1524 1525int 1526df_restore_state(DF_SAVE_RESTORE * df_state) 1527{ 1528 unsigned long i; 1529 1530 /* CLEAR VCFG AND DCFG */ 1531 1532 WRITE_VID32(DF_VIDEO_CONFIG, 0); 1533 WRITE_VID32(DF_DISPLAY_CONFIG, 0); 1534 1535 /* RESTORE DF MSRS */ 1536 1537 msr_write64(MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_CAP, &(df_state->msr_cap)); 1538 msr_write64(MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_CONFIG, 1539 &(df_state->msr_config)); 1540 msr_write64(MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_SMI, &(df_state->msr_smi)); 1541 msr_write64(MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_ERROR, 1542 &(df_state->msr_error)); 1543 msr_write64(MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_PM, &(df_state->msr_pm)); 1544 msr_write64(MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_DIAG, 1545 &(df_state->msr_diag)); 1546 msr_write64(MSR_DEVICE_GEODELX_DF, DF_MBD_MSR_DIAG_DF, 1547 &(df_state->msr_df_diag)); 1548 msr_write64(MSR_DEVICE_GEODELX_DF, DF_MSR_PAD_SEL, 1549 &(df_state->msr_pad_sel)); 1550 1551 /* RESTORE ALL DF REGISTERS */ 1552 1553 WRITE_VID32(DF_VIDEO_X_POS, df_state->video_x); 1554 WRITE_VID32(DF_VIDEO_Y_POS, df_state->video_y); 1555 WRITE_VID32(DF_VIDEO_SCALER, df_state->video_scaler); 1556 WRITE_VID32(DF_VIDEO_COLOR_KEY, df_state->video_color_key); 1557 WRITE_VID32(DF_VIDEO_COLOR_MASK, df_state->video_color_mask); 1558 WRITE_VID32(DF_SATURATION_LIMIT, df_state->sat_limit); 1559 WRITE_VID32(DF_VID_MISC, df_state->vid_misc); 1560 WRITE_VID32(DF_VIDEO_YSCALE, df_state->video_yscale); 1561 WRITE_VID32(DF_VIDEO_XSCALE, df_state->video_xscale); 1562 WRITE_VID32(DF_VID_ALPHA_CONTROL, df_state->vid_alpha_control); 1563 WRITE_VID32(DF_CURSOR_COLOR_KEY, df_state->cursor_key); 1564 WRITE_VID32(DF_CURSOR_COLOR_MASK, df_state->cursor_mask); 1565 WRITE_VID32(DF_CURSOR_COLOR_1, df_state->cursor_color1); 1566 WRITE_VID32(DF_CURSOR_COLOR_2, df_state->cursor_color2); 1567 WRITE_VID32(DF_ALPHA_XPOS_1, df_state->alpha_xpos1); 1568 WRITE_VID32(DF_ALPHA_YPOS_1, df_state->alpha_ypos1); 1569 WRITE_VID32(DF_ALPHA_COLOR_1, df_state->alpha_color1); 1570 WRITE_VID32(DF_ALPHA_CONTROL_1, df_state->alpha_control1); 1571 WRITE_VID32(DF_ALPHA_XPOS_2, df_state->alpha_xpos2); 1572 WRITE_VID32(DF_ALPHA_YPOS_2, df_state->alpha_ypos2); 1573 WRITE_VID32(DF_ALPHA_COLOR_2, df_state->alpha_color2); 1574 WRITE_VID32(DF_ALPHA_CONTROL_2, df_state->alpha_control1); 1575 WRITE_VID32(DF_ALPHA_XPOS_3, df_state->alpha_xpos3); 1576 WRITE_VID32(DF_ALPHA_YPOS_3, df_state->alpha_ypos3); 1577 WRITE_VID32(DF_ALPHA_COLOR_3, df_state->alpha_color3); 1578 WRITE_VID32(DF_ALPHA_CONTROL_3, df_state->alpha_control3); 1579 WRITE_VID32(DF_VIDEO_REQUEST, df_state->vid_request); 1580 WRITE_VID32(DF_VID_YPOS_EVEN, df_state->vid_ypos_even); 1581 WRITE_VID32(DF_VID_ALPHA_Y_EVEN_1, df_state->alpha_ypos_even1); 1582 WRITE_VID32(DF_VID_ALPHA_Y_EVEN_2, df_state->alpha_ypos_even2); 1583 WRITE_VID32(DF_VID_ALPHA_Y_EVEN_3, df_state->alpha_ypos_even3); 1584 WRITE_VID32(DF_VIDEO_PANEL_TIM1, df_state->panel_tim1); 1585 WRITE_VID32(DF_VIDEO_PANEL_TIM2, df_state->panel_tim2); 1586 WRITE_VID32(DF_POWER_MANAGEMENT, df_state->panel_pm); 1587 WRITE_VID32(DF_DITHER_CONTROL, df_state->panel_dither); 1588 1589 /* RESTORE DF PALETTE */ 1590 1591 WRITE_VID32(DF_PALETTE_ADDRESS, 0); 1592 for (i = 0; i < 256; i++) 1593 WRITE_VID32(DF_PALETTE_DATA, df_state->palette[i]); 1594 1595 /* RESTORE FILTER COEFFICIENTS */ 1596 1597 for (i = 0; i < 512; i++) 1598 WRITE_VID32(DF_COEFFICIENT_BASE + (i << 2), df_state->coefficients[i]); 1599 1600 /* RESTORE DCFG AND VCFG */ 1601 1602 WRITE_VID32(DF_DISPLAY_CONFIG, df_state->dcfg); 1603 WRITE_VID32(DF_VIDEO_CONFIG, df_state->vcfg); 1604 1605 return CIM_STATUS_OK; 1606} 1607 1608/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1609 * CIMARRON DF READ ROUTINES 1610 * These routines are included for use in diagnostics or when debugging. They 1611 * can be optionally excluded from a project. 1612 *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 1613 1614#if CIMARRON_INCLUDE_DF_READ_ROUTINES 1615 1616/*--------------------------------------------------------------------------- 1617 * df_read_composite_crc 1618 * 1619 * This routine reads the CRC of the combination of graphics/video data. This 1620 * CRC checks data immediately before the CRT DACs. 1621 *--------------------------------------------------------------------------*/ 1622 1623unsigned long 1624df_read_composite_crc(int crc_source) 1625{ 1626 Q_WORD msr_value; 1627 unsigned long crc; 1628 unsigned long interlaced; 1629 unsigned long line, field; 1630 unsigned long timeout = 1000; 1631 1632 if (!(READ_REG32(DC3_DISPLAY_CFG) & DC3_DCFG_TGEN)) 1633 return 0xFFFFFFFF; 1634 1635 /* ENABLE 32-BIT CRCS */ 1636 1637 msr_read64(MSR_DEVICE_GEODELX_DF, DF_MBD_MSR_DIAG_DF, &msr_value); 1638 msr_value.low |= DF_DIAG_32BIT_CRC; 1639 msr_write64(MSR_DEVICE_GEODELX_DF, DF_MBD_MSR_DIAG_DF, &msr_value); 1640 1641 /* RESET THE CRC */ 1642 1643 WRITE_VID32(DF_VID_CRC, 0); 1644 1645 /* WAIT FOR THE RESET TO BE LATCHED */ 1646 1647 while ((READ_VID32(DF_VID_CRC32) != 0x00000001) && timeout) 1648 timeout--; 1649 1650 /* WAIT FOR THE CORRECT FIELD */ 1651 /* We use the VG line count and field indicator to determine when */ 1652 /* to kick off a CRC. */ 1653 1654 if (crc_source & DF_CRC_SOURCE_EVEN) 1655 field = 0; 1656 else 1657 field = DC3_LNCNT_EVEN_FIELD; 1658 1659 if ((interlaced = (READ_REG32(DC3_IRQ_FILT_CTL) & DC3_IRQFILT_INTL_EN))) { 1660 /* WAIT FOR THE BEGINNING OF THE FIELD (LINE 1-5) */ 1661 /* Note that we wait for the field to be odd when CRCing the even */ 1662 /* field and vice versa. This is because the CRC will not begin */ 1663 /* until the following field. */ 1664 1665 do { 1666 line = READ_REG32(DC3_LINE_CNT_STATUS); 1667 } while ((line & DC3_LNCNT_EVEN_FIELD) != field || 1668 ((line & DC3_LNCNT_V_LINE_CNT) >> 16) < 10 || 1669 ((line & DC3_LNCNT_V_LINE_CNT) >> 16) > 15); 1670 } 1671 else { 1672 /* NON-INTERLACED - EVEN FIELD CRCS ARE INVALID */ 1673 1674 if (crc_source & DF_CRC_SOURCE_EVEN) 1675 return 0xFFFFFFFF; 1676 } 1677 1678 /* ENABLE THE CRC */ 1679 1680 WRITE_VID32(DF_VID_CRC, 1); 1681 1682 /* WAIT FOR THE CRC TO BE COMPLETED */ 1683 1684 while (!(READ_VID32(DF_VID_CRC) & 4)); 1685 1686 crc = READ_VID32(DF_VID_CRC32); 1687 1688 return crc; 1689} 1690 1691/*--------------------------------------------------------------------------- 1692 * df_read_composite_window_crc 1693 * 1694 * This routine reads the CRC of a rectangular subsection of the combination 1695 * of graphics/video data. 1696 *--------------------------------------------------------------------------*/ 1697 1698unsigned long 1699df_read_composite_window_crc(unsigned long x, unsigned long y, 1700 unsigned long width, unsigned long height, 1701 int source) 1702{ 1703 Q_WORD msr_value; 1704 unsigned long interlaced; 1705 unsigned long line, field; 1706 unsigned long crc = 0; 1707 unsigned long hsyncend, htotal, hsyncstart; 1708 unsigned long vsyncend, vtotal, vsyncstart; 1709 unsigned long hblankstart, hactive; 1710 unsigned long vblankstart, vactive; 1711 1712 hsyncend = ((READ_REG32(DC3_H_SYNC_TIMING) >> 16) & 0xFFF) + 1; 1713 htotal = ((READ_REG32(DC3_H_ACTIVE_TIMING) >> 16) & 0xFFF) + 1; 1714 hsyncstart = (READ_REG32(DC3_H_SYNC_TIMING) & 0xFFF) + 1; 1715 hactive = (READ_REG32(DC3_H_ACTIVE_TIMING) & 0xFFF) + 1; 1716 hblankstart = (READ_REG32(DC3_H_BLANK_TIMING) & 0xFFF) + 1; 1717 if ((interlaced = (READ_REG32(DC3_IRQ_FILT_CTL) & DC3_IRQFILT_INTL_EN)) && 1718 !(source & DF_CRC_SOURCE_EVEN)) { 1719 vsyncend = ((READ_REG32(DC3_V_SYNC_EVEN) >> 16) & 0xFFF) + 1; 1720 vtotal = ((READ_REG32(DC3_V_ACTIVE_EVEN) >> 16) & 0xFFF) + 1; 1721 vsyncstart = (READ_REG32(DC3_V_SYNC_EVEN) & 0xFFF) + 1; 1722 vactive = (READ_REG32(DC3_V_ACTIVE_EVEN) & 0xFFF) + 1; 1723 vblankstart = (READ_REG32(DC3_V_BLANK_EVEN) & 0xFFF) + 1; 1724 } 1725 else { 1726 vsyncend = ((READ_REG32(DC3_V_SYNC_TIMING) >> 16) & 0xFFF) + 1; 1727 vtotal = ((READ_REG32(DC3_V_ACTIVE_TIMING) >> 16) & 0xFFF) + 1; 1728 vsyncstart = (READ_REG32(DC3_V_SYNC_TIMING) & 0xFFF) + 1; 1729 vactive = (READ_REG32(DC3_V_ACTIVE_TIMING) & 0xFFF) + 1; 1730 vblankstart = (READ_REG32(DC3_V_BLANK_TIMING) & 0xFFF) + 1; 1731 } 1732 1733 /* TIMINGS MUST BE ACTIVE */ 1734 1735 if (!(READ_REG32(DC3_DISPLAY_CFG) & DC3_DCFG_TGEN)) 1736 return 0xFFFFFFFF; 1737 1738 /* DISABLE GLCP ACTIONS */ 1739 1740 msr_value.low = 0; 1741 msr_value.high = 0; 1742 msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_DIAGCTL, &msr_value); 1743 1744 /* ENABLE HW CLOCK GATING AND SET GLCP CLOCK TO DOT CLOCK */ 1745 1746 msr_value.low = 5; 1747 msr_write64(MSR_DEVICE_GEODELX_GLCP, MSR_GEODELINK_PM, &msr_value); 1748 msr_value.low = 0; 1749 msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_DBGCLKCTL, &msr_value); 1750 msr_value.low = 3; 1751 msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_DBGCLKCTL, &msr_value); 1752 1753 /* USE H4 FUNCTION A FOR HSYNC AND H4 FUNCTION B FOR NOT HSYNC */ 1754 /* HSYNC is bit 30 for the DF */ 1755 1756 msr_value.high = 0x00000001; 1757 msr_value.low = 0xE0000FF0; 1758 msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_H0CTL + 4, &msr_value); 1759 1760 /* USE H3 FUNCTION A FOR VSYNC AND H3 FUNCTION B FOR NOT VSYNC */ 1761 /* VSYNC is bit 54 for VG and bit 29 for DF */ 1762 1763 msr_value.high = 0x00000000; 1764 msr_value.low = 0x001D55AA; 1765 msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_H0CTL + 3, &msr_value); 1766 1767 /* M4 (XSTATE = 00 AND VSYNC HIGH) */ 1768 /* Goto state 01 */ 1769 /* Note: VSync = H3A */ 1770 1771 msr_value.high = 0x00000001; 1772 msr_value.low = 0x000000A0; 1773 msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_SETM0CTL + 4, &msr_value); 1774 1775 /* N0 (XSTATE = 01 AND VSYNC LOW) */ 1776 /* Goto state 02 */ 1777 /* Note: VSync low = H3B */ 1778 1779 msr_value.high = 0x00040000; 1780 msr_value.low = 0x000000C0; 1781 msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_SETN0CTL, &msr_value); 1782 1783 /* M5 (XSTATE = 10 AND VSYNC HIGH) */ 1784 /* Goto state 11 */ 1785 1786 msr_value.high = 0x00000001; 1787 msr_value.low = 0x00000120; 1788 msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_SETM0CTL + 5, &msr_value); 1789 1790 /* N1 (XSTATE = 10 and HSYNC LOW) */ 1791 /* Increment H. Counter */ 1792 /* Note: HSync = H4 */ 1793 1794 msr_value.high = 0x00080000; 1795 msr_value.low = 0x00000120; 1796 msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_SETN0CTL + 1, &msr_value); 1797 1798 /* M0 (XSTATE = 10 and H. COUNTER == LIMIT) */ 1799 /* Clear H. Counter and increment V. Counter */ 1800 1801 msr_value.high = 0x00000000; 1802 msr_value.low = 0x00000122; 1803 msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_SETM0CTL, &msr_value); 1804 1805 /* N4 (XSTATE = 10 && CMP0 <= H. COUNTER <= CMP1 && CMP2 <= V. COUNTER 1806 * <= CMP3) 1807 * CRC into REGB 1808 */ 1809 1810 msr_value.high = 0x00000000; 1811 msr_value.low = 0x10C20120; 1812 msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_SETN0CTL + 4, &msr_value); 1813 1814 /* COMPARATOR 0 VALUE */ 1815 /* Value = xstart + (htotal - hsync_end) - 1 */ 1816 /* The value will be adjusted for a border if necessary */ 1817 1818 msr_value.low = x + htotal - hsyncend - 1; 1819 if (READ_REG32(DC3_DISPLAY_CFG) & DC3_DCFG_DCEN) 1820 msr_value.low -= hblankstart - hactive; 1821 msr_value.low--; 1822 msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_CMPVAL0, &msr_value); 1823 1824 /* COMPARATOR 1 VALUE */ 1825 /* Value = xstart + (htotal - hsync_end - 1) - 1 + width */ 1826 1827 msr_value.low += width - 1; 1828 msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_CMPVAL0 + 2, &msr_value); 1829 1830 /* COMPARATOR 2 VALUE */ 1831 /* Value = ystart + vtotal - vsyncend */ 1832 1833 msr_value.low = (y + vtotal - vsyncend) << 16; 1834 if (READ_REG32(DC3_DISPLAY_CFG) & DC3_DCFG_DCEN) 1835 msr_value.low -= (vblankstart - vactive) << 16; 1836 msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_CMPVAL0 + 4, &msr_value); 1837 1838 /* COMPARATOR 3 VALUE */ 1839 /* Value = ystart + vtotal - vsyncend + height - 1 */ 1840 1841 msr_value.low += (height - 1) << 16; 1842 msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_CMPVAL0 + 6, &msr_value); 1843 1844 /* COMPARATOR MASKS */ 1845 /* Comparators 0 and 1 refer to lower 16 bits of RegB */ 1846 1847 msr_value.low = 0x0000FFFF; 1848 msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_CMPMASK0, &msr_value); 1849 msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_CMPMASK0 + 2, &msr_value); 1850 1851 /* Comparators 2 and 3 refer to upper 16 bits of RegB */ 1852 1853 msr_value.low = 0xFFFF0000; 1854 msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_CMPMASK0 + 4, &msr_value); 1855 msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_CMPMASK0 + 6, &msr_value); 1856 1857 /* SET REGB MASK */ 1858 /* We set the mask such that all only 24 bits of data are CRCed */ 1859 1860 msr_value.low = 0x00FFFFFF; 1861 msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_REGBMASK, &msr_value); 1862 1863 /* SET REGA LIMITS */ 1864 /* Lower counter uses htotal - sync_time - 1. */ 1865 /* Upper counter is 0xFFFF to prevent rollover. */ 1866 1867 msr_value.low = 0xFFFF0000 | (htotal - (hsyncend - hsyncstart) - 1); 1868 msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_REGAVAL, &msr_value); 1869 1870 /* ACTIONS */ 1871 1872 /* STATE 00->01 (SET 4M) */ 1873 1874 msr_value.low = 0x000C0000; 1875 msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 14, &msr_value); 1876 1877 /* STATE 01->10 (SET 0N) */ 1878 1879 msr_value.low = 0x0000000A; 1880 msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 15, &msr_value); 1881 1882 /* STATE 10->11 (SET 5M) */ 1883 1884 msr_value.low = 0x00C00000; 1885 msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 16, &msr_value); 1886 1887 /* CLEAR REGA WHEN TRANSITIONING TO STATE 10 */ 1888 /* Do not clear RegB as the initial value must be 0x00000001 */ 1889 1890 msr_value.low = 0x0000000A; 1891 msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0, &msr_value); 1892 1893 /* REGISTER ACTION 1 */ 1894 /* CRC into RegB if cmp0 <= h.counter <= cmp1 && cmp2 <= v. counter < 1895 * cmp3 && 7 xstate = 10 8 1896 * Increment h.counter if xstate = 10 and HSync is low. 1897 */ 1898 1899 msr_value.low = 0x000A00A0; 1900 msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 1, &msr_value); 1901 1902 /* REGISTER ACTION 2 */ 1903 /* Increment V. Counter in REGA */ 1904 1905 msr_value.low = 0x0000000C; 1906 msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 2, &msr_value); 1907 1908 /* SET REGB TO 0x00000001 */ 1909 1910 msr_value.low = 0x00000001; 1911 msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_REGB, &msr_value); 1912 1913 /* SET XSTATE TO 0 */ 1914 1915 msr_value.low = 0x00000000; 1916 msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_XSTATE, &msr_value); 1917 1918 /* CLEAR ALL OTHER ACTIONS */ 1919 /* This prevents side-effects from previous accesses to the GLCP */ 1920 /* debug logic. */ 1921 1922 msr_value.low = 0x00000000; 1923 msr_value.high = 0x00000000; 1924 msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 3, &msr_value); 1925 msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 4, &msr_value); 1926 msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 5, &msr_value); 1927 msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 6, &msr_value); 1928 msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 7, &msr_value); 1929 msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 8, &msr_value); 1930 msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 9, &msr_value); 1931 msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 10, &msr_value); 1932 msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 11, &msr_value); 1933 msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 12, &msr_value); 1934 msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 13, &msr_value); 1935 msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 17, &msr_value); 1936 msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 18, &msr_value); 1937 msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 19, &msr_value); 1938 msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_ACTION0 + 20, &msr_value); 1939 1940 /* WAIT FOR THE CORRECT FIELD */ 1941 /* We use the VG line count and field indicator to determine when */ 1942 /* to kick off a CRC. */ 1943 1944 if (source & DF_CRC_SOURCE_EVEN) 1945 field = 0; 1946 else 1947 field = DC3_LNCNT_EVEN_FIELD; 1948 1949 if (interlaced) { 1950 /* WAIT FOR THE BEGINNING OF THE FIELD (LINE 1-5) */ 1951 /* Note that we wait for the field to be odd when CRCing the even */ 1952 /* field and vice versa. This is because the CRC will not begin */ 1953 /* until the following field. */ 1954 1955 do { 1956 line = READ_REG32(DC3_LINE_CNT_STATUS); 1957 } while ((line & DC3_LNCNT_EVEN_FIELD) != field || 1958 ((line & DC3_LNCNT_V_LINE_CNT) >> 16) < 1 || 1959 ((line & DC3_LNCNT_V_LINE_CNT) >> 16) > 5); 1960 } 1961 else { 1962 /* NON-INTERLACED - EVEN FIELD CRCS ARE INVALID */ 1963 1964 if (source & DF_CRC_SOURCE_EVEN) 1965 return 0xFFFFFFFF; 1966 } 1967 1968 /* CONFIGURE DISPLAY FILTER TO LOAD DATA ONTO LOWER 32-BITS */ 1969 1970 msr_value.high = 0; 1971 msr_value.low = 0x0000800B; 1972 msr_write64(MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_DIAG, &msr_value); 1973 1974 /* CONFIGURE DIAG CONTROL */ 1975 /* Set RegA action1 to increment lower 16 bits and clear at limit. (5) 1976 * Set RegA action2 to increment upper 16 bits. (6) 1977 * Set RegB action1 to CRC32 (1) 1978 * Set all comparators to REGA override (0,1 lower mbus, 2,3 upper mbus) 1979 * Enable all actions 1980 */ 1981 1982 msr_value.low = 0x80EA20A0; 1983 msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_DIAGCTL, &msr_value); 1984 1985 /* DELAY TWO FRAMES */ 1986 1987 while (READ_REG32(DC3_LINE_CNT_STATUS) & DC3_LNCNT_VNA); 1988 while (!(READ_REG32(DC3_LINE_CNT_STATUS) & DC3_LNCNT_VNA)); 1989 while (READ_REG32(DC3_LINE_CNT_STATUS) & DC3_LNCNT_VNA); 1990 while (!(READ_REG32(DC3_LINE_CNT_STATUS) & DC3_LNCNT_VNA)); 1991 while (READ_REG32(DC3_LINE_CNT_STATUS) & DC3_LNCNT_VNA); 1992 1993 /* VERIFY THAT XSTATE = 11 */ 1994 1995 msr_read64(MSR_DEVICE_GEODELX_GLCP, GLCP_XSTATE, &msr_value); 1996 if ((msr_value.low & 3) == 3) { 1997 msr_read64(MSR_DEVICE_GEODELX_GLCP, GLCP_REGB, &msr_value); 1998 1999 crc = msr_value.low; 2000 } 2001 2002 /* DISABLE DF DIAG BUS OUTPUTS */ 2003 2004 msr_value.low = 0x00000000; 2005 msr_value.high = 0x00000000; 2006 msr_write64(MSR_DEVICE_GEODELX_DF, MSR_GEODELINK_DIAG, &msr_value); 2007 2008 /* DISABLE GLCP ACTIONS */ 2009 2010 msr_write64(MSR_DEVICE_GEODELX_GLCP, GLCP_DIAGCTL, &msr_value); 2011 2012 return crc; 2013} 2014 2015/*--------------------------------------------------------------------------- 2016 * df_read_panel_crc 2017 * 2018 * This routine reads the CRC for a frame of data after the panel dithering 2019 * logic. 2020 *--------------------------------------------------------------------------*/ 2021 2022unsigned long 2023df_read_panel_crc(void) 2024{ 2025 Q_WORD msr_value; 2026 unsigned long timeout = 1000; 2027 2028 if (!(READ_REG32(DC3_DISPLAY_CFG) & DC3_DCFG_TGEN)) 2029 return 0xFFFFFFFF; 2030 2031 /* ENABLE 32-BIT CRCS */ 2032 2033 msr_read64(MSR_DEVICE_GEODELX_DF, DF_MBD_MSR_DIAG_DF, &msr_value); 2034 msr_value.low |= DF_DIAG_32BIT_CRC; 2035 msr_write64(MSR_DEVICE_GEODELX_DF, DF_MBD_MSR_DIAG_DF, &msr_value); 2036 2037 /* RESET CRC */ 2038 2039 WRITE_VID32(DF_PANEL_CRC, 0); 2040 2041 /* WAIT FOR THE RESET TO BE LATCHED */ 2042 2043 while ((READ_VID32(DF_PANEL_CRC32) != 0x00000001) && timeout) 2044 timeout--; 2045 2046 WRITE_VID32(DF_PANEL_CRC, 1); 2047 2048 /* WAIT FOR THE CRC TO BE COMPLETED */ 2049 2050 while (!(READ_VID32(DF_PANEL_CRC) & 4)); 2051 2052 return READ_VID32(DF_PANEL_CRC32); 2053} 2054 2055/*--------------------------------------------------------------------------- 2056 * df_get_video_enable 2057 * 2058 * This routine reads the enable status of the video overlay. 2059 *--------------------------------------------------------------------------*/ 2060 2061int 2062df_get_video_enable(int *enable, unsigned long *flags) 2063{ 2064 *enable = 0; 2065 *flags = 0; 2066 if (READ_VID32(DF_VIDEO_CONFIG) & DF_VCFG_VID_EN) { 2067 *enable = 1; 2068 2069 /* CHECK FOR COLOR KEY DISABLED */ 2070 /* Color keying can be completely disabled when video is enabled to */ 2071 /* allow unhindered per-pixel alpha blending. As color keying is */ 2072 /* always disabled when video is disabled, it is only possible to */ 2073 /* test for this condition when video is enabled. */ 2074 2075 if (!(READ_VID32(DF_DISPLAY_CONFIG) & DF_DCFG_VG_CK) && 2076 !(READ_REG32(DC3_COLOR_KEY) & DC3_CLR_KEY_ENABLE)) { 2077 *flags = DF_ENABLEFLAG_NOCOLORKEY; 2078 } 2079 } 2080 2081 return CIM_STATUS_OK; 2082} 2083 2084/*--------------------------------------------------------------------------- 2085 * df_get_video_source_configuration 2086 * 2087 * This routine reads the current configuration of the source buffers for the 2088 * video overlay. 2089 *--------------------------------------------------------------------------*/ 2090 2091int 2092df_get_video_source_configuration(DF_VIDEO_SOURCE_PARAMS * video_source_odd, 2093 DF_VIDEO_SOURCE_PARAMS * video_source_even) 2094{ 2095 unsigned long format, temp; 2096 unsigned long size; 2097 2098 /* READ VIDEO FORMAT */ 2099 2100 temp = READ_VID32(DF_VIDEO_CONFIG); 2101 2102 format = (temp >> 2) & 3; 2103 if (temp & DF_VCFG_4_2_0_MODE) 2104 format |= 4; 2105 else if (READ_VID32(DF_VID_ALPHA_CONTROL) & DF_VIDEO_INPUT_IS_RGB) 2106 format |= 8; 2107 video_source_odd->video_format = format; 2108 2109 /* CHECK IF SOURCE IS HD VIDEO */ 2110 2111 if (READ_VID32(DF_VID_ALPHA_CONTROL) & DF_HD_VIDEO) 2112 video_source_odd->flags = DF_SOURCEFLAG_HDTVSOURCE; 2113 else 2114 video_source_odd->flags = 0; 2115 2116 /* READ SCALING ALGORITHM */ 2117 2118 if (READ_VID32(DF_VID_MISC) & DF_USER_IMPLICIT_SCALING) 2119 video_source_odd->flags |= DF_SOURCEFLAG_IMPLICITSCALING; 2120 2121 /* READ VIDEO PITCH */ 2122 2123 temp = READ_REG32(DC3_VID_YUV_PITCH); 2124 video_source_odd->y_pitch = (temp & 0xFFFF) << 3; 2125 video_source_odd->uv_pitch = (temp >> 16) << 3; 2126 2127 /* READ VIDEO SIZE */ 2128 2129 temp = READ_VID32(DF_VIDEO_CONFIG); 2130 size = (temp >> 8) & 0xFF; 2131 if (temp & DF_VCFG_LINE_SIZE_BIT8) 2132 size |= 0x100; 2133 if (temp & DF_VCFG_LINE_SIZE_BIT9) 2134 size |= 0x200; 2135 2136 video_source_odd->width = size << 1; 2137 video_source_odd->height = READ_VID32(DF_VIDEO_SCALER) & 0x7FF; 2138 2139 /* READ VIDEO OFFSETS */ 2140 2141 video_source_odd->y_offset = READ_REG32(DC3_VID_Y_ST_OFFSET) & 0xFFFFFFF; 2142 video_source_odd->u_offset = READ_REG32(DC3_VID_U_ST_OFFSET) & 0xFFFFFFF; 2143 video_source_odd->v_offset = READ_REG32(DC3_VID_V_ST_OFFSET) & 0xFFFFFFF; 2144 2145 if (READ_REG32(DC3_IRQ_FILT_CTL) & DC3_IRQFILT_INTL_EN) { 2146 video_source_even->y_offset = 2147 READ_REG32(DC3_VID_EVEN_Y_ST_OFFSET) & 0xFFFFFFF; 2148 video_source_even->u_offset = 2149 READ_REG32(DC3_VID_EVEN_U_ST_OFFSET) & 0xFFFFFFF; 2150 video_source_even->v_offset = 2151 READ_REG32(DC3_VID_EVEN_V_ST_OFFSET) & 0xFFFFFFF; 2152 } 2153 2154 return CIM_STATUS_OK; 2155} 2156 2157/*--------------------------------------------------------------------------- 2158 * df_get_video_position 2159 * 2160 * This routine reads the current position of the video overlay. 2161 *--------------------------------------------------------------------------*/ 2162 2163int 2164df_get_video_position(DF_VIDEO_POSITION * video_window) 2165{ 2166 unsigned long xreg, yreg, dst_clip, clip; 2167 unsigned long height; 2168 unsigned long xend, yend; 2169 unsigned long hsyncend, htotal; 2170 unsigned long vsyncend, vtotal; 2171 unsigned long hadjust, vadjust; 2172 unsigned long misc, gfxscale; 2173 unsigned long temp; 2174 long xstart, ystart; 2175 2176 video_window->flags = DF_POSFLAG_DIRECTCLIP; 2177 2178 hsyncend = ((READ_REG32(DC3_H_SYNC_TIMING) >> 16) & 0xFFF) + 1; 2179 htotal = ((READ_REG32(DC3_H_ACTIVE_TIMING) >> 16) & 0xFFF) + 1; 2180 2181 /* ODD FIELD START COUNTS FROM THE EVEN FIELD TIMINGS */ 2182 /* We assume that the even field y position is always programmed */ 2183 /* to be just after the odd field. */ 2184 2185 if (READ_REG32(DC3_IRQ_FILT_CTL) & DC3_IRQFILT_INTL_EN) { 2186 vsyncend = ((READ_REG32(DC3_V_SYNC_EVEN) >> 16) & 0xFFF) + 1; 2187 vtotal = ((READ_REG32(DC3_V_ACTIVE_EVEN) >> 16) & 0xFFF) + 1; 2188 } 2189 else { 2190 vsyncend = ((READ_REG32(DC3_V_SYNC_TIMING) >> 16) & 0xFFF) + 1; 2191 vtotal = ((READ_REG32(DC3_V_ACTIVE_TIMING) >> 16) & 0xFFF) + 1; 2192 } 2193 2194 hadjust = htotal - hsyncend - 14; 2195 vadjust = vtotal - vsyncend + 1; 2196 2197 xreg = READ_VID32(DF_VIDEO_X_POS); 2198 yreg = READ_VID32(DF_VIDEO_Y_POS); 2199 2200 xstart = (xreg & 0xFFF) - hadjust; 2201 ystart = (yreg & 0x7FF) - vadjust; 2202 xend = ((xreg >> 16) & 0xFFF) - hadjust; 2203 yend = ((yreg >> 16) & 0x7FF) - vadjust; 2204 2205 height = yend - ystart; 2206 2207 if (READ_REG32(DC3_IRQ_FILT_CTL) & DC3_IRQFILT_INTL_EN) { 2208 /* Y COORDINATE IS ACTUALLY 2X THE ODD FIELD START */ 2209 2210 ystart <<= 1; 2211 2212 /* CALCULATE THE EXACT VIDEO HEIGHT */ 2213 /* The height of the video window is the sum of the */ 2214 /* odd and even field heights. */ 2215 2216 yreg = READ_VID32(DF_VID_YPOS_EVEN); 2217 height += ((yreg >> 16) & 0x7FF) - (yreg & 0x7FF); 2218 } 2219 2220 clip = ((READ_VID32(DF_VIDEO_CONFIG) >> 16) & 0x1FF) << 2; 2221 2222 /* ADJUST FOR CLIPPING VALUES THAT ARE NOT FOUR-PIXEL ALIGNED */ 2223 2224 dst_clip = 0; 2225 if (xstart < 0) { 2226 dst_clip += -xstart; 2227 xstart = 0; 2228 } 2229 2230 /* REVERSE THE GRAPHICS SCALE */ 2231 2232 misc = READ_VID32(DF_VID_MISC); 2233 if (misc & DF_USER_IMPLICIT_SCALING) { 2234 gfxscale = READ_REG32(DC3_GFX_SCALE); 2235 2236 if (gfxscale != 0x40004000) { 2237 temp = ystart + height; 2238 temp = (temp * (gfxscale >> 16)) / 0x4000; 2239 2240 xstart = (xstart * (gfxscale & 0xFFFF)) / 0x4000; 2241 xend = (xend * (gfxscale & 0xFFFF)) / 0x4000; 2242 ystart = (ystart * (gfxscale >> 16)) / 0x4000; 2243 height = temp - ystart; 2244 } 2245 } 2246 2247 video_window->left_clip = clip; 2248 video_window->dst_clip = dst_clip; 2249 video_window->x = xstart; 2250 video_window->y = ystart; 2251 video_window->width = xend - xstart; 2252 video_window->height = height; 2253 2254 return CIM_STATUS_OK; 2255} 2256 2257/*--------------------------------------------------------------------------- 2258 * df_get_video_scale 2259 * 2260 * This routine reads the current scale values for video scaling. 2261 *--------------------------------------------------------------------------*/ 2262 2263int 2264df_get_video_scale(unsigned long *x_scale, unsigned long *y_scale) 2265{ 2266 *x_scale = READ_VID32(DF_VIDEO_XSCALE) & 0x000FFFFF; 2267 *y_scale = READ_VID32(DF_VIDEO_YSCALE) & 0x000FFFFF; 2268 return CIM_STATUS_OK; 2269} 2270 2271/*--------------------------------------------------------------------------- 2272 * df_get_video_filter_coefficients 2273 * 2274 * This routine reads the coefficients for the video scaler/filter. 2275 *--------------------------------------------------------------------------*/ 2276 2277int 2278df_get_video_filter_coefficients(long taps[][4], int *phase256) 2279{ 2280 unsigned long i, temp; 2281 long coeff; 2282 2283 if (READ_VID32(DF_VIDEO_SCALER) & DF_SCALE_128_PHASES) 2284 *phase256 = 0; 2285 else 2286 *phase256 = 1; 2287 2288 for (i = 0; i < 256; i++) { 2289 temp = READ_VID32(DF_COEFFICIENT_BASE + (i << 3)); 2290 2291 /* TAP 0 */ 2292 2293 coeff = temp & 0x7FFF; 2294 if (temp & 0x8000) 2295 coeff = -coeff; 2296 taps[i][0] = coeff; 2297 2298 /* TAP 1 */ 2299 2300 temp >>= 16; 2301 coeff = temp & 0x7FFF; 2302 if (temp & 0x8000) 2303 coeff = -coeff; 2304 taps[i][1] = coeff; 2305 2306 temp = READ_VID32(DF_COEFFICIENT_BASE + (i << 3) + 4); 2307 2308 /* TAP 2 */ 2309 2310 coeff = temp & 0x7FFF; 2311 if (temp & 0x8000) 2312 coeff = -coeff; 2313 taps[i][2] = coeff; 2314 2315 /* TAP 3 */ 2316 2317 temp >>= 16; 2318 coeff = temp & 0x7FFF; 2319 if (temp & 0x8000) 2320 coeff = -coeff; 2321 taps[i][3] = coeff; 2322 } 2323 2324 return CIM_STATUS_OK; 2325} 2326 2327/*--------------------------------------------------------------------------- 2328 * df_get_video_color_key 2329 * 2330 * This routine reads the current settings for hardware color/chroma keying. 2331 *--------------------------------------------------------------------------*/ 2332 2333int 2334df_get_video_color_key(unsigned long *key, unsigned long *mask, int *graphics) 2335{ 2336 unsigned long chroma = READ_VID32(DF_DISPLAY_CONFIG) & DF_DCFG_VG_CK; 2337 2338 if (chroma) { 2339 /* CHROMA KEY - READ KEY AND MASK FROM DF */ 2340 2341 *graphics = 0; 2342 *key = READ_VID32(DF_VIDEO_COLOR_KEY) & 0xFFFFFF; 2343 *mask = READ_VID32(DF_VIDEO_COLOR_MASK) & 0xFFFFFF; 2344 } 2345 else { 2346 *graphics = 1; 2347 2348 *key = READ_REG32(DC3_COLOR_KEY) & 0xFFFFFF; 2349 *mask = READ_REG32(DC3_COLOR_MASK) & 0xFFFFFF; 2350 } 2351 2352 return CIM_STATUS_OK; 2353} 2354 2355/*--------------------------------------------------------------------------- 2356 * df_get_video_palette_entry 2357 * 2358 * This routine returns a single palette entry. 2359 *--------------------------------------------------------------------------*/ 2360 2361int 2362df_get_video_palette_entry(unsigned long index, unsigned long *palette) 2363{ 2364 if (index > 0xFF) 2365 return CIM_STATUS_INVALIDPARAMS; 2366 2367 /* READ A SINGLE ENTRY */ 2368 2369 WRITE_VID32(DF_PALETTE_ADDRESS, index); 2370 *palette = READ_VID32(DF_PALETTE_DATA); 2371 2372 return CIM_STATUS_OK; 2373} 2374 2375/*--------------------------------------------------------------------------- 2376 * df_get_video_palette 2377 * 2378 * This routine returns the entire video palette. 2379 *--------------------------------------------------------------------------*/ 2380 2381int 2382df_get_video_palette(unsigned long *palette) 2383{ 2384 unsigned long i; 2385 2386 WRITE_VID32(DF_PALETTE_ADDRESS, 0); 2387 for (i = 0; i < 256; i++) 2388 palette[i] = READ_VID32(DF_PALETTE_DATA); 2389 2390 return CIM_STATUS_OK; 2391} 2392 2393/*--------------------------------------------------------------------------- 2394 * df_get_video_cursor_color_key 2395 * 2396 * This routine returns the current configuration for the hardware video cursor 2397 * color key. 2398 *--------------------------------------------------------------------------*/ 2399 2400int 2401df_get_video_cursor_color_key(DF_VIDEO_CURSOR_PARAMS * cursor_color_key) 2402{ 2403 unsigned long key; 2404 2405 cursor_color_key->flags = 0; 2406 cursor_color_key->color1 = READ_VID32(DF_CURSOR_COLOR_1) & 0xFFFFFF; 2407 cursor_color_key->color2 = READ_VID32(DF_CURSOR_COLOR_2) & 0xFFFFFF; 2408 cursor_color_key->mask = READ_VID32(DF_CURSOR_COLOR_MASK) & 0xFFFFFF; 2409 2410 key = READ_VID32(DF_CURSOR_COLOR_KEY); 2411 cursor_color_key->key = key & 0xFFFFFF; 2412 cursor_color_key->select_color2 = (key >> 24) & 0x1F; 2413 2414 return CIM_STATUS_OK; 2415} 2416 2417/*--------------------------------------------------------------------------- 2418 * df_get_video_cursor_color_key_enable 2419 * 2420 * This routine returns the current enable status of the hardware video cursor 2421 * color key. 2422 *--------------------------------------------------------------------------*/ 2423 2424int 2425df_get_video_cursor_color_key_enable(void) 2426{ 2427 if (READ_VID32(DF_CURSOR_COLOR_KEY) & DF_CURSOR_COLOR_KEY_ENABLE) 2428 return 1; 2429 2430 return 0; 2431} 2432 2433/*--------------------------------------------------------------------------- 2434 * df_get_alpha_window_configuration 2435 * 2436 * This routine reads the current configuration for one of the three hardware 2437 * alpha regions. 2438 *--------------------------------------------------------------------------*/ 2439 2440int 2441df_get_alpha_window_configuration(int window, 2442 DF_ALPHA_REGION_PARAMS * alpha_data) 2443{ 2444 unsigned long pos, color, alpha_ctl; 2445 unsigned long hsyncend, htotal; 2446 unsigned long vsyncend, vtotal; 2447 unsigned long hadjust, vadjust; 2448 unsigned long xreg, yreg; 2449 unsigned long misc, gfxscale; 2450 unsigned long temp; 2451 char delta; 2452 2453 if (window > 2) 2454 return CIM_STATUS_INVALIDPARAMS; 2455 2456 hsyncend = ((READ_REG32(DC3_H_SYNC_TIMING) >> 16) & 0xFFF) + 1; 2457 htotal = ((READ_REG32(DC3_H_ACTIVE_TIMING) >> 16) & 0xFFF) + 1; 2458 if (READ_REG32(DC3_IRQ_FILT_CTL) & DC3_IRQFILT_INTL_EN) { 2459 vtotal = ((READ_REG32(DC3_V_ACTIVE_EVEN) >> 16) & 0xFFF) + 1; 2460 vsyncend = ((READ_REG32(DC3_V_SYNC_EVEN) >> 16) & 0xFFF) + 1; 2461 } 2462 else { 2463 vtotal = ((READ_REG32(DC3_V_ACTIVE_TIMING) >> 16) & 0xFFF) + 1; 2464 vsyncend = ((READ_REG32(DC3_V_SYNC_TIMING) >> 16) & 0xFFF) + 1; 2465 } 2466 2467 /* GET PRIORITY */ 2468 2469 pos = 16 + (window << 1); 2470 alpha_data->priority = (READ_VID32(DF_VID_ALPHA_CONTROL) >> pos) & 3L; 2471 2472 /* GET ALPHA WINDOW */ 2473 2474 hadjust = htotal - hsyncend - 2; 2475 vadjust = vtotal - vsyncend + 1; 2476 2477 xreg = READ_VID32(DF_ALPHA_XPOS_1 + (window << 5)); 2478 yreg = READ_VID32(DF_ALPHA_YPOS_1 + (window << 5)); 2479 alpha_data->width = ((xreg >> 16) & 0xFFF) - (xreg & 0xFFF); 2480 alpha_data->height = ((yreg >> 16) & 0x7FF) - (yreg & 0x7FF); 2481 alpha_data->x = (xreg & 0xFFF) - hadjust; 2482 alpha_data->y = (yreg & 0x7FF) - vadjust; 2483 2484 /* REVERSE THE GRAPHICS SCALE */ 2485 2486 misc = READ_VID32(DF_VID_MISC); 2487 if (misc & DF_USER_IMPLICIT_SCALING) { 2488 gfxscale = READ_REG32(DC3_GFX_SCALE); 2489 if (gfxscale != 0x40004000) { 2490 temp = alpha_data->y + alpha_data->height; 2491 temp = (temp * (gfxscale >> 16)) / 0x4000; 2492 2493 alpha_data->x = (alpha_data->x * (gfxscale & 0xFFFF)) / 0x4000; 2494 alpha_data->width = 2495 (alpha_data->width * (gfxscale & 0xFFFF)) / 0x4000; 2496 alpha_data->y = (alpha_data->y * (gfxscale >> 16)) / 0x4000; 2497 alpha_data->height = temp - alpha_data->y; 2498 } 2499 } 2500 2501 if (READ_REG32(DC3_IRQ_FILT_CTL) & DC3_IRQFILT_INTL_EN) { 2502 /* Y COORDINATE IS ACTUALLY 2X THE ODD FIELD START */ 2503 2504 alpha_data->y <<= 1; 2505 2506 /* CALCULATE THE EXACT VIDEO HEIGHT */ 2507 /* The height of the video window is the sum of the */ 2508 /* odd and even field heights. */ 2509 2510 yreg = READ_VID32(DF_VID_ALPHA_Y_EVEN_1 + (window << 3)); 2511 alpha_data->height += ((yreg >> 16) & 0x7FF) - (yreg & 0x7FF); 2512 } 2513 2514 /* GET COLOR REGISTER */ 2515 2516 color = READ_VID32(DF_ALPHA_COLOR_1 + (window << 5)); 2517 alpha_data->color = color & 0xFFFFFF; 2518 if (color & DF_ALPHA_COLOR_ENABLE) 2519 alpha_data->flags = DF_ALPHAFLAG_COLORENABLED; 2520 else 2521 alpha_data->flags = 0; 2522 2523 /* GET ALPHA VALUE, DELTA AND PER PIXEL */ 2524 2525 alpha_ctl = READ_VID32(DF_ALPHA_CONTROL_1 + (window << 5)); 2526 alpha_data->alpha_value = alpha_ctl & 0xFF; 2527 if (alpha_ctl & DF_ACTRL_PERPIXEL_EN) 2528 alpha_data->flags |= DF_ALPHAFLAG_PERPIXELENABLED; 2529 2530 delta = (char) ((alpha_ctl >> 8) & 0xFF); 2531 alpha_data->delta = (long) delta; 2532 return CIM_STATUS_OK; 2533} 2534 2535/*--------------------------------------------------------------------------- 2536 * df_get_alpha_window_enable 2537 * 2538 * This routine reads the current enable status of one of the three hardware 2539 * alpha regions. 2540 *--------------------------------------------------------------------------*/ 2541 2542int 2543df_get_alpha_window_enable(int window) 2544{ 2545 if (window > 2) 2546 return 0; 2547 2548 if (READ_VID32(DF_ALPHA_CONTROL_1 + (window << 5)) & DF_ACTRL_WIN_ENABLE) 2549 return 1; 2550 2551 return 0; 2552} 2553 2554/*--------------------------------------------------------------------------- 2555 * df_get_video_request 2556 * 2557 * This routine reads the horizontal (pixel) and vertical (line) video request 2558 * values. 2559 *--------------------------------------------------------------------------*/ 2560 2561int 2562df_get_video_request(unsigned long *x, unsigned long *y) 2563{ 2564 unsigned long request; 2565 unsigned long hsyncend, htotal; 2566 unsigned long vsyncend, vtotal; 2567 2568 hsyncend = ((READ_REG32(DC3_H_SYNC_TIMING) >> 16) & 0xFFF) + 1; 2569 vsyncend = ((READ_REG32(DC3_V_SYNC_TIMING) >> 16) & 0xFFF) + 1; 2570 htotal = ((READ_REG32(DC3_H_ACTIVE_TIMING) >> 16) & 0xFFF) + 1; 2571 vtotal = ((READ_REG32(DC3_V_ACTIVE_TIMING) >> 16) & 0xFFF) + 1; 2572 2573 request = READ_VID32(DF_VIDEO_REQUEST); 2574 *x = ((request >> 16) & 0xFFF) - (htotal - hsyncend - 2); 2575 *y = (request & 0x7FF) - (vtotal - vsyncend + 1); 2576 2577 return CIM_STATUS_OK; 2578} 2579 2580/*--------------------------------------------------------------------------- 2581 * df_get_output_color_space 2582 * 2583 * This routine sets the color space used when combining graphics and video. 2584 *--------------------------------------------------------------------------*/ 2585 2586int 2587df_get_output_color_space(int *color_space) 2588{ 2589 unsigned long alpha_ctl; 2590 2591 alpha_ctl = READ_VID32(DF_VID_ALPHA_CONTROL); 2592 2593 if ((alpha_ctl & DF_CSC_VIDEO_YUV_TO_RGB) || 2594 !(alpha_ctl & DF_CSC_GRAPHICS_RGB_TO_YUV)) { 2595 if (alpha_ctl & DF_ALPHA_DRGB) 2596 *color_space = DF_OUTPUT_ARGB; 2597 else 2598 *color_space = DF_OUTPUT_RGB; 2599 } 2600 else { 2601 *color_space = DF_OUTPUT_SDTV; 2602 2603 if (alpha_ctl & DF_HD_GRAPHICS) 2604 *color_space = DF_OUTPUT_HDTV; 2605 } 2606 2607 return CIM_STATUS_OK; 2608} 2609 2610#endif 2611