tv_1200.c revision 71d7fec4
1/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nsc/gfx/tv_1200.c,v 1.1 2002/12/10 15:12:27 alanh Exp $ */
2/*
3 * $Workfile: tv_1200.c $
4 *
5 * This file contains routines to control the SC1200 TVOUT and TV encoder.
6 *
7 * NSC_LIC_ALTERNATIVE_PREAMBLE
8 *
9 * Revision 1.0
10 *
11 * National Semiconductor Alternative GPL-BSD License
12 *
13 * National Semiconductor Corporation licenses this software
14 * ("Software"):
15 *
16 *      Durango
17 *
18 * under one of the two following licenses, depending on how the
19 * Software is received by the Licensee.
20 *
21 * If this Software is received as part of the Linux Framebuffer or
22 * other GPL licensed software, then the GPL license designated
23 * NSC_LIC_GPL applies to this Software; in all other circumstances
24 * then the BSD-style license designated NSC_LIC_BSD shall apply.
25 *
26 * END_NSC_LIC_ALTERNATIVE_PREAMBLE */
27
28/* NSC_LIC_BSD
29 *
30 * National Semiconductor Corporation Open Source License for Durango
31 *
32 * (BSD License with Export Notice)
33 *
34 * Copyright (c) 1999-2001
35 * National Semiconductor Corporation.
36 * All rights reserved.
37 *
38 * Redistribution and use in source and binary forms, with or without
39 * modification, are permitted provided that the following conditions
40 * are met:
41 *
42 *   * Redistributions of source code must retain the above copyright
43 *     notice, this list of conditions and the following disclaimer.
44 *
45 *   * Redistributions in binary form must reproduce the above
46 *     copyright notice, this list of conditions and the following
47 *     disclaimer in the documentation and/or other materials provided
48 *     with the distribution.
49 *
50 *   * Neither the name of the National Semiconductor Corporation nor
51 *     the names of its contributors may be used to endorse or promote
52 *     products derived from this software without specific prior
53 *     written permission.
54 *
55 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
56 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
57 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
58 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
59 * NATIONAL SEMICONDUCTOR CORPORATION OR CONTRIBUTORS BE LIABLE FOR ANY
60 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
61 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
62 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
63 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
64 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE,
65 * INTELLECTUAL PROPERTY INFRINGEMENT, OR OTHERWISE) ARISING IN ANY WAY
66 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
67 * OF SUCH DAMAGE.
68 *
69 * EXPORT LAWS: THIS LICENSE ADDS NO RESTRICTIONS TO THE EXPORT LAWS OF
70 * YOUR JURISDICTION. It is licensee's responsibility to comply with
71 * any export regulations applicable in licensee's jurisdiction. Under
72 * CURRENT (2001) U.S. export regulations this software
73 * is eligible for export from the U.S. and can be downloaded by or
74 * otherwise exported or reexported worldwide EXCEPT to U.S. embargoed
75 * destinations which include Cuba, Iraq, Libya, North Korea, Iran,
76 * Syria, Sudan, Afghanistan and any other country to which the U.S.
77 * has embargoed goods and services.
78 *
79 * END_NSC_LIC_BSD */
80
81/* NSC_LIC_GPL
82 *
83 * National Semiconductor Corporation Gnu General Public License for Durango
84 *
85 * (GPL License with Export Notice)
86 *
87 * Copyright (c) 1999-2001
88 * National Semiconductor Corporation.
89 * All rights reserved.
90 *
91 * Redistribution and use in source and binary forms, with or without
92 * modification, are permitted under the terms of the GNU General
93 * Public License as published by the Free Software Foundation; either
94 * version 2 of the License, or (at your option) any later version
95 *
96 * In addition to the terms of the GNU General Public License, neither
97 * the name of the National Semiconductor Corporation nor the names of
98 * its contributors may be used to endorse or promote products derived
99 * from this software without specific prior written permission.
100 *
101 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
102 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
103 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
104 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
105 * NATIONAL SEMICONDUCTOR CORPORATION OR CONTRIBUTORS BE LIABLE FOR ANY
106 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
107 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
108 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
109 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
110 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE,
111 * INTELLECTUAL PROPERTY INFRINGEMENT, OR OTHERWISE) ARISING IN ANY WAY
112 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
113 * OF SUCH DAMAGE. See the GNU General Public License for more details.
114 *
115 * EXPORT LAWS: THIS LICENSE ADDS NO RESTRICTIONS TO THE EXPORT LAWS OF
116 * YOUR JURISDICTION. It is licensee's responsibility to comply with
117 * any export regulations applicable in licensee's jurisdiction. Under
118 * CURRENT (2001) U.S. export regulations this software
119 * is eligible for export from the U.S. and can be downloaded by or
120 * otherwise exported or reexported worldwide EXCEPT to U.S. embargoed
121 * destinations which include Cuba, Iraq, Libya, North Korea, Iran,
122 * Syria, Sudan, Afghanistan and any other country to which the U.S.
123 * has embargoed goods and services.
124 *
125 * You should have received a copy of the GNU General Public License
126 * along with this file; if not, write to the Free Software Foundation,
127 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
128 *
129 * END_NSC_LIC_GPL */
130
131int sc1200_set_tv_format(TVStandardType format, GfxOnTVType resolution);
132int sc1200_set_tv_output(int output);
133int sc1200_set_tv_enable(int enable);
134int sc1200_set_tv_flicker_filter(int ff);
135int sc1200_set_tv_sub_carrier_reset(int screset);
136int sc1200_set_tv_vphase(int vphase);
137int sc1200_set_tv_YC_delay(int delay);
138int sc1200_set_tvenc_reset_interval(int interval);
139int sc1200_set_tv_cc_enable(int enable);
140int sc1200_set_tv_cc_data(unsigned char data1, unsigned char data2);
141int sc1200_set_tv_display(int width, int height);
142int sc1200_test_tvout_odd_field(void);
143int sc1200_test_tvenc_odd_field(void);
144int sc1200_set_tv_field_status_invert(int enable);
145int sc1200_get_tv_vphase(void);
146int sc1200_get_tv_enable(unsigned int *p_on);
147int sc1200_get_tv_output(void);
148int sc1200_get_tv_mode_count(TVStandardType format);
149int sc1200_get_tv_display_mode(int *width, int *height, int *bpp, int *hz);
150int sc1200_get_tv_display_mode_frequency(unsigned short width,
151					 unsigned short height,
152					 TVStandardType format,
153					 int *frequency);
154int sc1200_is_tv_display_mode_supported(unsigned short width,
155					unsigned short height,
156					TVStandardType format);
157
158int sc1200_get_tv_standard(unsigned long *p_standard);
159int sc1200_get_available_tv_standards(unsigned long *p_standards);
160int sc1200_set_tv_standard(unsigned long standard);
161int sc1200_get_tv_vga_mode(unsigned long *p_vga_mode);
162int sc1200_get_available_tv_vga_modes(unsigned long *p_vga_modes);
163int sc1200_set_tv_vga_mode(unsigned long vga_mode);
164int sc1200_get_tvout_mode(unsigned long *p_tvout_mode);
165int sc1200_set_tvout_mode(unsigned long tvout_mode);
166int sc1200_get_sharpness(int *p_sharpness);
167int sc1200_set_sharpness(int sharpness);
168int sc1200_get_flicker_filter(int *p_flicker);
169int sc1200_set_flicker_filter(int flicker);
170int sc1200_get_overscan(int *p_x, int *p_y);
171int sc1200_set_overscan(int x, int y);
172int sc1200_get_position(int *p_x, int *p_y);
173int sc1200_set_position(int x, int y);
174int sc1200_get_color(int *p_color);
175int sc1200_set_color(int color);
176int sc1200_get_brightness(int *p_brightness);
177int sc1200_set_brightness(int brightness);
178int sc1200_get_contrast(int *p_contrast);
179int sc1200_set_contrast(int constrast);
180int sc1200_get_yc_filter(unsigned int *p_yc_filter);
181int sc1200_set_yc_filter(unsigned int yc_filter);
182int sc1200_get_aps_trigger_bits(unsigned int *p_trigger_bits);
183int sc1200_set_aps_trigger_bits(unsigned int trigger_bits);
184unsigned char cc_add_parity_bit(unsigned char data);
185
186/*-----------------------------------------------------------------------------
187 * gfx_set_tv_format
188 *
189 * This routine sets the TV encoder registers to the specified format
190 * and resolution.
191 *-----------------------------------------------------------------------------
192 */
193#if GFX_TV_DYNAMIC
194int
195sc1200_set_tv_format(TVStandardType format, GfxOnTVType resolution)
196#else
197int
198gfx_set_tv_format(TVStandardType format, GfxOnTVType resolution)
199#endif
200{
201   unsigned long ctrl2, mode;
202
203   /* Save TV output mode */
204   ctrl2 =
205	 READ_VID32(SC1200_TVENC_TIM_CTRL_2) & (SC1200_TVENC_OUTPUT_YCBCR |
206						SC1200_TVENC_CFS_MASK);
207   /* Save flicker filter setting */
208   mode = READ_VID32(SC1200_TVOUT_HORZ_SCALING) &
209	 SC1200_TVOUT_FLICKER_FILTER_MASK;
210
211   switch (format) {
212   case TV_STANDARD_NTSC:
213      /* Horizontal Sync Start is 848 */
214      /* Horizontal Sync End is 856 */
215      WRITE_VID32(SC1200_TVOUT_HORZ_SYNC, 0x03580350);
216      /* Vertical Sync Start is 0 */
217      /* Vertical Sync End is 1 */
218      /* Vertical Display Start Skew is 1 */
219      /* Vertical Display End Skew is 1 */
220      WRITE_VID32(SC1200_TVOUT_VERT_SYNC, 0x05001000);
221      /* Disable vertical down scaling, take all lines */
222      if (gfx_chip_revision <= SC1200_REV_B3)
223	 WRITE_VID32(SC1200_TVOUT_VERT_DOWNSCALE, 0xffffffff);
224      /* Enable video timing */
225      /* Reset sub carrier every two frames */
226      /* Disable BLANK */
227      /* Enable color burst */
228      /* Add the IRE offset */
229      /* NTSC color encoding */
230      /* Video generator timing is 525 lines / 60Hz */
231      /* Horizontal and Vertical counters are initialized to HPHASE & VPHASE */
232      /* VPHASE is 2, HPHASE is 0x50 */
233      WRITE_VID32(SC1200_TVENC_TIM_CTRL_1, 0xa2a01050);
234      /* Increase horizontal blanking interval */
235      /* Low Water Mark for Y is 0x1F */
236      /* Low Water Mark for Cb is 0xF */
237      /* HUE is 0 */
238      /* SCPHASE is 0xF9 */
239      WRITE_VID32(SC1200_TVENC_TIM_CTRL_2, 0x9ff000f9 | ctrl2);
240      /* Subcarrier Frequency is 3.579545 MHz */
241      WRITE_VID32(SC1200_TVENC_SUB_FREQ, 0x21f07c1f);
242      /* VSTART is 18, HSTART is 113 */
243      WRITE_VID32(SC1200_TVENC_DISP_POS, 0x00120071);
244      /* Display size: HEIGHT is 239, WIDTH is 719 */
245      WRITE_VID32(SC1200_TVENC_DISP_SIZE, 0x00ef02cf);
246      switch (resolution) {
247      case GFX_ON_TV_SQUARE_PIXELS:
248	 if (gfx_chip_revision <= SC1200_REV_B3) {
249	    /* Horizontal Display start is 116 */
250	    /* Total number of pixels per line is 857 */
251	    WRITE_VID32(SC1200_TVOUT_HORZ_TIM, 0x00740359);
252	    /* HSYNC generated in the TV Encoder module */
253	    /* Interval between resets of TV Encoder is once every odd field */
254	    /* Enable Horizontal interpolation */
255	    /* Enable Horizontal up scaling 9/8 */
256	    /* Disable Horizontal downscale */
257	    WRITE_VID32(SC1200_TVOUT_HORZ_SCALING, 0x10020700 | mode);
258	    /* Horizontal display end is 919, i.e. 720 active pixels */
259	    /* Total number of display lines per field is 240 */
260	    WRITE_VID32(SC1200_TVOUT_LINE_END, 0x039700f0);
261	 } else {			/* Use new scaler available in Rev. C */
262	    /* Horizontal Display start is 111 */
263	    /* Total number of pixels per line is 857 */
264	    WRITE_VID32(SC1200_TVOUT_HORZ_TIM, 0x006f0359);
265	    /* HSYNC generated in the TV Encoder module */
266	    /* Interval between resets of TV Encoder is once every odd field */
267	    /* Enable Horizontal interpolation */
268	    /* Disable Horizontal up scaling 9/8 */
269	    /* Disable Horizontal downscale */
270	    WRITE_VID32(SC1200_TVOUT_HORZ_SCALING, 0x10020500 | mode);
271	    /* Set Horizontal upscaling to 64/58 (~ 11/10) */
272	    WRITE_VID32(SC1200_TVOUT_HORZ_PRE_ENCODER_SCALE, 0x3A000000);
273	    /* Horizontal display end is 900, i.e. 706 active pixels */
274	    /* Total number of display lines per field is 240 */
275	    WRITE_VID32(SC1200_TVOUT_LINE_END, 0x038400f0);
276	 }
277	 break;
278      case GFX_ON_TV_NO_SCALING:
279	 /* Horizontal Display start is 116 */
280	 /* Total number of pixels per line is 857 */
281	 WRITE_VID32(SC1200_TVOUT_HORZ_TIM, 0x00740359);
282	 /* HSYNC generated in the TV Encoder module */
283	 /* Interval between resets of TV Encoder is once every odd field */
284	 /* Enable Horizontal interpolation */
285	 /* Disable Horizontal up scaling 9/8 */
286	 /* Disable Horizontal downscale */
287	 WRITE_VID32(SC1200_TVOUT_HORZ_SCALING, 0x10020500 | mode);
288	 /* Disable Horizontal scaling (set to 64/64) */
289	 if (gfx_chip_revision >= SC1200_REV_C1)
290	    WRITE_VID32(SC1200_TVOUT_HORZ_PRE_ENCODER_SCALE, 0x40000000);
291	 /* Horizontal display end is 919, i.e. 720 active pixels */
292	 /* Total number of display lines per field is 240 */
293	 WRITE_VID32(SC1200_TVOUT_LINE_END, 0x039700f0);
294	 break;
295      default:
296	 return (GFX_STATUS_BAD_PARAMETER);
297      }
298      break;
299   case TV_STANDARD_PAL:
300      /* Horizontal Sync Start is 854 */
301      /* Horizontal Sync End is 862 */
302      WRITE_VID32(SC1200_TVOUT_HORZ_SYNC, 0x035e0356);
303      /* Vertical Sync Start is 0 */
304      /* Vertical Sync End is 1 */
305      /* Vertical Display Start Skew is 1 */
306      /* Vertical Display End Skew is 1 */
307      WRITE_VID32(SC1200_TVOUT_VERT_SYNC, 0x05001000);
308      /* Disable vertical down scaling, take all lines */
309      if (gfx_chip_revision <= SC1200_REV_B3)
310	 WRITE_VID32(SC1200_TVOUT_VERT_DOWNSCALE, 0xffffffff);
311      /* Enable video timing */
312      /* Never reset sub carrier (should be every 4 frames but doesn't work with genlock) */
313      /* Disable BLANK */
314      /* Enable color burst */
315      /* Do not add the IRE offset */
316      /* NTSC color encoding */
317      /* Video generator timing is 625 lines / 50Hz */
318      /* Horizontal and Vertical counters are initialized to HPHASE & VPHASE */
319      /* VPHASE is 2, HPHASE is 50 */
320      WRITE_VID32(SC1200_TVENC_TIM_CTRL_1, 0xB1201050);
321      /* Increase horizontal blanking interval */
322      /* Low Water Mark for Y is 0x1F */
323      /* Low Water Mark for Cb is 0xF */
324      /* HUE is 0 */
325      /* SCPHASE is 0xD9 */
326      WRITE_VID32(SC1200_TVENC_TIM_CTRL_2, 0x9ff000d9 | ctrl2);
327      /* Subcarrier Frequency is 4.43361875 MHz */
328      WRITE_VID32(SC1200_TVENC_SUB_FREQ, 0x2a098acb);
329      /* VSTART is 22, HSTART is 123 */
330      WRITE_VID32(SC1200_TVENC_DISP_POS, 0x0016007b);
331      /* Display size: HEIGHT is 287, WIDTH is 719 */
332      WRITE_VID32(SC1200_TVENC_DISP_SIZE, 0x011f02cf);
333      switch (resolution) {
334      case GFX_ON_TV_NO_SCALING:
335	 /* Horizontal Display start is 124 */
336	 /* Total number of pixels per line is 863 */
337	 WRITE_VID32(SC1200_TVOUT_HORZ_TIM, 0x007c035f);
338	 /* HSYNC generated in the TV Encoder module */
339	 /* Interval between resets of TV Encoder is once every odd field */
340	 /* Enable Horizontal interpolation */
341	 /* Disable Horizontal up scaling 9/8 */
342	 /* Disable Horizontal downscale */
343	 WRITE_VID32(SC1200_TVOUT_HORZ_SCALING, 0x10020500 | mode);
344	 /* Disable Horizontal scaling (set to 64/64) */
345	 if (gfx_chip_revision >= SC1200_REV_C1)
346	    WRITE_VID32(SC1200_TVOUT_HORZ_PRE_ENCODER_SCALE, 0x40000000);
347	 /* Horizontal display end is 924, i.e. 720 active pixels */
348	 /* Total number of display lines per field is 288 */
349	 WRITE_VID32(SC1200_TVOUT_LINE_END, 0x039c0120);
350	 break;
351      case GFX_ON_TV_SQUARE_PIXELS:
352	 /* Horizontal Display start is 122 */
353	 /* Total number of pixels per line is 863 */
354	 WRITE_VID32(SC1200_TVOUT_HORZ_TIM, 0x007a035f);
355	 if (gfx_chip_revision <= SC1200_REV_B3) {
356	    /* HSYNC generated in the TV Encoder module */
357	    /* Interval between resets of TV Encoder is once every odd field */
358	    /* Enable Horizontal interpolation */
359	    /* Disable Horizontal up scaling 9/8 */
360	    /* Horizontal downscale m/(m+1), m = 11, (i.e. 11/12 - closest possible to 54/59) */
361	    WRITE_VID32(SC1200_TVOUT_HORZ_SCALING, 0x1002040b | mode);
362	    /* Horizontal display end is 906, i.e. 704 active pixels */
363	    /* Total number of display lines per field is 288 */
364	    WRITE_VID32(SC1200_TVOUT_LINE_END, 0x038a0120);
365	 } else {
366	    /* HSYNC generated in the TV Encoder module */
367	    /* Interval between resets of TV Encoder is once every odd field */
368	    /* Enable Horizontal interpolation */
369	    /* Disable Horizontal up scaling 9/8 */
370	    /* Disable Horizontal downscale */
371	    WRITE_VID32(SC1200_TVOUT_HORZ_SCALING, 0x10020500 | mode);
372	    /* Set Horizontal down scaling to 64/70 (closest possible to 54/59) */
373	    WRITE_VID32(SC1200_TVOUT_HORZ_PRE_ENCODER_SCALE, 0x46000000);
374	    /* Horizontal display end is 904, i.e. 702 active pixels */
375	    /* Total number of display lines per field is 288 */
376	    WRITE_VID32(SC1200_TVOUT_LINE_END, 0x03880120);
377	 }
378	 break;
379      default:
380	 return (GFX_STATUS_BAD_PARAMETER);
381      }
382      break;
383   default:
384      return (GFX_STATUS_BAD_PARAMETER);
385   }
386   return (GFX_STATUS_OK);
387}
388
389/*-----------------------------------------------------------------------------
390 * gfx_set_tv_output
391 *
392 * This routine sets the TV encoder registers to the specified output type.
393 * Supported output types are : S-VIDEO, Composite, YUV and SCART.
394 *-----------------------------------------------------------------------------
395 */
396#if GFX_TV_DYNAMIC
397int
398sc1200_set_tv_output(int output)
399#else
400int
401gfx_set_tv_output(int output)
402#endif
403{
404   unsigned long ctrl2, ctrl3;
405
406   ctrl2 = READ_VID32(SC1200_TVENC_TIM_CTRL_2);
407   ctrl3 = READ_VID32(SC1200_TVENC_TIM_CTRL_3);
408   ctrl2 &= ~(SC1200_TVENC_OUTPUT_YCBCR | SC1200_TVENC_CFS_MASK);
409   ctrl3 &= ~(SC1200_TVENC_CM | SC1200_TVENC_SYNCMODE_MASK | SC1200_TVENC_CS);
410   switch (output) {
411   case TV_OUTPUT_COMPOSITE:
412      /* Analog outputs provide Y, C and CVBS */
413      /* Chrominance Lowpass filter is 1.3MHz (for composite video output) */
414      WRITE_VID32(SC1200_TVENC_TIM_CTRL_2, ctrl2 | SC1200_TVENC_CFS_CVBS);
415      WRITE_VID32(SC1200_TVENC_TIM_CTRL_3, ctrl3);
416      break;
417   case TV_OUTPUT_S_VIDEO:
418      /* Analog outputs provide Y, C and CVBS */
419      /* Chrominance Lowpass filter is 1.8MHz (for S-video output) */
420      WRITE_VID32(SC1200_TVENC_TIM_CTRL_2, ctrl2 | SC1200_TVENC_CFS_SVIDEO);
421      WRITE_VID32(SC1200_TVENC_TIM_CTRL_3, ctrl3);
422      break;
423   case TV_OUTPUT_YUV:
424      /* Analog outputs provide Y, Cb and Cr */
425      /* A 7.5 IRE setup is applied to the output */
426      WRITE_VID32(SC1200_TVENC_TIM_CTRL_2,
427		  ctrl2 | SC1200_TVENC_OUTPUT_YCBCR |
428		  SC1200_TVENC_CFS_BYPASS);
429      WRITE_VID32(SC1200_TVENC_TIM_CTRL_3,
430		  ctrl3 | SC1200_TVENC_CM | SC1200_TVENC_CS);
431      break;
432   case TV_OUTPUT_SCART:
433      /* Analog outputs provide SCART (RGB and CVBS) */
434      /* Sync is added to green signal */
435      WRITE_VID32(SC1200_TVENC_TIM_CTRL_2, ctrl2 | SC1200_TVENC_CFS_CVBS);
436      WRITE_VID32(SC1200_TVENC_TIM_CTRL_3,
437		  ctrl3 | SC1200_TVENC_CM | SC1200_TVENC_SYNC_ON_GREEN);
438      break;
439   default:
440      return (GFX_STATUS_BAD_PARAMETER);
441   }
442
443   /* Adjusts the internal voltage reference */
444   ctrl2 = READ_VID32(SC1200_TVENC_DAC_CONTROL);
445   ctrl2 &= ~SC1200_TVENC_TRIM_MASK;
446
447   /* Bypass for issue #926 : Inadequate chroma level of S-Video output */
448   if ((gfx_chip_revision == SC1200_REV_B3) && (output == TV_OUTPUT_S_VIDEO))
449      ctrl2 |= 0x7;
450   else
451      ctrl2 |= 0x5;
452
453   WRITE_VID32(SC1200_TVENC_DAC_CONTROL, ctrl2);
454
455   /* Disable 4:2:2 to 4:4:4 converter interpolation */
456   WRITE_VID32(SC1200_TVOUT_DEBUG, SC1200_TVOUT_CONVERTER_INTERPOLATION);
457
458   return (GFX_STATUS_OK);
459}
460
461/*-----------------------------------------------------------------------------
462 * gfx_set_tv_enable
463 *
464 * This routine enables or disables the TV output.
465 *-----------------------------------------------------------------------------
466 */
467#if GFX_TV_DYNAMIC
468int
469sc1200_set_tv_enable(int enable)
470#else
471int
472gfx_set_tv_enable(int enable)
473#endif
474{
475   unsigned long value_tim, value_dac;
476
477   value_tim = READ_VID32(SC1200_TVENC_TIM_CTRL_1);
478   value_dac = READ_VID32(SC1200_TVENC_DAC_CONTROL);
479
480   if (enable) {
481      value_tim |= SC1200_TVENC_VIDEO_TIMING_ENABLE;
482      value_dac &= ~SC1200_TVENC_POWER_DOWN;
483      /* ENABLE GRAPHICS DISPLAY LOGIC IN VIDEO PROCESSOR */
484      gfx_set_screen_enable(1);
485   } else {
486      value_tim &= ~SC1200_TVENC_VIDEO_TIMING_ENABLE;
487      value_dac |= SC1200_TVENC_POWER_DOWN;
488      /* Do not disable the graphics display logic because it might be needed for CRT */
489   }
490
491   WRITE_VID32(SC1200_TVENC_TIM_CTRL_1, value_tim);
492   WRITE_VID32(SC1200_TVENC_DAC_CONTROL, value_dac);
493
494   return (GFX_STATUS_OK);
495}
496
497/*-----------------------------------------------------------------------------
498 * gfx_set_tv_flicker_filter
499 *
500 * This routine configures the TV out flicker filter.
501 *-----------------------------------------------------------------------------
502 */
503#if GFX_TV_DYNAMIC
504int
505sc1200_set_tv_flicker_filter(int ff)
506#else
507int
508gfx_set_tv_flicker_filter(int ff)
509#endif
510{
511   unsigned long mode;
512
513   mode = READ_VID32(SC1200_TVOUT_HORZ_SCALING);
514   mode &= ~SC1200_TVOUT_FLICKER_FILTER_MASK;
515   switch (ff) {
516   case TV_FLICKER_FILTER_NONE:
517      WRITE_VID32(SC1200_TVOUT_HORZ_SCALING,
518		  mode | SC1200_TVOUT_FLICKER_FILTER_DISABLED);
519      break;
520   case TV_FLICKER_FILTER_NORMAL:
521      WRITE_VID32(SC1200_TVOUT_HORZ_SCALING,
522		  mode | SC1200_TVOUT_FLICKER_FILTER_FOURTH_HALF_FOURTH);
523      break;
524   case TV_FLICKER_FILTER_INTERLACED:
525      WRITE_VID32(SC1200_TVOUT_HORZ_SCALING,
526		  mode | SC1200_TVOUT_FLICKER_FILTER_HALF_ONE_HALF);
527      break;
528   default:
529      return GFX_STATUS_BAD_PARAMETER;
530   }
531   return (GFX_STATUS_OK);
532}
533
534/*-----------------------------------------------------------------------------
535 * gfx_set_tv_sub_carrier_reset
536 *
537 * This routine configures the TV encoder sub carrier reset interval.
538 *-----------------------------------------------------------------------------
539 */
540#if GFX_TV_DYNAMIC
541int
542sc1200_set_tv_sub_carrier_reset(int screset)
543#else
544int
545gfx_set_tv_sub_carrier_reset(int screset)
546#endif
547{
548   unsigned long mode;
549
550   mode = READ_VID32(SC1200_TVENC_TIM_CTRL_1);
551   mode &= ~SC1200_TVENC_SUB_CARRIER_RESET_MASK;
552   switch (screset) {
553   case TV_SUB_CARRIER_RESET_NEVER:
554      WRITE_VID32(SC1200_TVENC_TIM_CTRL_1,
555		  mode | SC1200_TVENC_SUB_CARRIER_RESET_NEVER);
556      break;
557   case TV_SUB_CARRIER_RESET_EVERY_TWO_LINES:
558      WRITE_VID32(SC1200_TVENC_TIM_CTRL_1,
559		  mode | SC1200_TVENC_SUB_CARRIER_RESET_EVERY_TWO_LINES);
560      break;
561   case TV_SUB_CARRIER_RESET_EVERY_TWO_FRAMES:
562      WRITE_VID32(SC1200_TVENC_TIM_CTRL_1,
563		  mode | SC1200_TVENC_SUB_CARRIER_RESET_EVERY_TWO_FRAMES);
564      break;
565   case TV_SUB_CARRIER_RESET_EVERY_FOUR_FRAMES:
566      WRITE_VID32(SC1200_TVENC_TIM_CTRL_1,
567		  mode | SC1200_TVENC_SUB_CARRIER_RESET_EVERY_FOUR_FRAMES);
568      break;
569   default:
570      return GFX_STATUS_BAD_PARAMETER;
571   }
572   return (GFX_STATUS_OK);
573}
574
575/*-----------------------------------------------------------------------------
576 * gfx_set_tv_vphase
577 *
578 * This routine sets the tv encoder VPHASE value.
579 *-----------------------------------------------------------------------------
580 */
581#if GFX_TV_DYNAMIC
582int
583sc1200_set_tv_vphase(int vphase)
584#else
585int
586gfx_set_tv_vphase(int vphase)
587#endif
588{
589   unsigned long mode = READ_VID32(SC1200_TVENC_TIM_CTRL_1);
590
591   mode &= ~SC1200_TVENC_VPHASE_MASK;
592   mode |= (vphase << SC1200_TVENC_VPHASE_POS) & SC1200_TVENC_VPHASE_MASK;
593   WRITE_VID32(SC1200_TVENC_TIM_CTRL_1, mode);
594   return (GFX_STATUS_OK);
595}
596
597/*-----------------------------------------------------------------------------
598 * gfx_set_tv_YC_delay
599 *
600 * This routine configures the TV out Y/C delay.
601 *-----------------------------------------------------------------------------
602 */
603#if GFX_TV_DYNAMIC
604int
605sc1200_set_tv_YC_delay(int delay)
606#else
607int
608gfx_set_tv_YC_delay(int delay)
609#endif
610{
611   unsigned long mode;
612
613   /* This feature is implemented in Rev C1 */
614   if (gfx_chip_revision < SC1200_REV_C1)
615      return (GFX_STATUS_OK);
616
617   mode = READ_VID32(SC1200_TVOUT_HORZ_PRE_ENCODER_SCALE);
618   mode &= ~SC1200_TVOUT_YC_DELAY_MASK;
619   switch (delay) {
620   case TV_YC_DELAY_NONE:
621      WRITE_VID32(SC1200_TVOUT_HORZ_PRE_ENCODER_SCALE,
622		  mode | SC1200_TVOUT_YC_DELAY_NONE);
623      break;
624   case TV_Y_DELAY_ONE_PIXEL:
625      WRITE_VID32(SC1200_TVOUT_HORZ_PRE_ENCODER_SCALE,
626		  mode | SC1200_TVOUT_Y_DELAY_ONE_PIXEL);
627      break;
628   case TV_C_DELAY_ONE_PIXEL:
629      WRITE_VID32(SC1200_TVOUT_HORZ_PRE_ENCODER_SCALE,
630		  mode | SC1200_TVOUT_C_DELAY_ONE_PIXEL);
631      break;
632   case TV_C_DELAY_TWO_PIXELS:
633      WRITE_VID32(SC1200_TVOUT_HORZ_PRE_ENCODER_SCALE,
634		  mode | SC1200_TVOUT_C_DELAY_TWO_PIXELS);
635      break;
636   default:
637      return GFX_STATUS_BAD_PARAMETER;
638   }
639   return (GFX_STATUS_OK);
640}
641
642/*-----------------------------------------------------------------------------
643 * gfx_set_tvenc_reset_interval
644 *
645 * This routine sets the interval between external resets of the TV encoder
646 * timing generator by the TV out.
647 *-----------------------------------------------------------------------------
648 */
649#if GFX_TV_DYNAMIC
650int
651sc1200_set_tvenc_reset_interval(int interval)
652#else
653int
654gfx_set_tvenc_reset_interval(int interval)
655#endif
656{
657   unsigned long value;
658
659   value = READ_VID32(SC1200_TVOUT_HORZ_SCALING);
660   value &= ~SC1200_TVENC_EXTERNAL_RESET_INTERVAL_MASK;
661   switch (interval) {
662   case TVENC_RESET_EVERY_ODD_FIELD:
663      WRITE_VID32(SC1200_TVOUT_HORZ_SCALING,
664		  value | SC1200_TVENC_EXTERNAL_RESET_EVERY_ODD_FIELD);
665      break;
666   case TVENC_RESET_EVERY_EVEN_FIELD:
667      WRITE_VID32(SC1200_TVOUT_HORZ_SCALING,
668		  value | SC1200_TVENC_EXTERNAL_RESET_EVERY_EVEN_FIELD);
669      break;
670   case TVENC_RESET_NEXT_ODD_FIELD:
671      WRITE_VID32(SC1200_TVOUT_HORZ_SCALING,
672		  value | SC1200_TVENC_EXTERNAL_RESET_NEXT_ODD_FIELD);
673      break;
674   case TVENC_RESET_NEXT_EVEN_FIELD:
675      WRITE_VID32(SC1200_TVOUT_HORZ_SCALING,
676		  value | SC1200_TVENC_EXTERNAL_RESET_NEXT_EVEN_FIELD);
677      break;
678   case TVENC_RESET_EVERY_FIELD:
679      WRITE_VID32(SC1200_TVOUT_HORZ_SCALING,
680		  value | SC1200_TVENC_EXTERNAL_RESET_EVERY_FIELD);
681      break;
682   case TVENC_RESET_EVERY_X_ODD_FIELDS:
683   case TVENC_RESET_EVERY_X_EVEN_FIELDS:
684      return GFX_STATUS_UNSUPPORTED;
685   default:
686      return GFX_STATUS_BAD_PARAMETER;
687   }
688   return (GFX_STATUS_OK);
689}
690
691/*-----------------------------------------------------------------------------
692 * gfx_set_tv_cc_enable
693 *
694 * This routine enables or disables the use of the hardware CC registers
695 * in the TV encoder.
696 *-----------------------------------------------------------------------------
697 */
698#if GFX_TV_DYNAMIC
699int
700sc1200_set_tv_cc_enable(int enable)
701#else
702int
703gfx_set_tv_cc_enable(int enable)
704#endif
705{
706   unsigned long value;
707
708   value = READ_VID32(SC1200_TVENC_CC_CONTROL);
709   value &= ~(0x0005F);
710   if (enable)
711      value |= 0x51;
712   WRITE_VID32(SC1200_TVENC_CC_CONTROL, value);
713   return (0);
714}
715
716/*---------------------------------------------------------------------------
717 * gfx_set_tv_display
718 *
719 * This routine sets the timings in the display controller to support a
720 * TV resolution.
721 *---------------------------------------------------------------------------
722 */
723#if GFX_TV_DYNAMIC
724int
725sc1200_set_tv_display(int width, int height)
726#else
727int
728gfx_set_tv_display(int width, int height)
729#endif
730{
731   DISPLAYMODE *pMode;
732   unsigned int i;
733
734   for (i = 0; i < NUM_TV_MODES; i++) {
735      pMode = &TVTimings[i];
736      if ((unsigned)width == pMode->hactive
737	  && (unsigned)height == pMode->vactive)
738	 break;
739   }
740
741   if (i == NUM_TV_MODES)
742      return 0;
743
744   gfx_set_display_timings(gfx_get_display_bpp(),
745			   (unsigned short)pMode->flags, pMode->hactive,
746			   pMode->hblankstart, pMode->hsyncstart,
747			   pMode->hsyncend, pMode->hblankend, pMode->htotal,
748			   pMode->vactive, pMode->vblankstart,
749			   pMode->vsyncstart, pMode->vsyncend,
750			   pMode->vblankend, pMode->vtotal, pMode->frequency);
751
752   return 1;
753}
754
755/*-----------------------------------------------------------------------------
756 * cc_add_parity_bit
757 *
758 * This routine adds the (odd) parity bit to the data character.
759 *-----------------------------------------------------------------------------
760 */
761unsigned char
762cc_add_parity_bit(unsigned char data)
763{
764   int i, num = 0;
765   unsigned char d = data;
766
767   for (i = 0; i < 7; i++) {
768      if (d & 0x1)
769	 num++;
770      d >>= 1;
771   }
772   if (num & 0x1)
773      return (data & ~0x80);
774   else
775      return (data | 0x80);
776}
777
778/*-----------------------------------------------------------------------------
779 * gfx_set_tv_cc_data
780 *
781 * This routine writes the two specified characters to the CC data register
782 * of the TV encoder.
783 *-----------------------------------------------------------------------------
784 */
785#if GFX_TV_DYNAMIC
786int
787sc1200_set_tv_cc_data(unsigned char data1, unsigned char data2)
788#else
789int
790gfx_set_tv_cc_data(unsigned char data1, unsigned char data2)
791#endif
792{
793   unsigned long value;
794
795   value = cc_add_parity_bit(data1) | (cc_add_parity_bit(data2) << 8);
796   WRITE_VID32(SC1200_TVENC_CC_DATA, value);
797   return (0);
798}
799
800/*---------------------------------------------------------------------------
801 * gfx_test_tvout_odd_field
802 *
803 * This routine returns 1 if the current TVout field is odd. Otherwise returns 0.
804 *---------------------------------------------------------------------------
805 */
806#if GFX_TV_DYNAMIC
807int
808sc1200_test_tvout_odd_field(void)
809#else
810int
811gfx_test_tvout_odd_field(void)
812#endif
813{
814   unsigned long debug = READ_VID32(SC1200_TVOUT_DEBUG);
815
816   WRITE_VID32(SC1200_TVOUT_DEBUG, debug | SC1200_TVOUT_FIELD_STATUS_TV);
817   if (READ_VID32(SC1200_TVOUT_DEBUG) & SC1200_TVOUT_FIELD_STATUS_EVEN)
818      return (0);
819   else
820      return (1);
821}
822
823/*---------------------------------------------------------------------------
824 * gfx_test_tvenc_odd_field
825 *
826 * This routine returns 1 if the current TV encoder field is odd. Otherwise returns 0.
827 *---------------------------------------------------------------------------
828 */
829#if GFX_TV_DYNAMIC
830int
831sc1200_test_tvenc_odd_field(void)
832#else
833int
834gfx_test_tvenc_odd_field(void)
835#endif
836{
837   unsigned long debug = READ_VID32(SC1200_TVOUT_DEBUG);
838
839   WRITE_VID32(SC1200_TVOUT_DEBUG, debug & ~SC1200_TVOUT_FIELD_STATUS_TV);
840   if (READ_VID32(SC1200_TVOUT_DEBUG) & SC1200_TVOUT_FIELD_STATUS_EVEN)
841      return (0);
842   else
843      return (1);
844}
845
846/*-----------------------------------------------------------------------------
847 * gfx_set_tv_field_status_invert
848 *
849 * This routines determines whether the tvout/tvencoder field status bit is
850 * inverted (enable = 1) or not (enable = 0).
851 *-----------------------------------------------------------------------------
852 */
853#if GFX_TV_DYNAMIC
854int
855sc1200_set_tv_field_status_invert(int enable)
856#else
857int
858gfx_set_tv_field_status_invert(int enable)
859#endif
860{
861   unsigned long value;
862
863   value = READ_VID32(SC1200_TVOUT_DEBUG);
864
865   if (enable) {
866      value |= SC1200_TVOUT_FIELD_STATUS_INVERT;
867   } else {
868      value &= ~(SC1200_TVOUT_FIELD_STATUS_INVERT);
869   }
870
871   WRITE_VID32(SC1200_TVOUT_DEBUG, value);
872
873   return (GFX_STATUS_OK);
874}
875
876/*---------------------------------------------------------------------------
877 * gfx_get_tv_vphase
878 *
879 * This routine returns the tv encoder vertical phase.
880 *---------------------------------------------------------------------------
881 */
882#if GFX_TV_DYNAMIC
883int
884sc1200_get_tv_vphase(void)
885#else
886int
887gfx_get_tv_vphase(void)
888#endif
889{
890   unsigned long mode = READ_VID32(SC1200_TVENC_TIM_CTRL_1);
891
892   return (int)((mode & SC1200_TVENC_VPHASE_MASK) >> SC1200_TVENC_VPHASE_POS);
893}
894
895/*---------------------------------------------------------------------------
896 * gfx_get_tv_enable
897 *
898 * This routine returns the current tv enable status
899 *---------------------------------------------------------------------------
900 */
901#if GFX_TV_DYNAMIC
902int
903sc1200_get_tv_enable(unsigned int *p_on)
904#else
905int
906gfx_get_tv_enable(unsigned int *p_on)
907#endif
908{
909   unsigned long control = READ_VID32(SC1200_TVENC_DAC_CONTROL);
910
911   *p_on = (unsigned int)(!(control & SC1200_TVENC_POWER_DOWN));
912
913   return GFX_STATUS_OK;
914}
915
916/*---------------------------------------------------------------------------
917 * gfx_get_tv_output
918 *
919 * This routine returns the current programmed TV output type.  It does not
920 * detect invalid configurations.
921 *---------------------------------------------------------------------------
922 */
923#if GFX_TV_DYNAMIC
924int
925sc1200_get_tv_output(void)
926#else
927int
928gfx_get_tv_output(void)
929#endif
930{
931   unsigned long ctrl2, ctrl3;
932   int format = 0;
933
934   ctrl2 = READ_VID32(SC1200_TVENC_TIM_CTRL_2);
935   ctrl3 = READ_VID32(SC1200_TVENC_TIM_CTRL_3);
936
937   if ((ctrl2 & SC1200_TVENC_CFS_MASK) == SC1200_TVENC_CFS_SVIDEO)
938      format = TV_OUTPUT_S_VIDEO;
939   else if (ctrl2 & SC1200_TVENC_OUTPUT_YCBCR)
940      format = TV_OUTPUT_YUV;
941   else if ((ctrl2 & SC1200_TVENC_CFS_MASK) == SC1200_TVENC_CFS_CVBS) {
942      if (ctrl3 & SC1200_TVENC_CM)
943	 format = TV_OUTPUT_SCART;
944      else
945	 format = TV_OUTPUT_COMPOSITE;
946   }
947
948   return format;
949}
950
951/*---------------------------------------------------------------------------
952 * gfx_get_tv_mode_count
953 *
954 * This routine returns the number of valid TV out resolutions.
955 *---------------------------------------------------------------------------
956 */
957#if GFX_TV_DYNAMIC
958int
959sc1200_get_tv_mode_count(TVStandardType format)
960#else
961int
962gfx_get_tv_mode_count(TVStandardType format)
963#endif
964{
965   unsigned int mode, count = 0;
966   unsigned long flag;
967
968   switch (format) {
969   case TV_STANDARD_NTSC:
970      flag = GFX_MODE_TV_NTSC;
971      break;
972   case TV_STANDARD_PAL:
973      flag = GFX_MODE_TV_PAL;
974      break;
975   default:
976      return 0;
977   }
978
979   for (mode = 0; mode < NUM_TV_MODES; mode++) {
980      if (TVTimings[mode].flags & flag)
981	 count++;
982   }
983
984   return count;
985}
986
987/*---------------------------------------------------------------------------
988 * gfx_get_tv_display_mode
989 *
990 * This routine returns the current TV display parameters.
991 *---------------------------------------------------------------------------
992 */
993#if GFX_TV_DYNAMIC
994int
995sc1200_get_tv_display_mode(int *width, int *height, int *bpp, int *hz)
996#else
997int
998gfx_get_tv_display_mode(int *width, int *height, int *bpp, int *hz)
999#endif
1000{
1001   unsigned long frequency;
1002   unsigned long mode, flags;
1003
1004   *width = gfx_get_hactive();
1005   *height = gfx_get_vactive();
1006   *bpp = gfx_get_display_bpp();
1007   frequency = gfx_get_clock_frequency();
1008
1009   for (mode = 0; mode < NUM_TV_MODES; mode++) {
1010      if (TVTimings[mode].hactive == (unsigned short)(*width) &&
1011	  TVTimings[mode].vactive == (unsigned short)(*height) &&
1012	  TVTimings[mode].frequency == frequency) {
1013	 flags = TVTimings[mode].flags;
1014
1015	 if (flags & GFX_MODE_TV_NTSC)
1016	    *hz = 60;
1017	 else if (flags & GFX_MODE_TV_PAL)
1018	    *hz = 50;
1019	 else
1020	    *hz = 0;
1021	 return (1);
1022      }
1023   }
1024
1025   return -1;
1026}
1027
1028/*---------------------------------------------------------------------------
1029 * gfx_get_tv_display_mode_frequency
1030 *
1031 * This routine returns the PLL frequency of a given TV mode.
1032 *---------------------------------------------------------------------------
1033 */
1034#if GFX_TV_DYNAMIC
1035int
1036sc1200_get_tv_display_mode_frequency(unsigned short width,
1037				     unsigned short height,
1038				     TVStandardType format, int *frequency)
1039#else
1040int
1041gfx_get_tv_display_mode_frequency(unsigned short width, unsigned short height,
1042				  TVStandardType format, int *frequency)
1043#endif
1044{
1045   unsigned long mode, flag;
1046   int retval = -1;
1047
1048   *frequency = 0;
1049
1050   switch (format) {
1051   case TV_STANDARD_NTSC:
1052      flag = GFX_MODE_TV_NTSC;
1053      break;
1054   case TV_STANDARD_PAL:
1055      flag = GFX_MODE_TV_PAL;
1056      break;
1057   default:
1058      return -1;
1059   }
1060
1061   for (mode = 0; mode < NUM_TV_MODES; mode++) {
1062      if ((TVTimings[mode].hactive == width) &&
1063	  (TVTimings[mode].vactive == height) &&
1064	  (TVTimings[mode].flags & flag)) {
1065	 *frequency = TVTimings[mode].frequency;
1066	 retval = 1;
1067      }
1068   }
1069   return retval;
1070}
1071
1072/*---------------------------------------------------------------------------
1073 * gfx_is_tv_display_mode_supported
1074 *
1075 * Returns >= 0 if the mode is available, -1 if the mode could not be found
1076 *---------------------------------------------------------------------------
1077 */
1078#if GFX_TV_DYNAMIC
1079int
1080sc1200_is_tv_display_mode_supported(unsigned short width,
1081				    unsigned short height,
1082				    TVStandardType format)
1083#else
1084int
1085gfx_is_tv_display_mode_supported(unsigned short width, unsigned short height,
1086				 TVStandardType format)
1087#endif
1088{
1089   unsigned long mode, flag;
1090
1091   switch (format) {
1092   case TV_STANDARD_NTSC:
1093      flag = GFX_MODE_TV_NTSC;
1094      break;
1095   case TV_STANDARD_PAL:
1096      flag = GFX_MODE_TV_PAL;
1097      break;
1098   default:
1099      return -1;
1100   }
1101
1102   for (mode = 0; mode < NUM_TV_MODES; mode++) {
1103      if (TVTimings[mode].hactive == width &&
1104	  TVTimings[mode].vactive == height &&
1105	  (TVTimings[mode].flags & flag)) {
1106	 return ((int)mode);
1107      }
1108   }
1109
1110   return -1;
1111}
1112
1113/* END OF FILE */
1114