1/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nsc/gfx/saa7114.c,v 1.1 2002/12/10 15:12:27 alanh Exp $ */ 2/* 3 * $Workfile: saa7114.c $ 4 * 5 * This file contains routines to control the Philips SAA7114 video decoder. 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 131/*---------------------------*/ 132/* TABLE OF DEFAULT VALUES */ 133/*---------------------------*/ 134 135typedef struct tagGFX_SAA7114_INIT 136{ 137 unsigned char index; 138 unsigned char value; 139} 140GFX_SAA7114_INIT; 141 142/* Task A is for VBI raw data and task B is for video */ 143 144GFX_SAA7114_INIT gfx_saa7114_init_values[] = { 145 {0x01, 0x08}, {0x02, 0xC0}, {0x03, 0x00}, {0x04, 0x90}, 146 {0x05, 0x90}, {0x06, 0xEB}, {0x07, 0xE0}, {0x08, 0x88}, 147 {0x09, 0x40}, {0x0A, 0x80}, {0x0B, 0x44}, {0x0C, 0x40}, 148 {0x0D, 0x00}, {0x0E, 0x89}, {0x0F, 0x2E}, {0x10, 0x0E}, 149 {0x11, 0x00}, {0x12, 0x05}, {0x13, 0x00}, {0x14, 0x08}, 150 {0x15, 0x11}, {0x16, 0xFE}, {0x17, 0x00}, {0x18, 0x40}, 151 {0x19, 0x80}, {0x30, 0xBC}, {0x31, 0xDF}, {0x32, 0x02}, 152 {0x34, 0xCD}, {0x35, 0xCC}, {0x36, 0x3A}, {0x38, 0x03}, 153 {0x39, 0x10}, {0x3A, 0x00}, {0x40, 0x00}, {0x41, 0xFF}, 154 {0x42, 0xFF}, {0x43, 0xFF}, {0x44, 0xFF}, {0x45, 0xFF}, 155 {0x46, 0xFF}, {0x47, 0xFF}, {0x48, 0xFF}, {0x49, 0xFF}, 156 {0x4A, 0xFF}, {0x4B, 0xFF}, {0x4C, 0xFF}, {0x4D, 0xFF}, 157 {0x4E, 0xFF}, {0x4F, 0xFF}, {0x50, 0xFF}, {0x51, 0xFF}, 158 {0x52, 0xFF}, {0x53, 0xFF}, {0x54, 0xFF}, {0x55, 0xFF}, 159 {0x56, 0xFF}, {0x57, 0xFF}, {0x58, 0x00}, {0x59, 0x47}, 160 {0x5A, 0x06}, {0x5B, 0x43}, {0x5D, 0x3E}, {0x5E, 0x00}, 161 {0x80, 0x30}, {0x83, 0x00}, {0x84, 0x60}, {0x85, 0x00}, 162 {0x86, 0xE5}, {0x87, 0x01}, {0x88, 0xF8}, 163 164 /* VBI task */ 165 166 {0x90, 0x01}, {0x91, 0xC8}, {0x92, 0x08}, {0x93, 0x84}, 167 {0x94, 0x10}, {0x95, 0x00}, {0x96, 0xD0}, {0x97, 0x02}, 168 {0x98, 0x05}, {0x99, 0x00}, {0x9A, 0x0B}, {0x9B, 0x00}, 169 {0x9C, 0xA0}, {0x9D, 0x05}, {0x9E, 0x0B}, {0x9F, 0x00}, 170 {0xA0, 0x01}, {0xA1, 0x00}, {0xA2, 0x00}, {0xA4, 0x80}, 171 {0xA5, 0x40}, {0xA6, 0x40}, {0xA8, 0x00}, {0xA9, 0x02}, 172 {0xAA, 0x00}, {0xAC, 0x00}, {0xAD, 0x01}, {0xAE, 0x00}, 173 {0xB0, 0x00}, {0xB1, 0x04}, {0xB2, 0x00}, {0xB3, 0x04}, 174 {0xB4, 0x00}, {0xB8, 0x00}, {0xB9, 0x00}, {0xBA, 0x00}, 175 {0xBB, 0x00}, {0xBC, 0x00}, {0xBD, 0x00}, {0xBE, 0x00}, 176 {0xBF, 0x00}, 177 178 /* Video task */ 179 180 {0xC0, 0x80}, {0xC1, 0x08}, {0xC2, 0x00}, {0xC3, 0x80}, 181 {0xC4, 0x10}, {0xC5, 0x00}, {0xC6, 0xD0}, {0xC7, 0x02}, 182 {0xC8, 0x11}, {0xC9, 0x00}, {0xCA, 0xF1}, {0xCB, 0x00}, 183 {0xCC, 0xD0}, {0xCD, 0x02}, {0xCE, 0xF1}, {0xCF, 0x00}, 184 {0xD0, 0x01}, {0xD1, 0x00}, {0xD2, 0x00}, {0xD4, 0x80}, 185 {0xD5, 0x40}, {0xD6, 0x40}, {0xD8, 0x00}, {0xD9, 0x04}, 186 {0xDA, 0x00}, {0xDC, 0x00}, {0xDD, 0x02}, {0xDE, 0x00}, 187 {0xE0, 0x00}, {0xE1, 0x04}, {0xE2, 0x00}, {0xE3, 0x04}, 188 {0xE4, 0x00}, {0xE8, 0x00}, {0xE9, 0x00}, {0xEA, 0x00}, 189 {0xEB, 0x00}, {0xEC, 0x00}, {0xED, 0x00}, {0xEE, 0x00}, 190 {0xEF, 0x00}, 191}; 192 193#define GFX_NUM_SAA7114_INIT_VALUES sizeof(gfx_saa7114_init_values)/sizeof(GFX_SAA7114_INIT) 194 195/*-----------------------------------------------------*/ 196/* TABLE OF FIR PREFILTER RECOMMENDED VALUES */ 197/*-----------------------------------------------------*/ 198 199int optimize_for_aliasing = 0; 200 201typedef struct tagGFX_SAA7114_FIR_PREFILTER 202{ 203 unsigned char prescaler; 204 unsigned char acl_low; 205 unsigned char prefilter_low; 206 unsigned char acl_high; 207 unsigned char prefilter_high; 208} 209GFX_SAA7114_FIR_PREFILTER; 210 211GFX_SAA7114_FIR_PREFILTER gfx_saa7114_fir_values[] = { 212 {0x01, 0x00, 0x00, 0x00, 0x00}, {0x02, 0x02, 0x5A, 0x01, 0x51}, 213 {0x03, 0x04, 0xAB, 0x03, 0xA2}, {0x04, 0x07, 0xA3, 0x04, 0xAB}, 214 {0x05, 0x08, 0xAC, 0x07, 0xA3}, {0x06, 0x08, 0xFC, 0x07, 0xF3}, 215 {0x07, 0x08, 0xFC, 0x07, 0xF3}, {0x08, 0x0F, 0xF4, 0x08, 0xFC}, 216 {0x09, 0x0F, 0xF4, 0x08, 0xFC}, {0x0A, 0x10, 0xFD, 0x08, 0xFC}, 217 {0x0B, 0x10, 0xFD, 0x08, 0xFC}, {0x0C, 0x10, 0xFD, 0x08, 0xFC}, 218 {0x0D, 0x10, 0xFD, 0x10, 0xFD}, {0x0E, 0x10, 0xFD, 0x10, 0xFD}, 219 {0x0F, 0x1F, 0xF5, 0x10, 0xFD}, {0x10, 0x20, 0xFE, 0x10, 0xFD}, 220 {0x11, 0x20, 0xFE, 0x10, 0xFD}, {0x12, 0x20, 0xFE, 0x10, 0xFD}, 221 {0x13, 0x20, 0xFE, 0x20, 0xFE}, {0x14, 0x20, 0xFE, 0x20, 0xFE}, 222 {0x15, 0x20, 0xFE, 0x20, 0xFE}, {0x16, 0x20, 0xFE, 0x20, 0xFE}, 223 {0x17, 0x20, 0xFE, 0x20, 0xFE}, {0x18, 0x20, 0xFE, 0x20, 0xFE}, 224 {0x19, 0x20, 0xFE, 0x20, 0xFE}, {0x1A, 0x20, 0xFE, 0x20, 0xFE}, 225 {0x1B, 0x20, 0xFE, 0x20, 0xFE}, {0x1C, 0x20, 0xFE, 0x20, 0xFE}, 226 {0x1D, 0x20, 0xFE, 0x20, 0xFE}, {0x1E, 0x20, 0xFE, 0x20, 0xFE}, 227 {0x1F, 0x20, 0xFE, 0x20, 0xFE}, {0x20, 0x3F, 0xFF, 0x20, 0xFE}, 228 {0x21, 0x3F, 0xFF, 0x20, 0xFE}, {0x22, 0x3F, 0xFF, 0x20, 0xFE}, 229 {0x23, 0x3F, 0xFF, 0x20, 0xFF} 230}; 231 232int saa7114_set_decoder_defaults(void); 233int saa7114_set_decoder_analog_input(unsigned char input); 234int saa7114_set_decoder_brightness(unsigned char brightness); 235int saa7114_set_decoder_contrast(unsigned char contrast); 236int saa7114_set_decoder_hue(char hue); 237int saa7114_set_decoder_saturation(unsigned char saturation); 238int saa7114_set_decoder_input_offset(unsigned short x, unsigned short y); 239int saa7114_set_decoder_input_size(unsigned short width, 240 unsigned short height); 241int saa7114_set_decoder_output_size(unsigned short width, 242 unsigned short height); 243int saa7114_set_decoder_scale(unsigned short srcw, unsigned short srch, 244 unsigned short dstw, unsigned short dsth); 245int saa7114_set_decoder_vbi_format(int start, int end, int format); 246int saa7114_set_decoder_vbi_enable(int enable); 247int saa7114_set_decoder_vbi_upscale(void); 248int saa7114_set_decoder_TV_standard(TVStandardType TVStandard); 249int saa7114_set_decoder_luminance_filter(unsigned char lufi); 250int saa7114_decoder_software_reset(void); 251int saa7114_decoder_detect_macrovision(void); 252int saa7114_decoder_detect_video(void); 253 254/* READ ROUTINES IN GFX_DCDR.C */ 255 256unsigned char saa7114_get_decoder_brightness(void); 257unsigned char saa7114_get_decoder_contrast(void); 258char saa7114_get_decoder_hue(void); 259unsigned char saa7114_get_decoder_saturation(void); 260unsigned long saa7114_get_decoder_input_offset(void); 261unsigned long saa7114_get_decoder_input_size(void); 262unsigned long saa7114_get_decoder_output_size(void); 263int saa7114_get_decoder_vbi_format(int line); 264int saa7114_write_reg(unsigned char reg, unsigned char val); 265int saa7114_read_reg(unsigned char reg, unsigned char *val); 266 267int 268saa7114_write_reg(unsigned char reg, unsigned char val) 269{ 270 return gfx_i2c_write(2, SAA7114_CHIPADDR, reg, 1, &val); 271} 272 273int 274saa7114_read_reg(unsigned char reg, unsigned char *val) 275{ 276 return gfx_i2c_read(2, SAA7114_CHIPADDR, reg, 1, val); 277} 278 279/*----------------------------------------------------------------------------- 280 * gfx_set_decoder_vbi_upscale 281 * 282 * This routine configures the video decoder task A to upscale raw VBI data 283 * horizontally to match a different system clock. 284 * The upscale is from 13.5 MHz (SAA7114) to 14.318 MHz (Bt835). 285 *----------------------------------------------------------------------------- 286 */ 287#if GFX_DECODER_DYNAMIC 288int 289saa7114_set_decoder_vbi_upscale(void) 290#else 291int 292gfx_set_decoder_vbi_upscale(void) 293#endif 294{ 295 /* Set horizontal output length to 1528 (720 * 2 * 14.318 / 13.5) */ 296 saa7114_write_reg(SAA7114_TASK_A_HORZ_OUTPUT_LO, 0xF8); 297 saa7114_write_reg(SAA7114_TASK_A_HORZ_OUTPUT_HI, 0x05); 298 299 /* Set horizontal luminance scaling increment to 484 (1024 * 13.5 / 28.636) */ 300 saa7114_write_reg(SAA7114_TASK_A_HSCALE_LUMA_LO, 0xE4); 301 saa7114_write_reg(SAA7114_TASK_A_HSCALE_LUMA_HI, 0x01); 302 303 /* Set horizontal chrominance scaling increment to 242 */ 304 saa7114_write_reg(SAA7114_TASK_A_HSCALE_CHROMA_LO, 0xF2); 305 saa7114_write_reg(SAA7114_TASK_A_HSCALE_CHROMA_HI, 0x00); 306 307 return GFX_STATUS_OK; 308} 309 310/*----------------------------------------------------------------------------- 311 * gfx_decoder_software_reset 312 * 313 * This routine performs a software reset of the decoder. 314 *----------------------------------------------------------------------------- 315 */ 316#if GFX_DECODER_DYNAMIC 317int 318saa7114_decoder_software_reset(void) 319#else 320int 321gfx_decoder_software_reset(void) 322#endif 323{ 324 saa7114_write_reg(0x88, 0xC0); 325 /* I2C-bus latency should be sufficient for resetting the internal state machine. */ 326 /* gfx_delay_milliseconds(10); */ 327 saa7114_write_reg(0x88, 0xF0); 328 return GFX_STATUS_OK; 329} 330 331/*----------------------------------------------------------------------------- 332 * gfx_decoder_detect_macrovision 333 * 334 * This routine detects if macrovision exists in the input of the video decoder. 335 *----------------------------------------------------------------------------- 336 */ 337#if GFX_DECODER_DYNAMIC 338int 339saa7114_decoder_detect_macrovision(void) 340#else 341int 342gfx_decoder_detect_macrovision(void) 343#endif 344{ 345 unsigned char macrovision = 0xff; 346 347 saa7114_read_reg(SAA7114_STATUS, ¯ovision); 348 return ((macrovision & 0x02) >> 1); 349} 350 351/*----------------------------------------------------------------------------- 352 * gfx_decoder_detect_video 353 * 354 * This routine detects if video exists in the input of the video decoder. 355 *----------------------------------------------------------------------------- 356 */ 357#if GFX_DECODER_DYNAMIC 358int 359saa7114_decoder_detect_video(void) 360#else 361int 362gfx_decoder_detect_video(void) 363#endif 364{ 365 unsigned char video = 0xff; 366 367 saa7114_read_reg(SAA7114_STATUS, &video); 368 return !((video & 0x40) >> 6); 369} 370 371/*----------------------------------------------------------------------------- 372 * gfx_set_decoder_defaults 373 * 374 * This routine is called to set the initial register values of the 375 * video decoder. 376 *----------------------------------------------------------------------------- 377 */ 378#if GFX_DECODER_DYNAMIC 379int 380saa7114_set_decoder_defaults(void) 381#else 382int 383gfx_set_decoder_defaults(void) 384#endif 385{ 386 unsigned int i; 387 388 /* LOOP THROUGH INDEX/DATA PAIRS IN THE TABLE */ 389 390 for (i = 0; i < GFX_NUM_SAA7114_INIT_VALUES; i++) { 391 saa7114_write_reg(gfx_saa7114_init_values[i].index, 392 gfx_saa7114_init_values[i].value); 393 } 394 395 gfx_decoder_software_reset(); 396 return (0); 397} 398 399/*----------------------------------------------------------------------------- 400 * gfx_set_decoder_analog_input 401 * 402 * This routine sets the analog input of the video decoder. 403 *----------------------------------------------------------------------------- 404 */ 405#if GFX_DECODER_DYNAMIC 406int 407saa7114_set_decoder_analog_input(unsigned char input) 408#else 409int 410gfx_set_decoder_analog_input(unsigned char input) 411#endif 412{ 413 saa7114_write_reg(SAA7114_ANALOG_INPUT_CTRL1, input); 414 return (0); 415} 416 417/*----------------------------------------------------------------------------- 418 * gfx_set_decoder_brightness 419 * 420 * This routine sets the brightness of the video decoder. 421 *----------------------------------------------------------------------------- 422 */ 423#if GFX_DECODER_DYNAMIC 424int 425saa7114_set_decoder_brightness(unsigned char brightness) 426#else 427int 428gfx_set_decoder_brightness(unsigned char brightness) 429#endif 430{ 431 saa7114_write_reg(SAA7114_BRIGHTNESS, brightness); 432 return (0); 433} 434 435/*----------------------------------------------------------------------------- 436 * gfx_set_decoder_contrast 437 * 438 * This routine sets the contrast of the video decoder. 439 *----------------------------------------------------------------------------- 440 */ 441#if GFX_DECODER_DYNAMIC 442int 443saa7114_set_decoder_contrast(unsigned char contrast) 444#else 445int 446gfx_set_decoder_contrast(unsigned char contrast) 447#endif 448{ 449 saa7114_write_reg(SAA7114_CONTRAST, (unsigned char)(contrast >> 1)); 450 return (0); 451} 452 453/*----------------------------------------------------------------------------- 454 * gfx_set_decoder_hue 455 * 456 * This routine sets the hue control of the video decoder. 457 *----------------------------------------------------------------------------- 458 */ 459#if GFX_DECODER_DYNAMIC 460int 461saa7114_set_decoder_hue(char hue) 462#else 463int 464gfx_set_decoder_hue(char hue) 465#endif 466{ 467 saa7114_write_reg(SAA7114_HUE, (unsigned char)hue); 468 return (0); 469} 470 471/*----------------------------------------------------------------------------- 472 * gfx_set_decoder_saturation 473 * 474 * This routine sets the saturation adjustment of the video decoder. 475 *----------------------------------------------------------------------------- 476 */ 477#if GFX_DECODER_DYNAMIC 478int 479saa7114_set_decoder_saturation(unsigned char saturation) 480#else 481int 482gfx_set_decoder_saturation(unsigned char saturation) 483#endif 484{ 485 saa7114_write_reg(SAA7114_SATURATION, (unsigned char)(saturation >> 1)); 486 return (0); 487} 488 489/*----------------------------------------------------------------------------- 490 * gfx_set_decoder_input_offset 491 * 492 * This routine sets the size of the decoder input window. 493 *----------------------------------------------------------------------------- 494 */ 495#if GFX_DECODER_DYNAMIC 496int 497saa7114_set_decoder_input_offset(unsigned short x, unsigned short y) 498#else 499int 500gfx_set_decoder_input_offset(unsigned short x, unsigned short y) 501#endif 502{ 503 /* SET THE INPUT WINDOW OFFSET */ 504 505 saa7114_write_reg(SAA7114_HORZ_OFFSET_LO, (unsigned char)(x & 0x00FF)); 506 saa7114_write_reg(SAA7114_HORZ_OFFSET_HI, (unsigned char)(x >> 8)); 507 saa7114_write_reg(SAA7114_VERT_OFFSET_LO, (unsigned char)(y & 0x00FF)); 508 saa7114_write_reg(SAA7114_VERT_OFFSET_HI, (unsigned char)(y >> 8)); 509 510 gfx_decoder_software_reset(); 511 return (0); 512} 513 514/*----------------------------------------------------------------------------- 515 * gfx_set_decoder_input_size 516 * 517 * This routine sets the size of the decoder input window. 518 *----------------------------------------------------------------------------- 519 */ 520#if GFX_DECODER_DYNAMIC 521int 522saa7114_set_decoder_input_size(unsigned short width, unsigned short height) 523#else 524int 525gfx_set_decoder_input_size(unsigned short width, unsigned short height) 526#endif 527{ 528 /* DIVIDE HEIGHT BY TWO FOR INTERLACING */ 529 530 height = (height + 1) >> 1; 531 532 /* SET THE INPUT WINDOW SIZE */ 533 534 saa7114_write_reg(SAA7114_HORZ_INPUT_LO, (unsigned char)(width & 0x00FF)); 535 saa7114_write_reg(SAA7114_HORZ_INPUT_HI, (unsigned char)(width >> 8)); 536 saa7114_write_reg(SAA7114_VERT_INPUT_LO, (unsigned char)(height & 0x00FF)); 537 saa7114_write_reg(SAA7114_VERT_INPUT_HI, (unsigned char)(height >> 8)); 538 539 gfx_decoder_software_reset(); 540 return (0); 541} 542 543/*----------------------------------------------------------------------------- 544 * gfx_set_decoder_output_size 545 * 546 * This routine sets the size of the decoder output window. 547 *----------------------------------------------------------------------------- 548 */ 549#if GFX_DECODER_DYNAMIC 550int 551saa7114_set_decoder_output_size(unsigned short width, unsigned short height) 552#else 553int 554gfx_set_decoder_output_size(unsigned short width, unsigned short height) 555#endif 556{ 557 /* ROUND WIDTH UP TO EVEN NUMBER TO PREVENT DECODER BECOMING STUCK */ 558 559 width = ((width + 1) >> 1) << 1; 560 561 /* DIVIDE HEIGHT BY TWO FOR INTERLACING */ 562 563 height = (height + 1) >> 1; 564 565 /* SET THE OUTPUT WINDOW SIZE */ 566 567 saa7114_write_reg(SAA7114_HORZ_OUTPUT_LO, (unsigned char)(width & 0x00FF)); 568 saa7114_write_reg(SAA7114_HORZ_OUTPUT_HI, (unsigned char)(width >> 8)); 569 saa7114_write_reg(SAA7114_VERT_OUTPUT_LO, 570 (unsigned char)(height & 0x00FF)); 571 saa7114_write_reg(SAA7114_VERT_OUTPUT_HI, (unsigned char)(height >> 8)); 572 573 gfx_decoder_software_reset(); 574 return (0); 575} 576 577/*----------------------------------------------------------------------------- 578 * gfx_set_decoder_scale 579 * 580 * This routine sets the scaling of the video decoder. 581 *----------------------------------------------------------------------------- 582 */ 583#if GFX_DECODER_DYNAMIC 584int 585saa7114_set_decoder_scale(unsigned short srcw, unsigned short srch, 586 unsigned short dstw, unsigned short dsth) 587#else 588int 589gfx_set_decoder_scale(unsigned short srcw, unsigned short srch, 590 unsigned short dstw, unsigned short dsth) 591#endif 592{ 593 unsigned char prescale = 0; 594 int scale = 0; 595 596 /* SET THE HORIZONTAL PRESCALE */ 597 /* Downscale from 1 to 1/63 source size. */ 598 599 if (dstw) 600 prescale = (unsigned char)(srcw / dstw); 601 if (!prescale) 602 prescale = 1; 603 if (prescale > 63) 604 return (1); 605 saa7114_write_reg(SAA7114_HORZ_PRESCALER, prescale); 606 607 /* USE FIR PREFILTER FUNCTIONALITY (OPTIMISATION) */ 608 609 if (prescale < 36) { 610 if (optimize_for_aliasing) { 611 saa7114_write_reg(SAA7114_HORZ_ACL, 612 gfx_saa7114_fir_values[prescale - 1].acl_low); 613 saa7114_write_reg(SAA7114_HORZ_FIR_PREFILTER, 614 gfx_saa7114_fir_values[prescale - 615 1].prefilter_low); 616 } else { 617 saa7114_write_reg(SAA7114_HORZ_ACL, 618 gfx_saa7114_fir_values[prescale - 1].acl_high); 619 saa7114_write_reg(SAA7114_HORZ_FIR_PREFILTER, 620 gfx_saa7114_fir_values[prescale - 621 1].prefilter_high); 622 } 623 } else { 624 /* SAME SETTINGS FOR RATIO 1/35 DOWNTO 1/63 */ 625 if (optimize_for_aliasing) { 626 saa7114_write_reg(SAA7114_HORZ_ACL, 627 gfx_saa7114_fir_values[34].acl_low); 628 saa7114_write_reg(SAA7114_HORZ_FIR_PREFILTER, 629 gfx_saa7114_fir_values[34].prefilter_low); 630 } else { 631 saa7114_write_reg(SAA7114_HORZ_ACL, 632 gfx_saa7114_fir_values[34].acl_high); 633 saa7114_write_reg(SAA7114_HORZ_FIR_PREFILTER, 634 gfx_saa7114_fir_values[34].prefilter_high); 635 } 636 } 637 638 /* SET THE HORIZONTAL SCALING */ 639 640 if (!dstw) 641 return (1); 642 scale = ((1024 * srcw * 1000) / (dstw * prescale)) / 1000; 643 if ((scale > 8191) || (scale < 300)) 644 return (1); 645 saa7114_write_reg(SAA7114_HSCALE_LUMA_LO, (unsigned char)(scale & 0x00FF)); 646 saa7114_write_reg(SAA7114_HSCALE_LUMA_HI, (unsigned char)(scale >> 8)); 647 scale >>= 1; 648 saa7114_write_reg(SAA7114_HSCALE_CHROMA_LO, 649 (unsigned char)(scale & 0x00FF)); 650 saa7114_write_reg(SAA7114_HSCALE_CHROMA_HI, (unsigned char)(scale >> 8)); 651 652 /* SET THE VERTICAL SCALING (INTERPOLATION MODE) */ 653 654 if (!dsth) 655 return (1); 656 657 /* ROUND DESTINATION HEIGHT UP TO EVEN NUMBER TO PREVENT DECODER BECOMING STUCK */ 658 659 dsth = ((dsth + 1) >> 1) << 1; 660 661 scale = (int)((1024 * srch) / dsth); 662 saa7114_write_reg(SAA7114_VSCALE_LUMA_LO, (unsigned char)(scale & 0x00FF)); 663 saa7114_write_reg(SAA7114_VSCALE_LUMA_HI, (unsigned char)(scale >> 8)); 664 saa7114_write_reg(SAA7114_VSCALE_CHROMA_LO, 665 (unsigned char)(scale & 0x00FF)); 666 saa7114_write_reg(SAA7114_VSCALE_CHROMA_HI, (unsigned char)(scale >> 8)); 667 668 if (dsth >= (srch >> 1)) { 669 /* USE INTERPOLATION MODE FOR SCALE FACTOR ABOVE 0.5 */ 670 671 saa7114_write_reg(SAA7114_VSCALE_CONTROL, 0x00); 672 673 /* SET VERTICAL PHASE REGISTER FOR CORRECT SCALED INTERLACED OUTPUT (OPTIMISATION) */ 674 /* THE OPTIMISATION IS BASED ON OFIDC = 0 (REG 90h[6] = 0 ) */ 675 saa7114_write_reg(SAA7114_VSCALE_CHROMA_OFFS0, SAA7114_VSCALE_PHO); 676 saa7114_write_reg(SAA7114_VSCALE_CHROMA_OFFS1, SAA7114_VSCALE_PHO); 677 saa7114_write_reg(SAA7114_VSCALE_CHROMA_OFFS2, 678 (unsigned char)(SAA7114_VSCALE_PHO + scale / 64 - 679 16)); 680 saa7114_write_reg(SAA7114_VSCALE_CHROMA_OFFS3, 681 (unsigned char)(SAA7114_VSCALE_PHO + scale / 64 - 682 16)); 683 684 saa7114_write_reg(SAA7114_VSCALE_LUMINA_OFFS0, SAA7114_VSCALE_PHO); 685 saa7114_write_reg(SAA7114_VSCALE_LUMINA_OFFS1, SAA7114_VSCALE_PHO); 686 saa7114_write_reg(SAA7114_VSCALE_LUMINA_OFFS2, 687 (unsigned char)(SAA7114_VSCALE_PHO + scale / 64 - 688 16)); 689 saa7114_write_reg(SAA7114_VSCALE_LUMINA_OFFS3, 690 (unsigned char)(SAA7114_VSCALE_PHO + scale / 64 - 691 16)); 692 693 /* RESTORE CONTRAST AND SATURATION FOR INTERPOLATION MODE */ 694 695 saa7114_write_reg(SAA7114_FILTER_CONTRAST, (unsigned char)0x40); 696 saa7114_write_reg(SAA7114_FILTER_SATURATION, (unsigned char)0x40); 697 } else { 698 /* USE ACCUMULATION MODE FOR DOWNSCALING BY MORE THAN 2x */ 699 700 saa7114_write_reg(SAA7114_VSCALE_CONTROL, 0x01); 701 702 /* SET VERTICAL PHASE OFFSETS OFF (OPTIMISATION) */ 703 saa7114_write_reg(SAA7114_VSCALE_CHROMA_OFFS0, 0x00); 704 saa7114_write_reg(SAA7114_VSCALE_CHROMA_OFFS1, 0x00); 705 saa7114_write_reg(SAA7114_VSCALE_CHROMA_OFFS2, 0x00); 706 saa7114_write_reg(SAA7114_VSCALE_CHROMA_OFFS3, 0x00); 707 708 saa7114_write_reg(SAA7114_VSCALE_LUMINA_OFFS0, 0x00); 709 saa7114_write_reg(SAA7114_VSCALE_LUMINA_OFFS1, 0x00); 710 saa7114_write_reg(SAA7114_VSCALE_LUMINA_OFFS2, 0x00); 711 saa7114_write_reg(SAA7114_VSCALE_LUMINA_OFFS3, 0x00); 712 713 /* ADJUST CONTRAST AND SATURATION FOR ACCUMULATION MODE */ 714 715 if (srch) 716 scale = (64 * dsth) / srch; 717 saa7114_write_reg(SAA7114_FILTER_CONTRAST, (unsigned char)scale); 718 saa7114_write_reg(SAA7114_FILTER_SATURATION, (unsigned char)scale); 719 } 720 721 gfx_decoder_software_reset(); 722 return (0); 723} 724 725/*----------------------------------------------------------------------------- 726 * gfx_set_decoder_vbi_format 727 * 728 * This routine programs the decoder to produce the specified format of VBI 729 * data for the specified lines. 730 *----------------------------------------------------------------------------- 731 */ 732#if GFX_DECODER_DYNAMIC 733int 734saa7114_set_decoder_vbi_format(int start, int end, int format) 735#else 736int 737gfx_set_decoder_vbi_format(int start, int end, int format) 738#endif 739{ 740 int i; 741 unsigned char data; 742 743 for (i = start; i <= end; i++) { 744 switch (format) { 745 case VBI_FORMAT_VIDEO: 746 data = 0xFF; 747 break; /* Active video */ 748 case VBI_FORMAT_RAW: 749 data = 0x77; 750 break; /* Raw VBI data */ 751 case VBI_FORMAT_CC: 752 data = 0x55; 753 break; /* US CC */ 754 case VBI_FORMAT_NABTS: 755 data = 0xCC; 756 break; /* US NABTS */ 757 default: 758 return GFX_STATUS_BAD_PARAMETER; 759 } 760 saa7114_write_reg((unsigned char)(0x3F + i), data); 761 } 762 return GFX_STATUS_OK; 763} 764 765/*----------------------------------------------------------------------------- 766 * gfx_set_decoder_vbi_enable 767 * 768 * This routine enables or disables VBI transfer in the decoder. 769 *----------------------------------------------------------------------------- 770 */ 771#if GFX_DECODER_DYNAMIC 772int 773saa7114_set_decoder_vbi_enable(int enable) 774#else 775int 776gfx_set_decoder_vbi_enable(int enable) 777#endif 778{ 779 unsigned char data; 780 781 saa7114_read_reg(SAA7114_IPORT_CONTROL, &data); 782 if (enable) 783 data |= 0x80; 784 else 785 data &= ~0x80; 786 saa7114_write_reg(SAA7114_IPORT_CONTROL, data); 787 return GFX_STATUS_OK; 788} 789 790/*----------------------------------------------------------------------------- 791 * gfx_set_decoder_TV_standard 792 * 793 * This routine configures the decoder for the required TV standard. 794 *----------------------------------------------------------------------------- 795 */ 796#if GFX_DECODER_DYNAMIC 797int 798saa7114_set_decoder_TV_standard(TVStandardType TVStandard) 799#else 800int 801gfx_set_decoder_TV_standard(TVStandardType TVStandard) 802#endif 803{ 804 switch (TVStandard) { 805 case TV_STANDARD_NTSC: 806 saa7114_write_reg(0x0E, 0x89); 807 saa7114_write_reg(0x5A, 0x06); 808 break; 809 case TV_STANDARD_PAL: 810 saa7114_write_reg(0x0E, 0x81); 811 saa7114_write_reg(0x5A, 0x03); 812 break; 813 default: 814 return GFX_STATUS_BAD_PARAMETER; 815 } 816 gfx_decoder_software_reset(); 817 return GFX_STATUS_OK; 818} 819 820/*----------------------------------------------------------------------------- 821 * gfx_set_decoder_luminance_filter 822 * 823 * This routine sets the hue control of the video decoder. 824 *----------------------------------------------------------------------------- 825 */ 826#if GFX_DECODER_DYNAMIC 827int 828saa7114_set_decoder_luminance_filter(unsigned char lufi) 829#else 830int 831gfx_set_decoder_luminance_filter(unsigned char lufi) 832#endif 833{ 834 unsigned char data; 835 836 saa7114_read_reg(SAA7114_LUMINANCE_CONTROL, &data); 837 saa7114_write_reg(SAA7114_LUMINANCE_CONTROL, 838 (unsigned char)((data & ~0x0F) | (lufi & 0x0F))); 839 return (0); 840} 841 842/*************************************************************/ 843/* READ ROUTINES | INCLUDED FOR DIAGNOSTIC PURPOSES ONLY */ 844/*************************************************************/ 845 846#if GFX_READ_ROUTINES 847 848/*----------------------------------------------------------------------------- 849 * gfx_get_decoder_brightness 850 * 851 * This routine returns the current brightness of the video decoder. 852 *----------------------------------------------------------------------------- 853 */ 854#if GFX_DECODER_DYNAMIC 855unsigned char 856saa7114_get_decoder_brightness(void) 857#else 858unsigned char 859gfx_get_decoder_brightness(void) 860#endif 861{ 862 unsigned char brightness = 0; 863 864 saa7114_read_reg(SAA7114_BRIGHTNESS, &brightness); 865 return (brightness); 866} 867 868/*----------------------------------------------------------------------------- 869 * gfx_get_decoder_contrast 870 * 871 * This routine returns the current contrast of the video decoder. 872 *----------------------------------------------------------------------------- 873 */ 874#if GFX_DECODER_DYNAMIC 875unsigned char 876saa7114_get_decoder_contrast(void) 877#else 878unsigned char 879gfx_get_decoder_contrast(void) 880#endif 881{ 882 unsigned char contrast = 0; 883 884 saa7114_read_reg(SAA7114_CONTRAST, &contrast); 885 contrast <<= 1; 886 return (contrast); 887} 888 889/*----------------------------------------------------------------------------- 890 * gfx_get_decoder_hue 891 * 892 * This routine returns the current hue of the video decoder. 893 *----------------------------------------------------------------------------- 894 */ 895#if GFX_DECODER_DYNAMIC 896char 897saa7114_get_decoder_hue(void) 898#else 899char 900gfx_get_decoder_hue(void) 901#endif 902{ 903 unsigned char hue = 0; 904 905 saa7114_read_reg(SAA7114_HUE, &hue); 906 return ((char)hue); 907} 908 909/*----------------------------------------------------------------------------- 910 * gfx_get_decoder_saturation 911 * 912 * This routine returns the current saturation of the video decoder. 913 *----------------------------------------------------------------------------- 914 */ 915#if GFX_DECODER_DYNAMIC 916unsigned char 917saa7114_get_decoder_saturation(void) 918#else 919unsigned char 920gfx_get_decoder_saturation(void) 921#endif 922{ 923 unsigned char saturation = 0; 924 925 saa7114_read_reg(SAA7114_SATURATION, &saturation); 926 saturation <<= 1; 927 return (saturation); 928} 929 930/*----------------------------------------------------------------------------- 931 * gfx_get_decoder_input_offset 932 * 933 * This routine returns the offset into the input window. 934 *----------------------------------------------------------------------------- 935 */ 936#if GFX_DECODER_DYNAMIC 937unsigned long 938saa7114_get_decoder_input_offset(void) 939#else 940unsigned long 941gfx_get_decoder_input_offset(void) 942#endif 943{ 944 unsigned long value = 0; 945 unsigned char data; 946 947 saa7114_read_reg(SAA7114_HORZ_OFFSET_LO, &data); 948 value = (unsigned long)data; 949 saa7114_read_reg(SAA7114_HORZ_OFFSET_HI, &data); 950 value |= ((unsigned long)data) << 8; 951 saa7114_read_reg(SAA7114_VERT_OFFSET_LO, &data); 952 value |= ((unsigned long)data) << 16; 953 saa7114_read_reg(SAA7114_VERT_OFFSET_HI, &data); 954 value |= ((unsigned long)data) << 24; 955 return (value); 956} 957 958/*----------------------------------------------------------------------------- 959 * gfx_get_decoder_input_size 960 * 961 * This routine returns the current size of the input window 962 *----------------------------------------------------------------------------- 963 */ 964#if GFX_DECODER_DYNAMIC 965unsigned long 966saa7114_get_decoder_input_size(void) 967#else 968unsigned long 969gfx_get_decoder_input_size(void) 970#endif 971{ 972 unsigned long value = 0; 973 unsigned char data; 974 975 saa7114_read_reg(SAA7114_HORZ_INPUT_LO, &data); 976 value = (unsigned long)data; 977 saa7114_read_reg(SAA7114_HORZ_INPUT_HI, &data); 978 value |= ((unsigned long)data) << 8; 979 saa7114_read_reg(SAA7114_VERT_INPUT_LO, &data); 980 value |= ((unsigned long)data) << 17; 981 saa7114_read_reg(SAA7114_VERT_INPUT_HI, &data); 982 value |= ((unsigned long)data) << 25; 983 return (value); 984} 985 986/*----------------------------------------------------------------------------- 987 * gfx_get_decoder_output_size 988 * 989 * This routine returns the current size of the output window. 990 *----------------------------------------------------------------------------- 991 */ 992#if GFX_DECODER_DYNAMIC 993unsigned long 994saa7114_get_decoder_output_size(void) 995#else 996unsigned long 997gfx_get_decoder_output_size(void) 998#endif 999{ 1000 unsigned long value = 0; 1001 unsigned char data; 1002 1003 saa7114_read_reg(SAA7114_HORZ_OUTPUT_LO, &data); 1004 value = (unsigned long)data; 1005 saa7114_read_reg(SAA7114_HORZ_OUTPUT_HI, &data); 1006 value |= ((unsigned long)data) << 8; 1007 saa7114_read_reg(SAA7114_VERT_OUTPUT_LO, &data); 1008 value |= ((unsigned long)data) << 17; 1009 saa7114_read_reg(SAA7114_VERT_OUTPUT_HI, &data); 1010 value |= ((unsigned long)data) << 25; 1011 return (value); 1012} 1013 1014/*----------------------------------------------------------------------------- 1015 * gfx_get_decoder_vbi_format 1016 * 1017 * This routine returns the current format of VBI data for the specified line. 1018 *----------------------------------------------------------------------------- 1019 */ 1020#if GFX_DECODER_DYNAMIC 1021int 1022saa7114_get_decoder_vbi_format(int line) 1023#else 1024int 1025gfx_get_decoder_vbi_format(int line) 1026#endif 1027{ 1028 unsigned char format = 0, data; 1029 1030 saa7114_read_reg((unsigned char)(0x3F + line), &data); 1031 switch (data) { 1032 case 0xFF: 1033 format = VBI_FORMAT_VIDEO; 1034 break; /* Active video */ 1035 case 0x77: 1036 format = VBI_FORMAT_RAW; 1037 break; /* Raw VBI data */ 1038 case 0x55: 1039 format = VBI_FORMAT_CC; 1040 break; /* US CC */ 1041 case 0xCC: 1042 format = VBI_FORMAT_NABTS; 1043 break; /* US NABTS */ 1044 } 1045 return (format); 1046} 1047 1048#endif /* GFX_READ_ROUTINES */ 1049 1050/* END OF FILE */ 1051