1/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nsc/gfx/vid_1400.c,v 1.1 2002/12/10 15:12:27 alanh Exp $ */
2/*-----------------------------------------------------------------------------
3 * VID_1400.C
4 *
5 * Version 2.0 - February 21, 2000
6 *
7 * This file contains routines to control the SC1400 video overlay hardware.
8 *
9 * History:
10 *    Versions 0.1 through 2.0 by Brian Falardeau.
11 *
12 * Copyright (c) 1999-2000 National Semiconductor.
13 *-----------------------------------------------------------------------------
14 */
15
16/*----------------------------------------------------------------------------
17 * SC1400 PLL TABLE
18 *----------------------------------------------------------------------------
19 */
20
21typedef struct tagSC1400PLL
22{
23   long frequency;			/* 16.16 fixed point frequency */
24   unsigned long clock_select;		/* clock select register (0x2C) */
25}
26SC1400PLL;
27
28SC1400PLL gfx_sc1400_clock_table[] = {
29   {0x00192CCC, 0x00000000},		/*  25.1750 */
30   {0x001C526E, 0x00010000},		/*  28.3220 */
31   {0x001F8000, 0x00020000},		/*  31.5000 */
32   {0x00240000, 0x000E0000},		/*  36.0000 */
33   {0x00258000, 0x0010110C},		/*  37.5000 */
34   {0x00280000, 0x00040000},		/*  40.0000 */
35   {0x002CE666, 0x00090000},		/*  44.9000 */
36   {0x00320000, 0x00100C06},		/*  50.0000 */
37   {0x00325999, 0x0050600C},		/*  50.3500 */
38   {0x00360000, 0x00100100},		/*  54.0000 */
39   {0x0038643F, 0x0010160A},		/*  56.3916 */
40   {0x0038A3D7, 0x00506C0C},		/*  56.6440 */
41   {0x003B0000, 0x0010170A},		/*  59.6583 */
42   {0x003BA886, 0x00100A04},		/*  59.6583 */
43   {0x003F0000, 0x00100602},		/*  63.0000 */
44   {0x00410000, 0x00060000},		/*  65.0000 */
45   {0x00438000, 0x00100401},		/*  67.5000 */
46   {0x0046CCCC, 0x00101407},		/*  70.8000 */
47   {0x00480000, 0x00100702},		/*  72.0000 */
48   {0x004B0000, 0x00070000},		/*  75.0000 */
49   {0x004EC000, 0x0010220B},		/*  78.7500 */
50   {0x00500000, 0x00304C0C},		/*  80.0000 */
51   {0x00510000, 0x00100200},		/*  81.0000 */
52   {0x00550000, 0x00080000},		/*  85.0000 */
53   {0x0059CCCC, 0x00100902},		/*  89.8000 */
54   {0x00630000, 0x00100A02},		/*  99.0000 */
55   {0x00640000, 0x00102409},		/* 100.0000 */
56   {0x006C0000, 0x00100300},		/* 108.0000 */
57   {0x00870000, 0x00050000},		/* 135.0000 */
58   {0x009D8000, 0x00102205},		/* 157.5000 */
59   {0x00A20000, 0x00100500},		/* 162.0000 */
60   {0x00AA0000, 0x000B0000},		/* 170.0000 */
61   {0x00AF0000, 0x00100C01},		/* 175.0000 */
62   {0x00BD0000, 0x00100600},		/* 189.0000 */
63   {0x00CA0000, 0x00100E01},		/* 202.0000 */
64   {0x00E80000, 0x00102A04},		/* 232.0000 */
65};
66
67#define NUM_SC1400_FREQUENCIES sizeof(gfx_sc1400_clock_table)/sizeof(SC1400PLL)
68
69/*---------------------------------------------------------------------------
70 * gfx_reset_video (PRIVATE ROUTINE: NOT PART OF DURANGO API)
71 *
72 * This routine is used to disable all components of video overlay before
73 * performing a mode switch.
74 *---------------------------------------------------------------------------
75 */
76#if GFX_VIDEO_DYNAMIC
77void
78sc1400_reset_video(void)
79#else
80void
81gfx_reset_video(void)
82#endif
83{
84   gfx_set_video_enable(0);
85}
86
87/*---------------------------------------------------------------------------
88 * gfx_set_clock_frequency
89 *
90 * This routine sets the clock frequency, specified as a 16.16 fixed point
91 * value (0x00318000 = 49.5 MHz).  It will set the closest frequency found
92 * in the lookup table.
93 *---------------------------------------------------------------------------
94 */
95#if GFX_VIDEO_DYNAMIC
96void
97sc1400_set_clock_frequency(unsigned long frequency)
98#else
99void
100gfx_set_clock_frequency(unsigned long frequency)
101#endif
102{
103   int index;
104   unsigned long value;
105   long min, diff;
106
107   /* FIND THE REGISTER VALUES FOR THE DESIRED FREQUENCY */
108   /* Search the table for the closest frequency (16.16 format). */
109
110   value = gfx_sc1400_clock_table[0].clock_select;
111   min = (long)gfx_sc1400_clock_table[0].frequency - frequency;
112   if (min < 0L)
113      min = -min;
114   for (index = 1; index < NUM_SC1400_FREQUENCIES; index++) {
115      diff = (long)gfx_sc1400_clock_table[index].frequency - frequency;
116      if (diff < 0L)
117	 diff = -diff;
118      if (diff < min) {
119	 min = diff;
120	 value = gfx_sc1400_clock_table[index].clock_select;
121      }
122   }
123
124   /* SET THE DOT CLOCK REGISTER */
125
126   WRITE_VID32(SC1400_VID_MISC, 0x00001000);
127   WRITE_VID32(SC1400_VID_CLOCK_SELECT, value);
128   return;
129}
130
131/*-----------------------------------------------------------------------------
132 * gfx_set_video_enable
133 *
134 * This routine enables or disables the video overlay functionality.
135 *-----------------------------------------------------------------------------
136 */
137#if GFX_VIDEO_DYNAMIC
138int
139sc1400_set_video_enable(int enable)
140#else
141int
142gfx_set_video_enable(int enable)
143#endif
144{
145   unsigned long vcfg;
146
147   /* WAIT FOR VERTICAL BLANK TO START */
148   /* Otherwise a glitch can be observed. */
149
150   if (gfx_test_timing_active()) {
151      if (!gfx_test_vertical_active()) {
152	 while (!gfx_test_vertical_active()) ;
153      }
154      while (gfx_test_vertical_active()) ;
155   }
156   vcfg = READ_VID32(SC1400_VIDEO_CONFIG);
157   if (enable) {
158      /* ENABLE VIDEO OVERLAY FROM DISPLAY CONTROLLER */
159      /* Use private routine to abstract the display controller. */
160
161      gfx_set_display_video_enable(1);
162
163      /* SET SC1400 BUS CONTROL PARAMETERS */
164      /* Currently always high speed, 8-bit interface. */
165
166      vcfg |= SC1400_VCFG_HIGH_SPD_INT;
167      vcfg &= ~(SC1400_VCFG_EARLY_VID_RDY | SC1400_VCFG_16_BIT_EN);
168
169      /* ENABLE SC1400 VIDEO OVERLAY */
170
171      vcfg |= SC1400_VCFG_VID_EN;
172      WRITE_VID32(SC1400_VIDEO_CONFIG, vcfg);
173   } else {
174      /* DISABLE SC1400 VIDEO OVERLAY */
175
176      vcfg &= ~SC1400_VCFG_VID_EN;
177      WRITE_VID32(SC1400_VIDEO_CONFIG, vcfg);
178
179      /* DISABLE VIDEO OVERLAY FROM DISPLAY CONTROLLER */
180      /* Use private routine to abstract the display controller. */
181
182      gfx_set_display_video_enable(0);
183   }
184   return (0);
185}
186
187/*-----------------------------------------------------------------------------
188 * gfx_set_video_format
189 *
190 * Currently only sets 4:2:0 format, Y1 V Y0 U.
191 *-----------------------------------------------------------------------------
192 */
193#if GFX_VIDEO_DYNAMIC
194int
195sc1400_set_video_format(unsigned long format)
196#else
197int
198gfx_set_video_format(unsigned long format)
199#endif
200{
201   unsigned long vcfg = 0;
202
203   /* SET THE SC1400 VIDEO INPUT FORMAT */
204
205   vcfg = READ_VID32(SC1400_VIDEO_CONFIG);
206   vcfg &= ~(SC1400_VCFG_VID_INP_FORMAT | SC1400_VCFG_4_2_0_MODE);
207   vcfg &= ~(SC1400_VCFG_CSC_BYPASS);
208   if (format < 4)
209      vcfg |= (format << 2);
210   else
211      vcfg |= SC1400_VCFG_CSC_BYPASS;
212   WRITE_VID32(SC1400_VIDEO_CONFIG, vcfg);
213   return (0);
214}
215
216/*-----------------------------------------------------------------------------
217 * gfx_set_video_size
218 *
219 * This routine specifies the size of the source data.  It is used only
220 * to determine how much data to transfer per frame, and is not used to
221 * calculate the scaling value (that is handled by a separate routine).
222 *-----------------------------------------------------------------------------
223 */
224#if GFX_VIDEO_DYNAMIC
225int
226sc1400_set_video_size(unsigned short width, unsigned short height)
227#else
228int
229gfx_set_video_size(unsigned short width, unsigned short height)
230#endif
231{
232   unsigned long size, vcfg;
233
234   /* SET THE SC1400 VIDEO LINE SIZE */
235
236   vcfg = READ_VID32(SC1400_VIDEO_CONFIG);
237   vcfg &= ~(SC1400_VCFG_LINE_SIZE_LOWER_MASK | SC1400_VCFG_LINE_SIZE_UPPER);
238   size = (width >> 1);
239   vcfg |= (size & 0x00FF) << 8;
240   if (size & 0x0100)
241      vcfg |= SC1400_VCFG_LINE_SIZE_UPPER;
242   WRITE_VID32(SC1400_VIDEO_CONFIG, vcfg);
243
244   /* SET TOTAL VIDEO BUFFER SIZE IN DISPLAY CONTROLLER */
245   /* Use private routine to abstract the display controller. */
246
247   gfx_set_display_video_size(width, height);
248   return (0);
249}
250
251/*-----------------------------------------------------------------------------
252 * gfx_set_video_offset
253 *
254 * This routine sets the starting offset for the video buffer when only
255 * one offset needs to be specified.
256 *-----------------------------------------------------------------------------
257 */
258#if GFX_VIDEO_DYNAMIC
259int
260sc1400_set_video_offset(unsigned long offset)
261#else
262int
263gfx_set_video_offset(unsigned long offset)
264#endif
265{
266   /* SAVE VALUE FOR FUTURE CLIPPING OF THE TOP OF THE VIDEO WINDOW */
267
268   gfx_vid_offset = offset;
269
270   /* SET VIDEO BUFFER OFFSET IN DISPLAY CONTROLLER */
271   /* Use private routine to abstract the display controller. */
272
273   gfx_set_display_video_offset(offset);
274   return (0);
275}
276
277/*---------------------------------------------------------------------------
278 * gfx_set_video_scale
279 *
280 * This routine sets the scale factor for the video overlay window.  The
281 * size of the source and destination regions are specified in pixels.
282 *---------------------------------------------------------------------------
283 */
284#if GFX_VIDEO_DYNAMIC
285int
286sc1400_set_video_scale(unsigned short srcw, unsigned short srch,
287		       unsigned short dstw, unsigned short dsth)
288#else
289int
290gfx_set_video_scale(unsigned short srcw, unsigned short srch,
291		    unsigned short dstw, unsigned short dsth)
292#endif
293{
294   unsigned long xscale, yscale;
295
296   /* SAVE PARAMETERS */
297   /* These are needed for clipping the video window later. */
298
299   gfx_vid_srcw = srcw;
300   gfx_vid_srch = srch;
301   gfx_vid_dstw = dstw;
302   gfx_vid_dsth = dsth;
303
304   /* CALCULATE SC1400 SCALE FACTORS */
305   /* No downscaling in SC1400 so force to 1x if attempted. */
306
307   if (srcw < dstw)
308      xscale = (0x2000 * (srcw - 1)) / (dstw - 1);
309   else
310      xscale = 0x1FFF;
311   if (srch < dsth)
312      yscale = (0x2000 * (srch - 1)) / (dsth - 1);
313   else
314      yscale = 0x1FFF;
315   WRITE_VID32(SC1400_VIDEO_SCALE, (yscale << 16) | xscale);
316
317   /* CALL ROUTINE TO UPDATE WINDOW POSITION */
318   /* This is required because the scale values effect the number of */
319   /* source data pixels that need to be clipped, as well as the */
320   /* amount of data that needs to be transferred. */
321
322   gfx_set_video_window(gfx_vid_xpos, gfx_vid_ypos, gfx_vid_width,
323			gfx_vid_height);
324   return (0);
325}
326
327/*---------------------------------------------------------------------------
328 * gfx_set_video_window
329 *
330 * This routine sets the position and size of the video overlay window.  The
331 * position is specified in screen relative coordinates, and may be negative.
332 * The size of destination region is specified in pixels.  The line size
333 * indicates the number of bytes of source data per scanline.
334 *---------------------------------------------------------------------------
335 */
336#if GFX_VIDEO_DYNAMIC
337int
338sc1400_set_video_window(short x, short y, unsigned short w, unsigned short h)
339#else
340int
341gfx_set_video_window(short x, short y, unsigned short w, unsigned short h)
342#endif
343{
344   unsigned long vcfg = 0;
345   unsigned long hadjust, vadjust;
346   unsigned long initread;
347   unsigned long xstart, ystart, xend, yend;
348   unsigned long offset, line_size;
349
350   /* SAVE PARAMETERS */
351   /* These are needed to call this routine if the scale value changes. */
352
353   gfx_vid_xpos = x;
354   gfx_vid_ypos = y;
355   gfx_vid_width = w;
356   gfx_vid_height = h;
357
358   /* GET ADJUSTMENT VALUES */
359   /* Use routines to abstract version of display controller. */
360
361   hadjust = gfx_get_htotal() - gfx_get_hsync_end() - 13;
362   vadjust = gfx_get_vtotal() - gfx_get_vsync_end() + 1;
363
364   if (x > 0) {
365      /* NO CLIPPING ON LEFT */
366
367      xstart = x + hadjust;
368      initread = 0;
369   } else {
370      /* CLIPPING ON LEFT */
371      /* Adjust initial read for scale, checking for divide by zero */
372
373      xstart = hadjust;
374      initread = -x;
375      if (gfx_vid_dstw)
376	 initread = ((-x) * gfx_vid_srcw) / gfx_vid_dstw;
377      else
378	 initread = 0;
379   }
380
381   /* CLIPPING ON RIGHT */
382
383   xend = x + w;
384   if (xend > gfx_get_hactive())
385      xend = gfx_get_hactive();
386   xend += hadjust;
387
388   /* CLIPPING ON TOP */
389
390   offset = gfx_vid_offset;
391   if (y >= 0) {
392      ystart = y + vadjust;
393   } else {
394      ystart = vadjust;
395      line_size = (READ_VID32(SC1400_VIDEO_CONFIG) >> 7) & 0x000001FE;
396      if (READ_VID32(SC1400_VIDEO_CONFIG) & SC1400_VCFG_LINE_SIZE_UPPER)
397	 line_size += 512;
398      if (gfx_vid_dsth)
399	 offset = gfx_vid_offset + (line_size << 1) *
400	       (((-y) * gfx_vid_srch) / gfx_vid_dsth);
401   }
402
403   /* CLIPPING ON BOTTOM */
404
405   yend = y + h;
406   if (yend >= gfx_get_vactive())
407      yend = gfx_get_vactive();
408   yend += vadjust;
409
410   /* SET VIDEO BUFFER OFFSET IN DISPLAY CONTROLLER */
411   /* Use private routine to abstract the display controller. */
412
413   gfx_set_display_video_offset(offset);
414
415   /* DISABLE REGISTER UPDATES */
416
417   vcfg = READ_VID32(SC1400_VIDEO_CONFIG);
418   vcfg &= ~SC1400_VCFG_VID_REG_UPDATE;
419   WRITE_VID32(SC1400_VIDEO_CONFIG, vcfg);
420
421   /* SET VIDEO POSITION */
422
423   WRITE_VID32(SC1400_VIDEO_X_POS, (xend << 16) | xstart);
424   WRITE_VID32(SC1400_VIDEO_Y_POS, (yend << 16) | ystart);
425
426   /* SET INITIAL READ ADDRESS AND ENABLE REGISTER UPDATES */
427
428   vcfg &= ~SC1400_VCFG_INIT_READ_MASK;
429   vcfg |= (initread << 15) & SC1400_VCFG_INIT_READ_MASK;
430   vcfg |= SC1400_VCFG_VID_REG_UPDATE;
431   WRITE_VID32(SC1400_VIDEO_CONFIG, vcfg);
432   return (0);
433}
434
435/*---------------------------------------------------------------------------
436 * gfx_set_video_color_key
437 *
438 * This routine specifies the color key value and mask for the video overlay
439 * hardware.  To disable color key, the color and mask should both be set to
440 * zero.  The hardware uses the color key in the following equation:
441 *
442 * ((source data) & (color key mask)) == ((color key) & (color key mask))
443 *
444 * The source data can be either graphics data or video data.  The bluescreen
445 * parameter is set to have the hardware compare video data and clear to
446 * comapare graphics data.
447 *---------------------------------------------------------------------------
448 */
449#if GFX_VIDEO_DYNAMIC
450int
451sc1400_set_video_color_key(unsigned long key, unsigned long mask,
452			   int graphics)
453#else
454int
455gfx_set_video_color_key(unsigned long key, unsigned long mask, int graphics)
456#endif
457{
458   unsigned long dcfg = 0;
459
460   /* SET SC1400 COLOR KEY VALUE */
461
462   WRITE_VID32(SC1400_VIDEO_COLOR_KEY, key);
463   WRITE_VID32(SC1400_VIDEO_COLOR_MASK, mask);
464
465   /* SELECT GRAPHICS OR VIDEO DATA TO COMPARE TO THE COLOR KEY */
466
467   dcfg = READ_VID32(SC1400_DISPLAY_CONFIG);
468   if (graphics & 0x01)
469      dcfg &= ~SC1400_DCFG_VG_CK;
470   else
471      dcfg |= SC1400_DCFG_VG_CK;
472   WRITE_VID32(SC1400_DISPLAY_CONFIG, dcfg);
473   return (0);
474}
475
476/*---------------------------------------------------------------------------
477 * gfx_set_video_filter
478 *
479 * This routine enables or disables the video overlay filters.
480 *---------------------------------------------------------------------------
481 */
482#if GFX_VIDEO_DYNAMIC
483int
484sc1400_set_video_filter(int xfilter, int yfilter)
485#else
486int
487gfx_set_video_filter(int xfilter, int yfilter)
488#endif
489{
490   unsigned long vcfg = 0;
491
492   /* ENABLE OR DISABLE SC1400 VIDEO OVERLAY FILTERS */
493
494   vcfg = READ_VID32(SC1400_VIDEO_CONFIG);
495   vcfg &= ~(SC1400_VCFG_X_FILTER_EN | SC1400_VCFG_Y_FILTER_EN);
496   if (xfilter)
497      vcfg |= SC1400_VCFG_X_FILTER_EN;
498   if (yfilter)
499      vcfg |= SC1400_VCFG_Y_FILTER_EN;
500   WRITE_VID32(SC1400_VIDEO_CONFIG, vcfg);
501   return (0);
502}
503
504/*---------------------------------------------------------------------------
505 * gfx_set_video_palette
506 *
507 * This routine loads the video hardware palette.  If a NULL pointer is
508 * specified, the palette is bypassed (for SC1400, this means loading the
509 * palette with identity values).
510 *---------------------------------------------------------------------------
511 */
512#if GFX_VIDEO_DYNAMIC
513int
514sc1400_set_video_palette(unsigned long *palette)
515#else
516int
517gfx_set_video_palette(unsigned long *palette)
518#endif
519{
520   unsigned long i, entry;
521
522   /* LOAD SC1400 VIDEO PALETTE */
523
524   WRITE_VID32(SC1400_PALETTE_ADDRESS, 0);
525   for (i = 0; i < 256; i++) {
526      if (palette)
527	 entry = palette[i];
528      else
529	 entry = i | (i << 8) | (i << 16);
530      WRITE_VID32(SC1400_PALETTE_DATA, entry);
531   }
532   return (0);
533}
534
535/*************************************************************/
536/*  READ ROUTINES  |  INCLUDED FOR DIAGNOSTIC PURPOSES ONLY  */
537/*************************************************************/
538
539#if GFX_READ_ROUTINES
540
541/*---------------------------------------------------------------------------
542 * gfx_get_sync_polarities
543 *
544 * This routine returns the polarities of the sync pulses:
545 *     Bit 0: Set if negative horizontal polarity.
546 *     Bit 1: Set if negative vertical polarity.
547 *---------------------------------------------------------------------------
548 */
549#if GFX_VIDEO_DYNAMIC
550int
551sc1400_get_sync_polarities(void)
552#else
553int
554gfx_get_sync_polarities(void)
555#endif
556{
557   int polarities = 0;
558
559   if (READ_VID32(SC1400_DISPLAY_CONFIG) & 0x00000100)
560      polarities |= 1;
561   if (READ_VID32(SC1400_DISPLAY_CONFIG) & 0x00000200)
562      polarities |= 2;
563   return (polarities);
564}
565
566/*-----------------------------------------------------------------------------
567 * gfx_get_video_enable
568 *
569 * This routine returns the value "one" if video overlay is currently enabled,
570 * otherwise it returns the value "zero".
571 *-----------------------------------------------------------------------------
572 */
573#if GFX_VIDEO_DYNAMIC
574int
575sc1400_get_video_enable(void)
576#else
577int
578gfx_get_video_enable(void)
579#endif
580{
581   if (READ_VID32(SC1400_VIDEO_CONFIG) & SC1400_VCFG_VID_EN)
582      return (1);
583   return (0);
584}
585
586/*-----------------------------------------------------------------------------
587 * gfx_get_video_format
588 *
589 * This routine returns the current video overlay format.
590 *-----------------------------------------------------------------------------
591 */
592#if GFX_VIDEO_DYNAMIC
593int
594sc1400_get_video_format(void)
595#else
596int
597gfx_get_video_format(void)
598#endif
599{
600   unsigned long vcfg;
601
602   vcfg = READ_VID32(SC1400_VIDEO_CONFIG);
603   if (vcfg & SC1400_VCFG_CSC_BYPASS)
604      return (4);
605   else
606      return ((vcfg >> 2) & 3);
607}
608
609/*-----------------------------------------------------------------------------
610 * gfx_get_video_src_size
611 *
612 * This routine returns the size of the source video overlay buffer.  The
613 * return value is (height << 16) | width.
614 *-----------------------------------------------------------------------------
615 */
616#if GFX_VIDEO_DYNAMIC
617unsigned long
618sc1400_get_video_src_size(void)
619#else
620unsigned long
621gfx_get_video_src_size(void)
622#endif
623{
624   unsigned long width = 0, height = 0;
625
626   /* DETERMINE SOURCE WIDTH FROM THE SC1400 VIDEO LINE SIZE */
627
628   width = (READ_VID32(SC1400_VIDEO_CONFIG) >> 7) & 0x000001FE;
629   if (READ_VID32(SC1400_VIDEO_CONFIG) & SC1400_VCFG_LINE_SIZE_UPPER)
630      width += 512;
631
632   if (width) {
633      /* DETERMINE HEIGHT BY DIVIDING TOTAL SIZE BY WIDTH */
634      /* Get total size from display controller - abtracted. */
635
636      height = gfx_get_display_video_size() / (width << 1);
637   }
638   return ((height << 16) | width);
639}
640
641/*-----------------------------------------------------------------------------
642 * gfx_get_video_line_size
643 *
644 * This routine returns the line size of the source video overlay buffer, in
645 * pixels.
646 *-----------------------------------------------------------------------------
647 */
648#if GFX_VIDEO_DYNAMIC
649unsigned long
650sc1400_get_video_line_size(void)
651#else
652unsigned long
653gfx_get_video_line_size(void)
654#endif
655{
656   unsigned long width = 0;
657
658   /* DETERMINE SOURCE WIDTH FROM THE SC1400 VIDEO LINE SIZE */
659
660   width = (READ_VID32(SC1400_VIDEO_CONFIG) >> 7) & 0x000001FE;
661   if (READ_VID32(SC1400_VIDEO_CONFIG) & SC1400_VCFG_LINE_SIZE_UPPER)
662      width += 512;
663   return (width);
664}
665
666/*-----------------------------------------------------------------------------
667 * gfx_get_video_xclip
668 *
669 * This routine returns the number of bytes clipped on the left side of a
670 * video overlay line (skipped at beginning).
671 *-----------------------------------------------------------------------------
672 */
673#if GFX_VIDEO_DYNAMIC
674unsigned long
675sc1400_get_video_xclip(void)
676#else
677unsigned long
678gfx_get_video_xclip(void)
679#endif
680{
681   unsigned long clip = 0;
682
683   /* DETERMINE SOURCE WIDTH FROM THE SC1400 VIDEO LINE SIZE */
684
685   clip = (READ_VID32(SC1400_VIDEO_CONFIG) >> 14) & 0x000007FC;
686   return (clip);
687}
688
689/*-----------------------------------------------------------------------------
690 * gfx_get_video_offset
691 *
692 * This routine returns the current offset for the video overlay buffer.
693 *-----------------------------------------------------------------------------
694 */
695#if GFX_VIDEO_DYNAMIC
696unsigned long
697sc1400_get_video_offset(void)
698#else
699unsigned long
700gfx_get_video_offset(void)
701#endif
702{
703   return (gfx_get_display_video_offset());
704}
705
706/*---------------------------------------------------------------------------
707 * gfx_get_video_scale
708 *
709 * This routine returns the scale factor for the video overlay window.
710 *---------------------------------------------------------------------------
711 */
712#if GFX_VIDEO_DYNAMIC
713unsigned long
714sc1400_get_video_scale(void)
715#else
716unsigned long
717gfx_get_video_scale(void)
718#endif
719{
720   return (READ_VID32(SC1400_VIDEO_SCALE));
721}
722
723/*---------------------------------------------------------------------------
724 * gfx_get_video_dst_size
725 *
726 * This routine returns the size of the displayed video overlay window.
727 *---------------------------------------------------------------------------
728 */
729#if GFX_VIDEO_DYNAMIC
730unsigned long
731sc1400_get_video_dst_size(void)
732#else
733unsigned long
734gfx_get_video_dst_size(void)
735#endif
736{
737   unsigned long xsize, ysize;
738
739   xsize = READ_VID32(SC1400_VIDEO_X_POS);
740   xsize = ((xsize >> 16) & 0x3FF) - (xsize & 0x03FF);
741   ysize = READ_VID32(SC1400_VIDEO_Y_POS);
742   ysize = ((ysize >> 16) & 0x3FF) - (ysize & 0x03FF);
743   return ((ysize << 16) | xsize);
744}
745
746/*---------------------------------------------------------------------------
747 * gfx_get_video_position
748 *
749 * This routine returns the position of the video overlay window.  The
750 * return value is (ypos << 16) | xpos.
751 *---------------------------------------------------------------------------
752 */
753#if GFX_VIDEO_DYNAMIC
754unsigned long
755sc1400_get_video_position(void)
756#else
757unsigned long
758gfx_get_video_position(void)
759#endif
760{
761   unsigned long hadjust, vadjust;
762   unsigned long xpos, ypos;
763
764   /* READ HARDWARE POSITION */
765
766   xpos = READ_VID32(SC1400_VIDEO_X_POS) & 0x000003FF;
767   ypos = READ_VID32(SC1400_VIDEO_Y_POS) & 0x000003FF;
768
769   /* GET ADJUSTMENT VALUES */
770   /* Use routines to abstract version of display controller. */
771
772   hadjust = gfx_get_htotal() - gfx_get_hsync_end() - 13;
773   vadjust = gfx_get_vtotal() - gfx_get_vsync_end() + 1;
774   xpos -= hadjust;
775   ypos -= vadjust;
776   return ((ypos << 16) | (xpos & 0x0000FFFF));
777}
778
779/*---------------------------------------------------------------------------
780 * gfx_get_video_color_key
781 *
782 * This routine returns the current video color key value.
783 *---------------------------------------------------------------------------
784 */
785#if GFX_VIDEO_DYNAMIC
786unsigned long
787sc1400_get_video_color_key(void)
788#else
789unsigned long
790gfx_get_video_color_key(void)
791#endif
792{
793   return (READ_VID32(SC1400_VIDEO_COLOR_KEY));
794}
795
796/*---------------------------------------------------------------------------
797 * gfx_get_video_color_key_mask
798 *
799 * This routine returns the current video color mask value.
800 *---------------------------------------------------------------------------
801 */
802#if GFX_VIDEO_DYNAMIC
803unsigned long
804sc1400_get_video_color_key_mask(void)
805#else
806unsigned long
807gfx_get_video_color_key_mask(void)
808#endif
809{
810   return (READ_VID32(SC1400_VIDEO_COLOR_MASK));
811}
812
813/*---------------------------------------------------------------------------
814 * gfx_get_video_color_key_src
815 *
816 * This routine returns 0 for video data compare, 1 for graphics data.
817 *---------------------------------------------------------------------------
818 */
819#if GFX_VIDEO_DYNAMIC
820int
821sc1400_get_video_color_key_src(void)
822#else
823int
824gfx_get_video_color_key_src(void)
825#endif
826{
827   if (READ_VID32(SC1400_DISPLAY_CONFIG) & SC1400_DCFG_VG_CK)
828      return (0);
829   return (1);
830}
831
832/*---------------------------------------------------------------------------
833 * gfx_get_video_filter
834 *
835 * This routine returns if the filters are currently enabled.
836 *---------------------------------------------------------------------------
837 */
838#if GFX_VIDEO_DYNAMIC
839int
840sc1400_get_video_filter(void)
841#else
842int
843gfx_get_video_filter(void)
844#endif
845{
846   int retval = 0;
847
848   if (READ_VID32(SC1400_VIDEO_CONFIG) & SC1400_VCFG_X_FILTER_EN)
849      retval |= 1;
850   if (READ_VID32(SC1400_VIDEO_CONFIG) & SC1400_VCFG_Y_FILTER_EN)
851      retval |= 2;
852   return (retval);
853}
854
855/*---------------------------------------------------------------------------
856 * gfx_get_clock_frequency
857 *
858 * This routine returns the current clock frequency in 16.16 format.
859 * It reads the current register value and finds the match in the table.
860 * If no match is found, this routine returns 0.
861 *---------------------------------------------------------------------------
862 */
863#if GFX_VIDEO_DYNAMIC
864unsigned long
865sc1400_get_clock_frequency(void)
866#else
867unsigned long
868gfx_get_clock_frequency(void)
869#endif
870{
871   int index;
872   unsigned long value, mask;
873
874   mask = 0x007FFF0F;
875   value = READ_VID32(SC1400_VID_CLOCK_SELECT) & mask;
876   for (index = 0; index < NUM_SC1400_FREQUENCIES; index++) {
877      if ((gfx_sc1400_clock_table[index].clock_select & mask) == value)
878	 return (gfx_sc1400_clock_table[index].frequency);
879   }
880   return (0);
881}
882
883/*---------------------------------------------------------------------------
884 * gfx_read_crc
885 *
886 * This routine returns the hardware CRC value, which is used for automated
887 * testing.  The value is like a checksum, but will change if pixels move
888 * locations.
889 *---------------------------------------------------------------------------
890 */
891#if GFX_VIDEO_DYNAMIC
892unsigned long
893sc1400_read_crc(void)
894#else
895unsigned long
896gfx_read_crc(void)
897#endif
898{
899   unsigned long crc = 0xFFFFFFFF;
900
901   if (gfx_test_timing_active()) {
902      // WAIT UNTIL ACTIVE DISPLAY
903
904      while (!gfx_test_vertical_active()) ;
905
906      // RESET CRC DURING ACTIVE DISPLAY
907
908      WRITE_VID32(SC1400_VID_CRC, 0);
909      WRITE_VID32(SC1400_VID_CRC, 1);
910
911      // WAIT UNTIL NOT ACTIVE, THEN ACTIVE, NOT ACTIVE, THEN ACTIVE
912
913      while (gfx_test_vertical_active()) ;
914      while (!gfx_test_vertical_active()) ;
915      while (gfx_test_vertical_active()) ;
916      while (!gfx_test_vertical_active()) ;
917      crc = READ_VID32(SC1400_VID_CRC) >> 8;
918   }
919   return (crc);
920}
921
922#endif /* GFX_READ_ROUTINES */
923
924/* END OF FILE */
925