tv_1200.c revision 71d7fec4
1/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nsc/gfx/tv_1200.c,v 1.1 2002/12/10 15:12:27 alanh Exp $ */ 2/* 3 * $Workfile: tv_1200.c $ 4 * 5 * This file contains routines to control the SC1200 TVOUT and TV encoder. 6 * 7 * NSC_LIC_ALTERNATIVE_PREAMBLE 8 * 9 * Revision 1.0 10 * 11 * National Semiconductor Alternative GPL-BSD License 12 * 13 * National Semiconductor Corporation licenses this software 14 * ("Software"): 15 * 16 * Durango 17 * 18 * under one of the two following licenses, depending on how the 19 * Software is received by the Licensee. 20 * 21 * If this Software is received as part of the Linux Framebuffer or 22 * other GPL licensed software, then the GPL license designated 23 * NSC_LIC_GPL applies to this Software; in all other circumstances 24 * then the BSD-style license designated NSC_LIC_BSD shall apply. 25 * 26 * END_NSC_LIC_ALTERNATIVE_PREAMBLE */ 27 28/* NSC_LIC_BSD 29 * 30 * National Semiconductor Corporation Open Source License for Durango 31 * 32 * (BSD License with Export Notice) 33 * 34 * Copyright (c) 1999-2001 35 * National Semiconductor Corporation. 36 * All rights reserved. 37 * 38 * Redistribution and use in source and binary forms, with or without 39 * modification, are permitted provided that the following conditions 40 * are met: 41 * 42 * * Redistributions of source code must retain the above copyright 43 * notice, this list of conditions and the following disclaimer. 44 * 45 * * Redistributions in binary form must reproduce the above 46 * copyright notice, this list of conditions and the following 47 * disclaimer in the documentation and/or other materials provided 48 * with the distribution. 49 * 50 * * Neither the name of the National Semiconductor Corporation nor 51 * the names of its contributors may be used to endorse or promote 52 * products derived from this software without specific prior 53 * written permission. 54 * 55 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 56 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 57 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 58 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 59 * NATIONAL SEMICONDUCTOR CORPORATION OR CONTRIBUTORS BE LIABLE FOR ANY 60 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 61 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 62 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 63 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 64 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE, 65 * INTELLECTUAL PROPERTY INFRINGEMENT, OR OTHERWISE) ARISING IN ANY WAY 66 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 67 * OF SUCH DAMAGE. 68 * 69 * EXPORT LAWS: THIS LICENSE ADDS NO RESTRICTIONS TO THE EXPORT LAWS OF 70 * YOUR JURISDICTION. It is licensee's responsibility to comply with 71 * any export regulations applicable in licensee's jurisdiction. Under 72 * CURRENT (2001) U.S. export regulations this software 73 * is eligible for export from the U.S. and can be downloaded by or 74 * otherwise exported or reexported worldwide EXCEPT to U.S. embargoed 75 * destinations which include Cuba, Iraq, Libya, North Korea, Iran, 76 * Syria, Sudan, Afghanistan and any other country to which the U.S. 77 * has embargoed goods and services. 78 * 79 * END_NSC_LIC_BSD */ 80 81/* NSC_LIC_GPL 82 * 83 * National Semiconductor Corporation Gnu General Public License for Durango 84 * 85 * (GPL License with Export Notice) 86 * 87 * Copyright (c) 1999-2001 88 * National Semiconductor Corporation. 89 * All rights reserved. 90 * 91 * Redistribution and use in source and binary forms, with or without 92 * modification, are permitted under the terms of the GNU General 93 * Public License as published by the Free Software Foundation; either 94 * version 2 of the License, or (at your option) any later version 95 * 96 * In addition to the terms of the GNU General Public License, neither 97 * the name of the National Semiconductor Corporation nor the names of 98 * its contributors may be used to endorse or promote products derived 99 * from this software without specific prior written permission. 100 * 101 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 102 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 103 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 104 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 105 * NATIONAL SEMICONDUCTOR CORPORATION OR CONTRIBUTORS BE LIABLE FOR ANY 106 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 107 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 108 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 109 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 110 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE, 111 * INTELLECTUAL PROPERTY INFRINGEMENT, OR OTHERWISE) ARISING IN ANY WAY 112 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 113 * OF SUCH DAMAGE. See the GNU General Public License for more details. 114 * 115 * EXPORT LAWS: THIS LICENSE ADDS NO RESTRICTIONS TO THE EXPORT LAWS OF 116 * YOUR JURISDICTION. It is licensee's responsibility to comply with 117 * any export regulations applicable in licensee's jurisdiction. Under 118 * CURRENT (2001) U.S. export regulations this software 119 * is eligible for export from the U.S. and can be downloaded by or 120 * otherwise exported or reexported worldwide EXCEPT to U.S. embargoed 121 * destinations which include Cuba, Iraq, Libya, North Korea, Iran, 122 * Syria, Sudan, Afghanistan and any other country to which the U.S. 123 * has embargoed goods and services. 124 * 125 * You should have received a copy of the GNU General Public License 126 * along with this file; if not, write to the Free Software Foundation, 127 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 128 * 129 * END_NSC_LIC_GPL */ 130 131int sc1200_set_tv_format(TVStandardType format, GfxOnTVType resolution); 132int sc1200_set_tv_output(int output); 133int sc1200_set_tv_enable(int enable); 134int sc1200_set_tv_flicker_filter(int ff); 135int sc1200_set_tv_sub_carrier_reset(int screset); 136int sc1200_set_tv_vphase(int vphase); 137int sc1200_set_tv_YC_delay(int delay); 138int sc1200_set_tvenc_reset_interval(int interval); 139int sc1200_set_tv_cc_enable(int enable); 140int sc1200_set_tv_cc_data(unsigned char data1, unsigned char data2); 141int sc1200_set_tv_display(int width, int height); 142int sc1200_test_tvout_odd_field(void); 143int sc1200_test_tvenc_odd_field(void); 144int sc1200_set_tv_field_status_invert(int enable); 145int sc1200_get_tv_vphase(void); 146int sc1200_get_tv_enable(unsigned int *p_on); 147int sc1200_get_tv_output(void); 148int sc1200_get_tv_mode_count(TVStandardType format); 149int sc1200_get_tv_display_mode(int *width, int *height, int *bpp, int *hz); 150int sc1200_get_tv_display_mode_frequency(unsigned short width, 151 unsigned short height, 152 TVStandardType format, 153 int *frequency); 154int sc1200_is_tv_display_mode_supported(unsigned short width, 155 unsigned short height, 156 TVStandardType format); 157 158int sc1200_get_tv_standard(unsigned long *p_standard); 159int sc1200_get_available_tv_standards(unsigned long *p_standards); 160int sc1200_set_tv_standard(unsigned long standard); 161int sc1200_get_tv_vga_mode(unsigned long *p_vga_mode); 162int sc1200_get_available_tv_vga_modes(unsigned long *p_vga_modes); 163int sc1200_set_tv_vga_mode(unsigned long vga_mode); 164int sc1200_get_tvout_mode(unsigned long *p_tvout_mode); 165int sc1200_set_tvout_mode(unsigned long tvout_mode); 166int sc1200_get_sharpness(int *p_sharpness); 167int sc1200_set_sharpness(int sharpness); 168int sc1200_get_flicker_filter(int *p_flicker); 169int sc1200_set_flicker_filter(int flicker); 170int sc1200_get_overscan(int *p_x, int *p_y); 171int sc1200_set_overscan(int x, int y); 172int sc1200_get_position(int *p_x, int *p_y); 173int sc1200_set_position(int x, int y); 174int sc1200_get_color(int *p_color); 175int sc1200_set_color(int color); 176int sc1200_get_brightness(int *p_brightness); 177int sc1200_set_brightness(int brightness); 178int sc1200_get_contrast(int *p_contrast); 179int sc1200_set_contrast(int constrast); 180int sc1200_get_yc_filter(unsigned int *p_yc_filter); 181int sc1200_set_yc_filter(unsigned int yc_filter); 182int sc1200_get_aps_trigger_bits(unsigned int *p_trigger_bits); 183int sc1200_set_aps_trigger_bits(unsigned int trigger_bits); 184unsigned char cc_add_parity_bit(unsigned char data); 185 186/*----------------------------------------------------------------------------- 187 * gfx_set_tv_format 188 * 189 * This routine sets the TV encoder registers to the specified format 190 * and resolution. 191 *----------------------------------------------------------------------------- 192 */ 193#if GFX_TV_DYNAMIC 194int 195sc1200_set_tv_format(TVStandardType format, GfxOnTVType resolution) 196#else 197int 198gfx_set_tv_format(TVStandardType format, GfxOnTVType resolution) 199#endif 200{ 201 unsigned long ctrl2, mode; 202 203 /* Save TV output mode */ 204 ctrl2 = 205 READ_VID32(SC1200_TVENC_TIM_CTRL_2) & (SC1200_TVENC_OUTPUT_YCBCR | 206 SC1200_TVENC_CFS_MASK); 207 /* Save flicker filter setting */ 208 mode = READ_VID32(SC1200_TVOUT_HORZ_SCALING) & 209 SC1200_TVOUT_FLICKER_FILTER_MASK; 210 211 switch (format) { 212 case TV_STANDARD_NTSC: 213 /* Horizontal Sync Start is 848 */ 214 /* Horizontal Sync End is 856 */ 215 WRITE_VID32(SC1200_TVOUT_HORZ_SYNC, 0x03580350); 216 /* Vertical Sync Start is 0 */ 217 /* Vertical Sync End is 1 */ 218 /* Vertical Display Start Skew is 1 */ 219 /* Vertical Display End Skew is 1 */ 220 WRITE_VID32(SC1200_TVOUT_VERT_SYNC, 0x05001000); 221 /* Disable vertical down scaling, take all lines */ 222 if (gfx_chip_revision <= SC1200_REV_B3) 223 WRITE_VID32(SC1200_TVOUT_VERT_DOWNSCALE, 0xffffffff); 224 /* Enable video timing */ 225 /* Reset sub carrier every two frames */ 226 /* Disable BLANK */ 227 /* Enable color burst */ 228 /* Add the IRE offset */ 229 /* NTSC color encoding */ 230 /* Video generator timing is 525 lines / 60Hz */ 231 /* Horizontal and Vertical counters are initialized to HPHASE & VPHASE */ 232 /* VPHASE is 2, HPHASE is 0x50 */ 233 WRITE_VID32(SC1200_TVENC_TIM_CTRL_1, 0xa2a01050); 234 /* Increase horizontal blanking interval */ 235 /* Low Water Mark for Y is 0x1F */ 236 /* Low Water Mark for Cb is 0xF */ 237 /* HUE is 0 */ 238 /* SCPHASE is 0xF9 */ 239 WRITE_VID32(SC1200_TVENC_TIM_CTRL_2, 0x9ff000f9 | ctrl2); 240 /* Subcarrier Frequency is 3.579545 MHz */ 241 WRITE_VID32(SC1200_TVENC_SUB_FREQ, 0x21f07c1f); 242 /* VSTART is 18, HSTART is 113 */ 243 WRITE_VID32(SC1200_TVENC_DISP_POS, 0x00120071); 244 /* Display size: HEIGHT is 239, WIDTH is 719 */ 245 WRITE_VID32(SC1200_TVENC_DISP_SIZE, 0x00ef02cf); 246 switch (resolution) { 247 case GFX_ON_TV_SQUARE_PIXELS: 248 if (gfx_chip_revision <= SC1200_REV_B3) { 249 /* Horizontal Display start is 116 */ 250 /* Total number of pixels per line is 857 */ 251 WRITE_VID32(SC1200_TVOUT_HORZ_TIM, 0x00740359); 252 /* HSYNC generated in the TV Encoder module */ 253 /* Interval between resets of TV Encoder is once every odd field */ 254 /* Enable Horizontal interpolation */ 255 /* Enable Horizontal up scaling 9/8 */ 256 /* Disable Horizontal downscale */ 257 WRITE_VID32(SC1200_TVOUT_HORZ_SCALING, 0x10020700 | mode); 258 /* Horizontal display end is 919, i.e. 720 active pixels */ 259 /* Total number of display lines per field is 240 */ 260 WRITE_VID32(SC1200_TVOUT_LINE_END, 0x039700f0); 261 } else { /* Use new scaler available in Rev. C */ 262 /* Horizontal Display start is 111 */ 263 /* Total number of pixels per line is 857 */ 264 WRITE_VID32(SC1200_TVOUT_HORZ_TIM, 0x006f0359); 265 /* HSYNC generated in the TV Encoder module */ 266 /* Interval between resets of TV Encoder is once every odd field */ 267 /* Enable Horizontal interpolation */ 268 /* Disable Horizontal up scaling 9/8 */ 269 /* Disable Horizontal downscale */ 270 WRITE_VID32(SC1200_TVOUT_HORZ_SCALING, 0x10020500 | mode); 271 /* Set Horizontal upscaling to 64/58 (~ 11/10) */ 272 WRITE_VID32(SC1200_TVOUT_HORZ_PRE_ENCODER_SCALE, 0x3A000000); 273 /* Horizontal display end is 900, i.e. 706 active pixels */ 274 /* Total number of display lines per field is 240 */ 275 WRITE_VID32(SC1200_TVOUT_LINE_END, 0x038400f0); 276 } 277 break; 278 case GFX_ON_TV_NO_SCALING: 279 /* Horizontal Display start is 116 */ 280 /* Total number of pixels per line is 857 */ 281 WRITE_VID32(SC1200_TVOUT_HORZ_TIM, 0x00740359); 282 /* HSYNC generated in the TV Encoder module */ 283 /* Interval between resets of TV Encoder is once every odd field */ 284 /* Enable Horizontal interpolation */ 285 /* Disable Horizontal up scaling 9/8 */ 286 /* Disable Horizontal downscale */ 287 WRITE_VID32(SC1200_TVOUT_HORZ_SCALING, 0x10020500 | mode); 288 /* Disable Horizontal scaling (set to 64/64) */ 289 if (gfx_chip_revision >= SC1200_REV_C1) 290 WRITE_VID32(SC1200_TVOUT_HORZ_PRE_ENCODER_SCALE, 0x40000000); 291 /* Horizontal display end is 919, i.e. 720 active pixels */ 292 /* Total number of display lines per field is 240 */ 293 WRITE_VID32(SC1200_TVOUT_LINE_END, 0x039700f0); 294 break; 295 default: 296 return (GFX_STATUS_BAD_PARAMETER); 297 } 298 break; 299 case TV_STANDARD_PAL: 300 /* Horizontal Sync Start is 854 */ 301 /* Horizontal Sync End is 862 */ 302 WRITE_VID32(SC1200_TVOUT_HORZ_SYNC, 0x035e0356); 303 /* Vertical Sync Start is 0 */ 304 /* Vertical Sync End is 1 */ 305 /* Vertical Display Start Skew is 1 */ 306 /* Vertical Display End Skew is 1 */ 307 WRITE_VID32(SC1200_TVOUT_VERT_SYNC, 0x05001000); 308 /* Disable vertical down scaling, take all lines */ 309 if (gfx_chip_revision <= SC1200_REV_B3) 310 WRITE_VID32(SC1200_TVOUT_VERT_DOWNSCALE, 0xffffffff); 311 /* Enable video timing */ 312 /* Never reset sub carrier (should be every 4 frames but doesn't work with genlock) */ 313 /* Disable BLANK */ 314 /* Enable color burst */ 315 /* Do not add the IRE offset */ 316 /* NTSC color encoding */ 317 /* Video generator timing is 625 lines / 50Hz */ 318 /* Horizontal and Vertical counters are initialized to HPHASE & VPHASE */ 319 /* VPHASE is 2, HPHASE is 50 */ 320 WRITE_VID32(SC1200_TVENC_TIM_CTRL_1, 0xB1201050); 321 /* Increase horizontal blanking interval */ 322 /* Low Water Mark for Y is 0x1F */ 323 /* Low Water Mark for Cb is 0xF */ 324 /* HUE is 0 */ 325 /* SCPHASE is 0xD9 */ 326 WRITE_VID32(SC1200_TVENC_TIM_CTRL_2, 0x9ff000d9 | ctrl2); 327 /* Subcarrier Frequency is 4.43361875 MHz */ 328 WRITE_VID32(SC1200_TVENC_SUB_FREQ, 0x2a098acb); 329 /* VSTART is 22, HSTART is 123 */ 330 WRITE_VID32(SC1200_TVENC_DISP_POS, 0x0016007b); 331 /* Display size: HEIGHT is 287, WIDTH is 719 */ 332 WRITE_VID32(SC1200_TVENC_DISP_SIZE, 0x011f02cf); 333 switch (resolution) { 334 case GFX_ON_TV_NO_SCALING: 335 /* Horizontal Display start is 124 */ 336 /* Total number of pixels per line is 863 */ 337 WRITE_VID32(SC1200_TVOUT_HORZ_TIM, 0x007c035f); 338 /* HSYNC generated in the TV Encoder module */ 339 /* Interval between resets of TV Encoder is once every odd field */ 340 /* Enable Horizontal interpolation */ 341 /* Disable Horizontal up scaling 9/8 */ 342 /* Disable Horizontal downscale */ 343 WRITE_VID32(SC1200_TVOUT_HORZ_SCALING, 0x10020500 | mode); 344 /* Disable Horizontal scaling (set to 64/64) */ 345 if (gfx_chip_revision >= SC1200_REV_C1) 346 WRITE_VID32(SC1200_TVOUT_HORZ_PRE_ENCODER_SCALE, 0x40000000); 347 /* Horizontal display end is 924, i.e. 720 active pixels */ 348 /* Total number of display lines per field is 288 */ 349 WRITE_VID32(SC1200_TVOUT_LINE_END, 0x039c0120); 350 break; 351 case GFX_ON_TV_SQUARE_PIXELS: 352 /* Horizontal Display start is 122 */ 353 /* Total number of pixels per line is 863 */ 354 WRITE_VID32(SC1200_TVOUT_HORZ_TIM, 0x007a035f); 355 if (gfx_chip_revision <= SC1200_REV_B3) { 356 /* HSYNC generated in the TV Encoder module */ 357 /* Interval between resets of TV Encoder is once every odd field */ 358 /* Enable Horizontal interpolation */ 359 /* Disable Horizontal up scaling 9/8 */ 360 /* Horizontal downscale m/(m+1), m = 11, (i.e. 11/12 - closest possible to 54/59) */ 361 WRITE_VID32(SC1200_TVOUT_HORZ_SCALING, 0x1002040b | mode); 362 /* Horizontal display end is 906, i.e. 704 active pixels */ 363 /* Total number of display lines per field is 288 */ 364 WRITE_VID32(SC1200_TVOUT_LINE_END, 0x038a0120); 365 } else { 366 /* HSYNC generated in the TV Encoder module */ 367 /* Interval between resets of TV Encoder is once every odd field */ 368 /* Enable Horizontal interpolation */ 369 /* Disable Horizontal up scaling 9/8 */ 370 /* Disable Horizontal downscale */ 371 WRITE_VID32(SC1200_TVOUT_HORZ_SCALING, 0x10020500 | mode); 372 /* Set Horizontal down scaling to 64/70 (closest possible to 54/59) */ 373 WRITE_VID32(SC1200_TVOUT_HORZ_PRE_ENCODER_SCALE, 0x46000000); 374 /* Horizontal display end is 904, i.e. 702 active pixels */ 375 /* Total number of display lines per field is 288 */ 376 WRITE_VID32(SC1200_TVOUT_LINE_END, 0x03880120); 377 } 378 break; 379 default: 380 return (GFX_STATUS_BAD_PARAMETER); 381 } 382 break; 383 default: 384 return (GFX_STATUS_BAD_PARAMETER); 385 } 386 return (GFX_STATUS_OK); 387} 388 389/*----------------------------------------------------------------------------- 390 * gfx_set_tv_output 391 * 392 * This routine sets the TV encoder registers to the specified output type. 393 * Supported output types are : S-VIDEO, Composite, YUV and SCART. 394 *----------------------------------------------------------------------------- 395 */ 396#if GFX_TV_DYNAMIC 397int 398sc1200_set_tv_output(int output) 399#else 400int 401gfx_set_tv_output(int output) 402#endif 403{ 404 unsigned long ctrl2, ctrl3; 405 406 ctrl2 = READ_VID32(SC1200_TVENC_TIM_CTRL_2); 407 ctrl3 = READ_VID32(SC1200_TVENC_TIM_CTRL_3); 408 ctrl2 &= ~(SC1200_TVENC_OUTPUT_YCBCR | SC1200_TVENC_CFS_MASK); 409 ctrl3 &= ~(SC1200_TVENC_CM | SC1200_TVENC_SYNCMODE_MASK | SC1200_TVENC_CS); 410 switch (output) { 411 case TV_OUTPUT_COMPOSITE: 412 /* Analog outputs provide Y, C and CVBS */ 413 /* Chrominance Lowpass filter is 1.3MHz (for composite video output) */ 414 WRITE_VID32(SC1200_TVENC_TIM_CTRL_2, ctrl2 | SC1200_TVENC_CFS_CVBS); 415 WRITE_VID32(SC1200_TVENC_TIM_CTRL_3, ctrl3); 416 break; 417 case TV_OUTPUT_S_VIDEO: 418 /* Analog outputs provide Y, C and CVBS */ 419 /* Chrominance Lowpass filter is 1.8MHz (for S-video output) */ 420 WRITE_VID32(SC1200_TVENC_TIM_CTRL_2, ctrl2 | SC1200_TVENC_CFS_SVIDEO); 421 WRITE_VID32(SC1200_TVENC_TIM_CTRL_3, ctrl3); 422 break; 423 case TV_OUTPUT_YUV: 424 /* Analog outputs provide Y, Cb and Cr */ 425 /* A 7.5 IRE setup is applied to the output */ 426 WRITE_VID32(SC1200_TVENC_TIM_CTRL_2, 427 ctrl2 | SC1200_TVENC_OUTPUT_YCBCR | 428 SC1200_TVENC_CFS_BYPASS); 429 WRITE_VID32(SC1200_TVENC_TIM_CTRL_3, 430 ctrl3 | SC1200_TVENC_CM | SC1200_TVENC_CS); 431 break; 432 case TV_OUTPUT_SCART: 433 /* Analog outputs provide SCART (RGB and CVBS) */ 434 /* Sync is added to green signal */ 435 WRITE_VID32(SC1200_TVENC_TIM_CTRL_2, ctrl2 | SC1200_TVENC_CFS_CVBS); 436 WRITE_VID32(SC1200_TVENC_TIM_CTRL_3, 437 ctrl3 | SC1200_TVENC_CM | SC1200_TVENC_SYNC_ON_GREEN); 438 break; 439 default: 440 return (GFX_STATUS_BAD_PARAMETER); 441 } 442 443 /* Adjusts the internal voltage reference */ 444 ctrl2 = READ_VID32(SC1200_TVENC_DAC_CONTROL); 445 ctrl2 &= ~SC1200_TVENC_TRIM_MASK; 446 447 /* Bypass for issue #926 : Inadequate chroma level of S-Video output */ 448 if ((gfx_chip_revision == SC1200_REV_B3) && (output == TV_OUTPUT_S_VIDEO)) 449 ctrl2 |= 0x7; 450 else 451 ctrl2 |= 0x5; 452 453 WRITE_VID32(SC1200_TVENC_DAC_CONTROL, ctrl2); 454 455 /* Disable 4:2:2 to 4:4:4 converter interpolation */ 456 WRITE_VID32(SC1200_TVOUT_DEBUG, SC1200_TVOUT_CONVERTER_INTERPOLATION); 457 458 return (GFX_STATUS_OK); 459} 460 461/*----------------------------------------------------------------------------- 462 * gfx_set_tv_enable 463 * 464 * This routine enables or disables the TV output. 465 *----------------------------------------------------------------------------- 466 */ 467#if GFX_TV_DYNAMIC 468int 469sc1200_set_tv_enable(int enable) 470#else 471int 472gfx_set_tv_enable(int enable) 473#endif 474{ 475 unsigned long value_tim, value_dac; 476 477 value_tim = READ_VID32(SC1200_TVENC_TIM_CTRL_1); 478 value_dac = READ_VID32(SC1200_TVENC_DAC_CONTROL); 479 480 if (enable) { 481 value_tim |= SC1200_TVENC_VIDEO_TIMING_ENABLE; 482 value_dac &= ~SC1200_TVENC_POWER_DOWN; 483 /* ENABLE GRAPHICS DISPLAY LOGIC IN VIDEO PROCESSOR */ 484 gfx_set_screen_enable(1); 485 } else { 486 value_tim &= ~SC1200_TVENC_VIDEO_TIMING_ENABLE; 487 value_dac |= SC1200_TVENC_POWER_DOWN; 488 /* Do not disable the graphics display logic because it might be needed for CRT */ 489 } 490 491 WRITE_VID32(SC1200_TVENC_TIM_CTRL_1, value_tim); 492 WRITE_VID32(SC1200_TVENC_DAC_CONTROL, value_dac); 493 494 return (GFX_STATUS_OK); 495} 496 497/*----------------------------------------------------------------------------- 498 * gfx_set_tv_flicker_filter 499 * 500 * This routine configures the TV out flicker filter. 501 *----------------------------------------------------------------------------- 502 */ 503#if GFX_TV_DYNAMIC 504int 505sc1200_set_tv_flicker_filter(int ff) 506#else 507int 508gfx_set_tv_flicker_filter(int ff) 509#endif 510{ 511 unsigned long mode; 512 513 mode = READ_VID32(SC1200_TVOUT_HORZ_SCALING); 514 mode &= ~SC1200_TVOUT_FLICKER_FILTER_MASK; 515 switch (ff) { 516 case TV_FLICKER_FILTER_NONE: 517 WRITE_VID32(SC1200_TVOUT_HORZ_SCALING, 518 mode | SC1200_TVOUT_FLICKER_FILTER_DISABLED); 519 break; 520 case TV_FLICKER_FILTER_NORMAL: 521 WRITE_VID32(SC1200_TVOUT_HORZ_SCALING, 522 mode | SC1200_TVOUT_FLICKER_FILTER_FOURTH_HALF_FOURTH); 523 break; 524 case TV_FLICKER_FILTER_INTERLACED: 525 WRITE_VID32(SC1200_TVOUT_HORZ_SCALING, 526 mode | SC1200_TVOUT_FLICKER_FILTER_HALF_ONE_HALF); 527 break; 528 default: 529 return GFX_STATUS_BAD_PARAMETER; 530 } 531 return (GFX_STATUS_OK); 532} 533 534/*----------------------------------------------------------------------------- 535 * gfx_set_tv_sub_carrier_reset 536 * 537 * This routine configures the TV encoder sub carrier reset interval. 538 *----------------------------------------------------------------------------- 539 */ 540#if GFX_TV_DYNAMIC 541int 542sc1200_set_tv_sub_carrier_reset(int screset) 543#else 544int 545gfx_set_tv_sub_carrier_reset(int screset) 546#endif 547{ 548 unsigned long mode; 549 550 mode = READ_VID32(SC1200_TVENC_TIM_CTRL_1); 551 mode &= ~SC1200_TVENC_SUB_CARRIER_RESET_MASK; 552 switch (screset) { 553 case TV_SUB_CARRIER_RESET_NEVER: 554 WRITE_VID32(SC1200_TVENC_TIM_CTRL_1, 555 mode | SC1200_TVENC_SUB_CARRIER_RESET_NEVER); 556 break; 557 case TV_SUB_CARRIER_RESET_EVERY_TWO_LINES: 558 WRITE_VID32(SC1200_TVENC_TIM_CTRL_1, 559 mode | SC1200_TVENC_SUB_CARRIER_RESET_EVERY_TWO_LINES); 560 break; 561 case TV_SUB_CARRIER_RESET_EVERY_TWO_FRAMES: 562 WRITE_VID32(SC1200_TVENC_TIM_CTRL_1, 563 mode | SC1200_TVENC_SUB_CARRIER_RESET_EVERY_TWO_FRAMES); 564 break; 565 case TV_SUB_CARRIER_RESET_EVERY_FOUR_FRAMES: 566 WRITE_VID32(SC1200_TVENC_TIM_CTRL_1, 567 mode | SC1200_TVENC_SUB_CARRIER_RESET_EVERY_FOUR_FRAMES); 568 break; 569 default: 570 return GFX_STATUS_BAD_PARAMETER; 571 } 572 return (GFX_STATUS_OK); 573} 574 575/*----------------------------------------------------------------------------- 576 * gfx_set_tv_vphase 577 * 578 * This routine sets the tv encoder VPHASE value. 579 *----------------------------------------------------------------------------- 580 */ 581#if GFX_TV_DYNAMIC 582int 583sc1200_set_tv_vphase(int vphase) 584#else 585int 586gfx_set_tv_vphase(int vphase) 587#endif 588{ 589 unsigned long mode = READ_VID32(SC1200_TVENC_TIM_CTRL_1); 590 591 mode &= ~SC1200_TVENC_VPHASE_MASK; 592 mode |= (vphase << SC1200_TVENC_VPHASE_POS) & SC1200_TVENC_VPHASE_MASK; 593 WRITE_VID32(SC1200_TVENC_TIM_CTRL_1, mode); 594 return (GFX_STATUS_OK); 595} 596 597/*----------------------------------------------------------------------------- 598 * gfx_set_tv_YC_delay 599 * 600 * This routine configures the TV out Y/C delay. 601 *----------------------------------------------------------------------------- 602 */ 603#if GFX_TV_DYNAMIC 604int 605sc1200_set_tv_YC_delay(int delay) 606#else 607int 608gfx_set_tv_YC_delay(int delay) 609#endif 610{ 611 unsigned long mode; 612 613 /* This feature is implemented in Rev C1 */ 614 if (gfx_chip_revision < SC1200_REV_C1) 615 return (GFX_STATUS_OK); 616 617 mode = READ_VID32(SC1200_TVOUT_HORZ_PRE_ENCODER_SCALE); 618 mode &= ~SC1200_TVOUT_YC_DELAY_MASK; 619 switch (delay) { 620 case TV_YC_DELAY_NONE: 621 WRITE_VID32(SC1200_TVOUT_HORZ_PRE_ENCODER_SCALE, 622 mode | SC1200_TVOUT_YC_DELAY_NONE); 623 break; 624 case TV_Y_DELAY_ONE_PIXEL: 625 WRITE_VID32(SC1200_TVOUT_HORZ_PRE_ENCODER_SCALE, 626 mode | SC1200_TVOUT_Y_DELAY_ONE_PIXEL); 627 break; 628 case TV_C_DELAY_ONE_PIXEL: 629 WRITE_VID32(SC1200_TVOUT_HORZ_PRE_ENCODER_SCALE, 630 mode | SC1200_TVOUT_C_DELAY_ONE_PIXEL); 631 break; 632 case TV_C_DELAY_TWO_PIXELS: 633 WRITE_VID32(SC1200_TVOUT_HORZ_PRE_ENCODER_SCALE, 634 mode | SC1200_TVOUT_C_DELAY_TWO_PIXELS); 635 break; 636 default: 637 return GFX_STATUS_BAD_PARAMETER; 638 } 639 return (GFX_STATUS_OK); 640} 641 642/*----------------------------------------------------------------------------- 643 * gfx_set_tvenc_reset_interval 644 * 645 * This routine sets the interval between external resets of the TV encoder 646 * timing generator by the TV out. 647 *----------------------------------------------------------------------------- 648 */ 649#if GFX_TV_DYNAMIC 650int 651sc1200_set_tvenc_reset_interval(int interval) 652#else 653int 654gfx_set_tvenc_reset_interval(int interval) 655#endif 656{ 657 unsigned long value; 658 659 value = READ_VID32(SC1200_TVOUT_HORZ_SCALING); 660 value &= ~SC1200_TVENC_EXTERNAL_RESET_INTERVAL_MASK; 661 switch (interval) { 662 case TVENC_RESET_EVERY_ODD_FIELD: 663 WRITE_VID32(SC1200_TVOUT_HORZ_SCALING, 664 value | SC1200_TVENC_EXTERNAL_RESET_EVERY_ODD_FIELD); 665 break; 666 case TVENC_RESET_EVERY_EVEN_FIELD: 667 WRITE_VID32(SC1200_TVOUT_HORZ_SCALING, 668 value | SC1200_TVENC_EXTERNAL_RESET_EVERY_EVEN_FIELD); 669 break; 670 case TVENC_RESET_NEXT_ODD_FIELD: 671 WRITE_VID32(SC1200_TVOUT_HORZ_SCALING, 672 value | SC1200_TVENC_EXTERNAL_RESET_NEXT_ODD_FIELD); 673 break; 674 case TVENC_RESET_NEXT_EVEN_FIELD: 675 WRITE_VID32(SC1200_TVOUT_HORZ_SCALING, 676 value | SC1200_TVENC_EXTERNAL_RESET_NEXT_EVEN_FIELD); 677 break; 678 case TVENC_RESET_EVERY_FIELD: 679 WRITE_VID32(SC1200_TVOUT_HORZ_SCALING, 680 value | SC1200_TVENC_EXTERNAL_RESET_EVERY_FIELD); 681 break; 682 case TVENC_RESET_EVERY_X_ODD_FIELDS: 683 case TVENC_RESET_EVERY_X_EVEN_FIELDS: 684 return GFX_STATUS_UNSUPPORTED; 685 default: 686 return GFX_STATUS_BAD_PARAMETER; 687 } 688 return (GFX_STATUS_OK); 689} 690 691/*----------------------------------------------------------------------------- 692 * gfx_set_tv_cc_enable 693 * 694 * This routine enables or disables the use of the hardware CC registers 695 * in the TV encoder. 696 *----------------------------------------------------------------------------- 697 */ 698#if GFX_TV_DYNAMIC 699int 700sc1200_set_tv_cc_enable(int enable) 701#else 702int 703gfx_set_tv_cc_enable(int enable) 704#endif 705{ 706 unsigned long value; 707 708 value = READ_VID32(SC1200_TVENC_CC_CONTROL); 709 value &= ~(0x0005F); 710 if (enable) 711 value |= 0x51; 712 WRITE_VID32(SC1200_TVENC_CC_CONTROL, value); 713 return (0); 714} 715 716/*--------------------------------------------------------------------------- 717 * gfx_set_tv_display 718 * 719 * This routine sets the timings in the display controller to support a 720 * TV resolution. 721 *--------------------------------------------------------------------------- 722 */ 723#if GFX_TV_DYNAMIC 724int 725sc1200_set_tv_display(int width, int height) 726#else 727int 728gfx_set_tv_display(int width, int height) 729#endif 730{ 731 DISPLAYMODE *pMode; 732 unsigned int i; 733 734 for (i = 0; i < NUM_TV_MODES; i++) { 735 pMode = &TVTimings[i]; 736 if ((unsigned)width == pMode->hactive 737 && (unsigned)height == pMode->vactive) 738 break; 739 } 740 741 if (i == NUM_TV_MODES) 742 return 0; 743 744 gfx_set_display_timings(gfx_get_display_bpp(), 745 (unsigned short)pMode->flags, pMode->hactive, 746 pMode->hblankstart, pMode->hsyncstart, 747 pMode->hsyncend, pMode->hblankend, pMode->htotal, 748 pMode->vactive, pMode->vblankstart, 749 pMode->vsyncstart, pMode->vsyncend, 750 pMode->vblankend, pMode->vtotal, pMode->frequency); 751 752 return 1; 753} 754 755/*----------------------------------------------------------------------------- 756 * cc_add_parity_bit 757 * 758 * This routine adds the (odd) parity bit to the data character. 759 *----------------------------------------------------------------------------- 760 */ 761unsigned char 762cc_add_parity_bit(unsigned char data) 763{ 764 int i, num = 0; 765 unsigned char d = data; 766 767 for (i = 0; i < 7; i++) { 768 if (d & 0x1) 769 num++; 770 d >>= 1; 771 } 772 if (num & 0x1) 773 return (data & ~0x80); 774 else 775 return (data | 0x80); 776} 777 778/*----------------------------------------------------------------------------- 779 * gfx_set_tv_cc_data 780 * 781 * This routine writes the two specified characters to the CC data register 782 * of the TV encoder. 783 *----------------------------------------------------------------------------- 784 */ 785#if GFX_TV_DYNAMIC 786int 787sc1200_set_tv_cc_data(unsigned char data1, unsigned char data2) 788#else 789int 790gfx_set_tv_cc_data(unsigned char data1, unsigned char data2) 791#endif 792{ 793 unsigned long value; 794 795 value = cc_add_parity_bit(data1) | (cc_add_parity_bit(data2) << 8); 796 WRITE_VID32(SC1200_TVENC_CC_DATA, value); 797 return (0); 798} 799 800/*--------------------------------------------------------------------------- 801 * gfx_test_tvout_odd_field 802 * 803 * This routine returns 1 if the current TVout field is odd. Otherwise returns 0. 804 *--------------------------------------------------------------------------- 805 */ 806#if GFX_TV_DYNAMIC 807int 808sc1200_test_tvout_odd_field(void) 809#else 810int 811gfx_test_tvout_odd_field(void) 812#endif 813{ 814 unsigned long debug = READ_VID32(SC1200_TVOUT_DEBUG); 815 816 WRITE_VID32(SC1200_TVOUT_DEBUG, debug | SC1200_TVOUT_FIELD_STATUS_TV); 817 if (READ_VID32(SC1200_TVOUT_DEBUG) & SC1200_TVOUT_FIELD_STATUS_EVEN) 818 return (0); 819 else 820 return (1); 821} 822 823/*--------------------------------------------------------------------------- 824 * gfx_test_tvenc_odd_field 825 * 826 * This routine returns 1 if the current TV encoder field is odd. Otherwise returns 0. 827 *--------------------------------------------------------------------------- 828 */ 829#if GFX_TV_DYNAMIC 830int 831sc1200_test_tvenc_odd_field(void) 832#else 833int 834gfx_test_tvenc_odd_field(void) 835#endif 836{ 837 unsigned long debug = READ_VID32(SC1200_TVOUT_DEBUG); 838 839 WRITE_VID32(SC1200_TVOUT_DEBUG, debug & ~SC1200_TVOUT_FIELD_STATUS_TV); 840 if (READ_VID32(SC1200_TVOUT_DEBUG) & SC1200_TVOUT_FIELD_STATUS_EVEN) 841 return (0); 842 else 843 return (1); 844} 845 846/*----------------------------------------------------------------------------- 847 * gfx_set_tv_field_status_invert 848 * 849 * This routines determines whether the tvout/tvencoder field status bit is 850 * inverted (enable = 1) or not (enable = 0). 851 *----------------------------------------------------------------------------- 852 */ 853#if GFX_TV_DYNAMIC 854int 855sc1200_set_tv_field_status_invert(int enable) 856#else 857int 858gfx_set_tv_field_status_invert(int enable) 859#endif 860{ 861 unsigned long value; 862 863 value = READ_VID32(SC1200_TVOUT_DEBUG); 864 865 if (enable) { 866 value |= SC1200_TVOUT_FIELD_STATUS_INVERT; 867 } else { 868 value &= ~(SC1200_TVOUT_FIELD_STATUS_INVERT); 869 } 870 871 WRITE_VID32(SC1200_TVOUT_DEBUG, value); 872 873 return (GFX_STATUS_OK); 874} 875 876/*--------------------------------------------------------------------------- 877 * gfx_get_tv_vphase 878 * 879 * This routine returns the tv encoder vertical phase. 880 *--------------------------------------------------------------------------- 881 */ 882#if GFX_TV_DYNAMIC 883int 884sc1200_get_tv_vphase(void) 885#else 886int 887gfx_get_tv_vphase(void) 888#endif 889{ 890 unsigned long mode = READ_VID32(SC1200_TVENC_TIM_CTRL_1); 891 892 return (int)((mode & SC1200_TVENC_VPHASE_MASK) >> SC1200_TVENC_VPHASE_POS); 893} 894 895/*--------------------------------------------------------------------------- 896 * gfx_get_tv_enable 897 * 898 * This routine returns the current tv enable status 899 *--------------------------------------------------------------------------- 900 */ 901#if GFX_TV_DYNAMIC 902int 903sc1200_get_tv_enable(unsigned int *p_on) 904#else 905int 906gfx_get_tv_enable(unsigned int *p_on) 907#endif 908{ 909 unsigned long control = READ_VID32(SC1200_TVENC_DAC_CONTROL); 910 911 *p_on = (unsigned int)(!(control & SC1200_TVENC_POWER_DOWN)); 912 913 return GFX_STATUS_OK; 914} 915 916/*--------------------------------------------------------------------------- 917 * gfx_get_tv_output 918 * 919 * This routine returns the current programmed TV output type. It does not 920 * detect invalid configurations. 921 *--------------------------------------------------------------------------- 922 */ 923#if GFX_TV_DYNAMIC 924int 925sc1200_get_tv_output(void) 926#else 927int 928gfx_get_tv_output(void) 929#endif 930{ 931 unsigned long ctrl2, ctrl3; 932 int format = 0; 933 934 ctrl2 = READ_VID32(SC1200_TVENC_TIM_CTRL_2); 935 ctrl3 = READ_VID32(SC1200_TVENC_TIM_CTRL_3); 936 937 if ((ctrl2 & SC1200_TVENC_CFS_MASK) == SC1200_TVENC_CFS_SVIDEO) 938 format = TV_OUTPUT_S_VIDEO; 939 else if (ctrl2 & SC1200_TVENC_OUTPUT_YCBCR) 940 format = TV_OUTPUT_YUV; 941 else if ((ctrl2 & SC1200_TVENC_CFS_MASK) == SC1200_TVENC_CFS_CVBS) { 942 if (ctrl3 & SC1200_TVENC_CM) 943 format = TV_OUTPUT_SCART; 944 else 945 format = TV_OUTPUT_COMPOSITE; 946 } 947 948 return format; 949} 950 951/*--------------------------------------------------------------------------- 952 * gfx_get_tv_mode_count 953 * 954 * This routine returns the number of valid TV out resolutions. 955 *--------------------------------------------------------------------------- 956 */ 957#if GFX_TV_DYNAMIC 958int 959sc1200_get_tv_mode_count(TVStandardType format) 960#else 961int 962gfx_get_tv_mode_count(TVStandardType format) 963#endif 964{ 965 unsigned int mode, count = 0; 966 unsigned long flag; 967 968 switch (format) { 969 case TV_STANDARD_NTSC: 970 flag = GFX_MODE_TV_NTSC; 971 break; 972 case TV_STANDARD_PAL: 973 flag = GFX_MODE_TV_PAL; 974 break; 975 default: 976 return 0; 977 } 978 979 for (mode = 0; mode < NUM_TV_MODES; mode++) { 980 if (TVTimings[mode].flags & flag) 981 count++; 982 } 983 984 return count; 985} 986 987/*--------------------------------------------------------------------------- 988 * gfx_get_tv_display_mode 989 * 990 * This routine returns the current TV display parameters. 991 *--------------------------------------------------------------------------- 992 */ 993#if GFX_TV_DYNAMIC 994int 995sc1200_get_tv_display_mode(int *width, int *height, int *bpp, int *hz) 996#else 997int 998gfx_get_tv_display_mode(int *width, int *height, int *bpp, int *hz) 999#endif 1000{ 1001 unsigned long frequency; 1002 unsigned long mode, flags; 1003 1004 *width = gfx_get_hactive(); 1005 *height = gfx_get_vactive(); 1006 *bpp = gfx_get_display_bpp(); 1007 frequency = gfx_get_clock_frequency(); 1008 1009 for (mode = 0; mode < NUM_TV_MODES; mode++) { 1010 if (TVTimings[mode].hactive == (unsigned short)(*width) && 1011 TVTimings[mode].vactive == (unsigned short)(*height) && 1012 TVTimings[mode].frequency == frequency) { 1013 flags = TVTimings[mode].flags; 1014 1015 if (flags & GFX_MODE_TV_NTSC) 1016 *hz = 60; 1017 else if (flags & GFX_MODE_TV_PAL) 1018 *hz = 50; 1019 else 1020 *hz = 0; 1021 return (1); 1022 } 1023 } 1024 1025 return -1; 1026} 1027 1028/*--------------------------------------------------------------------------- 1029 * gfx_get_tv_display_mode_frequency 1030 * 1031 * This routine returns the PLL frequency of a given TV mode. 1032 *--------------------------------------------------------------------------- 1033 */ 1034#if GFX_TV_DYNAMIC 1035int 1036sc1200_get_tv_display_mode_frequency(unsigned short width, 1037 unsigned short height, 1038 TVStandardType format, int *frequency) 1039#else 1040int 1041gfx_get_tv_display_mode_frequency(unsigned short width, unsigned short height, 1042 TVStandardType format, int *frequency) 1043#endif 1044{ 1045 unsigned long mode, flag; 1046 int retval = -1; 1047 1048 *frequency = 0; 1049 1050 switch (format) { 1051 case TV_STANDARD_NTSC: 1052 flag = GFX_MODE_TV_NTSC; 1053 break; 1054 case TV_STANDARD_PAL: 1055 flag = GFX_MODE_TV_PAL; 1056 break; 1057 default: 1058 return -1; 1059 } 1060 1061 for (mode = 0; mode < NUM_TV_MODES; mode++) { 1062 if ((TVTimings[mode].hactive == width) && 1063 (TVTimings[mode].vactive == height) && 1064 (TVTimings[mode].flags & flag)) { 1065 *frequency = TVTimings[mode].frequency; 1066 retval = 1; 1067 } 1068 } 1069 return retval; 1070} 1071 1072/*--------------------------------------------------------------------------- 1073 * gfx_is_tv_display_mode_supported 1074 * 1075 * Returns >= 0 if the mode is available, -1 if the mode could not be found 1076 *--------------------------------------------------------------------------- 1077 */ 1078#if GFX_TV_DYNAMIC 1079int 1080sc1200_is_tv_display_mode_supported(unsigned short width, 1081 unsigned short height, 1082 TVStandardType format) 1083#else 1084int 1085gfx_is_tv_display_mode_supported(unsigned short width, unsigned short height, 1086 TVStandardType format) 1087#endif 1088{ 1089 unsigned long mode, flag; 1090 1091 switch (format) { 1092 case TV_STANDARD_NTSC: 1093 flag = GFX_MODE_TV_NTSC; 1094 break; 1095 case TV_STANDARD_PAL: 1096 flag = GFX_MODE_TV_PAL; 1097 break; 1098 default: 1099 return -1; 1100 } 1101 1102 for (mode = 0; mode < NUM_TV_MODES; mode++) { 1103 if (TVTimings[mode].hactive == width && 1104 TVTimings[mode].vactive == height && 1105 (TVTimings[mode].flags & flag)) { 1106 return ((int)mode); 1107 } 1108 } 1109 1110 return -1; 1111} 1112 1113/* END OF FILE */ 1114