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