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