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