tv_1200.c revision f29dbc25
1f29dbc25Smrg/* Copyright (c) 2005 Advanced Micro Devices, Inc.
2f29dbc25Smrg *
3f29dbc25Smrg * Permission is hereby granted, free of charge, to any person obtaining a copy
4f29dbc25Smrg * of this software and associated documentation files (the "Software"), to
5f29dbc25Smrg * deal in the Software without restriction, including without limitation the
6f29dbc25Smrg * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7f29dbc25Smrg * sell copies of the Software, and to permit persons to whom the Software is
8f29dbc25Smrg * furnished to do so, subject to the following conditions:
9f29dbc25Smrg *
10f29dbc25Smrg * The above copyright notice and this permission notice shall be included in
11f29dbc25Smrg * all copies or substantial portions of the Software.
12f29dbc25Smrg *
13f29dbc25Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14f29dbc25Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15f29dbc25Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16f29dbc25Smrg * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17f29dbc25Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18f29dbc25Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19f29dbc25Smrg * IN THE SOFTWARE.
20f29dbc25Smrg *
21f29dbc25Smrg * Neither the name of the Advanced Micro Devices, Inc. nor the names of its
22f29dbc25Smrg * contributors may be used to endorse or promote products derived from this
23f29dbc25Smrg * software without specific prior written permission.
24f29dbc25Smrg * */
25f29dbc25Smrg
26f29dbc25Smrg/*
27f29dbc25Smrg * This file contains routines to control the SC1200 TVOUT and TV encoder.
28f29dbc25Smrg * */
29f29dbc25Smrg
30f29dbc25Smrg/*----------------------------------------------------------------------------
31f29dbc25Smrg * gfx_set_tv_format
32f29dbc25Smrg *
33f29dbc25Smrg * This routine sets the TV encoder registers to the specified format
34f29dbc25Smrg * and resolution.
35f29dbc25Smrg *----------------------------------------------------------------------------
36f29dbc25Smrg */
37f29dbc25Smrg#if GFX_TV_DYNAMIC
38f29dbc25Smrgint
39f29dbc25Smrgsc1200_set_tv_format(TVStandardType format, GfxOnTVType resolution)
40f29dbc25Smrg#else
41f29dbc25Smrgint
42f29dbc25Smrggfx_set_tv_format(TVStandardType format, GfxOnTVType resolution)
43f29dbc25Smrg#endif
44f29dbc25Smrg{
45f29dbc25Smrg    unsigned long ctrl2, mode;
46f29dbc25Smrg
47f29dbc25Smrg    /* Save TV output mode */
48f29dbc25Smrg    ctrl2 =
49f29dbc25Smrg        READ_VID32(SC1200_TVENC_TIM_CTRL_2) & (SC1200_TVENC_OUTPUT_YCBCR |
50f29dbc25Smrg        SC1200_TVENC_CFS_MASK);
51f29dbc25Smrg    /* Save flicker filter setting */
52f29dbc25Smrg    mode =
53f29dbc25Smrg        READ_VID32(SC1200_TVOUT_HORZ_SCALING) &
54f29dbc25Smrg        SC1200_TVOUT_FLICKER_FILTER_MASK;
55f29dbc25Smrg
56f29dbc25Smrg    switch (format) {
57f29dbc25Smrg    case TV_STANDARD_NTSC:
58f29dbc25Smrg        /* Horizontal Sync Start is 848 */
59f29dbc25Smrg        /* Horizontal Sync End is 856 */
60f29dbc25Smrg        WRITE_VID32(SC1200_TVOUT_HORZ_SYNC, 0x03580350);
61f29dbc25Smrg        /* Vertical Sync Start is 0 */
62f29dbc25Smrg        /* Vertical Sync End is 1 */
63f29dbc25Smrg        /* Vertical Display Start Skew is 1 */
64f29dbc25Smrg        /* Vertical Display End Skew is 1 */
65f29dbc25Smrg        WRITE_VID32(SC1200_TVOUT_VERT_SYNC, 0x05001000);
66f29dbc25Smrg        /* Disable vertical down scaling, take all lines */
67f29dbc25Smrg        if (gfx_chip_revision <= SC1200_REV_B3)
68f29dbc25Smrg            WRITE_VID32(SC1200_TVOUT_VERT_DOWNSCALE, 0xffffffff);
69f29dbc25Smrg        /* Enable video timing */
70f29dbc25Smrg        /* Reset sub carrier every two frames */
71f29dbc25Smrg        /* Disable BLANK */
72f29dbc25Smrg        /* Enable color burst */
73f29dbc25Smrg        /* Add the IRE offset */
74f29dbc25Smrg        /* NTSC color encoding */
75f29dbc25Smrg        /* Video generator timing is 525 lines / 60Hz */
76f29dbc25Smrg        /* Horizontal and Vertical counters are initialized to HPHASE &
77f29dbc25Smrg         * VPHASE */
78f29dbc25Smrg        /* VPHASE is 2, HPHASE is 0x50 */
79f29dbc25Smrg        WRITE_VID32(SC1200_TVENC_TIM_CTRL_1, 0xa2a01050);
80f29dbc25Smrg        /* Increase horizontal blanking interval */
81f29dbc25Smrg        /* Low Water Mark for Y is 0x1F */
82f29dbc25Smrg        /* Low Water Mark for Cb is 0xF */
83f29dbc25Smrg        /* HUE is 0 */
84f29dbc25Smrg        /* SCPHASE is 0xF9 */
85f29dbc25Smrg        WRITE_VID32(SC1200_TVENC_TIM_CTRL_2, 0x9ff000f9 | ctrl2);
86f29dbc25Smrg        /* Subcarrier Frequency is 3.579545 MHz */
87f29dbc25Smrg        WRITE_VID32(SC1200_TVENC_SUB_FREQ, 0x21f07c1f);
88f29dbc25Smrg        /* VSTART is 18, HSTART is 113 */
89f29dbc25Smrg        WRITE_VID32(SC1200_TVENC_DISP_POS, 0x00120071);
90f29dbc25Smrg        /* Display size: HEIGHT is 239, WIDTH is 719 */
91f29dbc25Smrg        WRITE_VID32(SC1200_TVENC_DISP_SIZE, 0x00ef02cf);
92f29dbc25Smrg        switch (resolution) {
93f29dbc25Smrg        case GFX_ON_TV_SQUARE_PIXELS:
94f29dbc25Smrg            if (gfx_chip_revision <= SC1200_REV_B3) {
95f29dbc25Smrg                /* Horizontal Display start is 116 */
96f29dbc25Smrg                /* Total number of pixels per line is 857 */
97f29dbc25Smrg                WRITE_VID32(SC1200_TVOUT_HORZ_TIM, 0x00740359);
98f29dbc25Smrg                /* HSYNC generated in the TV Encoder module */
99f29dbc25Smrg                /* Interval between resets of TV Encoder is once every odd
100f29dbc25Smrg                 * field */
101f29dbc25Smrg                /* Enable Horizontal interpolation */
102f29dbc25Smrg                /* Enable Horizontal up scaling 9/8 */
103f29dbc25Smrg                /* Disable Horizontal downscale */
104f29dbc25Smrg                WRITE_VID32(SC1200_TVOUT_HORZ_SCALING, 0x10020700 | mode);
105f29dbc25Smrg                /* Horizontal display end is 919, i.e. 720 active pixels */
106f29dbc25Smrg                /* Total number of display lines per field is 240 */
107f29dbc25Smrg                WRITE_VID32(SC1200_TVOUT_LINE_END, 0x039700f0);
108f29dbc25Smrg            } else {                   /* Use new scaler available in Rev. C */
109f29dbc25Smrg                /* Horizontal Display start is 111 */
110f29dbc25Smrg                /* Total number of pixels per line is 857 */
111f29dbc25Smrg                WRITE_VID32(SC1200_TVOUT_HORZ_TIM, 0x006f0359);
112f29dbc25Smrg                /* HSYNC generated in the TV Encoder module */
113f29dbc25Smrg                /* Interval between resets of TV Encoder is once every odd
114f29dbc25Smrg                 * field */
115f29dbc25Smrg                /* Enable Horizontal interpolation */
116f29dbc25Smrg                /* Disable Horizontal up scaling 9/8 */
117f29dbc25Smrg                /* Disable Horizontal downscale */
118f29dbc25Smrg                WRITE_VID32(SC1200_TVOUT_HORZ_SCALING, 0x10020500 | mode);
119f29dbc25Smrg                /* Set Horizontal upscaling to 64/58 (~ 11/10) */
120f29dbc25Smrg                WRITE_VID32(SC1200_TVOUT_HORZ_PRE_ENCODER_SCALE, 0x3A000000);
121f29dbc25Smrg                /* Horizontal display end is 900, i.e. 706 active pixels */
122f29dbc25Smrg                /* Total number of display lines per field is 240 */
123f29dbc25Smrg                WRITE_VID32(SC1200_TVOUT_LINE_END, 0x038400f0);
124f29dbc25Smrg            }
125f29dbc25Smrg            break;
126f29dbc25Smrg        case GFX_ON_TV_NO_SCALING:
127f29dbc25Smrg            /* Horizontal Display start is 116 */
128f29dbc25Smrg            /* Total number of pixels per line is 857 */
129f29dbc25Smrg            WRITE_VID32(SC1200_TVOUT_HORZ_TIM, 0x00740359);
130f29dbc25Smrg            /* HSYNC generated in the TV Encoder module */
131f29dbc25Smrg            /* Interval between resets of TV Encoder is once every odd field */
132f29dbc25Smrg            /* Enable Horizontal interpolation */
133f29dbc25Smrg            /* Disable Horizontal up scaling 9/8 */
134f29dbc25Smrg            /* Disable Horizontal downscale */
135f29dbc25Smrg            WRITE_VID32(SC1200_TVOUT_HORZ_SCALING, 0x10020500 | mode);
136f29dbc25Smrg            /* Disable Horizontal scaling (set to 64/64) */
137f29dbc25Smrg            if (gfx_chip_revision >= SC1200_REV_C1)
138f29dbc25Smrg                WRITE_VID32(SC1200_TVOUT_HORZ_PRE_ENCODER_SCALE, 0x40000000);
139f29dbc25Smrg            /* Horizontal display end is 919, i.e. 720 active pixels */
140f29dbc25Smrg            /* Total number of display lines per field is 240 */
141f29dbc25Smrg            WRITE_VID32(SC1200_TVOUT_LINE_END, 0x039700f0);
142f29dbc25Smrg            break;
143f29dbc25Smrg        default:
144f29dbc25Smrg            return (GFX_STATUS_BAD_PARAMETER);
145f29dbc25Smrg        }
146f29dbc25Smrg        break;
147f29dbc25Smrg    case TV_STANDARD_PAL:
148f29dbc25Smrg        /* Horizontal Sync Start is 854 */
149f29dbc25Smrg        /* Horizontal Sync End is 862 */
150f29dbc25Smrg        WRITE_VID32(SC1200_TVOUT_HORZ_SYNC, 0x035e0356);
151f29dbc25Smrg        /* Vertical Sync Start is 0 */
152f29dbc25Smrg        /* Vertical Sync End is 1 */
153f29dbc25Smrg        /* Vertical Display Start Skew is 1 */
154f29dbc25Smrg        /* Vertical Display End Skew is 1 */
155f29dbc25Smrg        WRITE_VID32(SC1200_TVOUT_VERT_SYNC, 0x05001000);
156f29dbc25Smrg        /* Disable vertical down scaling, take all lines */
157f29dbc25Smrg        if (gfx_chip_revision <= SC1200_REV_B3)
158f29dbc25Smrg            WRITE_VID32(SC1200_TVOUT_VERT_DOWNSCALE, 0xffffffff);
159f29dbc25Smrg        /* Enable video timing */
160f29dbc25Smrg        /* Never reset sub carrier (should be every 4 frames but doesn't work
161f29dbc25Smrg         * with genlock) */
162f29dbc25Smrg        /* Disable BLANK */
163f29dbc25Smrg        /* Enable color burst */
164f29dbc25Smrg        /* Do not add the IRE offset */
165f29dbc25Smrg        /* NTSC color encoding */
166f29dbc25Smrg        /* Video generator timing is 625 lines / 50Hz */
167f29dbc25Smrg        /* Horizontal and Vertical counters are initialized to HPHASE & VPHASE
168f29dbc25Smrg         * */
169f29dbc25Smrg        /* VPHASE is 2, HPHASE is 50 */
170f29dbc25Smrg        WRITE_VID32(SC1200_TVENC_TIM_CTRL_1, 0xB1201050);
171f29dbc25Smrg        /* Increase horizontal blanking interval */
172f29dbc25Smrg        /* Low Water Mark for Y is 0x1F */
173f29dbc25Smrg        /* Low Water Mark for Cb is 0xF */
174f29dbc25Smrg        /* HUE is 0 */
175f29dbc25Smrg        /* SCPHASE is 0xD9 */
176f29dbc25Smrg        WRITE_VID32(SC1200_TVENC_TIM_CTRL_2, 0x9ff000d9 | ctrl2);
177f29dbc25Smrg        /* Subcarrier Frequency is 4.43361875 MHz */
178f29dbc25Smrg        WRITE_VID32(SC1200_TVENC_SUB_FREQ, 0x2a098acb);
179f29dbc25Smrg        /* VSTART is 22, HSTART is 123 */
180f29dbc25Smrg        WRITE_VID32(SC1200_TVENC_DISP_POS, 0x0016007b);
181f29dbc25Smrg        /* Display size: HEIGHT is 287, WIDTH is 719 */
182f29dbc25Smrg        WRITE_VID32(SC1200_TVENC_DISP_SIZE, 0x011f02cf);
183f29dbc25Smrg        switch (resolution) {
184f29dbc25Smrg        case GFX_ON_TV_NO_SCALING:
185f29dbc25Smrg            /* Horizontal Display start is 124 */
186f29dbc25Smrg            /* Total number of pixels per line is 863 */
187f29dbc25Smrg            WRITE_VID32(SC1200_TVOUT_HORZ_TIM, 0x007c035f);
188f29dbc25Smrg            /* HSYNC generated in the TV Encoder module */
189f29dbc25Smrg            /* Interval between resets of TV Encoder is once every odd field */
190f29dbc25Smrg            /* Enable Horizontal interpolation */
191f29dbc25Smrg            /* Disable Horizontal up scaling 9/8 */
192f29dbc25Smrg            /* Disable Horizontal downscale */
193f29dbc25Smrg            WRITE_VID32(SC1200_TVOUT_HORZ_SCALING, 0x10020500 | mode);
194f29dbc25Smrg            /* Disable Horizontal scaling (set to 64/64) */
195f29dbc25Smrg            if (gfx_chip_revision >= SC1200_REV_C1)
196f29dbc25Smrg                WRITE_VID32(SC1200_TVOUT_HORZ_PRE_ENCODER_SCALE, 0x40000000);
197f29dbc25Smrg            /* Horizontal display end is 924, i.e. 720 active pixels */
198f29dbc25Smrg            /* Total number of display lines per field is 288 */
199f29dbc25Smrg            WRITE_VID32(SC1200_TVOUT_LINE_END, 0x039c0120);
200f29dbc25Smrg            break;
201f29dbc25Smrg        case GFX_ON_TV_SQUARE_PIXELS:
202f29dbc25Smrg            /* Horizontal Display start is 122 */
203f29dbc25Smrg            /* Total number of pixels per line is 863 */
204f29dbc25Smrg            WRITE_VID32(SC1200_TVOUT_HORZ_TIM, 0x007a035f);
205f29dbc25Smrg            if (gfx_chip_revision <= SC1200_REV_B3) {
206f29dbc25Smrg                /* HSYNC generated in the TV Encoder module */
207f29dbc25Smrg                /* Interval between resets of TV Encoder is once every odd
208f29dbc25Smrg                 * field */
209f29dbc25Smrg                /* Enable Horizontal interpolation */
210f29dbc25Smrg                /* Disable Horizontal up scaling 9/8 */
211f29dbc25Smrg                /* Horizontal downscale m/(m+1), m = 11, (i.e. 11/12 - closest
212f29dbc25Smrg                 * possible to 54/59) */
213f29dbc25Smrg                WRITE_VID32(SC1200_TVOUT_HORZ_SCALING, 0x1002040b | mode);
214f29dbc25Smrg                /* Horizontal display end is 906, i.e. 704 active pixels */
215f29dbc25Smrg                /* Total number of display lines per field is 288 */
216f29dbc25Smrg                WRITE_VID32(SC1200_TVOUT_LINE_END, 0x038a0120);
217f29dbc25Smrg            } else {
218f29dbc25Smrg                /* HSYNC generated in the TV Encoder module */
219f29dbc25Smrg                /* Interval between resets of TV Encoder is once every odd
220f29dbc25Smrg                 * field */
221f29dbc25Smrg                /* Enable Horizontal interpolation */
222f29dbc25Smrg                /* Disable Horizontal up scaling 9/8 */
223f29dbc25Smrg                /* Disable Horizontal downscale */
224f29dbc25Smrg                WRITE_VID32(SC1200_TVOUT_HORZ_SCALING, 0x10020500 | mode);
225f29dbc25Smrg                /* Set Horizontal down scaling to 64/70 (closest possible to
226f29dbc25Smrg                 * 54/59) */
227f29dbc25Smrg                WRITE_VID32(SC1200_TVOUT_HORZ_PRE_ENCODER_SCALE, 0x46000000);
228f29dbc25Smrg                /* Horizontal display end is 904, i.e. 702 active pixels */
229f29dbc25Smrg                /* Total number of display lines per field is 288 */
230f29dbc25Smrg                WRITE_VID32(SC1200_TVOUT_LINE_END, 0x03880120);
231f29dbc25Smrg            }
232f29dbc25Smrg            break;
233f29dbc25Smrg        default:
234f29dbc25Smrg            return (GFX_STATUS_BAD_PARAMETER);
235f29dbc25Smrg        }
236f29dbc25Smrg        break;
237f29dbc25Smrg    default:
238f29dbc25Smrg        return (GFX_STATUS_BAD_PARAMETER);
239f29dbc25Smrg    }
240f29dbc25Smrg    return (GFX_STATUS_OK);
241f29dbc25Smrg}
242f29dbc25Smrg
243f29dbc25Smrg/*----------------------------------------------------------------------------
244f29dbc25Smrg * gfx_set_tv_output
245f29dbc25Smrg *
246f29dbc25Smrg * This routine sets the TV encoder registers to the specified output type.
247f29dbc25Smrg * Supported output types are : S-VIDEO, Composite, YUV and SCART.
248f29dbc25Smrg *----------------------------------------------------------------------------
249f29dbc25Smrg */
250f29dbc25Smrg#if GFX_TV_DYNAMIC
251f29dbc25Smrgint
252f29dbc25Smrgsc1200_set_tv_output(int output)
253f29dbc25Smrg#else
254f29dbc25Smrgint
255f29dbc25Smrggfx_set_tv_output(int output)
256f29dbc25Smrg#endif
257f29dbc25Smrg{
258f29dbc25Smrg    unsigned long ctrl2, ctrl3;
259f29dbc25Smrg
260f29dbc25Smrg    ctrl2 = READ_VID32(SC1200_TVENC_TIM_CTRL_2);
261f29dbc25Smrg    ctrl3 = READ_VID32(SC1200_TVENC_TIM_CTRL_3);
262f29dbc25Smrg    ctrl2 &= ~(SC1200_TVENC_OUTPUT_YCBCR | SC1200_TVENC_CFS_MASK);
263f29dbc25Smrg    ctrl3 &=
264f29dbc25Smrg        ~(SC1200_TVENC_CM | SC1200_TVENC_SYNCMODE_MASK | SC1200_TVENC_CS);
265f29dbc25Smrg    switch (output) {
266f29dbc25Smrg    case TV_OUTPUT_COMPOSITE:
267f29dbc25Smrg        /* Analog outputs provide Y, C and CVBS */
268f29dbc25Smrg        /* Chrominance Lowpass filter is 1.3MHz (for composite video output) */
269f29dbc25Smrg        WRITE_VID32(SC1200_TVENC_TIM_CTRL_2, ctrl2 | SC1200_TVENC_CFS_CVBS);
270f29dbc25Smrg        WRITE_VID32(SC1200_TVENC_TIM_CTRL_3, ctrl3);
271f29dbc25Smrg        break;
272f29dbc25Smrg    case TV_OUTPUT_S_VIDEO:
273f29dbc25Smrg        /* Analog outputs provide Y, C and CVBS */
274f29dbc25Smrg        /* Chrominance Lowpass filter is 1.8MHz (for S-video output) */
275f29dbc25Smrg        WRITE_VID32(SC1200_TVENC_TIM_CTRL_2, ctrl2 | SC1200_TVENC_CFS_SVIDEO);
276f29dbc25Smrg        WRITE_VID32(SC1200_TVENC_TIM_CTRL_3, ctrl3);
277f29dbc25Smrg        break;
278f29dbc25Smrg    case TV_OUTPUT_YUV:
279f29dbc25Smrg        /* Analog outputs provide Y, Cb and Cr */
280f29dbc25Smrg        /* A 7.5 IRE setup is applied to the output */
281f29dbc25Smrg        WRITE_VID32(SC1200_TVENC_TIM_CTRL_2,
282f29dbc25Smrg            ctrl2 | SC1200_TVENC_OUTPUT_YCBCR | SC1200_TVENC_CFS_BYPASS);
283f29dbc25Smrg        WRITE_VID32(SC1200_TVENC_TIM_CTRL_3,
284f29dbc25Smrg            ctrl3 | SC1200_TVENC_CM | SC1200_TVENC_CS);
285f29dbc25Smrg        break;
286f29dbc25Smrg    case TV_OUTPUT_SCART:
287f29dbc25Smrg        /* Analog outputs provide SCART (RGB and CVBS) */
288f29dbc25Smrg        /* Sync is added to green signal */
289f29dbc25Smrg        WRITE_VID32(SC1200_TVENC_TIM_CTRL_2, ctrl2 | SC1200_TVENC_CFS_CVBS);
290f29dbc25Smrg        WRITE_VID32(SC1200_TVENC_TIM_CTRL_3,
291f29dbc25Smrg            ctrl3 | SC1200_TVENC_CM | SC1200_TVENC_SYNC_ON_GREEN);
292f29dbc25Smrg        break;
293f29dbc25Smrg    default:
294f29dbc25Smrg        return (GFX_STATUS_BAD_PARAMETER);
295f29dbc25Smrg    }
296f29dbc25Smrg
297f29dbc25Smrg    /* Adjusts the internal voltage reference */
298f29dbc25Smrg    ctrl2 = READ_VID32(SC1200_TVENC_DAC_CONTROL);
299f29dbc25Smrg    ctrl2 &= ~SC1200_TVENC_TRIM_MASK;
300f29dbc25Smrg
301f29dbc25Smrg    /* Bypass for issue #926 : Inadequate chroma level of S-Video output */
302f29dbc25Smrg    if ((gfx_chip_revision == SC1200_REV_B3) && (output == TV_OUTPUT_S_VIDEO))
303f29dbc25Smrg        ctrl2 |= 0x7;
304f29dbc25Smrg    else
305f29dbc25Smrg        ctrl2 |= 0x5;
306f29dbc25Smrg
307f29dbc25Smrg    WRITE_VID32(SC1200_TVENC_DAC_CONTROL, ctrl2);
308f29dbc25Smrg
309f29dbc25Smrg    /* Disable 4:2:2 to 4:4:4 converter interpolation */
310f29dbc25Smrg    WRITE_VID32(SC1200_TVOUT_DEBUG, SC1200_TVOUT_CONVERTER_INTERPOLATION);
311f29dbc25Smrg
312f29dbc25Smrg    return (GFX_STATUS_OK);
313f29dbc25Smrg}
314f29dbc25Smrg
315f29dbc25Smrg/*----------------------------------------------------------------------------
316f29dbc25Smrg * gfx_set_tv_enable
317f29dbc25Smrg *
318f29dbc25Smrg * This routine enables or disables the TV output.
319f29dbc25Smrg *----------------------------------------------------------------------------
320f29dbc25Smrg */
321f29dbc25Smrg#if GFX_TV_DYNAMIC
322f29dbc25Smrgint
323f29dbc25Smrgsc1200_set_tv_enable(int enable)
324f29dbc25Smrg#else
325f29dbc25Smrgint
326f29dbc25Smrggfx_set_tv_enable(int enable)
327f29dbc25Smrg#endif
328f29dbc25Smrg{
329f29dbc25Smrg    unsigned long value_tim, value_dac;
330f29dbc25Smrg
331f29dbc25Smrg    value_tim = READ_VID32(SC1200_TVENC_TIM_CTRL_1);
332f29dbc25Smrg    value_dac = READ_VID32(SC1200_TVENC_DAC_CONTROL);
333f29dbc25Smrg
334f29dbc25Smrg    if (enable) {
335f29dbc25Smrg        value_tim |= SC1200_TVENC_VIDEO_TIMING_ENABLE;
336f29dbc25Smrg        value_dac &= ~SC1200_TVENC_POWER_DOWN;
337f29dbc25Smrg        /* ENABLE GRAPHICS DISPLAY LOGIC IN VIDEO PROCESSOR */
338f29dbc25Smrg        gfx_set_screen_enable(1);
339f29dbc25Smrg    } else {
340f29dbc25Smrg        value_tim &= ~SC1200_TVENC_VIDEO_TIMING_ENABLE;
341f29dbc25Smrg        value_dac |= SC1200_TVENC_POWER_DOWN;
342f29dbc25Smrg        /* Do not disable the graphics display logic because it might be
343f29dbc25Smrg         * needed for CRT */
344f29dbc25Smrg    }
345f29dbc25Smrg
346f29dbc25Smrg    WRITE_VID32(SC1200_TVENC_TIM_CTRL_1, value_tim);
347f29dbc25Smrg    WRITE_VID32(SC1200_TVENC_DAC_CONTROL, value_dac);
348f29dbc25Smrg
349f29dbc25Smrg    return (GFX_STATUS_OK);
350f29dbc25Smrg}
351f29dbc25Smrg
352f29dbc25Smrg/*----------------------------------------------------------------------------
353f29dbc25Smrg * gfx_set_tv_flicker_filter
354f29dbc25Smrg *
355f29dbc25Smrg * This routine configures the TV out flicker filter.
356f29dbc25Smrg *----------------------------------------------------------------------------
357f29dbc25Smrg */
358f29dbc25Smrg#if GFX_TV_DYNAMIC
359f29dbc25Smrgint
360f29dbc25Smrgsc1200_set_tv_flicker_filter(int ff)
361f29dbc25Smrg#else
362f29dbc25Smrgint
363f29dbc25Smrggfx_set_tv_flicker_filter(int ff)
364f29dbc25Smrg#endif
365f29dbc25Smrg{
366f29dbc25Smrg    unsigned long mode;
367f29dbc25Smrg
368f29dbc25Smrg    mode = READ_VID32(SC1200_TVOUT_HORZ_SCALING);
369f29dbc25Smrg    mode &= ~SC1200_TVOUT_FLICKER_FILTER_MASK;
370f29dbc25Smrg    switch (ff) {
371f29dbc25Smrg    case TV_FLICKER_FILTER_NONE:
372f29dbc25Smrg        WRITE_VID32(SC1200_TVOUT_HORZ_SCALING,
373f29dbc25Smrg            mode | SC1200_TVOUT_FLICKER_FILTER_DISABLED);
374f29dbc25Smrg        break;
375f29dbc25Smrg    case TV_FLICKER_FILTER_NORMAL:
376f29dbc25Smrg        WRITE_VID32(SC1200_TVOUT_HORZ_SCALING,
377f29dbc25Smrg            mode | SC1200_TVOUT_FLICKER_FILTER_FOURTH_HALF_FOURTH);
378f29dbc25Smrg        break;
379f29dbc25Smrg    case TV_FLICKER_FILTER_INTERLACED:
380f29dbc25Smrg        WRITE_VID32(SC1200_TVOUT_HORZ_SCALING,
381f29dbc25Smrg            mode | SC1200_TVOUT_FLICKER_FILTER_HALF_ONE_HALF);
382f29dbc25Smrg        break;
383f29dbc25Smrg    default:
384f29dbc25Smrg        return GFX_STATUS_BAD_PARAMETER;
385f29dbc25Smrg    }
386f29dbc25Smrg    return (GFX_STATUS_OK);
387f29dbc25Smrg}
388f29dbc25Smrg
389f29dbc25Smrg/*----------------------------------------------------------------------------
390f29dbc25Smrg * gfx_set_tv_sub_carrier_reset
391f29dbc25Smrg *
392f29dbc25Smrg * This routine configures the TV encoder sub carrier reset interval.
393f29dbc25Smrg *----------------------------------------------------------------------------
394f29dbc25Smrg */
395f29dbc25Smrg#if GFX_TV_DYNAMIC
396f29dbc25Smrgint
397f29dbc25Smrgsc1200_set_tv_sub_carrier_reset(int screset)
398f29dbc25Smrg#else
399f29dbc25Smrgint
400f29dbc25Smrggfx_set_tv_sub_carrier_reset(int screset)
401f29dbc25Smrg#endif
402f29dbc25Smrg{
403f29dbc25Smrg    unsigned long mode;
404f29dbc25Smrg
405f29dbc25Smrg    mode = READ_VID32(SC1200_TVENC_TIM_CTRL_1);
406f29dbc25Smrg    mode &= ~SC1200_TVENC_SUB_CARRIER_RESET_MASK;
407f29dbc25Smrg    switch (screset) {
408f29dbc25Smrg    case TV_SUB_CARRIER_RESET_NEVER:
409f29dbc25Smrg        WRITE_VID32(SC1200_TVENC_TIM_CTRL_1,
410f29dbc25Smrg            mode | SC1200_TVENC_SUB_CARRIER_RESET_NEVER);
411f29dbc25Smrg        break;
412f29dbc25Smrg    case TV_SUB_CARRIER_RESET_EVERY_TWO_LINES:
413f29dbc25Smrg        WRITE_VID32(SC1200_TVENC_TIM_CTRL_1,
414f29dbc25Smrg            mode | SC1200_TVENC_SUB_CARRIER_RESET_EVERY_TWO_LINES);
415f29dbc25Smrg        break;
416f29dbc25Smrg    case TV_SUB_CARRIER_RESET_EVERY_TWO_FRAMES:
417f29dbc25Smrg        WRITE_VID32(SC1200_TVENC_TIM_CTRL_1,
418f29dbc25Smrg            mode | SC1200_TVENC_SUB_CARRIER_RESET_EVERY_TWO_FRAMES);
419f29dbc25Smrg        break;
420f29dbc25Smrg    case TV_SUB_CARRIER_RESET_EVERY_FOUR_FRAMES:
421f29dbc25Smrg        WRITE_VID32(SC1200_TVENC_TIM_CTRL_1,
422f29dbc25Smrg            mode | SC1200_TVENC_SUB_CARRIER_RESET_EVERY_FOUR_FRAMES);
423f29dbc25Smrg        break;
424f29dbc25Smrg    default:
425f29dbc25Smrg        return GFX_STATUS_BAD_PARAMETER;
426f29dbc25Smrg    }
427f29dbc25Smrg    return (GFX_STATUS_OK);
428f29dbc25Smrg}
429f29dbc25Smrg
430f29dbc25Smrg/*----------------------------------------------------------------------------
431f29dbc25Smrg * gfx_set_tv_vphase
432f29dbc25Smrg *
433f29dbc25Smrg * This routine sets the tv encoder VPHASE value.
434f29dbc25Smrg *----------------------------------------------------------------------------
435f29dbc25Smrg */
436f29dbc25Smrg#if GFX_TV_DYNAMIC
437f29dbc25Smrgint
438f29dbc25Smrgsc1200_set_tv_vphase(int vphase)
439f29dbc25Smrg#else
440f29dbc25Smrgint
441f29dbc25Smrggfx_set_tv_vphase(int vphase)
442f29dbc25Smrg#endif
443f29dbc25Smrg{
444f29dbc25Smrg    unsigned long mode = READ_VID32(SC1200_TVENC_TIM_CTRL_1);
445f29dbc25Smrg
446f29dbc25Smrg    mode &= ~SC1200_TVENC_VPHASE_MASK;
447f29dbc25Smrg    mode |= (vphase << SC1200_TVENC_VPHASE_POS) & SC1200_TVENC_VPHASE_MASK;
448f29dbc25Smrg    WRITE_VID32(SC1200_TVENC_TIM_CTRL_1, mode);
449f29dbc25Smrg    return (GFX_STATUS_OK);
450f29dbc25Smrg}
451f29dbc25Smrg
452f29dbc25Smrg/*----------------------------------------------------------------------------
453f29dbc25Smrg * gfx_set_tv_YC_delay
454f29dbc25Smrg *
455f29dbc25Smrg * This routine configures the TV out Y/C delay.
456f29dbc25Smrg *----------------------------------------------------------------------------
457f29dbc25Smrg */
458f29dbc25Smrg#if GFX_TV_DYNAMIC
459f29dbc25Smrgint
460f29dbc25Smrgsc1200_set_tv_YC_delay(int delay)
461f29dbc25Smrg#else
462f29dbc25Smrgint
463f29dbc25Smrggfx_set_tv_YC_delay(int delay)
464f29dbc25Smrg#endif
465f29dbc25Smrg{
466f29dbc25Smrg    unsigned long mode;
467f29dbc25Smrg
468f29dbc25Smrg    /* This feature is implemented in Rev C1 */
469f29dbc25Smrg    if (gfx_chip_revision < SC1200_REV_C1)
470f29dbc25Smrg        return (GFX_STATUS_OK);
471f29dbc25Smrg
472f29dbc25Smrg    mode = READ_VID32(SC1200_TVOUT_HORZ_PRE_ENCODER_SCALE);
473f29dbc25Smrg    mode &= ~SC1200_TVOUT_YC_DELAY_MASK;
474f29dbc25Smrg    switch (delay) {
475f29dbc25Smrg    case TV_YC_DELAY_NONE:
476f29dbc25Smrg        WRITE_VID32(SC1200_TVOUT_HORZ_PRE_ENCODER_SCALE,
477f29dbc25Smrg            mode | SC1200_TVOUT_YC_DELAY_NONE);
478f29dbc25Smrg        break;
479f29dbc25Smrg    case TV_Y_DELAY_ONE_PIXEL:
480f29dbc25Smrg        WRITE_VID32(SC1200_TVOUT_HORZ_PRE_ENCODER_SCALE,
481f29dbc25Smrg            mode | SC1200_TVOUT_Y_DELAY_ONE_PIXEL);
482f29dbc25Smrg        break;
483f29dbc25Smrg    case TV_C_DELAY_ONE_PIXEL:
484f29dbc25Smrg        WRITE_VID32(SC1200_TVOUT_HORZ_PRE_ENCODER_SCALE,
485f29dbc25Smrg            mode | SC1200_TVOUT_C_DELAY_ONE_PIXEL);
486f29dbc25Smrg        break;
487f29dbc25Smrg    case TV_C_DELAY_TWO_PIXELS:
488f29dbc25Smrg        WRITE_VID32(SC1200_TVOUT_HORZ_PRE_ENCODER_SCALE,
489f29dbc25Smrg            mode | SC1200_TVOUT_C_DELAY_TWO_PIXELS);
490f29dbc25Smrg        break;
491f29dbc25Smrg    default:
492f29dbc25Smrg        return GFX_STATUS_BAD_PARAMETER;
493f29dbc25Smrg    }
494f29dbc25Smrg    return (GFX_STATUS_OK);
495f29dbc25Smrg}
496f29dbc25Smrg
497f29dbc25Smrg/*----------------------------------------------------------------------------
498f29dbc25Smrg * gfx_set_tvenc_reset_interval
499f29dbc25Smrg *
500f29dbc25Smrg * This routine sets the interval between external resets of the TV encoder
501f29dbc25Smrg * timing generator by the TV out.
502f29dbc25Smrg *----------------------------------------------------------------------------
503f29dbc25Smrg */
504f29dbc25Smrg#if GFX_TV_DYNAMIC
505f29dbc25Smrgint
506f29dbc25Smrgsc1200_set_tvenc_reset_interval(int interval)
507f29dbc25Smrg#else
508f29dbc25Smrgint
509f29dbc25Smrggfx_set_tvenc_reset_interval(int interval)
510f29dbc25Smrg#endif
511f29dbc25Smrg{
512f29dbc25Smrg    unsigned long value;
513f29dbc25Smrg
514f29dbc25Smrg    value = READ_VID32(SC1200_TVOUT_HORZ_SCALING);
515f29dbc25Smrg    value &= ~SC1200_TVENC_EXTERNAL_RESET_INTERVAL_MASK;
516f29dbc25Smrg    switch (interval) {
517f29dbc25Smrg    case TVENC_RESET_EVERY_ODD_FIELD:
518f29dbc25Smrg        WRITE_VID32(SC1200_TVOUT_HORZ_SCALING,
519f29dbc25Smrg            value | SC1200_TVENC_EXTERNAL_RESET_EVERY_ODD_FIELD);
520f29dbc25Smrg        break;
521f29dbc25Smrg    case TVENC_RESET_EVERY_EVEN_FIELD:
522f29dbc25Smrg        WRITE_VID32(SC1200_TVOUT_HORZ_SCALING,
523f29dbc25Smrg            value | SC1200_TVENC_EXTERNAL_RESET_EVERY_EVEN_FIELD);
524f29dbc25Smrg        break;
525f29dbc25Smrg    case TVENC_RESET_NEXT_ODD_FIELD:
526f29dbc25Smrg        WRITE_VID32(SC1200_TVOUT_HORZ_SCALING,
527f29dbc25Smrg            value | SC1200_TVENC_EXTERNAL_RESET_NEXT_ODD_FIELD);
528f29dbc25Smrg        break;
529f29dbc25Smrg    case TVENC_RESET_NEXT_EVEN_FIELD:
530f29dbc25Smrg        WRITE_VID32(SC1200_TVOUT_HORZ_SCALING,
531f29dbc25Smrg            value | SC1200_TVENC_EXTERNAL_RESET_NEXT_EVEN_FIELD);
532f29dbc25Smrg        break;
533f29dbc25Smrg    case TVENC_RESET_EVERY_FIELD:
534f29dbc25Smrg        WRITE_VID32(SC1200_TVOUT_HORZ_SCALING,
535f29dbc25Smrg            value | SC1200_TVENC_EXTERNAL_RESET_EVERY_FIELD);
536f29dbc25Smrg        break;
537f29dbc25Smrg    case TVENC_RESET_EVERY_X_ODD_FIELDS:
538f29dbc25Smrg    case TVENC_RESET_EVERY_X_EVEN_FIELDS:
539f29dbc25Smrg        return GFX_STATUS_UNSUPPORTED;
540f29dbc25Smrg    default:
541f29dbc25Smrg        return GFX_STATUS_BAD_PARAMETER;
542f29dbc25Smrg    }
543f29dbc25Smrg    return (GFX_STATUS_OK);
544f29dbc25Smrg}
545f29dbc25Smrg
546f29dbc25Smrg/*----------------------------------------------------------------------------
547f29dbc25Smrg * gfx_set_tv_cc_enable
548f29dbc25Smrg *
549f29dbc25Smrg * This routine enables or disables the use of the hardware CC registers
550f29dbc25Smrg * in the TV encoder.
551f29dbc25Smrg *----------------------------------------------------------------------------
552f29dbc25Smrg */
553f29dbc25Smrg#if GFX_TV_DYNAMIC
554f29dbc25Smrgint
555f29dbc25Smrgsc1200_set_tv_cc_enable(int enable)
556f29dbc25Smrg#else
557f29dbc25Smrgint
558f29dbc25Smrggfx_set_tv_cc_enable(int enable)
559f29dbc25Smrg#endif
560f29dbc25Smrg{
561f29dbc25Smrg    unsigned long value;
562f29dbc25Smrg
563f29dbc25Smrg    value = READ_VID32(SC1200_TVENC_CC_CONTROL);
564f29dbc25Smrg    value &= ~(0x0005F);
565f29dbc25Smrg    if (enable)
566f29dbc25Smrg        value |= 0x51;
567f29dbc25Smrg    WRITE_VID32(SC1200_TVENC_CC_CONTROL, value);
568f29dbc25Smrg    return (0);
569f29dbc25Smrg}
570f29dbc25Smrg
571f29dbc25Smrg/*---------------------------------------------------------------------------
572f29dbc25Smrg * gfx_set_tv_display
573f29dbc25Smrg *
574f29dbc25Smrg * This routine sets the timings in the display controller to support a
575f29dbc25Smrg * TV resolution.
576f29dbc25Smrg *---------------------------------------------------------------------------
577f29dbc25Smrg */
578f29dbc25Smrg#if GFX_TV_DYNAMIC
579f29dbc25Smrgint
580f29dbc25Smrgsc1200_set_tv_display(int width, int height)
581f29dbc25Smrg#else
582f29dbc25Smrgint
583f29dbc25Smrggfx_set_tv_display(int width, int height)
584f29dbc25Smrg#endif
585f29dbc25Smrg{
586f29dbc25Smrg    DISPLAYMODE *pMode;
587f29dbc25Smrg    unsigned int i;
588f29dbc25Smrg
589f29dbc25Smrg    for (i = 0; i < NUM_TV_MODES; i++) {
590f29dbc25Smrg        pMode = &TVTimings[i];
591f29dbc25Smrg        if ((unsigned)width == pMode->hactive
592f29dbc25Smrg            && (unsigned)height == pMode->vactive)
593f29dbc25Smrg            break;
594f29dbc25Smrg    }
595f29dbc25Smrg
596f29dbc25Smrg    if (i == NUM_TV_MODES)
597f29dbc25Smrg        return 0;
598f29dbc25Smrg
599f29dbc25Smrg    gfx_set_display_timings(gfx_get_display_bpp(),
600f29dbc25Smrg        (unsigned short)pMode->flags, pMode->hactive, pMode->hblankstart,
601f29dbc25Smrg        pMode->hsyncstart, pMode->hsyncend, pMode->hblankend, pMode->htotal,
602f29dbc25Smrg        pMode->vactive, pMode->vblankstart, pMode->vsyncstart,
603f29dbc25Smrg        pMode->vsyncend, pMode->vblankend, pMode->vtotal, pMode->frequency);
604f29dbc25Smrg
605f29dbc25Smrg    return 1;
606f29dbc25Smrg}
607f29dbc25Smrg
608f29dbc25Smrg/*----------------------------------------------------------------------------
609f29dbc25Smrg * cc_add_parity_bit
610f29dbc25Smrg *
611f29dbc25Smrg * This routine adds the (odd) parity bit to the data character.
612f29dbc25Smrg *----------------------------------------------------------------------------
613f29dbc25Smrg */
614f29dbc25Smrgunsigned char
615f29dbc25Smrgcc_add_parity_bit(unsigned char data)
616f29dbc25Smrg{
617f29dbc25Smrg    int i, num = 0;
618f29dbc25Smrg    unsigned char d = data;
619f29dbc25Smrg
620f29dbc25Smrg    for (i = 0; i < 7; i++) {
621f29dbc25Smrg        if (d & 0x1)
622f29dbc25Smrg            num++;
623f29dbc25Smrg        d >>= 1;
624f29dbc25Smrg    }
625f29dbc25Smrg    if (num & 0x1)
626f29dbc25Smrg        return (data & ~0x80);
627f29dbc25Smrg    else
628f29dbc25Smrg        return (data | 0x80);
629f29dbc25Smrg}
630f29dbc25Smrg
631f29dbc25Smrg/*----------------------------------------------------------------------------
632f29dbc25Smrg * gfx_set_tv_cc_data
633f29dbc25Smrg *
634f29dbc25Smrg * This routine writes the two specified characters to the CC data register
635f29dbc25Smrg * of the TV encoder.
636f29dbc25Smrg *----------------------------------------------------------------------------
637f29dbc25Smrg */
638f29dbc25Smrg#if GFX_TV_DYNAMIC
639f29dbc25Smrgint
640f29dbc25Smrgsc1200_set_tv_cc_data(unsigned char data1, unsigned char data2)
641f29dbc25Smrg#else
642f29dbc25Smrgint
643f29dbc25Smrggfx_set_tv_cc_data(unsigned char data1, unsigned char data2)
644f29dbc25Smrg#endif
645f29dbc25Smrg{
646f29dbc25Smrg    unsigned long value;
647f29dbc25Smrg
648f29dbc25Smrg    value = cc_add_parity_bit(data1) | (cc_add_parity_bit(data2) << 8);
649f29dbc25Smrg    WRITE_VID32(SC1200_TVENC_CC_DATA, value);
650f29dbc25Smrg    return (0);
651f29dbc25Smrg}
652f29dbc25Smrg
653f29dbc25Smrg/*---------------------------------------------------------------------------
654f29dbc25Smrg * gfx_test_tvout_odd_field
655f29dbc25Smrg *
656f29dbc25Smrg * This routine returns 1 if the current TVout field is odd. Otherwise returns
657f29dbc25Smrg * 0.
658f29dbc25Smrg *---------------------------------------------------------------------------
659f29dbc25Smrg */
660f29dbc25Smrg#if GFX_TV_DYNAMIC
661f29dbc25Smrgint
662f29dbc25Smrgsc1200_test_tvout_odd_field(void)
663f29dbc25Smrg#else
664f29dbc25Smrgint
665f29dbc25Smrggfx_test_tvout_odd_field(void)
666f29dbc25Smrg#endif
667f29dbc25Smrg{
668f29dbc25Smrg    unsigned long debug = READ_VID32(SC1200_TVOUT_DEBUG);
669f29dbc25Smrg
670f29dbc25Smrg    WRITE_VID32(SC1200_TVOUT_DEBUG, debug | SC1200_TVOUT_FIELD_STATUS_TV);
671f29dbc25Smrg    if (READ_VID32(SC1200_TVOUT_DEBUG) & SC1200_TVOUT_FIELD_STATUS_EVEN)
672f29dbc25Smrg        return (0);
673f29dbc25Smrg    else
674f29dbc25Smrg        return (1);
675f29dbc25Smrg}
676f29dbc25Smrg
677f29dbc25Smrg/*---------------------------------------------------------------------------
678f29dbc25Smrg * gfx_test_tvenc_odd_field
679f29dbc25Smrg *
680f29dbc25Smrg * This routine returns 1 if the current TV encoder field is odd. Otherwise
681f29dbc25Smrg * returns 0.
682f29dbc25Smrg *---------------------------------------------------------------------------
683f29dbc25Smrg */
684f29dbc25Smrg#if GFX_TV_DYNAMIC
685f29dbc25Smrgint
686f29dbc25Smrgsc1200_test_tvenc_odd_field(void)
687f29dbc25Smrg#else
688f29dbc25Smrgint
689f29dbc25Smrggfx_test_tvenc_odd_field(void)
690f29dbc25Smrg#endif
691f29dbc25Smrg{
692f29dbc25Smrg    unsigned long debug = READ_VID32(SC1200_TVOUT_DEBUG);
693f29dbc25Smrg
694f29dbc25Smrg    WRITE_VID32(SC1200_TVOUT_DEBUG, debug & ~SC1200_TVOUT_FIELD_STATUS_TV);
695f29dbc25Smrg    if (READ_VID32(SC1200_TVOUT_DEBUG) & SC1200_TVOUT_FIELD_STATUS_EVEN)
696f29dbc25Smrg        return (0);
697f29dbc25Smrg    else
698f29dbc25Smrg        return (1);
699f29dbc25Smrg}
700f29dbc25Smrg
701f29dbc25Smrg/*----------------------------------------------------------------------------
702f29dbc25Smrg * gfx_set_tv_field_status_invert
703f29dbc25Smrg *
704f29dbc25Smrg * This routines determines whether the tvout/tvencoder field status bit is
705f29dbc25Smrg * inverted (enable = 1) or not (enable = 0).
706f29dbc25Smrg *----------------------------------------------------------------------------
707f29dbc25Smrg */
708f29dbc25Smrg#if GFX_TV_DYNAMIC
709f29dbc25Smrgint
710f29dbc25Smrgsc1200_set_tv_field_status_invert(int enable)
711f29dbc25Smrg#else
712f29dbc25Smrgint
713f29dbc25Smrggfx_set_tv_field_status_invert(int enable)
714f29dbc25Smrg#endif
715f29dbc25Smrg{
716f29dbc25Smrg    unsigned long value;
717f29dbc25Smrg
718f29dbc25Smrg    value = READ_VID32(SC1200_TVOUT_DEBUG);
719f29dbc25Smrg
720f29dbc25Smrg    if (enable) {
721f29dbc25Smrg        value |= SC1200_TVOUT_FIELD_STATUS_INVERT;
722f29dbc25Smrg    } else {
723f29dbc25Smrg        value &= ~(SC1200_TVOUT_FIELD_STATUS_INVERT);
724f29dbc25Smrg    }
725f29dbc25Smrg
726f29dbc25Smrg    WRITE_VID32(SC1200_TVOUT_DEBUG, value);
727f29dbc25Smrg
728f29dbc25Smrg    return (GFX_STATUS_OK);
729f29dbc25Smrg}
730f29dbc25Smrg
731f29dbc25Smrg/*---------------------------------------------------------------------------
732f29dbc25Smrg * gfx_get_tv_vphase
733f29dbc25Smrg *
734f29dbc25Smrg * This routine returns the tv encoder vertical phase.
735f29dbc25Smrg *---------------------------------------------------------------------------
736f29dbc25Smrg */
737f29dbc25Smrg#if GFX_TV_DYNAMIC
738f29dbc25Smrgint
739f29dbc25Smrgsc1200_get_tv_vphase(void)
740f29dbc25Smrg#else
741f29dbc25Smrgint
742f29dbc25Smrggfx_get_tv_vphase(void)
743f29dbc25Smrg#endif
744f29dbc25Smrg{
745f29dbc25Smrg    unsigned long mode = READ_VID32(SC1200_TVENC_TIM_CTRL_1);
746f29dbc25Smrg
747f29dbc25Smrg    return (int)((mode & SC1200_TVENC_VPHASE_MASK) >>
748f29dbc25Smrg        SC1200_TVENC_VPHASE_POS);
749f29dbc25Smrg}
750f29dbc25Smrg
751f29dbc25Smrg/*---------------------------------------------------------------------------
752f29dbc25Smrg * gfx_get_tv_enable
753f29dbc25Smrg *
754f29dbc25Smrg * This routine returns the current tv enable status
755f29dbc25Smrg *---------------------------------------------------------------------------
756f29dbc25Smrg */
757f29dbc25Smrg#if GFX_TV_DYNAMIC
758f29dbc25Smrgint
759f29dbc25Smrgsc1200_get_tv_enable(unsigned int *p_on)
760f29dbc25Smrg#else
761f29dbc25Smrgint
762f29dbc25Smrggfx_get_tv_enable(unsigned int *p_on)
763f29dbc25Smrg#endif
764f29dbc25Smrg{
765f29dbc25Smrg    unsigned long control = READ_VID32(SC1200_TVENC_DAC_CONTROL);
766f29dbc25Smrg
767f29dbc25Smrg    *p_on = (unsigned int)(!(control & SC1200_TVENC_POWER_DOWN));
768f29dbc25Smrg
769f29dbc25Smrg    return GFX_STATUS_OK;
770f29dbc25Smrg}
771f29dbc25Smrg
772f29dbc25Smrg/*---------------------------------------------------------------------------
773f29dbc25Smrg * gfx_get_tv_output
774f29dbc25Smrg *
775f29dbc25Smrg * This routine returns the current programmed TV output type.  It does not
776f29dbc25Smrg * detect invalid configurations.
777f29dbc25Smrg *---------------------------------------------------------------------------
778f29dbc25Smrg */
779f29dbc25Smrg#if GFX_TV_DYNAMIC
780f29dbc25Smrgint
781f29dbc25Smrgsc1200_get_tv_output(void)
782f29dbc25Smrg#else
783f29dbc25Smrgint
784f29dbc25Smrggfx_get_tv_output(void)
785f29dbc25Smrg#endif
786f29dbc25Smrg{
787f29dbc25Smrg    unsigned long ctrl2, ctrl3;
788f29dbc25Smrg    int format = 0;
789f29dbc25Smrg
790f29dbc25Smrg    ctrl2 = READ_VID32(SC1200_TVENC_TIM_CTRL_2);
791f29dbc25Smrg    ctrl3 = READ_VID32(SC1200_TVENC_TIM_CTRL_3);
792f29dbc25Smrg
793f29dbc25Smrg    if ((ctrl2 & SC1200_TVENC_CFS_MASK) == SC1200_TVENC_CFS_SVIDEO)
794f29dbc25Smrg        format = TV_OUTPUT_S_VIDEO;
795f29dbc25Smrg    else if (ctrl2 & SC1200_TVENC_OUTPUT_YCBCR)
796f29dbc25Smrg        format = TV_OUTPUT_YUV;
797f29dbc25Smrg    else if ((ctrl2 & SC1200_TVENC_CFS_MASK) == SC1200_TVENC_CFS_CVBS) {
798f29dbc25Smrg        if (ctrl3 & SC1200_TVENC_CM)
799f29dbc25Smrg            format = TV_OUTPUT_SCART;
800f29dbc25Smrg        else
801f29dbc25Smrg            format = TV_OUTPUT_COMPOSITE;
802f29dbc25Smrg    }
803f29dbc25Smrg
804f29dbc25Smrg    return format;
805f29dbc25Smrg}
806f29dbc25Smrg
807f29dbc25Smrg/*---------------------------------------------------------------------------
808f29dbc25Smrg * gfx_get_tv_mode_count
809f29dbc25Smrg *
810f29dbc25Smrg * This routine returns the number of valid TV out resolutions.
811f29dbc25Smrg *---------------------------------------------------------------------------
812f29dbc25Smrg */
813f29dbc25Smrg#if GFX_TV_DYNAMIC
814f29dbc25Smrgint
815f29dbc25Smrgsc1200_get_tv_mode_count(TVStandardType format)
816f29dbc25Smrg#else
817f29dbc25Smrgint
818f29dbc25Smrggfx_get_tv_mode_count(TVStandardType format)
819f29dbc25Smrg#endif
820f29dbc25Smrg{
821f29dbc25Smrg    unsigned int mode, count = 0;
822f29dbc25Smrg    unsigned long flag;
823f29dbc25Smrg
824f29dbc25Smrg    switch (format) {
825f29dbc25Smrg    case TV_STANDARD_NTSC:
826f29dbc25Smrg        flag = GFX_MODE_TV_NTSC;
827f29dbc25Smrg        break;
828f29dbc25Smrg    case TV_STANDARD_PAL:
829f29dbc25Smrg        flag = GFX_MODE_TV_PAL;
830f29dbc25Smrg        break;
831f29dbc25Smrg    default:
832f29dbc25Smrg        return 0;
833f29dbc25Smrg    }
834f29dbc25Smrg
835f29dbc25Smrg    for (mode = 0; mode < NUM_TV_MODES; mode++) {
836f29dbc25Smrg        if (TVTimings[mode].flags & flag)
837f29dbc25Smrg            count++;
838f29dbc25Smrg    }
839f29dbc25Smrg
840f29dbc25Smrg    return count;
841f29dbc25Smrg}
842f29dbc25Smrg
843f29dbc25Smrg/*---------------------------------------------------------------------------
844f29dbc25Smrg * gfx_get_tv_display_mode
845f29dbc25Smrg *
846f29dbc25Smrg * This routine returns the current TV display parameters.
847f29dbc25Smrg *---------------------------------------------------------------------------
848f29dbc25Smrg */
849f29dbc25Smrg#if GFX_TV_DYNAMIC
850f29dbc25Smrgint
851f29dbc25Smrgsc1200_get_tv_display_mode(int *width, int *height, int *bpp, int *hz)
852f29dbc25Smrg#else
853f29dbc25Smrgint
854f29dbc25Smrggfx_get_tv_display_mode(int *width, int *height, int *bpp, int *hz)
855f29dbc25Smrg#endif
856f29dbc25Smrg{
857f29dbc25Smrg    unsigned long frequency;
858f29dbc25Smrg    unsigned long mode, flags;
859f29dbc25Smrg
860f29dbc25Smrg    *width = gfx_get_hactive();
861f29dbc25Smrg    *height = gfx_get_vactive();
862f29dbc25Smrg    *bpp = gfx_get_display_bpp();
863f29dbc25Smrg    frequency = gfx_get_clock_frequency();
864f29dbc25Smrg
865f29dbc25Smrg    for (mode = 0; mode < NUM_TV_MODES; mode++) {
866f29dbc25Smrg        if (TVTimings[mode].hactive == (unsigned short)(*width) &&
867f29dbc25Smrg            TVTimings[mode].vactive == (unsigned short)(*height) &&
868f29dbc25Smrg            TVTimings[mode].frequency == frequency) {
869f29dbc25Smrg            flags = TVTimings[mode].flags;
870f29dbc25Smrg
871f29dbc25Smrg            if (flags & GFX_MODE_TV_NTSC)
872f29dbc25Smrg                *hz = 60;
873f29dbc25Smrg            else if (flags & GFX_MODE_TV_PAL)
874f29dbc25Smrg                *hz = 50;
875f29dbc25Smrg            else
876f29dbc25Smrg                *hz = 0;
877f29dbc25Smrg            return (1);
878f29dbc25Smrg        }
879f29dbc25Smrg    }
880f29dbc25Smrg
881f29dbc25Smrg    return -1;
882f29dbc25Smrg}
883f29dbc25Smrg
884f29dbc25Smrg/*---------------------------------------------------------------------------
885f29dbc25Smrg * gfx_get_tv_display_mode_frequency
886f29dbc25Smrg *
887f29dbc25Smrg * This routine returns the PLL frequency of a given TV mode.
888f29dbc25Smrg *---------------------------------------------------------------------------
889f29dbc25Smrg */
890f29dbc25Smrg#if GFX_TV_DYNAMIC
891f29dbc25Smrgint
892f29dbc25Smrgsc1200_get_tv_display_mode_frequency(unsigned short width,
893f29dbc25Smrg    unsigned short height, TVStandardType format, int *frequency)
894f29dbc25Smrg#else
895f29dbc25Smrgint
896f29dbc25Smrggfx_get_tv_display_mode_frequency(unsigned short width, unsigned short height,
897f29dbc25Smrg    TVStandardType format, int *frequency)
898f29dbc25Smrg#endif
899f29dbc25Smrg{
900f29dbc25Smrg    unsigned long mode, flag;
901f29dbc25Smrg    int retval = -1;
902f29dbc25Smrg
903f29dbc25Smrg    *frequency = 0;
904f29dbc25Smrg
905f29dbc25Smrg    switch (format) {
906f29dbc25Smrg    case TV_STANDARD_NTSC:
907f29dbc25Smrg        flag = GFX_MODE_TV_NTSC;
908f29dbc25Smrg        break;
909f29dbc25Smrg    case TV_STANDARD_PAL:
910f29dbc25Smrg        flag = GFX_MODE_TV_PAL;
911f29dbc25Smrg        break;
912f29dbc25Smrg    default:
913f29dbc25Smrg        return -1;
914f29dbc25Smrg    }
915f29dbc25Smrg
916f29dbc25Smrg    for (mode = 0; mode < NUM_TV_MODES; mode++) {
917f29dbc25Smrg        if ((TVTimings[mode].hactive == width) &&
918f29dbc25Smrg            (TVTimings[mode].vactive == height) &&
919f29dbc25Smrg            (TVTimings[mode].flags & flag)) {
920f29dbc25Smrg            *frequency = TVTimings[mode].frequency;
921f29dbc25Smrg            retval = 1;
922f29dbc25Smrg        }
923f29dbc25Smrg    }
924f29dbc25Smrg    return retval;
925f29dbc25Smrg}
926f29dbc25Smrg
927f29dbc25Smrg/*---------------------------------------------------------------------------
928f29dbc25Smrg * gfx_is_tv_display_mode_supported
929f29dbc25Smrg *
930f29dbc25Smrg * Returns >= 0 if the mode is available, -1 if the mode could not be found
931f29dbc25Smrg *---------------------------------------------------------------------------
932f29dbc25Smrg */
933f29dbc25Smrg#if GFX_TV_DYNAMIC
934f29dbc25Smrgint
935f29dbc25Smrgsc1200_is_tv_display_mode_supported(unsigned short width,
936f29dbc25Smrg    unsigned short height, TVStandardType format)
937f29dbc25Smrg#else
938f29dbc25Smrgint
939f29dbc25Smrggfx_is_tv_display_mode_supported(unsigned short width, unsigned short height,
940f29dbc25Smrg    TVStandardType format)
941f29dbc25Smrg#endif
942f29dbc25Smrg{
943f29dbc25Smrg    unsigned long mode, flag;
944f29dbc25Smrg
945f29dbc25Smrg    switch (format) {
946f29dbc25Smrg    case TV_STANDARD_NTSC:
947f29dbc25Smrg        flag = GFX_MODE_TV_NTSC;
948f29dbc25Smrg        break;
949f29dbc25Smrg    case TV_STANDARD_PAL:
950f29dbc25Smrg        flag = GFX_MODE_TV_PAL;
951f29dbc25Smrg        break;
952f29dbc25Smrg    default:
953f29dbc25Smrg        return -1;
954f29dbc25Smrg    }
955f29dbc25Smrg
956f29dbc25Smrg    for (mode = 0; mode < NUM_TV_MODES; mode++) {
957f29dbc25Smrg        if (TVTimings[mode].hactive == width &&
958f29dbc25Smrg            TVTimings[mode].vactive == height &&
959f29dbc25Smrg            (TVTimings[mode].flags & flag)) {
960f29dbc25Smrg            return ((int)mode);
961f29dbc25Smrg        }
962f29dbc25Smrg    }
963f29dbc25Smrg
964f29dbc25Smrg    return -1;
965f29dbc25Smrg}
966f29dbc25Smrg
967f29dbc25Smrg/* END OF FILE */
968