3 * Copyright (C) 2005 Advanced Micro Devices, Inc. All Rights Reserved.
10 * Cimarron display filter routines. These routines program the video hardware.
15 /*---------------------------------------------------------------------------
18 * This routine enables or disables CRT output.
19 *---------------------------------------------------------------------------*/
21 int df_set_crt_enable (int crt_output
)
23 unsigned long config
, misc
;
25 config
= READ_VID32 (DF_DISPLAY_CONFIG
);
26 misc
= READ_VID32 (DF_VID_MISC
);
34 config
&= ~(DF_DCFG_DIS_EN
| DF_DCFG_HSYNC_EN
|
35 DF_DCFG_VSYNC_EN
| DF_DCFG_DAC_BL_EN
);
36 misc
|= DF_DAC_POWER_DOWN
;
39 /* ENABLE THE DISPLAY */
43 config
|= (DF_DCFG_DIS_EN
| DF_DCFG_HSYNC_EN
|
44 DF_DCFG_VSYNC_EN
| DF_DCFG_DAC_BL_EN
);
45 misc
&= ~(DF_DAC_POWER_DOWN
| DF_ANALOG_POWER_DOWN
);
48 /* HSYNC:OFF VSYNC:ON */
52 config
= (config
& ~(DF_DCFG_DIS_EN
| DF_DCFG_HSYNC_EN
| DF_DCFG_DAC_BL_EN
)) |
54 misc
|= DF_DAC_POWER_DOWN
;
57 /* HSYNC:ON VSYNC:OFF */
61 config
= (config
& ~(DF_DCFG_DIS_EN
| DF_DCFG_VSYNC_EN
| DF_DCFG_DAC_BL_EN
)) |
63 misc
|= DF_DAC_POWER_DOWN
;
67 return CIM_STATUS_INVALIDPARAMS
;
70 WRITE_VID32 (DF_DISPLAY_CONFIG
, config
);
71 WRITE_VID32 (DF_VID_MISC
, misc
);
76 /*---------------------------------------------------------------------------
79 * This routine enables or disables panel output.
80 *---------------------------------------------------------------------------*/
82 int df_set_panel_enable (int enable
)
86 pm
= READ_VID32 (DF_POWER_MANAGEMENT
);
88 if (enable
) pm
|= DF_PM_PANEL_ON
;
89 else pm
&= ~DF_PM_PANEL_ON
;
91 WRITE_VID32 (DF_POWER_MANAGEMENT
, pm
);
96 /*---------------------------------------------------------------------------
97 * df_configure_video_source
99 * This routine initializes all aspects of the source buffer for a video overlay.
100 *---------------------------------------------------------------------------*/
102 int df_configure_video_source (DF_VIDEO_SOURCE_PARAMS
*video_source_odd
,
103 DF_VIDEO_SOURCE_PARAMS
*video_source_even
)
105 unsigned long pitch
, ctrl
, vcfg
;
106 unsigned long lock
, vg_line
, gcfg
;
107 unsigned long width
, size
, scale
;
110 lock
= READ_REG32 (DC3_UNLOCK
);
111 vg_line
= READ_REG32 (DC3_LINE_SIZE
);
112 gcfg
= READ_REG32 (DC3_GENERAL_CFG
);
113 vcfg
= READ_VID32 (DF_VIDEO_CONFIG
);
114 ctrl
= READ_VID32 (DF_VID_ALPHA_CONTROL
);
115 scale
= READ_VID32 (DF_VIDEO_SCALER
);
117 /* STORE THE DESIRED SCALING PROCEDURE */
118 /* Cimarron supports two modes when programming the scale and position */
119 /* of the video window. The first mode is designed to implicitly apply */
120 /* the graphics scale to any video operations. The second applys the */
121 /* video unchanged, allowing complete control by the user. To allow */
122 /* visibility between modules, the current mode is stored in a spare */
123 /* bit in the DF miscellaneous register. */
125 misc
= READ_VID32 (DF_VID_MISC
);
126 if (video_source_odd
->flags
& DF_SOURCEFLAG_IMPLICITSCALING
)
127 misc
|= DF_USER_IMPLICIT_SCALING
;
129 misc
&= DF_USER_IMPLICIT_SCALING
;
130 WRITE_VID32 (DF_VID_MISC
, misc
);
132 /* PARAMETER - VIDEO PITCH */
134 pitch
= (video_source_odd
->y_pitch
>> 3) | ((video_source_odd
->uv_pitch
>> 3) << 16);
136 /* PARAMETER - VIDEO FORMAT */
138 gcfg
&= ~DC3_GCFG_YUV_420
;
139 vcfg
&= ~(DF_VCFG_VID_INP_FORMAT
| DF_VCFG_4_2_0_MODE
);
140 ctrl
&= ~(DF_VIDEO_INPUT_IS_RGB
| DF_CSC_VIDEO_YUV_TO_RGB
| DF_HD_VIDEO
|
143 /* SELECT PIXEL ORDERING */
145 switch (video_source_odd
->video_format
& 3)
147 case 0: vcfg
|= DF_VCFG_UYVY_FORMAT
; break;
148 case 1: vcfg
|= DF_VCFG_Y2YU_FORMAT
; break;
149 case 2: vcfg
|= DF_VCFG_YUYV_FORMAT
; break;
150 case 3: vcfg
|= DF_VCFG_YVYU_FORMAT
; break;
153 /* SELECT SOURCE FORMAT (4:2:2, 4:2:0, RGB) */
155 switch (video_source_odd
->video_format
>> 2)
157 case 0: ctrl
|= DF_CSC_VIDEO_YUV_TO_RGB
; break;
159 case 1: ctrl
|= DF_CSC_VIDEO_YUV_TO_RGB
;
160 vcfg
|= DF_VCFG_4_2_0_MODE
;
161 gcfg
|= DC3_GCFG_YUV_420
;
164 case 2: ctrl
|= DF_VIDEO_INPUT_IS_RGB
; break;
166 default: return CIM_STATUS_INVALIDPARAMS
;
169 /* ALIGN TO APPROPRIATE OUTPUT COLOR SPACE */
170 /* We have assumed until this point that the output color space is RGB */
171 /* and the input (if YUV) is always SDTV video. */
173 if (video_source_odd
->flags
& DF_SOURCEFLAG_HDTVSOURCE
)
176 if (ctrl
& DF_CSC_GRAPHICS_RGB_TO_YUV
)
178 /* YUV OUTPUT - DISABLE YUV->RGB AND ENABLE YUV->YUV */
180 ctrl
&= ~DF_CSC_VIDEO_YUV_TO_RGB
;
182 if ((!(ctrl
& DF_HD_VIDEO
) && (ctrl
& DF_HD_GRAPHICS
)) ||
183 ((ctrl
& DF_HD_VIDEO
) && !(ctrl
& DF_HD_GRAPHICS
)))
185 ctrl
|= DF_YUV_CSC_EN
;
189 /* PARAMETER - DISPLAY FILTER BUFFER SIZE */
190 /* The line size in the video generator must be 32-byte aligned. */
191 /* However, smaller alignments are managed by setting the */
192 /* appropriate pitch and clipping the video window. */
194 vcfg
&= ~(DF_VCFG_LINE_SIZE_LOWER_MASK
| DF_VCFG_LINE_SIZE_BIT8
|
195 DF_VCFG_LINE_SIZE_BIT9
);
197 size
= ((video_source_odd
->width
>> 1) + 7) & 0xFFF8;
199 vcfg
|= (size
& 0x00FF) << 8;
200 if (size
& 0x0100) vcfg
|= DF_VCFG_LINE_SIZE_BIT8
;
201 if (size
& 0x0200) vcfg
|= DF_VCFG_LINE_SIZE_BIT9
;
203 scale
= (scale
& ~0x7FF) | video_source_odd
->height
;
205 /* PARAMETER - VIDEO GENERATOR BUFFER SIZE */
207 vg_line
&= ~DC3_LINE_SIZE_VLS_MASK
;
209 if (gcfg
& DC3_GCFG_YUV_420
)
210 width
= ((video_source_odd
->width
>> 1) + 7) & 0xFFF8;
212 width
= ((video_source_odd
->width
<< 1) + 31) & 0xFFE0;
214 vg_line
|= (width
>> 3) << DC3_LINE_SIZE_VB_SHIFT
;
216 /* WRITE ALL PARAMETERS AT ONCE */
218 WRITE_REG32 (DC3_UNLOCK
, DC3_UNLOCK_VALUE
);
219 WRITE_VID32 (DF_VIDEO_CONFIG
, vcfg
);
220 WRITE_VID32 (DF_VID_ALPHA_CONTROL
, ctrl
);
221 WRITE_VID32 (DF_VIDEO_SCALER
, scale
);
222 WRITE_REG32 (DC3_GENERAL_CFG
, gcfg
);
223 WRITE_REG32 (DC3_LINE_SIZE
, vg_line
);
224 WRITE_REG32 (DC3_VID_YUV_PITCH
, pitch
);
226 /* WRITE EVEN OR ODD BUFFER OFFSETS */
227 /* The even buffer is only valid inside an interlaced display. */
229 if (READ_REG32 (DC3_IRQ_FILT_CTL
) & DC3_IRQFILT_INTL_EN
)
231 WRITE_REG32 (DC3_VID_EVEN_Y_ST_OFFSET
, video_source_even
->y_offset
);
232 WRITE_REG32 (DC3_VID_EVEN_U_ST_OFFSET
, video_source_even
->u_offset
);
233 WRITE_REG32 (DC3_VID_EVEN_V_ST_OFFSET
, video_source_even
->v_offset
);
236 WRITE_REG32 (DC3_VID_Y_ST_OFFSET
, video_source_odd
->y_offset
);
237 WRITE_REG32 (DC3_VID_U_ST_OFFSET
, video_source_odd
->u_offset
);
238 WRITE_REG32 (DC3_VID_V_ST_OFFSET
, video_source_odd
->v_offset
);
240 WRITE_REG32 (DC3_UNLOCK
, lock
);
242 return CIM_STATUS_OK
;
245 /*---------------------------------------------------------------------------
246 * df_set_video_offsets
248 * This routine sets the starting offset for the video buffer(s). The buffers
249 * can also be configured inside df_configure_video_source, but a separate
250 * routine is provided here to allow quick buffer flipping.
251 *---------------------------------------------------------------------------*/
253 int df_set_video_offsets (int even
, unsigned long y_offset
,
254 unsigned long u_offset
, unsigned long v_offset
)
256 unsigned long lock
= READ_REG32 (DC3_UNLOCK
);
258 WRITE_REG32 (DC3_UNLOCK
, DC3_UNLOCK_VALUE
);
262 WRITE_REG32 (DC3_VID_EVEN_Y_ST_OFFSET
, y_offset
);
263 WRITE_REG32 (DC3_VID_EVEN_U_ST_OFFSET
, u_offset
);
264 WRITE_REG32 (DC3_VID_EVEN_V_ST_OFFSET
, v_offset
);
268 WRITE_REG32 (DC3_VID_Y_ST_OFFSET
, y_offset
);
269 WRITE_REG32 (DC3_VID_U_ST_OFFSET
, u_offset
);
270 WRITE_REG32 (DC3_VID_V_ST_OFFSET
, v_offset
);
273 WRITE_REG32 (DC3_UNLOCK
, lock
);
275 return CIM_STATUS_OK
;
278 /*---------------------------------------------------------------------------
281 * This routine programs the horizontal/vertical scale factors for video. To
282 * disable scaling/filtering, this routine should be called with identical source
283 * and destination dimensions.
284 *---------------------------------------------------------------------------*/
286 int df_set_video_scale (unsigned long src_width
, unsigned long src_height
,
287 unsigned long dst_width
, unsigned long dst_height
, unsigned long flags
)
289 unsigned long temp
, misc
;
290 unsigned long scale
, gfxscale
;
291 unsigned long fbactive
, src
;
292 unsigned long size
, downscale
;
293 unsigned long vcfg
, gcfg
, unlock
;
295 /* APPLY THE GRAPHICS SCALE */
296 /* When requested by the user, we will adjust the video scale by the */
297 /* current graphics scale factor. This allows video to be programmed */
298 /* in terms of the graphics source resolution. */
300 misc
= READ_VID32 (DF_VID_MISC
);
301 if (misc
& DF_USER_IMPLICIT_SCALING
)
303 gfxscale
= READ_REG32 (DC3_GFX_SCALE
);
304 fbactive
= READ_REG32 (DC3_FB_ACTIVE
);
306 /* REVERSE ENGINEER THE SCALE FACTOR */
307 /* The graphics scale factor is (source / (dst - 1)), so a little */
308 /* math is performed to reverse engineer the correct scale for */
311 /* F = (0x4000*S)/(D-1) -> (D/S) = (((0x4000*S)/F)+1)/S */
313 scale
= gfxscale
& 0xFFFF;
314 src
= (fbactive
>> 16) + 1;
317 dst_width
= dst_width
* (((0x4000 * src
) / scale
) + 1);
321 scale
= gfxscale
>> 16;
322 src
= (fbactive
& 0xFFFF) + 1;
325 dst_height
= dst_height
* (((0x4000 * src
) / scale
) + 1);
330 /* CHECK FOR VALID SCALING FACTOR */
331 /* The display filter/video generator can support up to 8:1 */
332 /* horizontal downscale and up to 4:1 vertical downscale. */
333 /* Scale factors above 4:1 horizontal and 2:1 horizontal */
334 /* will have a quality impact. However, at such large scale */
335 /* factors, it might not matter, */
337 if (((flags
& DF_SCALEFLAG_CHANGEX
) && dst_width
< (src_width
>> 3)) ||
338 ((flags
& DF_SCALEFLAG_CHANGEY
) && dst_height
< (src_height
>> 2)))
340 return CIM_STATUS_INVALIDSCALE
;
343 /* ENABLE OR DISABLE ADVANCED SCALING FEATURES */
344 /* Scaling above 2:1 vertical and 4:1 horizontal relies */
345 /* on mechanisms beside the line filter. */
347 if (flags
& DF_SCALEFLAG_CHANGEX
)
349 scale
= READ_VID32 (DF_VIDEO_SCALER
);
350 vcfg
= READ_VID32 (DF_VIDEO_CONFIG
);
351 vcfg
&= ~(DF_VCFG_LINE_SIZE_LOWER_MASK
| DF_VCFG_LINE_SIZE_BIT8
|
352 DF_VCFG_LINE_SIZE_BIT9
);
354 if (dst_width
< (src_width
>> 2))
357 WRITE_VID32 (DF_VIDEO_SCALER
, scale
| DF_SCALE_DOUBLE_H_DOWNSCALE
);
361 WRITE_VID32 (DF_VIDEO_SCALER
, scale
& ~DF_SCALE_DOUBLE_H_DOWNSCALE
);
364 /* PROGRAM A NEW LINE SIZE */
365 /* The line size must be updated when using the Double Horizontal */
366 /* Downscale (DHD) bit. This is because the amount of VFIFO space */
367 /* consumed is effectively half in this mode. */
369 size
= ((src_width
>> 1) + 7) & 0xFFF8;
370 vcfg
|= (size
& 0x00FF) << 8;
371 if (size
& 0x0100) vcfg
|= DF_VCFG_LINE_SIZE_BIT8
;
372 if (size
& 0x0200) vcfg
|= DF_VCFG_LINE_SIZE_BIT9
;
373 WRITE_VID32 (DF_VIDEO_CONFIG
, vcfg
);
374 WRITE_VID32 (DF_VIDEO_XSCALE
, ((0x10000 * src_width
) / dst_width
));
376 if (flags
& DF_SCALEFLAG_CHANGEY
)
378 unlock
= READ_REG32 (DC3_UNLOCK
);
379 gcfg
= READ_REG32 (DC3_GENERAL_CFG
) & ~DC3_GCFG_VDSE
;
380 WRITE_REG32 (DC3_UNLOCK
, DC3_UNLOCK_VALUE
);
381 if (dst_height
< (src_height
>> 1))
383 gcfg
|= DC3_GCFG_VDSE
;
384 downscale
= READ_REG32 (DC3_VID_DS_DELTA
) & ~DC3_DS_DELTA_MASK
;
385 if (dst_height
== (src_height
>> 2))
386 downscale
|= (0x3FFF << 18);
388 downscale
|= (((src_height
>> 1) << 14) / dst_height
) << 18;
390 WRITE_REG32 (DC3_VID_DS_DELTA
, downscale
);
391 WRITE_VID32 (DF_VIDEO_YSCALE
, 0x20000);
395 WRITE_VID32 (DF_VIDEO_YSCALE
, ((0x10000 * src_height
) / dst_height
));
397 WRITE_REG32 (DC3_GENERAL_CFG
, gcfg
);
398 WRITE_REG32 (DC3_UNLOCK
, unlock
);
401 /* CHECK IF SCALING IS DISABLED */
402 /* If no scaling occurs, we disable the hardware filter. */
404 temp
= READ_VID32 (DF_VIDEO_CONFIG
);
405 if ((READ_VID32 (DF_VIDEO_XSCALE
) == 0x10000) &&
406 (READ_VID32 (DF_VIDEO_YSCALE
) == 0x10000))
408 WRITE_VID32 (DF_VIDEO_CONFIG
, (temp
| DF_VCFG_SC_BYP
));
411 WRITE_VID32 (DF_VIDEO_CONFIG
, (temp
& ~DF_VCFG_SC_BYP
));
413 return CIM_STATUS_OK
;
416 /*---------------------------------------------------------------------------
417 * df_set_video_position
419 * This routine programs the position of the video window on the display.
420 * An indent parameter is also passed to this program to prevent artifacts
421 * when the video window is moved beyond the left edge of the screen.
422 *---------------------------------------------------------------------------*/
424 int df_set_video_position (DF_VIDEO_POSITION
*video_window
)
426 unsigned long vblankstart_even
, vblankend_even
, vsyncend_even
, vtotal_even
, vactive_even
;
427 unsigned long hblankstart
, hblankend
, hsyncend
, htotal
, hactive
;
428 unsigned long vblankstart
, vblankend
, vsyncend
, vtotal
, vactive
;
429 unsigned long width
, height
, height_even
;
430 unsigned long adjust
, border_x
, border_y
, border_y_even
;
431 unsigned long xstart
, xend
;
432 unsigned long ystart
, yend
;
433 unsigned long ckey_x
, ckey_y
;
434 unsigned long x_copy
, y_copy
;
435 unsigned long width_copy
, height_copy
;
436 unsigned long vcfg
, initread
;
437 unsigned long xscale
, dst_clip
;
438 unsigned long ypos
, ypos_even
;
439 unsigned long y
, gfxscale
;
440 unsigned long misc
, fbactive
;
441 unsigned long scale
, src
;
442 unsigned long irq_ctl
;
443 unsigned long unlock
;
445 hsyncend
= ((READ_REG32 (DC3_H_SYNC_TIMING
) >> 16) & 0xFFF) + 1;
446 vsyncend
= ((READ_REG32 (DC3_V_SYNC_TIMING
) >> 16) & 0xFFF) + 1;
447 vblankend
= ((READ_REG32 (DC3_V_BLANK_TIMING
) >> 16) & 0xFFF) + 1;
448 hblankend
= ((READ_REG32 (DC3_H_BLANK_TIMING
) >> 16) & 0xFFF) + 1;
449 htotal
= ((READ_REG32 (DC3_H_ACTIVE_TIMING
) >> 16) & 0xFFF) + 1;
450 vtotal
= ((READ_REG32 (DC3_V_ACTIVE_TIMING
) >> 16) & 0xFFF) + 1;
451 vblankstart
= (READ_REG32 (DC3_V_BLANK_TIMING
) & 0xFFF) + 1;
452 hblankstart
= (READ_REG32 (DC3_H_BLANK_TIMING
) & 0xFFF) + 1;
453 hactive
= (READ_REG32 (DC3_H_ACTIVE_TIMING
) & 0xFFF) + 1;
454 vactive
= (READ_REG32 (DC3_V_ACTIVE_TIMING
) & 0xFFF) + 1;
455 unlock
= READ_REG32 (DC3_UNLOCK
);
457 /* INCLUDE BORDER IF REQUESTED */
459 if (video_window
->flags
& DF_POSFLAG_INCLUDEBORDER
)
461 border_x
= htotal
- hblankend
;
462 border_y
= vtotal
- vblankend
;
463 hactive
= hblankstart
+ htotal
- hblankend
;
464 vactive
= vblankstart
+ vtotal
- vblankend
;
468 border_x
= border_y
= 0;
471 /* APPLY THE GRAPHICS SCALE */
472 /* Do not alter the input data. */
474 width_copy
= video_window
->width
;
475 height_copy
= video_window
->height
;
476 x_copy
= video_window
->x
;
477 y_copy
= video_window
->y
;
479 misc
= READ_VID32 (DF_VID_MISC
);
480 if (misc
& DF_USER_IMPLICIT_SCALING
)
482 gfxscale
= READ_REG32 (DC3_GFX_SCALE
);
483 fbactive
= READ_REG32 (DC3_FB_ACTIVE
);
485 /* REVERSE ENGINEER THE SCALE FACTOR */
487 scale
= gfxscale
& 0xFFFF;
488 src
= (fbactive
>> 16) + 1;
491 width_copy
= width_copy
* (((0x4000 * src
) / scale
) + 1);
493 x_copy
= x_copy
* (((0x4000 * src
) / scale
) + 1);
497 scale
= gfxscale
>> 16;
498 src
= (fbactive
& 0xFFFF) + 1;
501 height_copy
= height_copy
* (((0x4000 * src
) / scale
) + 1);
503 y_copy
= y_copy
* (((0x4000 * src
) / scale
) + 1);
508 /* HANDLE INTERLACING */
509 /* When the output is interlaced, we must set the position and height */
510 /* on the fields and not on the composite image. */
512 if ((irq_ctl
= READ_REG32 (DC3_IRQ_FILT_CTL
)) & DC3_IRQFILT_INTL_EN
)
514 vsyncend_even
= ((READ_REG32 (DC3_V_SYNC_EVEN
) >> 16) & 0xFFF) + 1;
515 vtotal_even
= ((READ_REG32 (DC3_V_ACTIVE_EVEN
) >> 16) & 0xFFF) + 1;
516 vblankend_even
= ((READ_REG32 (DC3_V_BLANK_EVEN
) >> 16) & 0xFFF) + 1;
517 vactive_even
= (READ_REG32 (DC3_V_ACTIVE_EVEN
) & 0xFFF) + 1;
518 vblankstart_even
= (READ_REG32 (DC3_V_BLANK_EVEN
) & 0xFFF) + 1;
520 if (video_window
->flags
& DF_POSFLAG_INCLUDEBORDER
)
522 border_y_even
= vtotal_even
- vblankend_even
;
523 vactive_even
= vblankstart_even
+ vtotal_even
- vblankend_even
;
528 /* THE ODD FIELD MUST ALWAYS PRECEDE THE EVEN FIELD */
529 /* This implies that we can never start video on an odd y position */
530 /* in the composite image. This is required because the only way to */
531 /* accomplish an odd y start would be to switch the buffer offsets, */
532 /* which could have serious repercussions for genlocked VIP. */
536 /* CALCULATE Y POSITION FOR ODD FIELD */
537 /* Clip the video window to the odd field timings. Note that the */
538 /* height in the odd field may be greater if the video height is */
541 height
= (height_copy
+ 1) >> 1;
542 if ((y
+ height
) > vactive
)
543 height
= vactive
- y
;
545 ystart
= y
+ vtotal_even
- vsyncend_even
+ 1;
546 if (video_window
->flags
& DF_POSFLAG_INCLUDEBORDER
)
547 ystart
-= border_y_even
;
549 yend
= ystart
+ height
;
550 ypos
= (yend
<< 16) | ystart
;
552 /* CALCULATE Y POSITION FOR EVEN FIELD */
554 height_even
= height_copy
>> 1;
555 if ((y
+ height_even
) > vactive_even
)
556 height_even
= vactive_even
- y
;
558 ystart
= y
+ vtotal
- vsyncend
+ 1;
559 if (video_window
->flags
& DF_POSFLAG_INCLUDEBORDER
)
562 yend
= ystart
+ height_even
;
563 ypos_even
= (yend
<< 16) | ystart
;
565 /* CALCULATE ACTUAL FRAME BUFFER HEIGHT */
566 /* The y position and height are used to determine the actual */
567 /* placement of the color key region. The region will either be */
568 /* the sum of the even and odd fields (for interlaced addressing */
569 /* or flicker filtering) or it will be the union of the two (for */
570 /* line doubling). We must also adjust the region such that the */
571 /* origin (0, 0) is centered on the beginning of graphics data. */
572 /* This is only a problem if video is being displayed over the */
575 if ((READ_REG32 (DC3_GENLK_CTL
) & DC3_GC_FLICKER_FILTER_ENABLE
) ||
576 (irq_ctl
& DC3_IRQFILT_INTL_ADDR
))
579 height
+= height_even
;
580 adjust
= border_y
+ border_y_even
;
585 if (height_even
> height
)
586 height
= height_even
;
588 if (video_window
->flags
& DF_POSFLAG_INCLUDEBORDER
)
610 height
= height_copy
;
611 if ((y
+ height
) > vactive
)
612 height
= vactive
- y
;
614 ystart
= y
+ vtotal
- vsyncend
+ 1;
615 if (video_window
->flags
& DF_POSFLAG_INCLUDEBORDER
)
618 yend
= ystart
+ height
;
619 ypos
= (yend
<< 16) | ystart
;
623 /* HORIZONTAL POSITION */
624 /* The horizontal values are identical for the even and odd field. */
627 xstart
= x_copy
+ htotal
- hsyncend
- 14;
628 if (video_window
->flags
& DF_POSFLAG_INCLUDEBORDER
)
633 if ((x_copy
+ width
) > hactive
)
634 width
= hactive
- x_copy
;
636 xend
= xstart
+ width
;
638 /* CALCULATE LEFT CLIPPING PARAMETER */
639 /* The value passed in can be interpreted as destination pixels, in which */
640 /* case the video scale is factored in, or as source pixels, in which case */
641 /* the value is written directly. Also, the display filter's initial read */
642 /* address value is only programmable on 4-pixel increments. However, we */
643 /* can achieve an arbitrary left clip by adjusting the xstart value, as */
644 /* there is a 14-clock delay in which to play. Also, according to the */
645 /* designers, 4:2:0 and 4:2:2 behave identically when setting the initial */
646 /* read address. The addition of scaling further complicates the */
647 /* algorithm. When setting the initial read address, it is in terms of */
648 /* source pixels, while adjusting the xstart value is in destination pixels */
649 /* We may thus not be able to achieve a perfect clipping fit for scaled */
650 /* video. We compensate by including two clipping parameters in our */
651 /* structure. This allows us the user additional control and it allows us */
652 /* to accurately convey to the user the state of clipping on the machine. */
654 initread
= video_window
->left_clip
;
656 if (!(video_window
->flags
& DF_POSFLAG_DIRECTCLIP
))
658 xscale
= READ_VID32 (DF_VIDEO_XSCALE
) & 0xFFFFF;
659 initread
= (initread
* xscale
) / 0x10000;
661 dst_clip
= ((initread
& 3) * 0x10000) / xscale
;
664 dst_clip
= video_window
->dst_clip
;
667 /* We technically have a 14 pixel window in which to play. However, taking */
668 /* the entire 14 pixels makes the video timing a little hairy... Also note */
669 /* that we cannot do this when performing panel centering, as the video */
670 /* would then exceed the mode size. */
674 if (READ_REG32 (DC3_DISPLAY_CFG
) & DC3_DCFG_DCEN
)
679 vcfg
= READ_VID32 (DF_VIDEO_CONFIG
);
680 vcfg
&= ~DF_VCFG_INIT_READ_MASK
;
681 vcfg
|= (initread
>> 2) << 16;
683 /* SET COLOR KEY REGION */
684 /* We are assuming that color keying will never be desired outside */
685 /* of the video region. We adjust the color key region for graphics */
688 gfxscale
= READ_REG32 (DC3_GFX_SCALE
);
690 ckey_x
= ((x_copy
* (gfxscale
& 0xFFFF)) / 0x4000) |
691 ((((x_copy
+ width
) * (gfxscale
& 0xFFFF)) / 0x4000) << 16);
692 ckey_y
= ((y
* (gfxscale
>> 16)) / 0x4000) |
693 ((((y
+ height
) * (gfxscale
>> 16)) / 0x4000) << 16);
695 /* WRITE ALL PARAMETERS AT ONCE */
697 WRITE_REG32 (DC3_UNLOCK
, DC3_UNLOCK_VALUE
);
698 WRITE_REG32 (DC3_CLR_KEY_X
, ckey_x
);
699 WRITE_REG32 (DC3_CLR_KEY_Y
, ckey_y
);
700 WRITE_VID32 (DF_VIDEO_X_POS
, (xend
<< 16) | xstart
);
701 WRITE_VID32 (DF_VIDEO_Y_POS
, ypos
);
702 WRITE_VID32 (DF_VID_YPOS_EVEN
, ypos_even
);
703 WRITE_VID32 (DF_VIDEO_CONFIG
, vcfg
);
704 WRITE_REG32 (DC3_UNLOCK
, unlock
);
706 return CIM_STATUS_OK
;
709 /*---------------------------------------------------------------------------
710 * df_set_video_filter_coefficients
712 * This routine sets the horizontal and vertical filter coefficients for video
713 * scaling. These coefficients are used for upscaling and downscaling video.
714 * If the phase256 parameter is 1, the coefficient arrays are used as single
715 * arrays of 256 phases for both vertical and horizontal scaling. If the
716 * phase256 parameter is clear, the coefficient arrays are used as two 128-phase
717 * arrays. The first 128 entries represent the phases for vertical scaling.
718 * The last 128 entries represent the phases for horizontal scaling.
719 *---------------------------------------------------------------------------*/
721 int df_set_video_filter_coefficients (long taps
[][4], int phase256
)
723 unsigned long scale
, coeff0
, coeff1
;
727 /* SET PHASE COUNT AND CHOOSE COEFFICIENT ARRAY */
729 scale
= READ_VID32 (DF_VIDEO_SCALER
);
732 WRITE_VID32 (DF_VIDEO_SCALER
, (scale
& ~DF_SCALE_128_PHASES
));
733 defaults
= CimarronVideoFilter256
;
737 WRITE_VID32 (DF_VIDEO_SCALER
, (scale
| DF_SCALE_128_PHASES
));
738 defaults
= CimarronVideoFilter128
;
741 /* PROGRAM COEFFICIENTS */
743 for (i
= 0; i
< 256; i
++)
747 coeff0
= defaults
[i
][0];
748 coeff1
= defaults
[i
][1];
752 if (taps
[i
][1] < 0) coeff0
= -taps
[i
][1] | 0x8000;
753 else coeff0
= taps
[i
][1];
757 if (taps
[i
][0] < 0) coeff0
|= -taps
[i
][0] | 0x8000;
758 else coeff0
|= taps
[i
][0];
762 if (taps
[i
][3] < 0) coeff1
= -taps
[i
][3] | 0x8000;
763 else coeff1
= taps
[i
][3];
767 if (taps
[i
][2] < 0) coeff1
|= -taps
[i
][2] | 0x8000;
768 else coeff1
|= taps
[i
][2];
771 WRITE_VID32 ((DF_COEFFICIENT_BASE
+ (i
<< 3)), coeff0
);
772 WRITE_VID32 ((DF_COEFFICIENT_BASE
+ (i
<< 3) + 4), coeff1
);
775 return CIM_STATUS_OK
;
778 /*---------------------------------------------------------------------------
779 * df_set_video_enable
781 * This routine enables or disables the video overlay.
782 *---------------------------------------------------------------------------*/
784 int df_set_video_enable (int enable
, unsigned long flags
)
786 unsigned long vcfg
, lock
, gcfg
;
787 unsigned long dcfg
, vg_ckey
, fifo
= 0;
789 vcfg
= READ_VID32 (DF_VIDEO_CONFIG
);
790 lock
= READ_REG32 (DC3_UNLOCK
);
791 gcfg
= READ_REG32 (DC3_GENERAL_CFG
);
793 /* SET VIDEO FIFO END WATERMARK */
794 /* The video FIFO end watermark is set to 0 when video is disabled */
795 /* to allow low priority transactions in the VG. Otherwise, the */
796 /* priority will be forced high until the VG fills the video FIFO */
797 /* by not fetching video. That could take a while... Note that */
798 /* we set the end priority to be 4 greater than the start. We */
799 /* assume that the start priority has been configured by a modeset. */
801 dcfg
= READ_REG32 (DC3_DISPLAY_CFG
) & ~DC3_DCFG_VFHPEL_MASK
;
804 fifo
= ((dcfg
>> 12) & 0x0000000F) + 4;
808 WRITE_REG32 (DC3_UNLOCK
, DC3_UNLOCK_VALUE
);
809 WRITE_REG32 (DC3_DISPLAY_CFG
, dcfg
| (fifo
<< 16));
811 /* ENABLE OR DISABLE VIDEO */
812 /* The mechanism to fetch video data is enabled first and */
817 WRITE_REG32 (DC3_GENERAL_CFG
, (gcfg
| DC3_GCFG_VIDE
));
818 WRITE_VID32 (DF_VIDEO_CONFIG
, (vcfg
| DF_VCFG_VID_EN
));
820 /* DISABLE COLOR KEYING IF REQUESTED BY THE USER */
822 if (flags
& DF_ENABLEFLAG_NOCOLORKEY
)
824 /* OVERRIDE THE MODE TO COLOR KEYING */
826 dcfg
= READ_VID32 (DF_DISPLAY_CONFIG
);
827 WRITE_VID32 (DF_DISPLAY_CONFIG
, (dcfg
& ~DF_DCFG_VG_CK
));
829 /* DISABLE COLOR KEYING IN THE VG */
831 vg_ckey
= READ_REG32 (DC3_COLOR_KEY
);
832 WRITE_REG32 (DC3_COLOR_KEY
, (vg_ckey
& ~DC3_CLR_KEY_ENABLE
));
834 else if (!(READ_VID32 (DF_DISPLAY_CONFIG
) & DF_DCFG_VG_CK
))
836 /* OTHERWISE RE-ENABLE COLOR KEYING */
838 vg_ckey
= READ_REG32 (DC3_COLOR_KEY
);
839 WRITE_REG32 (DC3_COLOR_KEY
, (vg_ckey
| DC3_CLR_KEY_ENABLE
));
844 WRITE_VID32 (DF_VIDEO_CONFIG
, (vcfg
& ~DF_VCFG_VID_EN
));
845 WRITE_REG32 (DC3_GENERAL_CFG
, (gcfg
& ~DC3_GCFG_VIDE
));
847 /* DISABLE COLOR KEY WINDOW WHEN VIDEO IS INACTIVE */
848 /* To mimic legacy functionality, we disble color keying */
849 /* when the video window is not active. We will restore */
850 /* the enable when video is re-enabled if the appropriate */
851 /* bit is set in display config. */
853 vg_ckey
= READ_REG32 (DC3_COLOR_KEY
);
854 WRITE_REG32 (DC3_COLOR_KEY
, (vg_ckey
& ~DC3_CLR_KEY_ENABLE
));
856 WRITE_REG32 (DC3_UNLOCK
, lock
);
858 return CIM_STATUS_OK
;
861 /*---------------------------------------------------------------------------
862 * df_set_video_color_key
864 * This routine configures the video color/chroma key mechanism.
865 *---------------------------------------------------------------------------*/
867 int df_set_video_color_key (unsigned long key
, unsigned long mask
, int graphics
)
869 unsigned long lock
, vg_ckey
, df_dcfg
;
871 vg_ckey
= READ_REG32 (DC3_COLOR_KEY
);
872 lock
= READ_REG32 (DC3_UNLOCK
);
873 df_dcfg
= READ_VID32 (DF_DISPLAY_CONFIG
);
875 WRITE_REG32 (DC3_UNLOCK
, DC3_UNLOCK_VALUE
);
879 /* COLOR KEY - USE VG HARDWARE */
880 /* Note that color key is never enabled unless a video window */
881 /* is active. This is to match legacy behavior. */
883 df_dcfg
&= ~DF_DCFG_VG_CK
;
884 vg_ckey
= (vg_ckey
& 0xFF000000) | (key
& 0xFFFFFF);
885 if (READ_VID32 (DF_VIDEO_CONFIG
) & DF_VCFG_VID_EN
)
886 vg_ckey
|= DC3_CLR_KEY_ENABLE
;
888 vg_ckey
&= ~DC3_CLR_KEY_ENABLE
;
890 WRITE_VID32 (DF_DISPLAY_CONFIG
, df_dcfg
);
891 WRITE_REG32 (DC3_COLOR_KEY
, vg_ckey
);
892 WRITE_REG32 (DC3_COLOR_MASK
, (mask
& 0xFFFFFF));
896 /* CHROMA KEY - USE DF HARDWARE */
898 df_dcfg
|= DF_DCFG_VG_CK
;
899 vg_ckey
&= ~DC3_CLR_KEY_ENABLE
;
901 WRITE_REG32 (DC3_COLOR_KEY
, vg_ckey
);
902 WRITE_VID32 (DF_DISPLAY_CONFIG
, df_dcfg
);
903 WRITE_VID32 (DF_VIDEO_COLOR_KEY
, (key
& 0xFFFFFF));
904 WRITE_VID32 (DF_VIDEO_COLOR_MASK
, (mask
& 0xFFFFFF));
907 WRITE_REG32 (DC3_UNLOCK
, lock
);
909 return CIM_STATUS_OK
;
912 /*---------------------------------------------------------------------------
913 * df_set_video_palette
915 * This routine loads the video hardware palette. If a NULL pointer is
916 * specified, the palette is bypassed.
917 *--------------------------------------------------------------------------*/
919 int df_set_video_palette (unsigned long *palette
)
921 unsigned long i
, entry
;
922 unsigned long misc
, dcfg
;
924 /* LOAD GEODE LX VIDEO PALETTE */
926 WRITE_VID32 (DF_PALETTE_ADDRESS
, 0);
927 for (i
= 0; i
< 256; i
++)
929 if (palette
) entry
= palette
[i
];
930 else entry
= i
| (i
<< 8) | (i
<< 16);
931 WRITE_VID32 (DF_PALETTE_DATA
, entry
);
934 /* ENABLE THE VIDEO PALETTE */
935 /* Ensure that the video palette has an effect by routing video data */
936 /* through the palette RAM and clearing the 'Bypass Both' bit. */
938 dcfg
= READ_VID32 (DF_DISPLAY_CONFIG
);
939 misc
= READ_VID32 (DF_VID_MISC
);
941 dcfg
|= DF_DCFG_GV_PAL_BYP
;
942 misc
&= ~DF_GAMMA_BYPASS_BOTH
;
944 WRITE_VID32 (DF_DISPLAY_CONFIG
, dcfg
);
945 WRITE_VID32 (DF_VID_MISC
, misc
);
947 return CIM_STATUS_OK
;
950 /*---------------------------------------------------------------------------
951 * df_set_video_palette_entry
953 * This routine loads a single entry of the video hardware palette.
954 *--------------------------------------------------------------------------*/
956 int df_set_video_palette_entry (unsigned long index
, unsigned long palette
)
958 unsigned long misc
, dcfg
;
961 return CIM_STATUS_INVALIDPARAMS
;
963 /* SET A SINGLE ENTRY */
965 WRITE_VID32 (DF_PALETTE_ADDRESS
, index
);
966 WRITE_VID32 (DF_PALETTE_DATA
, palette
);
968 /* ENABLE THE VIDEO PALETTE */
969 /* Ensure that the video palette has an effect by routing video data */
970 /* through the palette RAM and clearing the 'Bypass Both' bit. */
972 dcfg
= READ_VID32 (DF_DISPLAY_CONFIG
);
973 misc
= READ_VID32 (DF_VID_MISC
);
975 dcfg
|= DF_DCFG_GV_PAL_BYP
;
976 misc
&= ~DF_GAMMA_BYPASS_BOTH
;
978 WRITE_VID32 (DF_DISPLAY_CONFIG
, dcfg
);
979 WRITE_VID32 (DF_VID_MISC
, misc
);
981 return CIM_STATUS_OK
;
984 /*---------------------------------------------------------------------------
985 * df_configure_video_cursor_color_key
987 * This routine configures the hardware video cursor color key mechanism.
988 *--------------------------------------------------------------------------*/
990 int df_configure_video_cursor_color_key (DF_VIDEO_CURSOR_PARAMS
*cursor_color_key
)
994 if (cursor_color_key
->select_color2
>= 24)
995 return CIM_STATUS_INVALIDPARAMS
;
997 key
= READ_VID32 (DF_CURSOR_COLOR_KEY
) & DF_CURSOR_COLOR_KEY_ENABLE
;
998 key
= key
| (cursor_color_key
->key
& 0xFFFFFF) | (cursor_color_key
->select_color2
<< 24);
1000 WRITE_VID32 (DF_CURSOR_COLOR_KEY
, key
);
1001 WRITE_VID32 (DF_CURSOR_COLOR_MASK
, (cursor_color_key
->mask
& 0xFFFFFF));
1002 WRITE_VID32 (DF_CURSOR_COLOR_1
, (cursor_color_key
->color1
& 0xFFFFFF));
1003 WRITE_VID32 (DF_CURSOR_COLOR_2
, (cursor_color_key
->color2
& 0xFFFFFF));
1005 return CIM_STATUS_OK
;
1008 /*---------------------------------------------------------------------------
1009 * df_set_video_cursor_color_key_enable
1011 * This routine enables or disables the video cursor color key.
1012 *--------------------------------------------------------------------------*/
1014 int df_set_video_cursor_color_key_enable (int enable
)
1016 unsigned long temp
= READ_VID32 (DF_CURSOR_COLOR_KEY
);
1018 if (enable
) temp
|= DF_CURSOR_COLOR_KEY_ENABLE
;
1019 else temp
&= ~DF_CURSOR_COLOR_KEY_ENABLE
;
1021 WRITE_VID32 (DF_CURSOR_COLOR_KEY
, temp
);
1023 return CIM_STATUS_OK
;
1026 /*---------------------------------------------------------------------------
1027 * df_configure_alpha_window
1029 * This routine configures one of the three hardware alpha regions.
1030 *--------------------------------------------------------------------------*/
1032 int df_configure_alpha_window (int window
, DF_ALPHA_REGION_PARAMS
*alpha_data
)
1034 unsigned long vsyncend_even
, vtotal_even
, vactive_even
;
1035 unsigned long hsyncend
, htotal
, hactive
;
1036 unsigned long vsyncend
, vtotal
, vactive
;
1037 unsigned long alpha_ctl
, pos
;
1038 unsigned long hadjust
, vadjust
;
1039 unsigned long y
, height
;
1040 unsigned long xstart
, xend
;
1041 unsigned long ystart
, yend
;
1042 unsigned long x_copy
, width_copy
;
1043 unsigned long y_copy
, height_copy
;
1044 unsigned long scale
, src
, misc
;
1045 unsigned long gfxscale
, fbactive
;
1046 unsigned long color
;
1049 return CIM_STATUS_INVALIDPARAMS
;
1051 hsyncend
= ((READ_REG32 (DC3_H_SYNC_TIMING
) >> 16) & 0xFFF) + 1;
1052 vsyncend
= ((READ_REG32 (DC3_V_SYNC_TIMING
) >> 16) & 0xFFF) + 1;
1053 htotal
= ((READ_REG32 (DC3_H_ACTIVE_TIMING
) >> 16) & 0xFFF) + 1;
1054 vtotal
= ((READ_REG32 (DC3_V_ACTIVE_TIMING
) >> 16) & 0xFFF) + 1;
1055 hactive
= (READ_REG32 (DC3_H_ACTIVE_TIMING
) & 0xFFF) + 1;
1056 vactive
= (READ_REG32 (DC3_V_ACTIVE_TIMING
) & 0xFFF) + 1;
1058 /* APPLY THE GRAPHICS SCALE */
1060 width_copy
= alpha_data
->width
;
1061 height_copy
= alpha_data
->height
;
1062 x_copy
= alpha_data
->x
;
1063 y_copy
= alpha_data
->y
;
1065 misc
= READ_VID32 (DF_VID_MISC
);
1066 if (misc
& DF_USER_IMPLICIT_SCALING
)
1068 gfxscale
= READ_REG32 (DC3_GFX_SCALE
);
1069 fbactive
= READ_REG32 (DC3_FB_ACTIVE
);
1071 /* REVERSE ENGINEER THE SCALE FACTOR */
1073 scale
= gfxscale
& 0xFFFF;
1074 src
= (fbactive
>> 16) + 1;
1075 if (scale
!= 0x4000)
1077 width_copy
= width_copy
* (((0x4000 * src
) / scale
) + 1);
1079 x_copy
= x_copy
* (((0x4000 * src
) / scale
) + 1);
1083 scale
= gfxscale
>> 16;
1084 src
= (fbactive
& 0xFFFF) + 1;
1085 if (scale
!= 0x4000)
1087 height_copy
= height_copy
* (((0x4000 * src
) / scale
) + 1);
1089 y_copy
= y_copy
* (((0x4000 * src
) / scale
) + 1);
1095 /* Priority is the only alpha parameter that is not in a register that */
1096 /* can be indexed based on the alpha window number. */
1098 pos
= 16 + (window
<< 1);
1099 alpha_ctl
= READ_VID32 (DF_VID_ALPHA_CONTROL
) & ~(3L << pos
);
1100 alpha_ctl
|= (alpha_data
->priority
& 3) << pos
;
1101 WRITE_VID32 (DF_VID_ALPHA_CONTROL
, alpha_ctl
);
1103 /* HANDLE INTERLACED MODES */
1105 if (READ_REG32 (DC3_IRQ_FILT_CTL
) & DC3_IRQFILT_INTL_EN
)
1107 vsyncend_even
= ((READ_REG32 (DC3_V_SYNC_EVEN
) >> 16) & 0xFFF) + 1;
1108 vtotal_even
= ((READ_REG32 (DC3_V_ACTIVE_EVEN
) >> 16) & 0xFFF) + 1;
1109 vactive_even
= (READ_REG32 (DC3_V_ACTIVE_EVEN
) & 0xFFF) + 1;
1113 /* SET Y POSITION FOR ODD FIELD */
1115 height
= (height_copy
+ 1) >> 1;
1116 vadjust
= vtotal_even
- vsyncend_even
+ 1;
1118 ystart
= y
+ vadjust
;
1119 yend
= y
+ vadjust
+ height
;
1121 if (yend
> (vactive
+ vadjust
))
1122 yend
= vactive
+ vadjust
;
1124 WRITE_VID32 ((DF_ALPHA_YPOS_1
+ (window
<< 5)), (ystart
| (yend
<< 16)));
1126 /* SET Y POSITION FOR EVEN FIELD */
1128 height
= height_copy
>> 1;
1129 vadjust
= vtotal
- vsyncend
+ 1;
1131 ystart
= y
+ vadjust
;
1132 yend
= y
+ vadjust
+ height
;
1134 if (yend
> (vactive_even
+ vadjust
))
1135 yend
= vactive_even
+ vadjust
;
1137 WRITE_VID32 ((DF_VID_ALPHA_Y_EVEN_1
+ (window
<< 3)), (ystart
| (yend
<< 16)));
1142 height
= height_copy
;
1143 vadjust
= vtotal
- vsyncend
+ 1;
1145 ystart
= y
+ vadjust
;
1146 yend
= y
+ vadjust
+ height
;
1148 if (yend
> (vactive
+ vadjust
))
1149 yend
= vactive
+ vadjust
;
1151 WRITE_VID32 ((DF_ALPHA_YPOS_1
+ (window
<< 5)), (ystart
| (yend
<< 16)));
1154 /* SET ALPHA X POSITION */
1155 /* The x position is the same for both the odd and even fields. */
1157 hadjust
= htotal
- hsyncend
- 2;
1159 xstart
= x_copy
+ hadjust
;
1160 xend
= x_copy
+ hadjust
+ width_copy
;
1162 if (xend
> (hactive
+ hadjust
))
1163 xend
= hactive
+ hadjust
;
1165 WRITE_VID32 ((DF_ALPHA_XPOS_1
+ (window
<< 5)), (xstart
| (xend
<< 16)));
1167 /* SET COLOR REGISTER */
1169 color
= alpha_data
->color
& 0xFFFFFF;
1170 if (alpha_data
->flags
& DF_ALPHAFLAG_COLORENABLED
)
1171 color
|= DF_ALPHA_COLOR_ENABLE
;
1173 WRITE_VID32 ((DF_ALPHA_COLOR_1
+ (window
<< 5)), color
);
1175 /* SET ALPHA VALUE, DELTA AND PER PIXEL */
1177 alpha_ctl
= READ_VID32 (DF_ALPHA_CONTROL_1
+ (window
<< 5)) & DF_ACTRL_WIN_ENABLE
;
1178 alpha_ctl
|= (alpha_data
->alpha_value
& 0xFF) | DF_ACTRL_LOAD_ALPHA
|
1179 (((unsigned long)alpha_data
->delta
& 0xFF) << 8);
1180 if (alpha_data
->flags
& DF_ALPHAFLAG_PERPIXELENABLED
)
1181 alpha_ctl
|= DF_ACTRL_PERPIXEL_EN
;
1183 WRITE_VID32 ((DF_ALPHA_CONTROL_1
+ (window
<< 5)), alpha_ctl
);
1185 return CIM_STATUS_OK
;
1188 /*---------------------------------------------------------------------------
1189 * df_set_alpha_window_enable
1191 * This routine enables or disables one of the three hardware alpha regions.
1192 *--------------------------------------------------------------------------*/
1194 int df_set_alpha_window_enable (int window
, int enable
)
1196 unsigned long alpha_ctl
;
1199 return CIM_STATUS_INVALIDPARAMS
;
1201 alpha_ctl
= READ_VID32 (DF_ALPHA_CONTROL_1
+ (window
<< 5));
1202 if (enable
) alpha_ctl
|= DF_ACTRL_WIN_ENABLE
;
1203 else alpha_ctl
&= ~DF_ACTRL_WIN_ENABLE
;
1204 WRITE_VID32 ((DF_ALPHA_CONTROL_1
+ (window
<< 5)), alpha_ctl
);
1206 return CIM_STATUS_OK
;
1209 /*---------------------------------------------------------------------------
1210 * df_set_no_ck_outside_alpha
1212 * This function affects how color/chroma keying is performed inside the video
1215 * If enable is 1, color/chroma key comparison is performed only inside
1216 * the enabled alpha windows. Outside the enabled alpha windows, video
1217 * is displayed if color keying is enabled, or graphics is displayed if
1218 * chroma keying is enabled.
1219 * If enable is 0, color/chroma key comparison is performed inside the
1220 * entire video window.
1221 *--------------------------------------------------------------------------*/
1223 int df_set_no_ck_outside_alpha (int enable
)
1225 unsigned long value
;
1227 value
= READ_VID32 (DF_VID_ALPHA_CONTROL
);
1228 if (enable
) value
|= DF_NO_CK_OUTSIDE_ALPHA
;
1229 else value
&= ~DF_NO_CK_OUTSIDE_ALPHA
;
1230 WRITE_VID32 (DF_VID_ALPHA_CONTROL
, value
);
1232 return CIM_STATUS_OK
;
1235 /*---------------------------------------------------------------------------
1236 * df_set_video_request
1238 * This routine sets the horizontal (pixel) and vertical (line) video request
1240 *--------------------------------------------------------------------------*/
1242 int df_set_video_request (unsigned long x
, unsigned long y
)
1244 unsigned long htotal
, hsyncend
;
1245 unsigned long vtotal
, vsyncend
;
1247 hsyncend
= ((READ_REG32 (DC3_H_SYNC_TIMING
) >> 16) & 0xFFF) + 1;
1248 vsyncend
= ((READ_REG32 (DC3_V_SYNC_TIMING
) >> 16) & 0xFFF) + 1;
1249 htotal
= ((READ_REG32 (DC3_H_ACTIVE_TIMING
) >> 16) & 0xFFF) + 1;
1250 vtotal
= ((READ_REG32 (DC3_V_ACTIVE_TIMING
) >> 16) & 0xFFF) + 1;
1252 /* SET DISPLAY FILTER VIDEO REQUEST */
1254 x
+= htotal
- hsyncend
- 2;
1255 y
+= vtotal
- vsyncend
+ 1;
1257 if (x
>= 0x1000 || y
>= 0x800)
1258 return CIM_STATUS_INVALIDPARAMS
;
1260 WRITE_VID32(DF_VIDEO_REQUEST
, (y
| (x
<< 16)));
1261 return CIM_STATUS_OK
;
1264 /*---------------------------------------------------------------------------
1265 * df_set_output_color_space
1267 * This routine sets the color space used when combining graphics and video.
1268 *--------------------------------------------------------------------------*/
1270 int df_set_output_color_space (int color_space
)
1272 unsigned long alpha_ctl
;
1274 alpha_ctl
= READ_VID32 (DF_VID_ALPHA_CONTROL
);
1276 alpha_ctl
&= ~(DF_CSC_GRAPHICS_RGB_TO_YUV
| DF_CSC_VIDEO_YUV_TO_RGB
|
1277 DF_HD_GRAPHICS
| DF_YUV_CSC_EN
| DF_ALPHA_DRGB
);
1280 /* Enable YUV->RGB CSC if necessary and enable alpha output if */
1283 if (color_space
== DF_OUTPUT_RGB
|| color_space
== DF_OUTPUT_ARGB
)
1285 if (!(alpha_ctl
& DF_VIDEO_INPUT_IS_RGB
))
1286 alpha_ctl
|= DF_CSC_VIDEO_YUV_TO_RGB
;
1288 if (color_space
== DF_OUTPUT_ARGB
)
1289 alpha_ctl
|= DF_ALPHA_DRGB
;
1293 /* Enable YUV->YUV CSC if necessary and enable RGB->YUV CSC. */
1295 else if (color_space
== DF_OUTPUT_SDTV
|| color_space
== DF_OUTPUT_HDTV
)
1297 alpha_ctl
|= DF_CSC_GRAPHICS_RGB_TO_YUV
;
1299 if ( ((alpha_ctl
& DF_HD_VIDEO
) && color_space
== DF_OUTPUT_SDTV
) ||
1300 (!(alpha_ctl
& DF_HD_VIDEO
) && color_space
== DF_OUTPUT_HDTV
))
1302 alpha_ctl
|= DF_YUV_CSC_EN
;
1305 if (color_space
== DF_OUTPUT_HDTV
)
1306 alpha_ctl
|= DF_HD_GRAPHICS
;
1309 return CIM_STATUS_INVALIDPARAMS
;
1311 WRITE_VID32 (DF_VID_ALPHA_CONTROL
, alpha_ctl
);
1313 return CIM_STATUS_OK
;
1316 /*---------------------------------------------------------------------------
1317 * df_set_output_path
1319 * This routine changes the current output path in the display filter.
1320 *--------------------------------------------------------------------------*/
1322 int df_set_output_path (int format
)
1324 unsigned long panel_tim2
, panel_pm
;
1325 unsigned long output
= 0;
1328 msr_read64 (MSR_DEVICE_GEODELX_DF
, MSR_GEODELINK_CONFIG
, &msr_value
);
1329 msr_value
.low
&= ~(DF_SIMULTANEOUS_CRT_FP
| DF_CONFIG_OUTPUT_MASK
);
1330 panel_tim2
= READ_VID32 (DF_VIDEO_PANEL_TIM2
);
1331 panel_pm
= READ_VID32 (DF_POWER_MANAGEMENT
);
1333 if (format
== DF_DISPLAY_CRT
)
1336 /* When CRT output is selected, the DF drives the DISP_EN signal */
1337 /* with the CRT display enable. As a consequence, systems that */
1338 /* wire the DISP_EN signal to the TFT backlight control will not */
1339 /* be able to set CRT-only output without leaving the backlight */
1340 /* enabled. To workaround this issue, we are setting simultaneous */
1341 /* TFT/CRT and disabling the TFT logic. The only caveat to this */
1342 /* is that some TFT pins are shared with VIP 601 pins. VIP 601 */
1343 /* will thus not work when in this pseudo-CRT mode. To address */
1344 /* THAT issue, normal CRT mode sets (in cim_vg.c) will set CRT */
1345 /* as the DF output format. This will allow VIP 601 on CRT-only */
1346 /* systems without a TFT attached. */
1348 panel_pm
&= ~DF_PM_PANEL_ON
;
1349 panel_tim2
|= DF_PMTIM2_TFT_PASSHTHROUGH
;
1350 output
= DF_OUTPUT_PANEL
| DF_SIMULTANEOUS_CRT_FP
;
1352 else if (format
== DF_DISPLAY_FP
|| format
== DF_DISPLAY_CRT_FP
)
1354 panel_pm
|= DF_PM_PANEL_ON
;
1355 panel_tim2
&= ~DF_PMTIM2_TFT_PASSHTHROUGH
;
1357 if (format
== DF_DISPLAY_FP
)
1358 output
= DF_OUTPUT_PANEL
;
1359 else if (format
== DF_DISPLAY_CRT_FP
)
1360 output
= DF_OUTPUT_PANEL
| DF_SIMULTANEOUS_CRT_FP
;
1366 case DF_DISPLAY_VOP
: output
= DF_OUTPUT_VOP
; break;
1367 case DF_DISPLAY_DRGB
: output
= DF_OUTPUT_DRGB
; break;
1368 case DF_DISPLAY_CRT_DRGB
: output
= DF_OUTPUT_DRGB
| DF_SIMULTANEOUS_CRT_FP
; break;
1370 return CIM_STATUS_INVALIDPARAMS
;
1373 msr_value
.low
|= output
;
1374 msr_write64 (MSR_DEVICE_GEODELX_DF
, MSR_GEODELINK_CONFIG
, &msr_value
);
1375 WRITE_VID32 (DF_VIDEO_PANEL_TIM2
, panel_tim2
);
1376 WRITE_VID32 (DF_POWER_MANAGEMENT
, panel_pm
);
1378 return CIM_STATUS_OK
;
1381 /*---------------------------------------------------------------------------
1382 * df_test_video_flip_status
1384 * This routine tests if a new video offset has been latched.
1385 *--------------------------------------------------------------------------*/
1387 unsigned long df_test_video_flip_status (void)
1389 return (READ_REG32 (DC3_LINE_CNT_STATUS
) & DC3_LNCNT_VFLIP
);
1392 /*---------------------------------------------------------------------------
1395 * This routine saves all persistent DF state information.
1396 *---------------------------------------------------------------------------*/
1398 int df_save_state (DF_SAVE_RESTORE
*df_state
)
1402 /* READ ALL DF REGISTERS */
1404 df_state
->vcfg
= READ_VID32 (DF_VIDEO_CONFIG
);
1405 df_state
->dcfg
= READ_VID32 (DF_DISPLAY_CONFIG
);
1406 df_state
->video_x
= READ_VID32 (DF_VIDEO_X_POS
);
1407 df_state
->video_y
= READ_VID32 (DF_VIDEO_Y_POS
);
1408 df_state
->video_scaler
= READ_VID32 (DF_VIDEO_SCALER
);
1409 df_state
->video_color_key
= READ_VID32 (DF_VIDEO_COLOR_KEY
);
1410 df_state
->video_color_mask
= READ_VID32 (DF_VIDEO_COLOR_MASK
);
1411 df_state
->sat_limit
= READ_VID32 (DF_SATURATION_LIMIT
);
1412 df_state
->vid_misc
= READ_VID32 (DF_VID_MISC
);
1413 df_state
->video_yscale
= READ_VID32 (DF_VIDEO_YSCALE
);
1414 df_state
->video_xscale
= READ_VID32 (DF_VIDEO_XSCALE
);
1415 df_state
->vid_alpha_control
= READ_VID32 (DF_VID_ALPHA_CONTROL
);
1416 df_state
->cursor_key
= READ_VID32 (DF_CURSOR_COLOR_KEY
);
1417 df_state
->cursor_mask
= READ_VID32 (DF_CURSOR_COLOR_MASK
);
1418 df_state
->cursor_color1
= READ_VID32 (DF_CURSOR_COLOR_1
);
1419 df_state
->cursor_color2
= READ_VID32 (DF_CURSOR_COLOR_2
);
1420 df_state
->alpha_xpos1
= READ_VID32 (DF_ALPHA_XPOS_1
);
1421 df_state
->alpha_ypos1
= READ_VID32 (DF_ALPHA_YPOS_1
);
1422 df_state
->alpha_color1
= READ_VID32 (DF_ALPHA_COLOR_1
);
1423 df_state
->alpha_control1
= READ_VID32 (DF_ALPHA_CONTROL_1
);
1424 df_state
->alpha_xpos2
= READ_VID32 (DF_ALPHA_XPOS_2
);
1425 df_state
->alpha_ypos2
= READ_VID32 (DF_ALPHA_YPOS_2
);
1426 df_state
->alpha_color2
= READ_VID32 (DF_ALPHA_COLOR_2
);
1427 df_state
->alpha_control2
= READ_VID32 (DF_ALPHA_CONTROL_2
);
1428 df_state
->alpha_xpos3
= READ_VID32 (DF_ALPHA_XPOS_3
);
1429 df_state
->alpha_ypos3
= READ_VID32 (DF_ALPHA_YPOS_3
);
1430 df_state
->alpha_color3
= READ_VID32 (DF_ALPHA_COLOR_3
);
1431 df_state
->alpha_control3
= READ_VID32 (DF_ALPHA_CONTROL_3
);
1432 df_state
->vid_request
= READ_VID32 (DF_VIDEO_REQUEST
);
1433 df_state
->vid_ypos_even
= READ_VID32 (DF_VID_YPOS_EVEN
);
1434 df_state
->alpha_ypos_even1
= READ_VID32 (DF_VID_ALPHA_Y_EVEN_1
);
1435 df_state
->alpha_ypos_even2
= READ_VID32 (DF_VID_ALPHA_Y_EVEN_2
);
1436 df_state
->alpha_ypos_even3
= READ_VID32 (DF_VID_ALPHA_Y_EVEN_3
);
1437 df_state
->panel_tim1
= READ_VID32 (DF_VIDEO_PANEL_TIM1
);
1438 df_state
->panel_tim2
= READ_VID32 (DF_VIDEO_PANEL_TIM2
);
1439 df_state
->panel_pm
= READ_VID32 (DF_POWER_MANAGEMENT
);
1440 df_state
->panel_dither
= READ_VID32 (DF_DITHER_CONTROL
);
1442 /* READ DF PALETTE */
1444 WRITE_VID32 (DF_PALETTE_ADDRESS
, 0);
1445 for (i
= 0; i
< 256; i
++)
1446 df_state
->palette
[i
] = READ_VID32 (DF_PALETTE_DATA
);
1448 /* READ FILTER COEFFICIENTS */
1450 for (i
= 0; i
< 512; i
++)
1451 df_state
->coefficients
[i
] = READ_VID32 (DF_COEFFICIENT_BASE
+ (i
<< 2));
1453 /* READ ALL DF MSRS */
1455 msr_read64 (MSR_DEVICE_GEODELX_DF
, MSR_GEODELINK_CAP
, &(df_state
->msr_cap
));
1456 msr_read64 (MSR_DEVICE_GEODELX_DF
, MSR_GEODELINK_CONFIG
, &(df_state
->msr_config
));
1457 msr_read64 (MSR_DEVICE_GEODELX_DF
, MSR_GEODELINK_SMI
, &(df_state
->msr_smi
));
1458 msr_read64 (MSR_DEVICE_GEODELX_DF
, MSR_GEODELINK_ERROR
, &(df_state
->msr_error
));
1459 msr_read64 (MSR_DEVICE_GEODELX_DF
, MSR_GEODELINK_PM
, &(df_state
->msr_pm
));
1460 msr_read64 (MSR_DEVICE_GEODELX_DF
, MSR_GEODELINK_DIAG
, &(df_state
->msr_diag
));
1461 msr_read64 (MSR_DEVICE_GEODELX_DF
, DF_MBD_MSR_DIAG_DF
, &(df_state
->msr_df_diag
));
1462 msr_read64 (MSR_DEVICE_GEODELX_DF
, DF_MSR_PAD_SEL
, &(df_state
->msr_pad_sel
));
1464 return CIM_STATUS_OK
;
1467 /*---------------------------------------------------------------------------
1470 * This routine restores all persistent DF state information.
1471 *---------------------------------------------------------------------------*/
1473 int df_restore_state (DF_SAVE_RESTORE
*df_state
)
1477 /* CLEAR VCFG AND DCFG */
1479 WRITE_VID32 (DF_VIDEO_CONFIG
, 0);
1480 WRITE_VID32 (DF_DISPLAY_CONFIG
, 0);
1482 /* RESTORE DF MSRS */
1484 msr_write64 (MSR_DEVICE_GEODELX_DF
, MSR_GEODELINK_CAP
, &(df_state
->msr_cap
));
1485 msr_write64 (MSR_DEVICE_GEODELX_DF
, MSR_GEODELINK_CONFIG
, &(df_state
->msr_config
));
1486 msr_write64 (MSR_DEVICE_GEODELX_DF
, MSR_GEODELINK_SMI
, &(df_state
->msr_smi
));
1487 msr_write64 (MSR_DEVICE_GEODELX_DF
, MSR_GEODELINK_ERROR
, &(df_state
->msr_error
));
1488 msr_write64 (MSR_DEVICE_GEODELX_DF
, MSR_GEODELINK_PM
, &(df_state
->msr_pm
));
1489 msr_write64 (MSR_DEVICE_GEODELX_DF
, MSR_GEODELINK_DIAG
, &(df_state
->msr_diag
));
1490 msr_write64 (MSR_DEVICE_GEODELX_DF
, DF_MBD_MSR_DIAG_DF
, &(df_state
->msr_df_diag
));
1491 msr_write64 (MSR_DEVICE_GEODELX_DF
, DF_MSR_PAD_SEL
, &(df_state
->msr_pad_sel
));
1493 /* RESTORE ALL DF REGISTERS */
1495 WRITE_VID32 (DF_VIDEO_X_POS
, df_state
->video_x
);
1496 WRITE_VID32 (DF_VIDEO_Y_POS
, df_state
->video_y
);
1497 WRITE_VID32 (DF_VIDEO_SCALER
, df_state
->video_scaler
);
1498 WRITE_VID32 (DF_VIDEO_COLOR_KEY
, df_state
->video_color_key
);
1499 WRITE_VID32 (DF_VIDEO_COLOR_MASK
, df_state
->video_color_mask
);
1500 WRITE_VID32 (DF_SATURATION_LIMIT
, df_state
->sat_limit
);
1501 WRITE_VID32 (DF_VID_MISC
, df_state
->vid_misc
);
1502 WRITE_VID32 (DF_VIDEO_YSCALE
, df_state
->video_yscale
);
1503 WRITE_VID32 (DF_VIDEO_XSCALE
, df_state
->video_xscale
);
1504 WRITE_VID32 (DF_VID_ALPHA_CONTROL
, df_state
->vid_alpha_control
);
1505 WRITE_VID32 (DF_CURSOR_COLOR_KEY
, df_state
->cursor_key
);
1506 WRITE_VID32 (DF_CURSOR_COLOR_MASK
, df_state
->cursor_mask
);
1507 WRITE_VID32 (DF_CURSOR_COLOR_1
, df_state
->cursor_color1
);
1508 WRITE_VID32 (DF_CURSOR_COLOR_2
, df_state
->cursor_color2
);
1509 WRITE_VID32 (DF_ALPHA_XPOS_1
, df_state
->alpha_xpos1
);
1510 WRITE_VID32 (DF_ALPHA_YPOS_1
, df_state
->alpha_ypos1
);
1511 WRITE_VID32 (DF_ALPHA_COLOR_1
, df_state
->alpha_color1
);
1512 WRITE_VID32 (DF_ALPHA_CONTROL_1
, df_state
->alpha_control1
);
1513 WRITE_VID32 (DF_ALPHA_XPOS_2
, df_state
->alpha_xpos2
);
1514 WRITE_VID32 (DF_ALPHA_YPOS_2
, df_state
->alpha_ypos2
);
1515 WRITE_VID32 (DF_ALPHA_COLOR_2
, df_state
->alpha_color2
);
1516 WRITE_VID32 (DF_ALPHA_CONTROL_2
, df_state
->alpha_control1
);
1517 WRITE_VID32 (DF_ALPHA_XPOS_3
, df_state
->alpha_xpos3
);
1518 WRITE_VID32 (DF_ALPHA_YPOS_3
, df_state
->alpha_ypos3
);
1519 WRITE_VID32 (DF_ALPHA_COLOR_3
, df_state
->alpha_color3
);
1520 WRITE_VID32 (DF_ALPHA_CONTROL_3
, df_state
->alpha_control3
);
1521 WRITE_VID32 (DF_VIDEO_REQUEST
, df_state
->vid_request
);
1522 WRITE_VID32 (DF_VID_YPOS_EVEN
, df_state
->vid_ypos_even
);
1523 WRITE_VID32 (DF_VID_ALPHA_Y_EVEN_1
, df_state
->alpha_ypos_even1
);
1524 WRITE_VID32 (DF_VID_ALPHA_Y_EVEN_2
, df_state
->alpha_ypos_even2
);
1525 WRITE_VID32 (DF_VID_ALPHA_Y_EVEN_3
, df_state
->alpha_ypos_even3
);
1526 WRITE_VID32 (DF_VIDEO_PANEL_TIM1
, df_state
->panel_tim1
);
1527 WRITE_VID32 (DF_VIDEO_PANEL_TIM2
, df_state
->panel_tim2
);
1528 WRITE_VID32 (DF_POWER_MANAGEMENT
, df_state
->panel_pm
);
1529 WRITE_VID32 (DF_DITHER_CONTROL
, df_state
->panel_dither
);
1531 /* RESTORE DF PALETTE */
1533 WRITE_VID32 (DF_PALETTE_ADDRESS
, 0);
1534 for (i
= 0; i
< 256; i
++)
1535 WRITE_VID32 (DF_PALETTE_DATA
, df_state
->palette
[i
]);
1537 /* RESTORE FILTER COEFFICIENTS */
1539 for (i
= 0; i
< 512; i
++)
1540 WRITE_VID32 (DF_COEFFICIENT_BASE
+ (i
<< 2), df_state
->coefficients
[i
]);
1542 /* RESTORE DCFG AND VCFG */
1544 WRITE_VID32 (DF_DISPLAY_CONFIG
, df_state
->dcfg
);
1545 WRITE_VID32 (DF_VIDEO_CONFIG
, df_state
->vcfg
);
1547 return CIM_STATUS_OK
;
1550 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1551 * CIMARRON DF READ ROUTINES
1552 * These routines are included for use in diagnostics or when debugging. They
1553 * can be optionally excluded from a project.
1554 *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
1556 #if CIMARRON_INCLUDE_DF_READ_ROUTINES
1558 /*---------------------------------------------------------------------------
1559 * df_read_composite_crc
1561 * This routine reads the CRC of the combination of graphics/video data. This
1562 * CRC checks data immediately before the CRT DACs.
1563 *---------------------------------------------------------------------------*/
1565 unsigned long df_read_composite_crc (int crc_source
)
1569 unsigned long interlaced
;
1570 unsigned long line
, field
;
1571 unsigned long timeout
= 1000;
1573 if (!(READ_REG32 (DC3_DISPLAY_CFG
) & DC3_DCFG_TGEN
))
1576 /* ENABLE 32-BIT CRCS */
1578 msr_read64 (MSR_DEVICE_GEODELX_DF
, DF_MBD_MSR_DIAG_DF
, &msr_value
);
1579 msr_value
.low
|= DF_DIAG_32BIT_CRC
;
1580 msr_write64 (MSR_DEVICE_GEODELX_DF
, DF_MBD_MSR_DIAG_DF
, &msr_value
);
1584 WRITE_VID32 (DF_VID_CRC
, 0);
1586 /* WAIT FOR THE RESET TO BE LATCHED */
1588 while ((READ_VID32 (DF_VID_CRC32
) != 0x00000001) && timeout
)
1591 /* WAIT FOR THE CORRECT FIELD */
1592 /* We use the VG line count and field indicator to determine when */
1593 /* to kick off a CRC. */
1595 if (crc_source
& DF_CRC_SOURCE_EVEN
) field
= 0;
1596 else field
= DC3_LNCNT_EVEN_FIELD
;
1598 if ((interlaced
= (READ_REG32 (DC3_IRQ_FILT_CTL
) & DC3_IRQFILT_INTL_EN
)))
1600 /* WAIT FOR THE BEGINNING OF THE FIELD (LINE 1-5) */
1601 /* Note that we wait for the field to be odd when CRCing the even */
1602 /* field and vice versa. This is because the CRC will not begin */
1603 /* until the following field. */
1607 line
= READ_REG32 (DC3_LINE_CNT_STATUS
);
1608 } while ((line
& DC3_LNCNT_EVEN_FIELD
) != field
||
1609 ((line
& DC3_LNCNT_V_LINE_CNT
) >> 16) < 10 ||
1610 ((line
& DC3_LNCNT_V_LINE_CNT
) >> 16) > 15);
1614 /* NON-INTERLACED - EVEN FIELD CRCS ARE INVALID */
1616 if (crc_source
& DF_CRC_SOURCE_EVEN
)
1620 /* ENABLE THE CRC */
1622 WRITE_VID32 (DF_VID_CRC
, 1);
1624 /* WAIT FOR THE CRC TO BE COMPLETED */
1626 while (!(READ_VID32 (DF_VID_CRC
) & 4))
1629 crc
= READ_VID32 (DF_VID_CRC32
);
1634 /*---------------------------------------------------------------------------
1635 * df_read_composite_window_crc
1637 * This routine reads the CRC of a rectangular subsection of the combination
1638 * of graphics/video data.
1639 *---------------------------------------------------------------------------*/
1641 unsigned long df_read_composite_window_crc (unsigned long x
, unsigned long y
,
1642 unsigned long width
, unsigned long height
, int source
)
1645 unsigned long interlaced
;
1646 unsigned long line
, field
;
1647 unsigned long crc
= 0;
1648 unsigned long hsyncend
, htotal
, hsyncstart
;
1649 unsigned long vsyncend
, vtotal
, vsyncstart
;
1650 unsigned long hblankstart
, hactive
;
1651 unsigned long vblankstart
, vactive
;
1653 hsyncend
= ((READ_REG32 (DC3_H_SYNC_TIMING
) >> 16) & 0xFFF) + 1;
1654 htotal
= ((READ_REG32 (DC3_H_ACTIVE_TIMING
) >> 16) & 0xFFF) + 1;
1655 hsyncstart
= (READ_REG32 (DC3_H_SYNC_TIMING
) & 0xFFF) + 1;
1656 hactive
= (READ_REG32 (DC3_H_ACTIVE_TIMING
) & 0xFFF) + 1;
1657 hblankstart
= (READ_REG32 (DC3_H_BLANK_TIMING
) & 0xFFF) + 1;
1658 if ((interlaced
= (READ_REG32 (DC3_IRQ_FILT_CTL
) & DC3_IRQFILT_INTL_EN
)) &&
1659 !(source
& DF_CRC_SOURCE_EVEN
))
1661 vsyncend
= ((READ_REG32 (DC3_V_SYNC_EVEN
) >> 16) & 0xFFF) + 1;
1662 vtotal
= ((READ_REG32 (DC3_V_ACTIVE_EVEN
) >> 16) & 0xFFF) + 1;
1663 vsyncstart
= (READ_REG32 (DC3_V_SYNC_EVEN
) & 0xFFF) + 1;
1664 vactive
= (READ_REG32 (DC3_V_ACTIVE_EVEN
) & 0xFFF) + 1;
1665 vblankstart
= (READ_REG32 (DC3_V_BLANK_EVEN
) & 0xFFF) + 1;
1669 vsyncend
= ((READ_REG32 (DC3_V_SYNC_TIMING
) >> 16) & 0xFFF) + 1;
1670 vtotal
= ((READ_REG32 (DC3_V_ACTIVE_TIMING
) >> 16) & 0xFFF) + 1;
1671 vsyncstart
= (READ_REG32 (DC3_V_SYNC_TIMING
) & 0xFFF) + 1;
1672 vactive
= (READ_REG32 (DC3_V_ACTIVE_TIMING
) & 0xFFF) + 1;
1673 vblankstart
= (READ_REG32 (DC3_V_BLANK_TIMING
) & 0xFFF) + 1;
1676 /* TIMINGS MUST BE ACTIVE */
1678 if (!(READ_REG32 (DC3_DISPLAY_CFG
) & DC3_DCFG_TGEN
))
1681 /* DISABLE GLCP ACTIONS */
1685 msr_write64 (MSR_DEVICE_GEODELX_GLCP
, GLCP_DIAGCTL
, &msr_value
);
1687 /* ENABLE HW CLOCK GATING AND SET GLCP CLOCK TO DOT CLOCK */
1690 msr_write64 (MSR_DEVICE_GEODELX_GLCP
, MSR_GEODELINK_PM
, &msr_value
);
1692 msr_write64 (MSR_DEVICE_GEODELX_GLCP
, GLCP_DBGCLKCTL
, &msr_value
);
1694 msr_write64 (MSR_DEVICE_GEODELX_GLCP
, GLCP_DBGCLKCTL
, &msr_value
);
1696 /* USE H4 FUNCTION A FOR HSYNC AND H4 FUNCTION B FOR NOT HSYNC */
1697 /* HSYNC is bit 30 for the DF */
1699 msr_value
.high
= 0x00000001;
1700 msr_value
.low
= 0xE0000FF0;
1701 msr_write64 (MSR_DEVICE_GEODELX_GLCP
, GLCP_H0CTL
+ 4, &msr_value
);
1703 /* USE H3 FUNCTION A FOR VSYNC AND H3 FUNCTION B FOR NOT VSYNC */
1704 /* VSYNC is bit 54 for VG and bit 29 for DF */
1706 msr_value
.high
= 0x00000000;
1707 msr_value
.low
= 0x001D55AA;
1708 msr_write64 (MSR_DEVICE_GEODELX_GLCP
, GLCP_H0CTL
+ 3, &msr_value
);
1710 /* M4 (XSTATE = 00 AND VSYNC HIGH) */
1712 /* Note: VSync = H3A */
1714 msr_value
.high
= 0x00000001;
1715 msr_value
.low
= 0x000000A0;
1716 msr_write64 (MSR_DEVICE_GEODELX_GLCP
, GLCP_SETM0CTL
+ 4, &msr_value
);
1718 /* N0 (XSTATE = 01 AND VSYNC LOW) */
1720 /* Note: VSync low = H3B */
1722 msr_value
.high
= 0x00040000;
1723 msr_value
.low
= 0x000000C0;
1724 msr_write64 (MSR_DEVICE_GEODELX_GLCP
, GLCP_SETN0CTL
, &msr_value
);
1726 /* M5 (XSTATE = 10 AND VSYNC HIGH) */
1729 msr_value
.high
= 0x00000001;
1730 msr_value
.low
= 0x00000120;
1731 msr_write64 (MSR_DEVICE_GEODELX_GLCP
, GLCP_SETM0CTL
+ 5, &msr_value
);
1733 /* N1 (XSTATE = 10 and HSYNC LOW) */
1734 /* Increment H. Counter */
1735 /* Note: HSync = H4 */
1737 msr_value
.high
= 0x00080000;
1738 msr_value
.low
= 0x00000120;
1739 msr_write64 (MSR_DEVICE_GEODELX_GLCP
, GLCP_SETN0CTL
+ 1, &msr_value
);
1741 /* M0 (XSTATE = 10 and H. COUNTER == LIMIT) */
1742 /* Clear H. Counter and increment V. Counter */
1744 msr_value
.high
= 0x00000000;
1745 msr_value
.low
= 0x00000122;
1746 msr_write64 (MSR_DEVICE_GEODELX_GLCP
, GLCP_SETM0CTL
, &msr_value
);
1748 /* N4 (XSTATE = 10 && CMP0 <= H. COUNTER <= CMP1 && CMP2 <= V. COUNTER <= CMP3) */
1751 msr_value
.high
= 0x00000000;
1752 msr_value
.low
= 0x10C20120;
1753 msr_write64 (MSR_DEVICE_GEODELX_GLCP
, GLCP_SETN0CTL
+ 4, &msr_value
);
1755 /* COMPARATOR 0 VALUE */
1756 /* Value = xstart + (htotal - hsync_end) - 1 */
1757 /* The value will be adjusted for a border if necessary */
1759 msr_value
.low
= x
+ htotal
- hsyncend
- 1;
1760 if (READ_REG32 (DC3_DISPLAY_CFG
) & DC3_DCFG_DCEN
)
1761 msr_value
.low
-= hblankstart
- hactive
;
1763 msr_write64 (MSR_DEVICE_GEODELX_GLCP
, GLCP_CMPVAL0
, &msr_value
);
1765 /* COMPARATOR 1 VALUE */
1766 /* Value = xstart + (htotal - hsync_end - 1) - 1 + width */
1768 msr_value
.low
+= width
- 1;
1769 msr_write64 (MSR_DEVICE_GEODELX_GLCP
, GLCP_CMPVAL0
+ 2, &msr_value
);
1771 /* COMPARATOR 2 VALUE */
1772 /* Value = ystart + vtotal - vsyncend */
1774 msr_value
.low
= (y
+ vtotal
- vsyncend
) << 16;
1775 if (READ_REG32 (DC3_DISPLAY_CFG
) & DC3_DCFG_DCEN
)
1776 msr_value
.low
-= (vblankstart
- vactive
) << 16;
1777 msr_write64 (MSR_DEVICE_GEODELX_GLCP
, GLCP_CMPVAL0
+ 4, &msr_value
);
1779 /* COMPARATOR 3 VALUE */
1780 /* Value = ystart + vtotal - vsyncend + height - 1 */
1782 msr_value
.low
+= (height
- 1) << 16;
1783 msr_write64 (MSR_DEVICE_GEODELX_GLCP
, GLCP_CMPVAL0
+ 6, &msr_value
);
1785 /* COMPARATOR MASKS */
1786 /* Comparators 0 and 1 refer to lower 16 bits of RegB */
1788 msr_value
.low
= 0x0000FFFF;
1789 msr_write64 (MSR_DEVICE_GEODELX_GLCP
, GLCP_CMPMASK0
, &msr_value
);
1790 msr_write64 (MSR_DEVICE_GEODELX_GLCP
, GLCP_CMPMASK0
+ 2, &msr_value
);
1792 /* Comparators 2 and 3 refer to upper 16 bits of RegB */
1794 msr_value
.low
= 0xFFFF0000;
1795 msr_write64 (MSR_DEVICE_GEODELX_GLCP
, GLCP_CMPMASK0
+ 4, &msr_value
);
1796 msr_write64 (MSR_DEVICE_GEODELX_GLCP
, GLCP_CMPMASK0
+ 6, &msr_value
);
1799 /* We set the mask such that all only 24 bits of data are CRCed */
1801 msr_value
.low
= 0x00FFFFFF;
1802 msr_write64 (MSR_DEVICE_GEODELX_GLCP
, GLCP_REGBMASK
, &msr_value
);
1804 /* SET REGA LIMITS */
1805 /* Lower counter uses htotal - sync_time - 1. */
1806 /* Upper counter is 0xFFFF to prevent rollover. */
1808 msr_value
.low
= 0xFFFF0000 | (htotal
- (hsyncend
- hsyncstart
) - 1);
1809 msr_write64 (MSR_DEVICE_GEODELX_GLCP
, GLCP_REGAVAL
, &msr_value
);
1813 /* STATE 00->01 (SET 4M) */
1815 msr_value
.low
= 0x000C0000;
1816 msr_write64 (MSR_DEVICE_GEODELX_GLCP
, GLCP_ACTION0
+ 14, &msr_value
);
1818 /* STATE 01->10 (SET 0N) */
1820 msr_value
.low
= 0x0000000A;
1821 msr_write64 (MSR_DEVICE_GEODELX_GLCP
, GLCP_ACTION0
+ 15, &msr_value
);
1823 /* STATE 10->11 (SET 5M) */
1825 msr_value
.low
= 0x00C00000;
1826 msr_write64 (MSR_DEVICE_GEODELX_GLCP
, GLCP_ACTION0
+ 16, &msr_value
);
1828 /* CLEAR REGA WHEN TRANSITIONING TO STATE 10 */
1829 /* Do not clear RegB as the initial value must be 0x00000001 */
1831 msr_value
.low
= 0x0000000A;
1832 msr_write64 (MSR_DEVICE_GEODELX_GLCP
, GLCP_ACTION0
, &msr_value
);
1834 /* REGISTER ACTION 1 */
1835 /* CRC into RegB if cmp0 <= h.counter <= cmp1 && cmp2 <= v. counter < cmp3 && 7 xstate = 10 8 */
1836 /* Increment h.counter if xstate = 10 and HSync is low. */
1838 msr_value
.low
= 0x000A00A0;
1839 msr_write64 (MSR_DEVICE_GEODELX_GLCP
, GLCP_ACTION0
+ 1, &msr_value
);
1841 /* REGISTER ACTION 2 */
1842 /* Increment V. Counter in REGA */
1844 msr_value
.low
= 0x0000000C;
1845 msr_write64 (MSR_DEVICE_GEODELX_GLCP
, GLCP_ACTION0
+ 2, &msr_value
);
1847 /* SET REGB TO 0x00000001 */
1849 msr_value
.low
= 0x00000001;
1850 msr_write64 (MSR_DEVICE_GEODELX_GLCP
, GLCP_REGB
, &msr_value
);
1852 /* SET XSTATE TO 0 */
1854 msr_value
.low
= 0x00000000;
1855 msr_write64 (MSR_DEVICE_GEODELX_GLCP
, GLCP_XSTATE
, &msr_value
);
1857 /* CLEAR ALL OTHER ACTIONS */
1858 /* This prevents side-effects from previous accesses to the GLCP */
1861 msr_value
.low
= 0x00000000;
1862 msr_value
.high
= 0x00000000;
1863 msr_write64 (MSR_DEVICE_GEODELX_GLCP
, GLCP_ACTION0
+ 3, &msr_value
);
1864 msr_write64 (MSR_DEVICE_GEODELX_GLCP
, GLCP_ACTION0
+ 4, &msr_value
);
1865 msr_write64 (MSR_DEVICE_GEODELX_GLCP
, GLCP_ACTION0
+ 5, &msr_value
);
1866 msr_write64 (MSR_DEVICE_GEODELX_GLCP
, GLCP_ACTION0
+ 6, &msr_value
);
1867 msr_write64 (MSR_DEVICE_GEODELX_GLCP
, GLCP_ACTION0
+ 7, &msr_value
);
1868 msr_write64 (MSR_DEVICE_GEODELX_GLCP
, GLCP_ACTION0
+ 8, &msr_value
);
1869 msr_write64 (MSR_DEVICE_GEODELX_GLCP
, GLCP_ACTION0
+ 9, &msr_value
);
1870 msr_write64 (MSR_DEVICE_GEODELX_GLCP
, GLCP_ACTION0
+ 10, &msr_value
);
1871 msr_write64 (MSR_DEVICE_GEODELX_GLCP
, GLCP_ACTION0
+ 11, &msr_value
);
1872 msr_write64 (MSR_DEVICE_GEODELX_GLCP
, GLCP_ACTION0
+ 12, &msr_value
);
1873 msr_write64 (MSR_DEVICE_GEODELX_GLCP
, GLCP_ACTION0
+ 13, &msr_value
);
1874 msr_write64 (MSR_DEVICE_GEODELX_GLCP
, GLCP_ACTION0
+ 17, &msr_value
);
1875 msr_write64 (MSR_DEVICE_GEODELX_GLCP
, GLCP_ACTION0
+ 18, &msr_value
);
1876 msr_write64 (MSR_DEVICE_GEODELX_GLCP
, GLCP_ACTION0
+ 19, &msr_value
);
1877 msr_write64 (MSR_DEVICE_GEODELX_GLCP
, GLCP_ACTION0
+ 20, &msr_value
);
1879 /* WAIT FOR THE CORRECT FIELD */
1880 /* We use the VG line count and field indicator to determine when */
1881 /* to kick off a CRC. */
1883 if (source
& DF_CRC_SOURCE_EVEN
) field
= 0;
1884 else field
= DC3_LNCNT_EVEN_FIELD
;
1888 /* WAIT FOR THE BEGINNING OF THE FIELD (LINE 1-5) */
1889 /* Note that we wait for the field to be odd when CRCing the even */
1890 /* field and vice versa. This is because the CRC will not begin */
1891 /* until the following field. */
1895 line
= READ_REG32 (DC3_LINE_CNT_STATUS
);
1896 } while ((line
& DC3_LNCNT_EVEN_FIELD
) != field
||
1897 ((line
& DC3_LNCNT_V_LINE_CNT
) >> 16) < 1 ||
1898 ((line
& DC3_LNCNT_V_LINE_CNT
) >> 16) > 5);
1902 /* NON-INTERLACED - EVEN FIELD CRCS ARE INVALID */
1904 if (source
& DF_CRC_SOURCE_EVEN
)
1908 /* CONFIGURE DISPLAY FILTER TO LOAD DATA ONTO LOWER 32-BITS */
1911 msr_value
.low
= 0x0000800B;
1912 msr_write64 (MSR_DEVICE_GEODELX_DF
, MSR_GEODELINK_DIAG
, &msr_value
);
1914 /* CONFIGURE DIAG CONTROL */
1915 /* Set RegA action1 to increment lower 16 bits and clear at limit. (5) */
1916 /* Set RegA action2 to increment upper 16 bits. (6) */
1917 /* Set RegB action1 to CRC32 (1) */
1918 /* Set all comparators to REGA override (0,1 lower mbus, 2,3 upper mbus) */
1919 /* Enable all actions */
1921 msr_value
.low
= 0x80EA20A0;
1922 msr_write64 (MSR_DEVICE_GEODELX_GLCP
, GLCP_DIAGCTL
, &msr_value
);
1924 /* DELAY TWO FRAMES */
1926 while (READ_REG32 (DC3_LINE_CNT_STATUS
) & DC3_LNCNT_VNA
);
1927 while (!(READ_REG32 (DC3_LINE_CNT_STATUS
) & DC3_LNCNT_VNA
));
1928 while (READ_REG32 (DC3_LINE_CNT_STATUS
) & DC3_LNCNT_VNA
);
1929 while (!(READ_REG32 (DC3_LINE_CNT_STATUS
) & DC3_LNCNT_VNA
));
1930 while (READ_REG32 (DC3_LINE_CNT_STATUS
) & DC3_LNCNT_VNA
);
1932 /* VERIFY THAT XSTATE = 11 */
1934 msr_read64 (MSR_DEVICE_GEODELX_GLCP
, GLCP_XSTATE
, &msr_value
);
1935 if ((msr_value
.low
& 3) == 3)
1937 msr_read64 (MSR_DEVICE_GEODELX_GLCP
, GLCP_REGB
, &msr_value
);
1939 crc
= msr_value
.low
;
1942 /* DISABLE DF DIAG BUS OUTPUTS */
1944 msr_value
.low
= 0x00000000;
1945 msr_value
.high
= 0x00000000;
1946 msr_write64 (MSR_DEVICE_GEODELX_DF
, MSR_GEODELINK_DIAG
, &msr_value
);
1948 /* DISABLE GLCP ACTIONS */
1950 msr_write64 (MSR_DEVICE_GEODELX_GLCP
, GLCP_DIAGCTL
, &msr_value
);
1955 /*---------------------------------------------------------------------------
1958 * This routine reads the CRC for a frame of data after the panel dithering
1960 *---------------------------------------------------------------------------*/
1962 unsigned long df_read_panel_crc (void)
1965 unsigned long timeout
= 1000;
1967 if (!(READ_REG32 (DC3_DISPLAY_CFG
) & DC3_DCFG_TGEN
))
1970 /* ENABLE 32-BIT CRCS */
1972 msr_read64 (MSR_DEVICE_GEODELX_DF
, DF_MBD_MSR_DIAG_DF
, &msr_value
);
1973 msr_value
.low
|= DF_DIAG_32BIT_CRC
;
1974 msr_write64 (MSR_DEVICE_GEODELX_DF
, DF_MBD_MSR_DIAG_DF
, &msr_value
);
1978 WRITE_VID32 (DF_PANEL_CRC
, 0);
1980 /* WAIT FOR THE RESET TO BE LATCHED */
1982 while ((READ_VID32 (DF_PANEL_CRC32
) != 0x00000001) && timeout
)
1985 WRITE_VID32 (DF_PANEL_CRC
, 1);
1987 /* WAIT FOR THE CRC TO BE COMPLETED */
1989 while (!(READ_VID32 (DF_PANEL_CRC
) & 4))
1992 return READ_VID32 (DF_PANEL_CRC32
);
1995 /*---------------------------------------------------------------------------
1996 * df_get_video_enable
1998 * This routine reads the enable status of the video overlay.
1999 *---------------------------------------------------------------------------*/
2001 int df_get_video_enable (int *enable
, unsigned long *flags
)
2005 if (READ_VID32 (DF_VIDEO_CONFIG
) & DF_VCFG_VID_EN
)
2009 /* CHECK FOR COLOR KEY DISABLED */
2010 /* Color keying can be completely disabled when video is enabled to */
2011 /* allow unhindered per-pixel alpha blending. As color keying is */
2012 /* always disabled when video is disabled, it is only possible to */
2013 /* test for this condition when video is enabled. */
2015 if (!(READ_VID32 (DF_DISPLAY_CONFIG
) & DF_DCFG_VG_CK
) &&
2016 !(READ_REG32 (DC3_COLOR_KEY
) & DC3_CLR_KEY_ENABLE
))
2018 *flags
= DF_ENABLEFLAG_NOCOLORKEY
;
2022 return CIM_STATUS_OK
;
2025 /*---------------------------------------------------------------------------
2026 * df_get_video_source_configuration
2028 * This routine reads the current configuration of the source buffers for the
2030 *---------------------------------------------------------------------------*/
2032 int df_get_video_source_configuration (DF_VIDEO_SOURCE_PARAMS
*video_source_odd
,
2033 DF_VIDEO_SOURCE_PARAMS
*video_source_even
)
2035 unsigned long format
, temp
;
2038 /* READ VIDEO FORMAT */
2040 temp
= READ_VID32 (DF_VIDEO_CONFIG
);
2042 format
= (temp
>> 2) & 3;
2043 if (temp
& DF_VCFG_4_2_0_MODE
)
2045 else if (READ_VID32 (DF_VID_ALPHA_CONTROL
) & DF_VIDEO_INPUT_IS_RGB
)
2047 video_source_odd
->video_format
= format
;
2049 /* CHECK IF SOURCE IS HD VIDEO */
2051 if (READ_VID32 (DF_VID_ALPHA_CONTROL
) & DF_HD_VIDEO
)
2052 video_source_odd
->flags
= DF_SOURCEFLAG_HDTVSOURCE
;
2054 video_source_odd
->flags
= 0;
2056 /* READ SCALING ALGORITHM */
2058 if (READ_VID32 (DF_VID_MISC
) & DF_USER_IMPLICIT_SCALING
)
2059 video_source_odd
->flags
|= DF_SOURCEFLAG_IMPLICITSCALING
;
2061 /* READ VIDEO PITCH */
2063 temp
= READ_REG32 (DC3_VID_YUV_PITCH
);
2064 video_source_odd
->y_pitch
= (temp
& 0xFFFF) << 3;
2065 video_source_odd
->uv_pitch
= (temp
>> 16) << 3;
2067 /* READ VIDEO SIZE */
2069 temp
= READ_VID32 (DF_VIDEO_CONFIG
);
2070 size
= (temp
>> 8) & 0xFF;
2071 if (temp
& DF_VCFG_LINE_SIZE_BIT8
) size
|= 0x100;
2072 if (temp
& DF_VCFG_LINE_SIZE_BIT9
) size
|= 0x200;
2074 video_source_odd
->width
= size
<< 1;
2075 video_source_odd
->height
= READ_VID32 (DF_VIDEO_SCALER
) & 0x7FF;
2077 /* READ VIDEO OFFSETS */
2079 video_source_odd
->y_offset
= READ_REG32 (DC3_VID_Y_ST_OFFSET
) & 0xFFFFFFF;
2080 video_source_odd
->u_offset
= READ_REG32 (DC3_VID_U_ST_OFFSET
) & 0xFFFFFFF;
2081 video_source_odd
->v_offset
= READ_REG32 (DC3_VID_V_ST_OFFSET
) & 0xFFFFFFF;
2083 if (READ_REG32 (DC3_IRQ_FILT_CTL
) & DC3_IRQFILT_INTL_EN
)
2085 video_source_even
->y_offset
= READ_REG32 (DC3_VID_EVEN_Y_ST_OFFSET
) & 0xFFFFFFF;
2086 video_source_even
->u_offset
= READ_REG32 (DC3_VID_EVEN_U_ST_OFFSET
) & 0xFFFFFFF;
2087 video_source_even
->v_offset
= READ_REG32 (DC3_VID_EVEN_V_ST_OFFSET
) & 0xFFFFFFF;
2090 return CIM_STATUS_OK
;
2093 /*---------------------------------------------------------------------------
2094 * df_get_video_position
2096 * This routine reads the current position of the video overlay.
2097 *---------------------------------------------------------------------------*/
2099 int df_get_video_position (DF_VIDEO_POSITION
*video_window
)
2101 unsigned long xreg
, yreg
, dst_clip
, clip
;
2102 unsigned long height
;
2103 unsigned long xend
, yend
;
2104 unsigned long hsyncend
, htotal
;
2105 unsigned long vsyncend
, vtotal
;
2106 unsigned long hadjust
, vadjust
;
2107 unsigned long misc
, gfxscale
;
2109 long xstart
, ystart
;
2111 video_window
->flags
= DF_POSFLAG_DIRECTCLIP
;
2113 hsyncend
= ((READ_REG32 (DC3_H_SYNC_TIMING
) >> 16) & 0xFFF) + 1;
2114 htotal
= ((READ_REG32 (DC3_H_ACTIVE_TIMING
) >> 16) & 0xFFF) + 1;
2116 /* ODD FIELD START COUNTS FROM THE EVEN FIELD TIMINGS */
2117 /* We assume that the even field y position is always programmed */
2118 /* to be just after the odd field. */
2120 if (READ_REG32 (DC3_IRQ_FILT_CTL
) & DC3_IRQFILT_INTL_EN
)
2122 vsyncend
= ((READ_REG32 (DC3_V_SYNC_EVEN
) >> 16) & 0xFFF) + 1;
2123 vtotal
= ((READ_REG32 (DC3_V_ACTIVE_EVEN
) >> 16) & 0xFFF) + 1;
2127 vsyncend
= ((READ_REG32 (DC3_V_SYNC_TIMING
) >> 16) & 0xFFF) + 1;
2128 vtotal
= ((READ_REG32 (DC3_V_ACTIVE_TIMING
) >> 16) & 0xFFF) + 1;
2131 hadjust
= htotal
- hsyncend
- 14;
2132 vadjust
= vtotal
- vsyncend
+ 1;
2134 xreg
= READ_VID32 (DF_VIDEO_X_POS
);
2135 yreg
= READ_VID32 (DF_VIDEO_Y_POS
);
2137 xstart
= (xreg
& 0xFFF) - hadjust
;
2138 ystart
= (yreg
& 0x7FF) - vadjust
;
2139 xend
= ((xreg
>> 16) & 0xFFF) - hadjust
;
2140 yend
= ((yreg
>> 16) & 0x7FF) - vadjust
;
2142 height
= yend
- ystart
;
2144 if (READ_REG32 (DC3_IRQ_FILT_CTL
) & DC3_IRQFILT_INTL_EN
)
2146 /* Y COORDINATE IS ACTUALLY 2X THE ODD FIELD START */
2150 /* CALCULATE THE EXACT VIDEO HEIGHT */
2151 /* The height of the video window is the sum of the */
2152 /* odd and even field heights. */
2154 yreg
= READ_VID32 (DF_VID_YPOS_EVEN
);
2155 height
+= ((yreg
>> 16) & 0x7FF) - (yreg
& 0x7FF);
2158 clip
= ((READ_VID32 (DF_VIDEO_CONFIG
) >> 16) & 0x1FF) << 2;
2160 /* ADJUST FOR CLIPPING VALUES THAT ARE NOT FOUR-PIXEL ALIGNED */
2165 dst_clip
+= -xstart
;
2169 /* REVERSE THE GRAPHICS SCALE */
2171 misc
= READ_VID32 (DF_VID_MISC
);
2172 if (misc
& DF_USER_IMPLICIT_SCALING
)
2174 gfxscale
= READ_REG32 (DC3_GFX_SCALE
);
2176 if (gfxscale
!= 0x40004000)
2178 temp
= ystart
+ height
;
2179 temp
= (temp
* (gfxscale
>> 16)) / 0x4000;
2181 xstart
= (xstart
* (gfxscale
& 0xFFFF)) / 0x4000;
2182 xend
= (xend
* (gfxscale
& 0xFFFF)) / 0x4000;
2183 ystart
= (ystart
* (gfxscale
>> 16)) / 0x4000;
2184 height
= temp
- ystart
;
2188 video_window
->left_clip
= clip
;
2189 video_window
->dst_clip
= dst_clip
;
2190 video_window
->x
= xstart
;
2191 video_window
->y
= ystart
;
2192 video_window
->width
= xend
- xstart
;
2193 video_window
->height
= height
;
2195 return CIM_STATUS_OK
;
2198 /*---------------------------------------------------------------------------
2199 * df_get_video_scale
2201 * This routine reads the current scale values for video scaling.
2202 *---------------------------------------------------------------------------*/
2204 int df_get_video_scale (unsigned long *x_scale
, unsigned long *y_scale
)
2206 *x_scale
= READ_VID32 (DF_VIDEO_XSCALE
) & 0x000FFFFF;
2207 *y_scale
= READ_VID32 (DF_VIDEO_YSCALE
) & 0x000FFFFF;
2208 return CIM_STATUS_OK
;
2211 /*---------------------------------------------------------------------------
2212 * df_get_video_filter_coefficients
2214 * This routine reads the coefficients for the video scaler/filter.
2215 *---------------------------------------------------------------------------*/
2217 int df_get_video_filter_coefficients (long taps
[][4], int *phase256
)
2219 unsigned long i
, temp
;
2222 if (READ_VID32 (DF_VIDEO_SCALER
) & DF_SCALE_128_PHASES
)
2227 for (i
= 0; i
< 256; i
++)
2229 temp
= READ_VID32 (DF_COEFFICIENT_BASE
+ (i
<< 3));
2233 coeff
= temp
& 0x7FFF;
2234 if (temp
& 0x8000) coeff
= -coeff
;
2240 coeff
= temp
& 0x7FFF;
2241 if (temp
& 0x8000) coeff
= -coeff
;
2244 temp
= READ_VID32 (DF_COEFFICIENT_BASE
+ (i
<< 3) + 4);
2248 coeff
= temp
& 0x7FFF;
2249 if (temp
& 0x8000) coeff
= -coeff
;
2255 coeff
= temp
& 0x7FFF;
2256 if (temp
& 0x8000) coeff
= -coeff
;
2260 return CIM_STATUS_OK
;
2263 /*---------------------------------------------------------------------------
2264 * df_get_video_color_key
2266 * This routine reads the current settings for hardware color/chroma keying.
2267 *---------------------------------------------------------------------------*/
2269 int df_get_video_color_key (unsigned long *key
, unsigned long *mask
, int *graphics
)
2271 unsigned long chroma
= READ_VID32 (DF_DISPLAY_CONFIG
) & DF_DCFG_VG_CK
;
2275 /* CHROMA KEY - READ KEY AND MASK FROM DF */
2278 *key
= READ_VID32 (DF_VIDEO_COLOR_KEY
) & 0xFFFFFF;
2279 *mask
= READ_VID32 (DF_VIDEO_COLOR_MASK
) & 0xFFFFFF;
2285 *key
= READ_REG32 (DC3_COLOR_KEY
) & 0xFFFFFF;
2286 *mask
= READ_REG32 (DC3_COLOR_MASK
) & 0xFFFFFF;
2289 return CIM_STATUS_OK
;
2292 /*---------------------------------------------------------------------------
2293 * df_get_video_palette_entry
2295 * This routine returns a single palette entry.
2296 *---------------------------------------------------------------------------*/
2298 int df_get_video_palette_entry(unsigned long index
, unsigned long *palette
)
2301 return CIM_STATUS_INVALIDPARAMS
;
2303 /* READ A SINGLE ENTRY */
2305 WRITE_VID32 (DF_PALETTE_ADDRESS
, index
);
2306 *palette
= READ_VID32 (DF_PALETTE_DATA
);
2308 return CIM_STATUS_OK
;
2311 /*---------------------------------------------------------------------------
2312 * df_get_video_palette
2314 * This routine returns the entire video palette.
2315 *---------------------------------------------------------------------------*/
2317 int df_get_video_palette (unsigned long *palette
)
2321 WRITE_VID32 (DF_PALETTE_ADDRESS
, 0);
2322 for (i
= 0; i
< 256; i
++)
2323 palette
[i
] = READ_VID32 (DF_PALETTE_DATA
);
2325 return CIM_STATUS_OK
;
2328 /*---------------------------------------------------------------------------
2329 * df_get_video_cursor_color_key
2331 * This routine returns the current configuration for the hardware video cursor
2333 *---------------------------------------------------------------------------*/
2335 int df_get_video_cursor_color_key (DF_VIDEO_CURSOR_PARAMS
*cursor_color_key
)
2339 cursor_color_key
->flags
= 0;
2340 cursor_color_key
->color1
= READ_VID32 (DF_CURSOR_COLOR_1
) & 0xFFFFFF;
2341 cursor_color_key
->color2
= READ_VID32 (DF_CURSOR_COLOR_2
) & 0xFFFFFF;
2342 cursor_color_key
->mask
= READ_VID32 (DF_CURSOR_COLOR_MASK
) & 0xFFFFFF;
2344 key
= READ_VID32 (DF_CURSOR_COLOR_KEY
);
2345 cursor_color_key
->key
= key
& 0xFFFFFF;
2346 cursor_color_key
->select_color2
= (key
>> 24) & 0x1F;
2348 return CIM_STATUS_OK
;
2351 /*---------------------------------------------------------------------------
2352 * df_get_video_cursor_color_key_enable
2354 * This routine returns the current enable status of the hardware video cursor
2356 *---------------------------------------------------------------------------*/
2358 int df_get_video_cursor_color_key_enable (void)
2360 if (READ_VID32 (DF_CURSOR_COLOR_KEY
) & DF_CURSOR_COLOR_KEY_ENABLE
)
2366 /*---------------------------------------------------------------------------
2367 * df_get_alpha_window_configuration
2369 * This routine reads the current configuration for one of the three hardware
2371 *---------------------------------------------------------------------------*/
2373 int df_get_alpha_window_configuration (int window
, DF_ALPHA_REGION_PARAMS
*alpha_data
)
2375 unsigned long pos
, color
, alpha_ctl
;
2376 unsigned long hsyncend
, htotal
;
2377 unsigned long vsyncend
, vtotal
;
2378 unsigned long hadjust
, vadjust
;
2379 unsigned long xreg
, yreg
;
2380 unsigned long misc
, gfxscale
;
2385 return CIM_STATUS_INVALIDPARAMS
;
2387 hsyncend
= ((READ_REG32 (DC3_H_SYNC_TIMING
) >> 16) & 0xFFF) + 1;
2388 htotal
= ((READ_REG32 (DC3_H_ACTIVE_TIMING
) >> 16) & 0xFFF) + 1;
2389 if (READ_REG32 (DC3_IRQ_FILT_CTL
) & DC3_IRQFILT_INTL_EN
)
2391 vtotal
= ((READ_REG32 (DC3_V_ACTIVE_EVEN
) >> 16) & 0xFFF) + 1;
2392 vsyncend
= ((READ_REG32 (DC3_V_SYNC_EVEN
) >> 16) & 0xFFF) + 1;
2396 vtotal
= ((READ_REG32 (DC3_V_ACTIVE_TIMING
) >> 16) & 0xFFF) + 1;
2397 vsyncend
= ((READ_REG32 (DC3_V_SYNC_TIMING
) >> 16) & 0xFFF) + 1;
2402 pos
= 16 + (window
<< 1);
2403 alpha_data
->priority
= (READ_VID32 (DF_VID_ALPHA_CONTROL
) >> pos
) & 3L;
2405 /* GET ALPHA WINDOW */
2407 hadjust
= htotal
- hsyncend
- 2;
2408 vadjust
= vtotal
- vsyncend
+ 1;
2410 xreg
= READ_VID32 (DF_ALPHA_XPOS_1
+ (window
<< 5));
2411 yreg
= READ_VID32 (DF_ALPHA_YPOS_1
+ (window
<< 5));
2412 alpha_data
->width
= ((xreg
>> 16) & 0xFFF) - (xreg
& 0xFFF);
2413 alpha_data
->height
= ((yreg
>> 16) & 0x7FF) - (yreg
& 0x7FF);
2414 alpha_data
->x
= (xreg
& 0xFFF) - hadjust
;
2415 alpha_data
->y
= (yreg
& 0x7FF) - vadjust
;
2417 /* REVERSE THE GRAPHICS SCALE */
2419 misc
= READ_VID32 (DF_VID_MISC
);
2420 if (misc
& DF_USER_IMPLICIT_SCALING
)
2422 gfxscale
= READ_REG32 (DC3_GFX_SCALE
);
2423 if (gfxscale
!= 0x40004000)
2425 temp
= alpha_data
->y
+ alpha_data
->height
;
2426 temp
= (temp
* (gfxscale
>> 16)) / 0x4000;
2428 alpha_data
->x
= (alpha_data
->x
* (gfxscale
& 0xFFFF)) / 0x4000;
2429 alpha_data
->width
= (alpha_data
->width
* (gfxscale
& 0xFFFF)) / 0x4000;
2430 alpha_data
->y
= (alpha_data
->y
* (gfxscale
>> 16)) / 0x4000;
2431 alpha_data
->height
= temp
- alpha_data
->y
;
2435 if (READ_REG32 (DC3_IRQ_FILT_CTL
) & DC3_IRQFILT_INTL_EN
)
2437 /* Y COORDINATE IS ACTUALLY 2X THE ODD FIELD START */
2439 alpha_data
->y
<<= 1;
2441 /* CALCULATE THE EXACT VIDEO HEIGHT */
2442 /* The height of the video window is the sum of the */
2443 /* odd and even field heights. */
2445 yreg
= READ_VID32 (DF_VID_ALPHA_Y_EVEN_1
+ (window
<< 3));
2446 alpha_data
->height
+= ((yreg
>> 16) & 0x7FF) - (yreg
& 0x7FF);
2449 /* GET COLOR REGISTER */
2451 color
= READ_VID32 (DF_ALPHA_COLOR_1
+ (window
<< 5));
2452 alpha_data
->color
= color
& 0xFFFFFF;
2453 if (color
& DF_ALPHA_COLOR_ENABLE
)
2454 alpha_data
->flags
= DF_ALPHAFLAG_COLORENABLED
;
2456 alpha_data
->flags
= 0;
2458 /* GET ALPHA VALUE, DELTA AND PER PIXEL */
2460 alpha_ctl
= READ_VID32 (DF_ALPHA_CONTROL_1
+ (window
<< 5));
2461 alpha_data
->alpha_value
= alpha_ctl
& 0xFF;
2462 if (alpha_ctl
& DF_ACTRL_PERPIXEL_EN
)
2463 alpha_data
->flags
|= DF_ALPHAFLAG_PERPIXELENABLED
;
2465 delta
= (char)((alpha_ctl
>> 8) & 0xFF);
2466 alpha_data
->delta
= (long)delta
;
2467 return CIM_STATUS_OK
;
2470 /*---------------------------------------------------------------------------
2471 * df_get_alpha_window_enable
2473 * This routine reads the current enable status of one of the three hardware
2475 *---------------------------------------------------------------------------*/
2477 int df_get_alpha_window_enable (int window
)
2482 if (READ_VID32 (DF_ALPHA_CONTROL_1
+ (window
<< 5)) & DF_ACTRL_WIN_ENABLE
)
2488 /*---------------------------------------------------------------------------
2489 * df_get_video_request
2491 * This routine reads the horizontal (pixel) and vertical (line) video request
2493 *--------------------------------------------------------------------------*/
2495 int df_get_video_request (unsigned long *x
, unsigned long *y
)
2497 unsigned long request
;
2498 unsigned long hsyncend
, htotal
;
2499 unsigned long vsyncend
, vtotal
;
2501 hsyncend
= ((READ_REG32 (DC3_H_SYNC_TIMING
) >> 16) & 0xFFF) + 1;
2502 vsyncend
= ((READ_REG32 (DC3_V_SYNC_TIMING
) >> 16) & 0xFFF) + 1;
2503 htotal
= ((READ_REG32 (DC3_H_ACTIVE_TIMING
) >> 16) & 0xFFF) + 1;
2504 vtotal
= ((READ_REG32 (DC3_V_ACTIVE_TIMING
) >> 16) & 0xFFF) + 1;
2506 request
= READ_VID32 (DF_VIDEO_REQUEST
);
2507 *x
= ((request
>> 16) & 0xFFF) - (htotal
- hsyncend
- 2);
2508 *y
= (request
& 0x7FF) - (vtotal
- vsyncend
+ 1);
2510 return CIM_STATUS_OK
;
2513 /*---------------------------------------------------------------------------
2514 * df_get_output_color_space
2516 * This routine sets the color space used when combining graphics and video.
2517 *--------------------------------------------------------------------------*/
2519 int df_get_output_color_space (int *color_space
)
2521 unsigned long alpha_ctl
;
2523 alpha_ctl
= READ_VID32 (DF_VID_ALPHA_CONTROL
);
2525 if ((alpha_ctl
& DF_CSC_VIDEO_YUV_TO_RGB
) ||
2526 !(alpha_ctl
& DF_CSC_GRAPHICS_RGB_TO_YUV
))
2528 if (alpha_ctl
& DF_ALPHA_DRGB
)
2529 *color_space
= DF_OUTPUT_ARGB
;
2531 *color_space
= DF_OUTPUT_RGB
;
2535 *color_space
= DF_OUTPUT_SDTV
;
2537 if (alpha_ctl
& DF_HD_GRAPHICS
)
2538 *color_space
= DF_OUTPUT_HDTV
;
2541 return CIM_STATUS_OK
;