added 2.6.29.6 aldebaran kernel
[nao-ulib.git] / kernel / 2.6.29.6-aldebaran-rt / lib / cimarron / cim / cim_df.c
blob805b28f33e745f50581f5540460f0438a820035e
1 /*
2 * <LIC_AMD_STD>
3 * Copyright (C) 2005 Advanced Micro Devices, Inc. All Rights Reserved.
4 * </LIC_AMD_STD>
6 * <CTL_AMD_STD>
7 * </CTL_AMD_STD>
9 * <DOC_AMD_STD>
10 * Cimarron display filter routines. These routines program the video hardware.
11 * </DOC_AMD_STD>
15 /*---------------------------------------------------------------------------
16 * df_set_crt_enable
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);
28 switch (crt_output)
30 /* DISABLE DISPLAY */
32 case DF_CRT_DISABLE:
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;
37 break;
39 /* ENABLE THE DISPLAY */
41 case DF_CRT_ENABLE:
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);
46 break;
48 /* HSYNC:OFF VSYNC:ON */
50 case DF_CRT_STANDBY:
52 config = (config & ~(DF_DCFG_DIS_EN | DF_DCFG_HSYNC_EN | DF_DCFG_DAC_BL_EN)) |
53 DF_DCFG_VSYNC_EN;
54 misc |= DF_DAC_POWER_DOWN;
55 break;
57 /* HSYNC:ON VSYNC:OFF */
59 case DF_CRT_SUSPEND:
61 config = (config & ~(DF_DCFG_DIS_EN | DF_DCFG_VSYNC_EN | DF_DCFG_DAC_BL_EN)) |
62 DF_DCFG_HSYNC_EN;
63 misc |= DF_DAC_POWER_DOWN;
64 break;
66 default:
67 return CIM_STATUS_INVALIDPARAMS;
70 WRITE_VID32 (DF_DISPLAY_CONFIG, config);
71 WRITE_VID32 (DF_VID_MISC, misc);
73 return CIM_STATUS_OK;
76 /*---------------------------------------------------------------------------
77 * df_set_panel_enable
79 * This routine enables or disables panel output.
80 *---------------------------------------------------------------------------*/
82 int df_set_panel_enable (int enable)
84 unsigned long pm;
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);
93 return CIM_STATUS_OK;
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;
108 unsigned long misc;
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;
128 else
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 |
141 DF_YUV_CSC_EN);
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;
162 break;
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)
174 ctrl |= DF_HD_VIDEO;
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;
211 else
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);
260 if (even)
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);
266 else
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 /*---------------------------------------------------------------------------
279 * df_set_video_scale
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 */
309 /* video. */
310 /* */
311 /* F = (0x4000*S)/(D-1) -> (D/S) = (((0x4000*S)/F)+1)/S */
313 scale = gfxscale & 0xFFFF;
314 src = (fbactive >> 16) + 1;
315 if (scale != 0x4000)
317 dst_width = dst_width * (((0x4000 * src) / scale) + 1);
318 dst_width /= src;
321 scale = gfxscale >> 16;
322 src = (fbactive & 0xFFFF) + 1;
323 if (scale != 0x4000)
325 dst_height = dst_height * (((0x4000 * src) / scale) + 1);
326 dst_height /= src;
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))
356 src_width >>= 1;
357 WRITE_VID32 (DF_VIDEO_SCALER, scale | DF_SCALE_DOUBLE_H_DOWNSCALE);
359 else
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);
387 else
388 downscale |= (((src_height >> 1) << 14) / dst_height) << 18;
390 WRITE_REG32 (DC3_VID_DS_DELTA, downscale);
391 WRITE_VID32 (DF_VIDEO_YSCALE, 0x20000);
393 else
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));
410 else
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;
466 else
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;
489 if (scale != 0x4000)
491 width_copy = width_copy * (((0x4000 * src) / scale) + 1);
492 width_copy /= src;
493 x_copy = x_copy * (((0x4000 * src) / scale) + 1);
494 x_copy /= src;
497 scale = gfxscale >> 16;
498 src = (fbactive & 0xFFFF) + 1;
499 if (scale != 0x4000)
501 height_copy = height_copy * (((0x4000 * src) / scale) + 1);
502 height_copy /= src;
503 y_copy = y_copy * (((0x4000 * src) / scale) + 1);
504 y_copy /= src;
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;
525 else
526 border_y_even = 0;
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. */
534 y = y_copy >> 1;
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 */
539 /* odd. */
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)
560 ystart -= border_y;
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 */
573 /* overscan area. */
575 if ((READ_REG32 (DC3_GENLK_CTL) & DC3_GC_FLICKER_FILTER_ENABLE) ||
576 (irq_ctl & DC3_IRQFILT_INTL_ADDR))
578 y <<= 1;
579 height += height_even;
580 adjust = border_y + border_y_even;
582 else
584 adjust = border_y;
585 if (height_even > height)
586 height = height_even;
588 if (video_window->flags & DF_POSFLAG_INCLUDEBORDER)
590 if (y > adjust)
592 y -= adjust;
593 adjust = 0;
595 else
597 adjust -= y;
598 if (height > adjust)
599 height -= adjust;
600 else
601 height = 0;
606 else
608 y = y_copy;
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)
616 ystart -= border_y;
618 yend = ystart + height;
619 ypos = (yend << 16) | ystart;
620 ypos_even = 0;
623 /* HORIZONTAL POSITION */
624 /* The horizontal values are identical for the even and odd field. */
626 width = width_copy;
627 xstart = x_copy + htotal - hsyncend - 14;
628 if (video_window->flags & DF_POSFLAG_INCLUDEBORDER)
629 xstart -= border_x;
631 /* RIGHT CLIPPING */
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;
655 dst_clip = 0;
656 if (!(video_window->flags & DF_POSFLAG_DIRECTCLIP))
658 xscale = READ_VID32 (DF_VIDEO_XSCALE) & 0xFFFFF;
659 initread = (initread * xscale) / 0x10000;
660 if (xscale)
661 dst_clip = ((initread & 3) * 0x10000) / xscale;
663 else
664 dst_clip = video_window->dst_clip;
666 /* LIMIT THE 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. */
672 if (dst_clip > 4)
673 dst_clip = 4;
674 if (READ_REG32 (DC3_DISPLAY_CFG) & DC3_DCFG_DCEN)
675 dst_clip = 0;
677 xstart -= dst_clip;
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 */
686 /* scaling. */
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;
724 unsigned long i;
725 long (*defaults)[2];
727 /* SET PHASE COUNT AND CHOOSE COEFFICIENT ARRAY */
729 scale = READ_VID32 (DF_VIDEO_SCALER);
730 if (phase256)
732 WRITE_VID32 (DF_VIDEO_SCALER, (scale & ~DF_SCALE_128_PHASES));
733 defaults = CimarronVideoFilter256;
735 else
737 WRITE_VID32 (DF_VIDEO_SCALER, (scale | DF_SCALE_128_PHASES));
738 defaults = CimarronVideoFilter128;
741 /* PROGRAM COEFFICIENTS */
743 for (i = 0; i < 256; i++)
745 if (!taps)
747 coeff0 = defaults[i][0];
748 coeff1 = defaults[i][1];
750 else
752 if (taps[i][1] < 0) coeff0 = -taps[i][1] | 0x8000;
753 else coeff0 = taps[i][1];
755 coeff0 <<= 16;
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];
765 coeff1 <<= 16;
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;
802 if (enable)
804 fifo = ((dcfg >> 12) & 0x0000000F) + 4;
805 if (fifo > 0xF)
806 fifo = 0xF;
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 */
813 /* disabled last. */
815 if (enable)
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));
842 else
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);
877 if (graphics)
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;
887 else
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));
894 else
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;
960 if (index > 0xFF)
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)
992 unsigned long 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;
1048 if (window > 2)
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);
1078 width_copy /= src;
1079 x_copy = x_copy * (((0x4000 * src) / scale) + 1);
1080 x_copy /= src;
1083 scale = gfxscale >> 16;
1084 src = (fbactive & 0xFFFF) + 1;
1085 if (scale != 0x4000)
1087 height_copy = height_copy * (((0x4000 * src) / scale) + 1);
1088 height_copy /= src;
1089 y_copy = y_copy * (((0x4000 * src) / scale) + 1);
1090 y_copy /= src;
1094 /* SET PRIORITY */
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;
1111 y = y_copy >> 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)));
1139 else
1141 y = y_copy;
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;
1198 if (window > 2)
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
1213 * window.
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
1239 * values.
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);
1279 /* OUTPUT IS RGB */
1280 /* Enable YUV->RGB CSC if necessary and enable alpha output if */
1281 /* requested. */
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;
1292 /* OUTPUT IS YUV */
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;
1308 else
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;
1326 Q_WORD msr_value;
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)
1335 /* SiBZ #4188 */
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;
1362 else
1364 switch (format)
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;
1369 default:
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 /*---------------------------------------------------------------------------
1393 * df_save_state
1395 * This routine saves all persistent DF state information.
1396 *---------------------------------------------------------------------------*/
1398 int df_save_state (DF_SAVE_RESTORE *df_state)
1400 unsigned long i;
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 /*---------------------------------------------------------------------------
1468 * df_restore_state
1470 * This routine restores all persistent DF state information.
1471 *---------------------------------------------------------------------------*/
1473 int df_restore_state (DF_SAVE_RESTORE *df_state)
1475 unsigned long i;
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)
1567 Q_WORD msr_value;
1568 unsigned long crc;
1569 unsigned long interlaced;
1570 unsigned long line, field;
1571 unsigned long timeout = 1000;
1573 if (!(READ_REG32 (DC3_DISPLAY_CFG) & DC3_DCFG_TGEN))
1574 return 0xFFFFFFFF;
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);
1582 /* RESET THE CRC */
1584 WRITE_VID32 (DF_VID_CRC, 0);
1586 /* WAIT FOR THE RESET TO BE LATCHED */
1588 while ((READ_VID32 (DF_VID_CRC32) != 0x00000001) && timeout)
1589 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);
1612 else
1614 /* NON-INTERLACED - EVEN FIELD CRCS ARE INVALID */
1616 if (crc_source & DF_CRC_SOURCE_EVEN)
1617 return 0xFFFFFFFF;
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);
1631 return crc;
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)
1644 Q_WORD msr_value;
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;
1667 else
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))
1679 return 0xFFFFFFFF;
1681 /* DISABLE GLCP ACTIONS */
1683 msr_value.low = 0;
1684 msr_value.high = 0;
1685 msr_write64 (MSR_DEVICE_GEODELX_GLCP, GLCP_DIAGCTL, &msr_value);
1687 /* ENABLE HW CLOCK GATING AND SET GLCP CLOCK TO DOT CLOCK */
1689 msr_value.low = 5;
1690 msr_write64 (MSR_DEVICE_GEODELX_GLCP, MSR_GEODELINK_PM, &msr_value);
1691 msr_value.low = 0;
1692 msr_write64 (MSR_DEVICE_GEODELX_GLCP, GLCP_DBGCLKCTL, &msr_value);
1693 msr_value.low = 3;
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) */
1711 /* Goto state 01 */
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) */
1719 /* Goto state 02 */
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) */
1727 /* Goto state 11 */
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) */
1749 /* CRC into REGB */
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;
1762 msr_value.low--;
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);
1798 /* SET REGB MASK */
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);
1811 /* ACTIONS */
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 */
1859 /* debug logic. */
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;
1886 if (interlaced)
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);
1900 else
1902 /* NON-INTERLACED - EVEN FIELD CRCS ARE INVALID */
1904 if (source & DF_CRC_SOURCE_EVEN)
1905 return 0xFFFFFFFF;
1908 /* CONFIGURE DISPLAY FILTER TO LOAD DATA ONTO LOWER 32-BITS */
1910 msr_value.high = 0;
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);
1952 return crc;
1955 /*---------------------------------------------------------------------------
1956 * df_read_panel_crc
1958 * This routine reads the CRC for a frame of data after the panel dithering
1959 * logic.
1960 *---------------------------------------------------------------------------*/
1962 unsigned long df_read_panel_crc (void)
1964 Q_WORD msr_value;
1965 unsigned long timeout = 1000;
1967 if (!(READ_REG32 (DC3_DISPLAY_CFG) & DC3_DCFG_TGEN))
1968 return 0xFFFFFFFF;
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);
1976 /* RESET CRC */
1978 WRITE_VID32 (DF_PANEL_CRC, 0);
1980 /* WAIT FOR THE RESET TO BE LATCHED */
1982 while ((READ_VID32 (DF_PANEL_CRC32) != 0x00000001) && timeout)
1983 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)
2003 *enable = 0;
2004 *flags = 0;
2005 if (READ_VID32 (DF_VIDEO_CONFIG) & DF_VCFG_VID_EN)
2007 *enable = 1;
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
2029 * video overlay.
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;
2036 unsigned long size;
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)
2044 format |= 4;
2045 else if (READ_VID32 (DF_VID_ALPHA_CONTROL) & DF_VIDEO_INPUT_IS_RGB)
2046 format |= 8;
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;
2053 else
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;
2108 unsigned long temp;
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;
2125 else
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 */
2148 ystart <<= 1;
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 */
2162 dst_clip = 0;
2163 if (xstart < 0)
2165 dst_clip += -xstart;
2166 xstart = 0;
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;
2220 long coeff;
2222 if (READ_VID32 (DF_VIDEO_SCALER) & DF_SCALE_128_PHASES)
2223 *phase256 = 0;
2224 else
2225 *phase256 = 1;
2227 for (i = 0; i < 256; i++)
2229 temp = READ_VID32 (DF_COEFFICIENT_BASE + (i << 3));
2231 /* TAP 0 */
2233 coeff = temp & 0x7FFF;
2234 if (temp & 0x8000) coeff = -coeff;
2235 taps[i][0] = coeff;
2237 /* TAP 1 */
2239 temp >>= 16;
2240 coeff = temp & 0x7FFF;
2241 if (temp & 0x8000) coeff = -coeff;
2242 taps[i][1] = coeff;
2244 temp = READ_VID32 (DF_COEFFICIENT_BASE + (i << 3) + 4);
2246 /* TAP 2 */
2248 coeff = temp & 0x7FFF;
2249 if (temp & 0x8000) coeff = -coeff;
2250 taps[i][2] = coeff;
2252 /* TAP 3 */
2254 temp >>= 16;
2255 coeff = temp & 0x7FFF;
2256 if (temp & 0x8000) coeff = -coeff;
2257 taps[i][3] = 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;
2273 if (chroma)
2275 /* CHROMA KEY - READ KEY AND MASK FROM DF */
2277 *graphics = 0;
2278 *key = READ_VID32 (DF_VIDEO_COLOR_KEY) & 0xFFFFFF;
2279 *mask = READ_VID32 (DF_VIDEO_COLOR_MASK) & 0xFFFFFF;
2281 else
2283 *graphics = 1;
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)
2300 if (index > 0xFF)
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)
2319 unsigned long i;
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
2332 * color key.
2333 *---------------------------------------------------------------------------*/
2335 int df_get_video_cursor_color_key (DF_VIDEO_CURSOR_PARAMS *cursor_color_key)
2337 unsigned long 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
2355 * color key.
2356 *---------------------------------------------------------------------------*/
2358 int df_get_video_cursor_color_key_enable (void)
2360 if (READ_VID32 (DF_CURSOR_COLOR_KEY) & DF_CURSOR_COLOR_KEY_ENABLE)
2361 return 1;
2363 return 0;
2366 /*---------------------------------------------------------------------------
2367 * df_get_alpha_window_configuration
2369 * This routine reads the current configuration for one of the three hardware
2370 * alpha regions.
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;
2381 unsigned long temp;
2382 char delta;
2384 if (window > 2)
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;
2394 else
2396 vtotal = ((READ_REG32 (DC3_V_ACTIVE_TIMING) >> 16) & 0xFFF) + 1;
2397 vsyncend = ((READ_REG32 (DC3_V_SYNC_TIMING) >> 16) & 0xFFF) + 1;
2400 /* GET PRIORITY */
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;
2455 else
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
2474 * alpha regions.
2475 *---------------------------------------------------------------------------*/
2477 int df_get_alpha_window_enable (int window)
2479 if (window > 2)
2480 return 0;
2482 if (READ_VID32 (DF_ALPHA_CONTROL_1 + (window << 5)) & DF_ACTRL_WIN_ENABLE)
2483 return 1;
2485 return 0;
2488 /*---------------------------------------------------------------------------
2489 * df_get_video_request
2491 * This routine reads the horizontal (pixel) and vertical (line) video request
2492 * values.
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;
2530 else
2531 *color_space = DF_OUTPUT_RGB;
2533 else
2535 *color_space = DF_OUTPUT_SDTV;
2537 if (alpha_ctl & DF_HD_GRAPHICS)
2538 *color_space = DF_OUTPUT_HDTV;
2541 return CIM_STATUS_OK;
2544 #endif