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