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