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