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 |
5004007ebaSmrg                                               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);
10804007ebaSmrg            }
10904007ebaSmrg            else {              /* Use new scaler available in Rev. C */
110f29dbc25Smrg                /* Horizontal Display start is 111 */
111f29dbc25Smrg                /* Total number of pixels per line is 857 */
112f29dbc25Smrg                WRITE_VID32(SC1200_TVOUT_HORZ_TIM, 0x006f0359);
113f29dbc25Smrg                /* HSYNC generated in the TV Encoder module */
114f29dbc25Smrg                /* Interval between resets of TV Encoder is once every odd
115f29dbc25Smrg                 * field */
116f29dbc25Smrg                /* Enable Horizontal interpolation */
117f29dbc25Smrg                /* Disable Horizontal up scaling 9/8 */
118f29dbc25Smrg                /* Disable Horizontal downscale */
119f29dbc25Smrg                WRITE_VID32(SC1200_TVOUT_HORZ_SCALING, 0x10020500 | mode);
120f29dbc25Smrg                /* Set Horizontal upscaling to 64/58 (~ 11/10) */
121f29dbc25Smrg                WRITE_VID32(SC1200_TVOUT_HORZ_PRE_ENCODER_SCALE, 0x3A000000);
122f29dbc25Smrg                /* Horizontal display end is 900, i.e. 706 active pixels */
123f29dbc25Smrg                /* Total number of display lines per field is 240 */
124f29dbc25Smrg                WRITE_VID32(SC1200_TVOUT_LINE_END, 0x038400f0);
125f29dbc25Smrg            }
126f29dbc25Smrg            break;
127f29dbc25Smrg        case GFX_ON_TV_NO_SCALING:
128f29dbc25Smrg            /* Horizontal Display start is 116 */
129f29dbc25Smrg            /* Total number of pixels per line is 857 */
130f29dbc25Smrg            WRITE_VID32(SC1200_TVOUT_HORZ_TIM, 0x00740359);
131f29dbc25Smrg            /* HSYNC generated in the TV Encoder module */
132f29dbc25Smrg            /* Interval between resets of TV Encoder is once every odd field */
133f29dbc25Smrg            /* Enable Horizontal interpolation */
134f29dbc25Smrg            /* Disable Horizontal up scaling 9/8 */
135f29dbc25Smrg            /* Disable Horizontal downscale */
136f29dbc25Smrg            WRITE_VID32(SC1200_TVOUT_HORZ_SCALING, 0x10020500 | mode);
137f29dbc25Smrg            /* Disable Horizontal scaling (set to 64/64) */
138f29dbc25Smrg            if (gfx_chip_revision >= SC1200_REV_C1)
139f29dbc25Smrg                WRITE_VID32(SC1200_TVOUT_HORZ_PRE_ENCODER_SCALE, 0x40000000);
140f29dbc25Smrg            /* Horizontal display end is 919, i.e. 720 active pixels */
141f29dbc25Smrg            /* Total number of display lines per field is 240 */
142f29dbc25Smrg            WRITE_VID32(SC1200_TVOUT_LINE_END, 0x039700f0);
143f29dbc25Smrg            break;
144f29dbc25Smrg        default:
145f29dbc25Smrg            return (GFX_STATUS_BAD_PARAMETER);
146f29dbc25Smrg        }
147f29dbc25Smrg        break;
148f29dbc25Smrg    case TV_STANDARD_PAL:
149f29dbc25Smrg        /* Horizontal Sync Start is 854 */
150f29dbc25Smrg        /* Horizontal Sync End is 862 */
151f29dbc25Smrg        WRITE_VID32(SC1200_TVOUT_HORZ_SYNC, 0x035e0356);
152f29dbc25Smrg        /* Vertical Sync Start is 0 */
153f29dbc25Smrg        /* Vertical Sync End is 1 */
154f29dbc25Smrg        /* Vertical Display Start Skew is 1 */
155f29dbc25Smrg        /* Vertical Display End Skew is 1 */
156f29dbc25Smrg        WRITE_VID32(SC1200_TVOUT_VERT_SYNC, 0x05001000);
157f29dbc25Smrg        /* Disable vertical down scaling, take all lines */
158f29dbc25Smrg        if (gfx_chip_revision <= SC1200_REV_B3)
159f29dbc25Smrg            WRITE_VID32(SC1200_TVOUT_VERT_DOWNSCALE, 0xffffffff);
160f29dbc25Smrg        /* Enable video timing */
161f29dbc25Smrg        /* Never reset sub carrier (should be every 4 frames but doesn't work
162f29dbc25Smrg         * with genlock) */
163f29dbc25Smrg        /* Disable BLANK */
164f29dbc25Smrg        /* Enable color burst */
165f29dbc25Smrg        /* Do not add the IRE offset */
166f29dbc25Smrg        /* NTSC color encoding */
167f29dbc25Smrg        /* Video generator timing is 625 lines / 50Hz */
168f29dbc25Smrg        /* Horizontal and Vertical counters are initialized to HPHASE & VPHASE
169f29dbc25Smrg         * */
170f29dbc25Smrg        /* VPHASE is 2, HPHASE is 50 */
171f29dbc25Smrg        WRITE_VID32(SC1200_TVENC_TIM_CTRL_1, 0xB1201050);
172f29dbc25Smrg        /* Increase horizontal blanking interval */
173f29dbc25Smrg        /* Low Water Mark for Y is 0x1F */
174f29dbc25Smrg        /* Low Water Mark for Cb is 0xF */
175f29dbc25Smrg        /* HUE is 0 */
176f29dbc25Smrg        /* SCPHASE is 0xD9 */
177f29dbc25Smrg        WRITE_VID32(SC1200_TVENC_TIM_CTRL_2, 0x9ff000d9 | ctrl2);
178f29dbc25Smrg        /* Subcarrier Frequency is 4.43361875 MHz */
179f29dbc25Smrg        WRITE_VID32(SC1200_TVENC_SUB_FREQ, 0x2a098acb);
180f29dbc25Smrg        /* VSTART is 22, HSTART is 123 */
181f29dbc25Smrg        WRITE_VID32(SC1200_TVENC_DISP_POS, 0x0016007b);
182f29dbc25Smrg        /* Display size: HEIGHT is 287, WIDTH is 719 */
183f29dbc25Smrg        WRITE_VID32(SC1200_TVENC_DISP_SIZE, 0x011f02cf);
184f29dbc25Smrg        switch (resolution) {
185f29dbc25Smrg        case GFX_ON_TV_NO_SCALING:
186f29dbc25Smrg            /* Horizontal Display start is 124 */
187f29dbc25Smrg            /* Total number of pixels per line is 863 */
188f29dbc25Smrg            WRITE_VID32(SC1200_TVOUT_HORZ_TIM, 0x007c035f);
189f29dbc25Smrg            /* HSYNC generated in the TV Encoder module */
190f29dbc25Smrg            /* Interval between resets of TV Encoder is once every odd field */
191f29dbc25Smrg            /* Enable Horizontal interpolation */
192f29dbc25Smrg            /* Disable Horizontal up scaling 9/8 */
193f29dbc25Smrg            /* Disable Horizontal downscale */
194f29dbc25Smrg            WRITE_VID32(SC1200_TVOUT_HORZ_SCALING, 0x10020500 | mode);
195f29dbc25Smrg            /* Disable Horizontal scaling (set to 64/64) */
196f29dbc25Smrg            if (gfx_chip_revision >= SC1200_REV_C1)
197f29dbc25Smrg                WRITE_VID32(SC1200_TVOUT_HORZ_PRE_ENCODER_SCALE, 0x40000000);
198f29dbc25Smrg            /* Horizontal display end is 924, i.e. 720 active pixels */
199f29dbc25Smrg            /* Total number of display lines per field is 288 */
200f29dbc25Smrg            WRITE_VID32(SC1200_TVOUT_LINE_END, 0x039c0120);
201f29dbc25Smrg            break;
202f29dbc25Smrg        case GFX_ON_TV_SQUARE_PIXELS:
203f29dbc25Smrg            /* Horizontal Display start is 122 */
204f29dbc25Smrg            /* Total number of pixels per line is 863 */
205f29dbc25Smrg            WRITE_VID32(SC1200_TVOUT_HORZ_TIM, 0x007a035f);
206f29dbc25Smrg            if (gfx_chip_revision <= SC1200_REV_B3) {
207f29dbc25Smrg                /* HSYNC generated in the TV Encoder module */
208f29dbc25Smrg                /* Interval between resets of TV Encoder is once every odd
209f29dbc25Smrg                 * field */
210f29dbc25Smrg                /* Enable Horizontal interpolation */
211f29dbc25Smrg                /* Disable Horizontal up scaling 9/8 */
212f29dbc25Smrg                /* Horizontal downscale m/(m+1), m = 11, (i.e. 11/12 - closest
213f29dbc25Smrg                 * possible to 54/59) */
214f29dbc25Smrg                WRITE_VID32(SC1200_TVOUT_HORZ_SCALING, 0x1002040b | mode);
215f29dbc25Smrg                /* Horizontal display end is 906, i.e. 704 active pixels */
216f29dbc25Smrg                /* Total number of display lines per field is 288 */
217f29dbc25Smrg                WRITE_VID32(SC1200_TVOUT_LINE_END, 0x038a0120);
21804007ebaSmrg            }
21904007ebaSmrg            else {
220f29dbc25Smrg                /* HSYNC generated in the TV Encoder module */
221f29dbc25Smrg                /* Interval between resets of TV Encoder is once every odd
222f29dbc25Smrg                 * field */
223f29dbc25Smrg                /* Enable Horizontal interpolation */
224f29dbc25Smrg                /* Disable Horizontal up scaling 9/8 */
225f29dbc25Smrg                /* Disable Horizontal downscale */
226f29dbc25Smrg                WRITE_VID32(SC1200_TVOUT_HORZ_SCALING, 0x10020500 | mode);
227f29dbc25Smrg                /* Set Horizontal down scaling to 64/70 (closest possible to
228f29dbc25Smrg                 * 54/59) */
229f29dbc25Smrg                WRITE_VID32(SC1200_TVOUT_HORZ_PRE_ENCODER_SCALE, 0x46000000);
230f29dbc25Smrg                /* Horizontal display end is 904, i.e. 702 active pixels */
231f29dbc25Smrg                /* Total number of display lines per field is 288 */
232f29dbc25Smrg                WRITE_VID32(SC1200_TVOUT_LINE_END, 0x03880120);
233f29dbc25Smrg            }
234f29dbc25Smrg            break;
235f29dbc25Smrg        default:
236f29dbc25Smrg            return (GFX_STATUS_BAD_PARAMETER);
237f29dbc25Smrg        }
238f29dbc25Smrg        break;
239f29dbc25Smrg    default:
240f29dbc25Smrg        return (GFX_STATUS_BAD_PARAMETER);
241f29dbc25Smrg    }
242f29dbc25Smrg    return (GFX_STATUS_OK);
243f29dbc25Smrg}
244f29dbc25Smrg
245f29dbc25Smrg/*----------------------------------------------------------------------------
246f29dbc25Smrg * gfx_set_tv_output
247f29dbc25Smrg *
248f29dbc25Smrg * This routine sets the TV encoder registers to the specified output type.
249f29dbc25Smrg * Supported output types are : S-VIDEO, Composite, YUV and SCART.
250f29dbc25Smrg *----------------------------------------------------------------------------
251f29dbc25Smrg */
252f29dbc25Smrg#if GFX_TV_DYNAMIC
253f29dbc25Smrgint
254f29dbc25Smrgsc1200_set_tv_output(int output)
255f29dbc25Smrg#else
256f29dbc25Smrgint
257f29dbc25Smrggfx_set_tv_output(int output)
258f29dbc25Smrg#endif
259f29dbc25Smrg{
260f29dbc25Smrg    unsigned long ctrl2, ctrl3;
261f29dbc25Smrg
262f29dbc25Smrg    ctrl2 = READ_VID32(SC1200_TVENC_TIM_CTRL_2);
263f29dbc25Smrg    ctrl3 = READ_VID32(SC1200_TVENC_TIM_CTRL_3);
264f29dbc25Smrg    ctrl2 &= ~(SC1200_TVENC_OUTPUT_YCBCR | SC1200_TVENC_CFS_MASK);
26504007ebaSmrg    ctrl3 &= ~(SC1200_TVENC_CM | SC1200_TVENC_SYNCMODE_MASK | SC1200_TVENC_CS);
266f29dbc25Smrg    switch (output) {
267f29dbc25Smrg    case TV_OUTPUT_COMPOSITE:
268f29dbc25Smrg        /* Analog outputs provide Y, C and CVBS */
269f29dbc25Smrg        /* Chrominance Lowpass filter is 1.3MHz (for composite video output) */
270f29dbc25Smrg        WRITE_VID32(SC1200_TVENC_TIM_CTRL_2, ctrl2 | SC1200_TVENC_CFS_CVBS);
271f29dbc25Smrg        WRITE_VID32(SC1200_TVENC_TIM_CTRL_3, ctrl3);
272f29dbc25Smrg        break;
273f29dbc25Smrg    case TV_OUTPUT_S_VIDEO:
274f29dbc25Smrg        /* Analog outputs provide Y, C and CVBS */
275f29dbc25Smrg        /* Chrominance Lowpass filter is 1.8MHz (for S-video output) */
276f29dbc25Smrg        WRITE_VID32(SC1200_TVENC_TIM_CTRL_2, ctrl2 | SC1200_TVENC_CFS_SVIDEO);
277f29dbc25Smrg        WRITE_VID32(SC1200_TVENC_TIM_CTRL_3, ctrl3);
278f29dbc25Smrg        break;
279f29dbc25Smrg    case TV_OUTPUT_YUV:
280f29dbc25Smrg        /* Analog outputs provide Y, Cb and Cr */
281f29dbc25Smrg        /* A 7.5 IRE setup is applied to the output */
282f29dbc25Smrg        WRITE_VID32(SC1200_TVENC_TIM_CTRL_2,
28304007ebaSmrg                    ctrl2 | SC1200_TVENC_OUTPUT_YCBCR |
28404007ebaSmrg                    SC1200_TVENC_CFS_BYPASS);
285f29dbc25Smrg        WRITE_VID32(SC1200_TVENC_TIM_CTRL_3,
28604007ebaSmrg                    ctrl3 | SC1200_TVENC_CM | SC1200_TVENC_CS);
287f29dbc25Smrg        break;
288f29dbc25Smrg    case TV_OUTPUT_SCART:
289f29dbc25Smrg        /* Analog outputs provide SCART (RGB and CVBS) */
290f29dbc25Smrg        /* Sync is added to green signal */
291f29dbc25Smrg        WRITE_VID32(SC1200_TVENC_TIM_CTRL_2, ctrl2 | SC1200_TVENC_CFS_CVBS);
292f29dbc25Smrg        WRITE_VID32(SC1200_TVENC_TIM_CTRL_3,
29304007ebaSmrg                    ctrl3 | SC1200_TVENC_CM | SC1200_TVENC_SYNC_ON_GREEN);
294f29dbc25Smrg        break;
295f29dbc25Smrg    default:
296f29dbc25Smrg        return (GFX_STATUS_BAD_PARAMETER);
297f29dbc25Smrg    }
298f29dbc25Smrg
299f29dbc25Smrg    /* Adjusts the internal voltage reference */
300f29dbc25Smrg    ctrl2 = READ_VID32(SC1200_TVENC_DAC_CONTROL);
301f29dbc25Smrg    ctrl2 &= ~SC1200_TVENC_TRIM_MASK;
302f29dbc25Smrg
303f29dbc25Smrg    /* Bypass for issue #926 : Inadequate chroma level of S-Video output */
304f29dbc25Smrg    if ((gfx_chip_revision == SC1200_REV_B3) && (output == TV_OUTPUT_S_VIDEO))
305f29dbc25Smrg        ctrl2 |= 0x7;
306f29dbc25Smrg    else
307f29dbc25Smrg        ctrl2 |= 0x5;
308f29dbc25Smrg
309f29dbc25Smrg    WRITE_VID32(SC1200_TVENC_DAC_CONTROL, ctrl2);
310f29dbc25Smrg
311f29dbc25Smrg    /* Disable 4:2:2 to 4:4:4 converter interpolation */
312f29dbc25Smrg    WRITE_VID32(SC1200_TVOUT_DEBUG, SC1200_TVOUT_CONVERTER_INTERPOLATION);
313f29dbc25Smrg
314f29dbc25Smrg    return (GFX_STATUS_OK);
315f29dbc25Smrg}
316f29dbc25Smrg
317f29dbc25Smrg/*----------------------------------------------------------------------------
318f29dbc25Smrg * gfx_set_tv_enable
319f29dbc25Smrg *
320f29dbc25Smrg * This routine enables or disables the TV output.
321f29dbc25Smrg *----------------------------------------------------------------------------
322f29dbc25Smrg */
323f29dbc25Smrg#if GFX_TV_DYNAMIC
324f29dbc25Smrgint
325f29dbc25Smrgsc1200_set_tv_enable(int enable)
326f29dbc25Smrg#else
327f29dbc25Smrgint
328f29dbc25Smrggfx_set_tv_enable(int enable)
329f29dbc25Smrg#endif
330f29dbc25Smrg{
331f29dbc25Smrg    unsigned long value_tim, value_dac;
332f29dbc25Smrg
333f29dbc25Smrg    value_tim = READ_VID32(SC1200_TVENC_TIM_CTRL_1);
334f29dbc25Smrg    value_dac = READ_VID32(SC1200_TVENC_DAC_CONTROL);
335f29dbc25Smrg
336f29dbc25Smrg    if (enable) {
337f29dbc25Smrg        value_tim |= SC1200_TVENC_VIDEO_TIMING_ENABLE;
338f29dbc25Smrg        value_dac &= ~SC1200_TVENC_POWER_DOWN;
339f29dbc25Smrg        /* ENABLE GRAPHICS DISPLAY LOGIC IN VIDEO PROCESSOR */
340f29dbc25Smrg        gfx_set_screen_enable(1);
34104007ebaSmrg    }
34204007ebaSmrg    else {
343f29dbc25Smrg        value_tim &= ~SC1200_TVENC_VIDEO_TIMING_ENABLE;
344f29dbc25Smrg        value_dac |= SC1200_TVENC_POWER_DOWN;
345f29dbc25Smrg        /* Do not disable the graphics display logic because it might be
346f29dbc25Smrg         * needed for CRT */
347f29dbc25Smrg    }
348f29dbc25Smrg
349f29dbc25Smrg    WRITE_VID32(SC1200_TVENC_TIM_CTRL_1, value_tim);
350f29dbc25Smrg    WRITE_VID32(SC1200_TVENC_DAC_CONTROL, value_dac);
351f29dbc25Smrg
352f29dbc25Smrg    return (GFX_STATUS_OK);
353f29dbc25Smrg}
354f29dbc25Smrg
355f29dbc25Smrg/*----------------------------------------------------------------------------
356f29dbc25Smrg * gfx_set_tv_flicker_filter
357f29dbc25Smrg *
358f29dbc25Smrg * This routine configures the TV out flicker filter.
359f29dbc25Smrg *----------------------------------------------------------------------------
360f29dbc25Smrg */
361f29dbc25Smrg#if GFX_TV_DYNAMIC
362f29dbc25Smrgint
363f29dbc25Smrgsc1200_set_tv_flicker_filter(int ff)
364f29dbc25Smrg#else
365f29dbc25Smrgint
366f29dbc25Smrggfx_set_tv_flicker_filter(int ff)
367f29dbc25Smrg#endif
368f29dbc25Smrg{
369f29dbc25Smrg    unsigned long mode;
370f29dbc25Smrg
371f29dbc25Smrg    mode = READ_VID32(SC1200_TVOUT_HORZ_SCALING);
372f29dbc25Smrg    mode &= ~SC1200_TVOUT_FLICKER_FILTER_MASK;
373f29dbc25Smrg    switch (ff) {
374f29dbc25Smrg    case TV_FLICKER_FILTER_NONE:
375f29dbc25Smrg        WRITE_VID32(SC1200_TVOUT_HORZ_SCALING,
37604007ebaSmrg                    mode | SC1200_TVOUT_FLICKER_FILTER_DISABLED);
377f29dbc25Smrg        break;
378f29dbc25Smrg    case TV_FLICKER_FILTER_NORMAL:
379f29dbc25Smrg        WRITE_VID32(SC1200_TVOUT_HORZ_SCALING,
38004007ebaSmrg                    mode | SC1200_TVOUT_FLICKER_FILTER_FOURTH_HALF_FOURTH);
381f29dbc25Smrg        break;
382f29dbc25Smrg    case TV_FLICKER_FILTER_INTERLACED:
383f29dbc25Smrg        WRITE_VID32(SC1200_TVOUT_HORZ_SCALING,
38404007ebaSmrg                    mode | SC1200_TVOUT_FLICKER_FILTER_HALF_ONE_HALF);
385f29dbc25Smrg        break;
386f29dbc25Smrg    default:
387f29dbc25Smrg        return GFX_STATUS_BAD_PARAMETER;
388f29dbc25Smrg    }
389f29dbc25Smrg    return (GFX_STATUS_OK);
390f29dbc25Smrg}
391f29dbc25Smrg
392f29dbc25Smrg/*----------------------------------------------------------------------------
393f29dbc25Smrg * gfx_set_tv_sub_carrier_reset
394f29dbc25Smrg *
395f29dbc25Smrg * This routine configures the TV encoder sub carrier reset interval.
396f29dbc25Smrg *----------------------------------------------------------------------------
397f29dbc25Smrg */
398f29dbc25Smrg#if GFX_TV_DYNAMIC
399f29dbc25Smrgint
400f29dbc25Smrgsc1200_set_tv_sub_carrier_reset(int screset)
401f29dbc25Smrg#else
402f29dbc25Smrgint
403f29dbc25Smrggfx_set_tv_sub_carrier_reset(int screset)
404f29dbc25Smrg#endif
405f29dbc25Smrg{
406f29dbc25Smrg    unsigned long mode;
407f29dbc25Smrg
408f29dbc25Smrg    mode = READ_VID32(SC1200_TVENC_TIM_CTRL_1);
409f29dbc25Smrg    mode &= ~SC1200_TVENC_SUB_CARRIER_RESET_MASK;
410f29dbc25Smrg    switch (screset) {
411f29dbc25Smrg    case TV_SUB_CARRIER_RESET_NEVER:
412f29dbc25Smrg        WRITE_VID32(SC1200_TVENC_TIM_CTRL_1,
41304007ebaSmrg                    mode | SC1200_TVENC_SUB_CARRIER_RESET_NEVER);
414f29dbc25Smrg        break;
415f29dbc25Smrg    case TV_SUB_CARRIER_RESET_EVERY_TWO_LINES:
416f29dbc25Smrg        WRITE_VID32(SC1200_TVENC_TIM_CTRL_1,
41704007ebaSmrg                    mode | SC1200_TVENC_SUB_CARRIER_RESET_EVERY_TWO_LINES);
418f29dbc25Smrg        break;
419f29dbc25Smrg    case TV_SUB_CARRIER_RESET_EVERY_TWO_FRAMES:
420f29dbc25Smrg        WRITE_VID32(SC1200_TVENC_TIM_CTRL_1,
42104007ebaSmrg                    mode | SC1200_TVENC_SUB_CARRIER_RESET_EVERY_TWO_FRAMES);
422f29dbc25Smrg        break;
423f29dbc25Smrg    case TV_SUB_CARRIER_RESET_EVERY_FOUR_FRAMES:
424f29dbc25Smrg        WRITE_VID32(SC1200_TVENC_TIM_CTRL_1,
42504007ebaSmrg                    mode | SC1200_TVENC_SUB_CARRIER_RESET_EVERY_FOUR_FRAMES);
426f29dbc25Smrg        break;
427f29dbc25Smrg    default:
428f29dbc25Smrg        return GFX_STATUS_BAD_PARAMETER;
429f29dbc25Smrg    }
430f29dbc25Smrg    return (GFX_STATUS_OK);
431f29dbc25Smrg}
432f29dbc25Smrg
433f29dbc25Smrg/*----------------------------------------------------------------------------
434f29dbc25Smrg * gfx_set_tv_vphase
435f29dbc25Smrg *
436f29dbc25Smrg * This routine sets the tv encoder VPHASE value.
437f29dbc25Smrg *----------------------------------------------------------------------------
438f29dbc25Smrg */
439f29dbc25Smrg#if GFX_TV_DYNAMIC
440f29dbc25Smrgint
441f29dbc25Smrgsc1200_set_tv_vphase(int vphase)
442f29dbc25Smrg#else
443f29dbc25Smrgint
444f29dbc25Smrggfx_set_tv_vphase(int vphase)
445f29dbc25Smrg#endif
446f29dbc25Smrg{
447f29dbc25Smrg    unsigned long mode = READ_VID32(SC1200_TVENC_TIM_CTRL_1);
448f29dbc25Smrg
449f29dbc25Smrg    mode &= ~SC1200_TVENC_VPHASE_MASK;
450f29dbc25Smrg    mode |= (vphase << SC1200_TVENC_VPHASE_POS) & SC1200_TVENC_VPHASE_MASK;
451f29dbc25Smrg    WRITE_VID32(SC1200_TVENC_TIM_CTRL_1, mode);
452f29dbc25Smrg    return (GFX_STATUS_OK);
453f29dbc25Smrg}
454f29dbc25Smrg
455f29dbc25Smrg/*----------------------------------------------------------------------------
456f29dbc25Smrg * gfx_set_tv_YC_delay
457f29dbc25Smrg *
458f29dbc25Smrg * This routine configures the TV out Y/C delay.
459f29dbc25Smrg *----------------------------------------------------------------------------
460f29dbc25Smrg */
461f29dbc25Smrg#if GFX_TV_DYNAMIC
462f29dbc25Smrgint
463f29dbc25Smrgsc1200_set_tv_YC_delay(int delay)
464f29dbc25Smrg#else
465f29dbc25Smrgint
466f29dbc25Smrggfx_set_tv_YC_delay(int delay)
467f29dbc25Smrg#endif
468f29dbc25Smrg{
469f29dbc25Smrg    unsigned long mode;
470f29dbc25Smrg
471f29dbc25Smrg    /* This feature is implemented in Rev C1 */
472f29dbc25Smrg    if (gfx_chip_revision < SC1200_REV_C1)
473f29dbc25Smrg        return (GFX_STATUS_OK);
474f29dbc25Smrg
475f29dbc25Smrg    mode = READ_VID32(SC1200_TVOUT_HORZ_PRE_ENCODER_SCALE);
476f29dbc25Smrg    mode &= ~SC1200_TVOUT_YC_DELAY_MASK;
477f29dbc25Smrg    switch (delay) {
478f29dbc25Smrg    case TV_YC_DELAY_NONE:
479f29dbc25Smrg        WRITE_VID32(SC1200_TVOUT_HORZ_PRE_ENCODER_SCALE,
48004007ebaSmrg                    mode | SC1200_TVOUT_YC_DELAY_NONE);
481f29dbc25Smrg        break;
482f29dbc25Smrg    case TV_Y_DELAY_ONE_PIXEL:
483f29dbc25Smrg        WRITE_VID32(SC1200_TVOUT_HORZ_PRE_ENCODER_SCALE,
48404007ebaSmrg                    mode | SC1200_TVOUT_Y_DELAY_ONE_PIXEL);
485f29dbc25Smrg        break;
486f29dbc25Smrg    case TV_C_DELAY_ONE_PIXEL:
487f29dbc25Smrg        WRITE_VID32(SC1200_TVOUT_HORZ_PRE_ENCODER_SCALE,
48804007ebaSmrg                    mode | SC1200_TVOUT_C_DELAY_ONE_PIXEL);
489f29dbc25Smrg        break;
490f29dbc25Smrg    case TV_C_DELAY_TWO_PIXELS:
491f29dbc25Smrg        WRITE_VID32(SC1200_TVOUT_HORZ_PRE_ENCODER_SCALE,
49204007ebaSmrg                    mode | SC1200_TVOUT_C_DELAY_TWO_PIXELS);
493f29dbc25Smrg        break;
494f29dbc25Smrg    default:
495f29dbc25Smrg        return GFX_STATUS_BAD_PARAMETER;
496f29dbc25Smrg    }
497f29dbc25Smrg    return (GFX_STATUS_OK);
498f29dbc25Smrg}
499f29dbc25Smrg
500f29dbc25Smrg/*----------------------------------------------------------------------------
501f29dbc25Smrg * gfx_set_tvenc_reset_interval
502f29dbc25Smrg *
503f29dbc25Smrg * This routine sets the interval between external resets of the TV encoder
504f29dbc25Smrg * timing generator by the TV out.
505f29dbc25Smrg *----------------------------------------------------------------------------
506f29dbc25Smrg */
507f29dbc25Smrg#if GFX_TV_DYNAMIC
508f29dbc25Smrgint
509f29dbc25Smrgsc1200_set_tvenc_reset_interval(int interval)
510f29dbc25Smrg#else
511f29dbc25Smrgint
512f29dbc25Smrggfx_set_tvenc_reset_interval(int interval)
513f29dbc25Smrg#endif
514f29dbc25Smrg{
515f29dbc25Smrg    unsigned long value;
516f29dbc25Smrg
517f29dbc25Smrg    value = READ_VID32(SC1200_TVOUT_HORZ_SCALING);
518f29dbc25Smrg    value &= ~SC1200_TVENC_EXTERNAL_RESET_INTERVAL_MASK;
519f29dbc25Smrg    switch (interval) {
520f29dbc25Smrg    case TVENC_RESET_EVERY_ODD_FIELD:
521f29dbc25Smrg        WRITE_VID32(SC1200_TVOUT_HORZ_SCALING,
52204007ebaSmrg                    value | SC1200_TVENC_EXTERNAL_RESET_EVERY_ODD_FIELD);
523f29dbc25Smrg        break;
524f29dbc25Smrg    case TVENC_RESET_EVERY_EVEN_FIELD:
525f29dbc25Smrg        WRITE_VID32(SC1200_TVOUT_HORZ_SCALING,
52604007ebaSmrg                    value | SC1200_TVENC_EXTERNAL_RESET_EVERY_EVEN_FIELD);
527f29dbc25Smrg        break;
528f29dbc25Smrg    case TVENC_RESET_NEXT_ODD_FIELD:
529f29dbc25Smrg        WRITE_VID32(SC1200_TVOUT_HORZ_SCALING,
53004007ebaSmrg                    value | SC1200_TVENC_EXTERNAL_RESET_NEXT_ODD_FIELD);
531f29dbc25Smrg        break;
532f29dbc25Smrg    case TVENC_RESET_NEXT_EVEN_FIELD:
533f29dbc25Smrg        WRITE_VID32(SC1200_TVOUT_HORZ_SCALING,
53404007ebaSmrg                    value | SC1200_TVENC_EXTERNAL_RESET_NEXT_EVEN_FIELD);
535f29dbc25Smrg        break;
536f29dbc25Smrg    case TVENC_RESET_EVERY_FIELD:
537f29dbc25Smrg        WRITE_VID32(SC1200_TVOUT_HORZ_SCALING,
53804007ebaSmrg                    value | SC1200_TVENC_EXTERNAL_RESET_EVERY_FIELD);
539f29dbc25Smrg        break;
540f29dbc25Smrg    case TVENC_RESET_EVERY_X_ODD_FIELDS:
541f29dbc25Smrg    case TVENC_RESET_EVERY_X_EVEN_FIELDS:
542f29dbc25Smrg        return GFX_STATUS_UNSUPPORTED;
543f29dbc25Smrg    default:
544f29dbc25Smrg        return GFX_STATUS_BAD_PARAMETER;
545f29dbc25Smrg    }
546f29dbc25Smrg    return (GFX_STATUS_OK);
547f29dbc25Smrg}
548f29dbc25Smrg
549f29dbc25Smrg/*----------------------------------------------------------------------------
550f29dbc25Smrg * gfx_set_tv_cc_enable
551f29dbc25Smrg *
552f29dbc25Smrg * This routine enables or disables the use of the hardware CC registers
553f29dbc25Smrg * in the TV encoder.
554f29dbc25Smrg *----------------------------------------------------------------------------
555f29dbc25Smrg */
556f29dbc25Smrg#if GFX_TV_DYNAMIC
557f29dbc25Smrgint
558f29dbc25Smrgsc1200_set_tv_cc_enable(int enable)
559f29dbc25Smrg#else
560f29dbc25Smrgint
561f29dbc25Smrggfx_set_tv_cc_enable(int enable)
562f29dbc25Smrg#endif
563f29dbc25Smrg{
564f29dbc25Smrg    unsigned long value;
565f29dbc25Smrg
566f29dbc25Smrg    value = READ_VID32(SC1200_TVENC_CC_CONTROL);
567f29dbc25Smrg    value &= ~(0x0005F);
568f29dbc25Smrg    if (enable)
569f29dbc25Smrg        value |= 0x51;
570f29dbc25Smrg    WRITE_VID32(SC1200_TVENC_CC_CONTROL, value);
571f29dbc25Smrg    return (0);
572f29dbc25Smrg}
573f29dbc25Smrg
574f29dbc25Smrg/*---------------------------------------------------------------------------
575f29dbc25Smrg * gfx_set_tv_display
576f29dbc25Smrg *
577f29dbc25Smrg * This routine sets the timings in the display controller to support a
578f29dbc25Smrg * TV resolution.
579f29dbc25Smrg *---------------------------------------------------------------------------
580f29dbc25Smrg */
581f29dbc25Smrg#if GFX_TV_DYNAMIC
582f29dbc25Smrgint
583f29dbc25Smrgsc1200_set_tv_display(int width, int height)
584f29dbc25Smrg#else
585f29dbc25Smrgint
586f29dbc25Smrggfx_set_tv_display(int width, int height)
587f29dbc25Smrg#endif
588f29dbc25Smrg{
589f29dbc25Smrg    DISPLAYMODE *pMode;
590f29dbc25Smrg    unsigned int i;
591f29dbc25Smrg
592f29dbc25Smrg    for (i = 0; i < NUM_TV_MODES; i++) {
593f29dbc25Smrg        pMode = &TVTimings[i];
59404007ebaSmrg        if ((unsigned) width == pMode->hactive
59504007ebaSmrg            && (unsigned) height == pMode->vactive)
596f29dbc25Smrg            break;
597f29dbc25Smrg    }
598f29dbc25Smrg
599f29dbc25Smrg    if (i == NUM_TV_MODES)
600f29dbc25Smrg        return 0;
601f29dbc25Smrg
602f29dbc25Smrg    gfx_set_display_timings(gfx_get_display_bpp(),
60304007ebaSmrg                            (unsigned short) pMode->flags, pMode->hactive,
60404007ebaSmrg                            pMode->hblankstart, pMode->hsyncstart,
60504007ebaSmrg                            pMode->hsyncend, pMode->hblankend, pMode->htotal,
60604007ebaSmrg                            pMode->vactive, pMode->vblankstart,
60704007ebaSmrg                            pMode->vsyncstart, pMode->vsyncend,
60804007ebaSmrg                            pMode->vblankend, pMode->vtotal, pMode->frequency);
609f29dbc25Smrg
610f29dbc25Smrg    return 1;
611f29dbc25Smrg}
612f29dbc25Smrg
613f29dbc25Smrg/*----------------------------------------------------------------------------
614f29dbc25Smrg * cc_add_parity_bit
615f29dbc25Smrg *
616f29dbc25Smrg * This routine adds the (odd) parity bit to the data character.
617f29dbc25Smrg *----------------------------------------------------------------------------
618f29dbc25Smrg */
619f29dbc25Smrgunsigned char
620f29dbc25Smrgcc_add_parity_bit(unsigned char data)
621f29dbc25Smrg{
622f29dbc25Smrg    int i, num = 0;
623f29dbc25Smrg    unsigned char d = data;
624f29dbc25Smrg
625f29dbc25Smrg    for (i = 0; i < 7; i++) {
626f29dbc25Smrg        if (d & 0x1)
627f29dbc25Smrg            num++;
628f29dbc25Smrg        d >>= 1;
629f29dbc25Smrg    }
630f29dbc25Smrg    if (num & 0x1)
631f29dbc25Smrg        return (data & ~0x80);
632f29dbc25Smrg    else
633f29dbc25Smrg        return (data | 0x80);
634f29dbc25Smrg}
635f29dbc25Smrg
636f29dbc25Smrg/*----------------------------------------------------------------------------
637f29dbc25Smrg * gfx_set_tv_cc_data
638f29dbc25Smrg *
639f29dbc25Smrg * This routine writes the two specified characters to the CC data register
640f29dbc25Smrg * of the TV encoder.
641f29dbc25Smrg *----------------------------------------------------------------------------
642f29dbc25Smrg */
643f29dbc25Smrg#if GFX_TV_DYNAMIC
644f29dbc25Smrgint
645f29dbc25Smrgsc1200_set_tv_cc_data(unsigned char data1, unsigned char data2)
646f29dbc25Smrg#else
647f29dbc25Smrgint
648f29dbc25Smrggfx_set_tv_cc_data(unsigned char data1, unsigned char data2)
649f29dbc25Smrg#endif
650f29dbc25Smrg{
651f29dbc25Smrg    unsigned long value;
652f29dbc25Smrg
653f29dbc25Smrg    value = cc_add_parity_bit(data1) | (cc_add_parity_bit(data2) << 8);
654f29dbc25Smrg    WRITE_VID32(SC1200_TVENC_CC_DATA, value);
655f29dbc25Smrg    return (0);
656f29dbc25Smrg}
657f29dbc25Smrg
658f29dbc25Smrg/*---------------------------------------------------------------------------
659f29dbc25Smrg * gfx_test_tvout_odd_field
660f29dbc25Smrg *
661f29dbc25Smrg * This routine returns 1 if the current TVout field is odd. Otherwise returns
662f29dbc25Smrg * 0.
663f29dbc25Smrg *---------------------------------------------------------------------------
664f29dbc25Smrg */
665f29dbc25Smrg#if GFX_TV_DYNAMIC
666f29dbc25Smrgint
667f29dbc25Smrgsc1200_test_tvout_odd_field(void)
668f29dbc25Smrg#else
669f29dbc25Smrgint
670f29dbc25Smrggfx_test_tvout_odd_field(void)
671f29dbc25Smrg#endif
672f29dbc25Smrg{
673f29dbc25Smrg    unsigned long debug = READ_VID32(SC1200_TVOUT_DEBUG);
674f29dbc25Smrg
675f29dbc25Smrg    WRITE_VID32(SC1200_TVOUT_DEBUG, debug | SC1200_TVOUT_FIELD_STATUS_TV);
676f29dbc25Smrg    if (READ_VID32(SC1200_TVOUT_DEBUG) & SC1200_TVOUT_FIELD_STATUS_EVEN)
677f29dbc25Smrg        return (0);
678f29dbc25Smrg    else
679f29dbc25Smrg        return (1);
680f29dbc25Smrg}
681f29dbc25Smrg
682f29dbc25Smrg/*---------------------------------------------------------------------------
683f29dbc25Smrg * gfx_test_tvenc_odd_field
684f29dbc25Smrg *
685f29dbc25Smrg * This routine returns 1 if the current TV encoder field is odd. Otherwise
686f29dbc25Smrg * returns 0.
687f29dbc25Smrg *---------------------------------------------------------------------------
688f29dbc25Smrg */
689f29dbc25Smrg#if GFX_TV_DYNAMIC
690f29dbc25Smrgint
691f29dbc25Smrgsc1200_test_tvenc_odd_field(void)
692f29dbc25Smrg#else
693f29dbc25Smrgint
694f29dbc25Smrggfx_test_tvenc_odd_field(void)
695f29dbc25Smrg#endif
696f29dbc25Smrg{
697f29dbc25Smrg    unsigned long debug = READ_VID32(SC1200_TVOUT_DEBUG);
698f29dbc25Smrg
699f29dbc25Smrg    WRITE_VID32(SC1200_TVOUT_DEBUG, debug & ~SC1200_TVOUT_FIELD_STATUS_TV);
700f29dbc25Smrg    if (READ_VID32(SC1200_TVOUT_DEBUG) & SC1200_TVOUT_FIELD_STATUS_EVEN)
701f29dbc25Smrg        return (0);
702f29dbc25Smrg    else
703f29dbc25Smrg        return (1);
704f29dbc25Smrg}
705f29dbc25Smrg
706f29dbc25Smrg/*----------------------------------------------------------------------------
707f29dbc25Smrg * gfx_set_tv_field_status_invert
708f29dbc25Smrg *
709f29dbc25Smrg * This routines determines whether the tvout/tvencoder field status bit is
710f29dbc25Smrg * inverted (enable = 1) or not (enable = 0).
711f29dbc25Smrg *----------------------------------------------------------------------------
712f29dbc25Smrg */
713f29dbc25Smrg#if GFX_TV_DYNAMIC
714f29dbc25Smrgint
715f29dbc25Smrgsc1200_set_tv_field_status_invert(int enable)
716f29dbc25Smrg#else
717f29dbc25Smrgint
718f29dbc25Smrggfx_set_tv_field_status_invert(int enable)
719f29dbc25Smrg#endif
720f29dbc25Smrg{
721f29dbc25Smrg    unsigned long value;
722f29dbc25Smrg
723f29dbc25Smrg    value = READ_VID32(SC1200_TVOUT_DEBUG);
724f29dbc25Smrg
725f29dbc25Smrg    if (enable) {
726f29dbc25Smrg        value |= SC1200_TVOUT_FIELD_STATUS_INVERT;
72704007ebaSmrg    }
72804007ebaSmrg    else {
729f29dbc25Smrg        value &= ~(SC1200_TVOUT_FIELD_STATUS_INVERT);
730f29dbc25Smrg    }
731f29dbc25Smrg
732f29dbc25Smrg    WRITE_VID32(SC1200_TVOUT_DEBUG, value);
733f29dbc25Smrg
734f29dbc25Smrg    return (GFX_STATUS_OK);
735f29dbc25Smrg}
736f29dbc25Smrg
737f29dbc25Smrg/*---------------------------------------------------------------------------
738f29dbc25Smrg * gfx_get_tv_vphase
739f29dbc25Smrg *
740f29dbc25Smrg * This routine returns the tv encoder vertical phase.
741f29dbc25Smrg *---------------------------------------------------------------------------
742f29dbc25Smrg */
743f29dbc25Smrg#if GFX_TV_DYNAMIC
744f29dbc25Smrgint
745f29dbc25Smrgsc1200_get_tv_vphase(void)
746f29dbc25Smrg#else
747f29dbc25Smrgint
748f29dbc25Smrggfx_get_tv_vphase(void)
749f29dbc25Smrg#endif
750f29dbc25Smrg{
751f29dbc25Smrg    unsigned long mode = READ_VID32(SC1200_TVENC_TIM_CTRL_1);
752f29dbc25Smrg
75304007ebaSmrg    return (int) ((mode & SC1200_TVENC_VPHASE_MASK) >> SC1200_TVENC_VPHASE_POS);
754f29dbc25Smrg}
755f29dbc25Smrg
756f29dbc25Smrg/*---------------------------------------------------------------------------
757f29dbc25Smrg * gfx_get_tv_enable
758f29dbc25Smrg *
759f29dbc25Smrg * This routine returns the current tv enable status
760f29dbc25Smrg *---------------------------------------------------------------------------
761f29dbc25Smrg */
762f29dbc25Smrg#if GFX_TV_DYNAMIC
763f29dbc25Smrgint
764f29dbc25Smrgsc1200_get_tv_enable(unsigned int *p_on)
765f29dbc25Smrg#else
766f29dbc25Smrgint
767f29dbc25Smrggfx_get_tv_enable(unsigned int *p_on)
768f29dbc25Smrg#endif
769f29dbc25Smrg{
770f29dbc25Smrg    unsigned long control = READ_VID32(SC1200_TVENC_DAC_CONTROL);
771f29dbc25Smrg
77204007ebaSmrg    *p_on = (unsigned int) (!(control & SC1200_TVENC_POWER_DOWN));
773f29dbc25Smrg
774f29dbc25Smrg    return GFX_STATUS_OK;
775f29dbc25Smrg}
776f29dbc25Smrg
777f29dbc25Smrg/*---------------------------------------------------------------------------
778f29dbc25Smrg * gfx_get_tv_output
779f29dbc25Smrg *
780f29dbc25Smrg * This routine returns the current programmed TV output type.  It does not
781f29dbc25Smrg * detect invalid configurations.
782f29dbc25Smrg *---------------------------------------------------------------------------
783f29dbc25Smrg */
784f29dbc25Smrg#if GFX_TV_DYNAMIC
785f29dbc25Smrgint
786f29dbc25Smrgsc1200_get_tv_output(void)
787f29dbc25Smrg#else
788f29dbc25Smrgint
789f29dbc25Smrggfx_get_tv_output(void)
790f29dbc25Smrg#endif
791f29dbc25Smrg{
792f29dbc25Smrg    unsigned long ctrl2, ctrl3;
793f29dbc25Smrg    int format = 0;
794f29dbc25Smrg
795f29dbc25Smrg    ctrl2 = READ_VID32(SC1200_TVENC_TIM_CTRL_2);
796f29dbc25Smrg    ctrl3 = READ_VID32(SC1200_TVENC_TIM_CTRL_3);
797f29dbc25Smrg
798f29dbc25Smrg    if ((ctrl2 & SC1200_TVENC_CFS_MASK) == SC1200_TVENC_CFS_SVIDEO)
799f29dbc25Smrg        format = TV_OUTPUT_S_VIDEO;
800f29dbc25Smrg    else if (ctrl2 & SC1200_TVENC_OUTPUT_YCBCR)
801f29dbc25Smrg        format = TV_OUTPUT_YUV;
802f29dbc25Smrg    else if ((ctrl2 & SC1200_TVENC_CFS_MASK) == SC1200_TVENC_CFS_CVBS) {
803f29dbc25Smrg        if (ctrl3 & SC1200_TVENC_CM)
804f29dbc25Smrg            format = TV_OUTPUT_SCART;
805f29dbc25Smrg        else
806f29dbc25Smrg            format = TV_OUTPUT_COMPOSITE;
807f29dbc25Smrg    }
808f29dbc25Smrg
809f29dbc25Smrg    return format;
810f29dbc25Smrg}
811f29dbc25Smrg
812f29dbc25Smrg/*---------------------------------------------------------------------------
813f29dbc25Smrg * gfx_get_tv_mode_count
814f29dbc25Smrg *
815f29dbc25Smrg * This routine returns the number of valid TV out resolutions.
816f29dbc25Smrg *---------------------------------------------------------------------------
817f29dbc25Smrg */
818f29dbc25Smrg#if GFX_TV_DYNAMIC
819f29dbc25Smrgint
820f29dbc25Smrgsc1200_get_tv_mode_count(TVStandardType format)
821f29dbc25Smrg#else
822f29dbc25Smrgint
823f29dbc25Smrggfx_get_tv_mode_count(TVStandardType format)
824f29dbc25Smrg#endif
825f29dbc25Smrg{
826f29dbc25Smrg    unsigned int mode, count = 0;
827f29dbc25Smrg    unsigned long flag;
828f29dbc25Smrg
829f29dbc25Smrg    switch (format) {
830f29dbc25Smrg    case TV_STANDARD_NTSC:
831f29dbc25Smrg        flag = GFX_MODE_TV_NTSC;
832f29dbc25Smrg        break;
833f29dbc25Smrg    case TV_STANDARD_PAL:
834f29dbc25Smrg        flag = GFX_MODE_TV_PAL;
835f29dbc25Smrg        break;
836f29dbc25Smrg    default:
837f29dbc25Smrg        return 0;
838f29dbc25Smrg    }
839f29dbc25Smrg
840f29dbc25Smrg    for (mode = 0; mode < NUM_TV_MODES; mode++) {
841f29dbc25Smrg        if (TVTimings[mode].flags & flag)
842f29dbc25Smrg            count++;
843f29dbc25Smrg    }
844f29dbc25Smrg
845f29dbc25Smrg    return count;
846f29dbc25Smrg}
847f29dbc25Smrg
848f29dbc25Smrg/*---------------------------------------------------------------------------
849f29dbc25Smrg * gfx_get_tv_display_mode
850f29dbc25Smrg *
851f29dbc25Smrg * This routine returns the current TV display parameters.
852f29dbc25Smrg *---------------------------------------------------------------------------
853f29dbc25Smrg */
854f29dbc25Smrg#if GFX_TV_DYNAMIC
855f29dbc25Smrgint
856f29dbc25Smrgsc1200_get_tv_display_mode(int *width, int *height, int *bpp, int *hz)
857f29dbc25Smrg#else
858f29dbc25Smrgint
859f29dbc25Smrggfx_get_tv_display_mode(int *width, int *height, int *bpp, int *hz)
860f29dbc25Smrg#endif
861f29dbc25Smrg{
862f29dbc25Smrg    unsigned long frequency;
863f29dbc25Smrg    unsigned long mode, flags;
864f29dbc25Smrg
865f29dbc25Smrg    *width = gfx_get_hactive();
866f29dbc25Smrg    *height = gfx_get_vactive();
867f29dbc25Smrg    *bpp = gfx_get_display_bpp();
868f29dbc25Smrg    frequency = gfx_get_clock_frequency();
869f29dbc25Smrg
870f29dbc25Smrg    for (mode = 0; mode < NUM_TV_MODES; mode++) {
87104007ebaSmrg        if (TVTimings[mode].hactive == (unsigned short) (*width) &&
87204007ebaSmrg            TVTimings[mode].vactive == (unsigned short) (*height) &&
873f29dbc25Smrg            TVTimings[mode].frequency == frequency) {
874f29dbc25Smrg            flags = TVTimings[mode].flags;
875f29dbc25Smrg
876f29dbc25Smrg            if (flags & GFX_MODE_TV_NTSC)
877f29dbc25Smrg                *hz = 60;
878f29dbc25Smrg            else if (flags & GFX_MODE_TV_PAL)
879f29dbc25Smrg                *hz = 50;
880f29dbc25Smrg            else
881f29dbc25Smrg                *hz = 0;
882f29dbc25Smrg            return (1);
883f29dbc25Smrg        }
884f29dbc25Smrg    }
885f29dbc25Smrg
886f29dbc25Smrg    return -1;
887f29dbc25Smrg}
888f29dbc25Smrg
889f29dbc25Smrg/*---------------------------------------------------------------------------
890f29dbc25Smrg * gfx_get_tv_display_mode_frequency
891f29dbc25Smrg *
892f29dbc25Smrg * This routine returns the PLL frequency of a given TV mode.
893f29dbc25Smrg *---------------------------------------------------------------------------
894f29dbc25Smrg */
895f29dbc25Smrg#if GFX_TV_DYNAMIC
896f29dbc25Smrgint
897f29dbc25Smrgsc1200_get_tv_display_mode_frequency(unsigned short width,
89804007ebaSmrg                                     unsigned short height,
89904007ebaSmrg                                     TVStandardType format, int *frequency)
900f29dbc25Smrg#else
901f29dbc25Smrgint
902f29dbc25Smrggfx_get_tv_display_mode_frequency(unsigned short width, unsigned short height,
90304007ebaSmrg                                  TVStandardType format, int *frequency)
904f29dbc25Smrg#endif
905f29dbc25Smrg{
906f29dbc25Smrg    unsigned long mode, flag;
907f29dbc25Smrg    int retval = -1;
908f29dbc25Smrg
909f29dbc25Smrg    *frequency = 0;
910f29dbc25Smrg
911f29dbc25Smrg    switch (format) {
912f29dbc25Smrg    case TV_STANDARD_NTSC:
913f29dbc25Smrg        flag = GFX_MODE_TV_NTSC;
914f29dbc25Smrg        break;
915f29dbc25Smrg    case TV_STANDARD_PAL:
916f29dbc25Smrg        flag = GFX_MODE_TV_PAL;
917f29dbc25Smrg        break;
918f29dbc25Smrg    default:
919f29dbc25Smrg        return -1;
920f29dbc25Smrg    }
921f29dbc25Smrg
922f29dbc25Smrg    for (mode = 0; mode < NUM_TV_MODES; mode++) {
923f29dbc25Smrg        if ((TVTimings[mode].hactive == width) &&
924f29dbc25Smrg            (TVTimings[mode].vactive == height) &&
925f29dbc25Smrg            (TVTimings[mode].flags & flag)) {
926f29dbc25Smrg            *frequency = TVTimings[mode].frequency;
927f29dbc25Smrg            retval = 1;
928f29dbc25Smrg        }
929f29dbc25Smrg    }
930f29dbc25Smrg    return retval;
931f29dbc25Smrg}
932f29dbc25Smrg
933f29dbc25Smrg/*---------------------------------------------------------------------------
934f29dbc25Smrg * gfx_is_tv_display_mode_supported
935f29dbc25Smrg *
936f29dbc25Smrg * Returns >= 0 if the mode is available, -1 if the mode could not be found
937f29dbc25Smrg *---------------------------------------------------------------------------
938f29dbc25Smrg */
939f29dbc25Smrg#if GFX_TV_DYNAMIC
940f29dbc25Smrgint
941f29dbc25Smrgsc1200_is_tv_display_mode_supported(unsigned short width,
94204007ebaSmrg                                    unsigned short height,
94304007ebaSmrg                                    TVStandardType format)
944f29dbc25Smrg#else
945f29dbc25Smrgint
946f29dbc25Smrggfx_is_tv_display_mode_supported(unsigned short width, unsigned short height,
94704007ebaSmrg                                 TVStandardType format)
948f29dbc25Smrg#endif
949f29dbc25Smrg{
950f29dbc25Smrg    unsigned long mode, flag;
951f29dbc25Smrg
952f29dbc25Smrg    switch (format) {
953f29dbc25Smrg    case TV_STANDARD_NTSC:
954f29dbc25Smrg        flag = GFX_MODE_TV_NTSC;
955f29dbc25Smrg        break;
956f29dbc25Smrg    case TV_STANDARD_PAL:
957f29dbc25Smrg        flag = GFX_MODE_TV_PAL;
958f29dbc25Smrg        break;
959f29dbc25Smrg    default:
960f29dbc25Smrg        return -1;
961f29dbc25Smrg    }
962f29dbc25Smrg
963f29dbc25Smrg    for (mode = 0; mode < NUM_TV_MODES; mode++) {
964f29dbc25Smrg        if (TVTimings[mode].hactive == width &&
965f29dbc25Smrg            TVTimings[mode].vactive == height &&
966f29dbc25Smrg            (TVTimings[mode].flags & flag)) {
96704007ebaSmrg            return ((int) mode);
968f29dbc25Smrg        }
969f29dbc25Smrg    }
970f29dbc25Smrg
971f29dbc25Smrg    return -1;
972f29dbc25Smrg}
973f29dbc25Smrg
974f29dbc25Smrg/* END OF FILE */
975