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