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#define FS450_DIRECTREG 0 27 28#include "tv_fs450.h" 29 30/*========================================================================== 31 * Macros 32 *========================================================================== 33 */ 34#undef fsmax 35#undef fsmin 36#define fsmax(a, b) ((a) > (b) ? (a) : (b)) 37#define fsmin(a, b) ((a) < (b) ? (a) : (b)) 38 39#undef range_limit 40#define range_limit(val,min_val,max_val) (fsmax((min_val),fsmin((val),(max_val)))) 41 42/*========================================================================== 43 * Registers 44 *========================================================================== 45 */ 46 47#define MAX_REGISTERS 32 48#define MAX_BITS 32 49 50#define READ 1 51#define WRITE 2 52#define READ_WRITE (READ | WRITE) 53 54typedef struct { 55 char *name; 56 unsigned long offset; 57 unsigned char bit_length; 58 unsigned char valid_bits; 59 unsigned char read_write; 60 char *bitfield_names[MAX_BITS]; 61} S_REGISTER_DESCRIP; 62 63typedef struct { 64 int source; 65 char *name; 66 S_REGISTER_DESCRIP registers[MAX_REGISTERS]; 67} S_SET_DESCRIP; 68 69const S_SET_DESCRIP *houston_regs(void); 70const S_SET_DESCRIP *encoder_regs(void); 71const S_SET_DESCRIP *macrovision_regs(void); 72const S_SET_DESCRIP *gcc_regs(void); 73 74/*========================================================================== 75 * Houston Register Addresses & Bit Definitions 76 *========================================================================== 77 */ 78#define HOUSTON_IHO 0x00 /* Input Horizontal Offset */ 79#define HOUSTON_IVO 0x02 /* Input Vertical Offset */ 80#define HOUSTON_IHA 0x04 /* Input Horizontal Active Width */ 81#define HOUSTON_VSC 0x06 /* Vertical Scaling Coefficient */ 82#define HOUSTON_HSC 0x08 /* Horizontal Scaling Coefficient */ 83#define HOUSTON_BYP 0x0A /* Bypass Register */ 84#define HOUSTON_CR 0x0C /* Control Register */ 85#define HOUSTON_SP 0x0E /* Status */ 86#define HOUSTON_NCONL 0x10 /* NCO numerator low word */ 87#define HOUSTON_NCONH 0x12 /* NCO numerator high word */ 88#define HOUSTON_NCODL 0x14 /* NCO denominator low word */ 89#define HOUSTON_NCODH 0x16 /* NCO denominator high word */ 90#define HOUSTON_APO 0x18 91#define HOUSTON_ALO 0x1A 92#define HOUSTON_AFO 0x1C 93#define HOUSTON_HSOUTWID 0x1E 94#define HOUSTON_HSOUTST 0x20 95#define HOUSTON_HSOUTEND 0x22 96#define HOUSTON_SHP 0x24 /* Sharpness */ 97#define HOUSTON_FLK 0x26 /* Flicker Filter */ 98#define HOUSTON_BCONTL 0x28 99#define HOUSTON_BCONTH 0x2A 100#define HOUSTON_BDONE 0x2C 101#define HOUSTON_BDIAGL 0x2E 102#define HOUSTON_BDIAGH 0x30 103#define HOUSTON_REV 0x32 104#define HOUSTON_MISC 0x34 105#define HOUSTON_FFO 0x36 106#define HOUSTON_FFO_LAT 0x38 107#define HOUSTON_VSOUTWID 0x3A 108#define HOUSTON_VSOUTST 0x3C 109#define HOUSTON_VSOUTEND 0x3E 110/* BYP Register Bits */ 111#define BYP_RGB_BYPASS 0x0001 112#define BYP_HDS_BYPASS 0x0002 113#define BYP_HDS_TBYPASS 0x0004 114#define BYP_CAC_BYPASS 0x0008 115#define BYP_R2V_SBYPASS 0x0010 116#define BYP_R2V_BYPASS 0x0020 117#define BYP_VDS_BYPASS 0x0040 118#define BYP_FFT_BYPASS 0x0080 119#define BYP_FIF_BYPASS 0x0100 120#define BYP_FIF_TBYPASS 0x0200 121#define BYP_HUS_BYPASS 0x0400 122#define BYP_HUS_TBYPASS 0x0800 123#define BYP_CCR_BYPASS 0x1000 124#define BYP_PLL_BYPASS 0x2000 125#define BYP_NCO_BYPASS 0x4000 126#define BYP_ENC_BYPASS 0x8000 127/* CR Register Bits */ 128#define CR_RESET 0x0001 129#define CR_CLKOFF 0x0002 130#define CR_NCO_EN 0x0004 131#define CR_COMPOFF 0x0008 132#define CR_YCOFF 0x0010 133#define CR_LP_EN 0x0020 134#define CR_CACQ_CLR 0x0040 135#define CR_FFO_CLR 0x0080 136#define CR_656_PAL_NTSC 0x0100 137#define CR_656_STD_VMI 0x0200 138#define CR_OFMT 0x0400 139#define CR_UIM_CLK 0x0800 140#define CR_UIM_DEC 0x1000 141#define CR_BIPGEN_EN1 0x2000 142#define CR_UIM_MOD0 0x4000 143#define CR_UIM_MOD1 0x8000 144/* Status Register Bits */ 145#define SP_CACQ_ST 0x0001 146#define SP_FFO_ST 0x0002 147#define SP_REVID_MASK 0x7FFC 148#define SP_MV_EN 0x8000 149/* BDONE Register Bits */ 150#define BDONE_BIST_DONE_A 0x0001 151#define BDONE_BIST_DONE_B 0x0002 152#define BDONE_BIST_DONE_C 0x0004 153#define BDONE_BIST_DONE_D 0x0008 154#define BDONE_BIST_DONE_E 0x0010 155#define BDONE_BIST_DONE_F 0x0020 156#define BDONE_BIST_DONE_G 0x0040 157/* BDIAGL Register Bits */ 158#define BDIAGL_BIST_DIAG_A 0x000F 159#define BDIAGL_BIST_DIAG_B 0x00F0 160#define BDIAGL_BIST_DIAG_C 0x0F00 161#define BDIAGL_BIST_DIAG_D 0xF000 162/* BDIAGH Register Bits */ 163#define BDIAGH_BIST_DIAG_E 0x000F 164#define BDIAGH_BIST_DIAG_F 0x000F 165#define BDIAGH_BIST_DIAG_G 0x000F 166/* MISC Register Bits */ 167#define MISC_TV_SHORT_FLD 0x0001 168#define MISC_ENC_TEST 0x0002 169#define MISC_DAC_TEST 0x0004 170#define MISC_MV_SOFT_EN 0x0008 171#define MISC_NCO_LOAD0 0x0010 172#define MISC_NCO_LOAD1 0x0020 173#define MISC_VGACKDIV 0x0200 174#define MISC_BRIDGE_SYNC 0x0400 175#define MISC_GTLIO_PD 0x8000 176/*========================================================================== 177 * Encoder Registers & Bit Definitions 178 *========================================================================== 179 */ 180#define ENC_CHROMA_FREQ 0x40 181#define ENC_CHROMA_PHASE 0x44 182#define ENC_REG05 0x45 183#define ENC_REG06 0x46 184#define ENC_REG07 0x47 185#define ENC_HSYNC_WIDTH 0x48 186#define ENC_BURST_WIDTH 0x49 187#define ENC_BACK_PORCH 0x4A 188#define ENC_CB_BURST_LEVEL 0x4B 189#define ENC_CR_BURST_LEVEL 0x4C 190#define ENC_SLAVE_MODE 0x4D 191#define ENC_BLACK_LEVEL 0x4e 192#define ENC_BLANK_LEVEL 0x50 193#define ENC_NUM_LINES 0x57 194#define ENC_WHITE_LEVEL 0x5e 195#define ENC_CB_GAIN 0x60 196#define ENC_CR_GAIN 0x62 197#define ENC_TINT 0x65 198#define ENC_BREEZE_WAY 0x69 199#define ENC_FRONT_PORCH 0x6C 200#define ENC_ACTIVELINE 0x71 201#define ENC_FIRST_LINE 0x73 202#define ENC_REG34 0x74 203#define ENC_SYNC_LEVEL 0x75 204#define ENC_VBI_BLANK_LEVEL 0x7C 205#define ENC_RESET 0x7e 206#define ENC_NOTCH_FILTER 0x8d 207/*========================================================================== 208 * Macrovision Registers & Bit Definitions 209 *========================================================================== 210 */ 211#define MV_N0 0x59 212#define MV_N1 0x52 213#define MV_N2 0x7b 214#define MV_N3 0x53 215#define MV_N4 0x79 216#define MV_N5 0x5d 217#define MV_N6 0x7a 218#define MV_N7 0x64 219#define MV_N8 0x54 220#define MV_N9 0x55 221#define MV_N10 0x56 222#define MV_N11 0x6d 223#define MV_N12 0x6f 224#define MV_N13 0x5a 225#define MV_N14 0x5b 226#define MV_N15 0x5c 227#define MV_N16 0x63 228#define MV_N17 0x66 229#define MV_N18 0x68 230#define MV_N19 0x67 231#define MV_N20 0x61 232#define MV_N21 0x6a 233#define MV_N22 0x76 234#define MV_AGC_PULSE_LEVEL 0x77 235#define MV_BP_PULSE_LEVEL 0x78 236/*========================================================================== 237 * The TRACE macro can be used to display debug information. It can display 238 * one or more parameters in a formatted string like printf. No code will be 239 * generated for a release build. Use double parentheses for compatibility 240 * with C #define statements. Newline characters are not added 241 * automatically. Usage example: 242 * 243 * TRACE(("Number is %d, Name is %s.\n",iNumber,lpszName)) 244 *========================================================================== 245 */ 246#define TRACE(parameters) {} 247/* GCC timing structure */ 248typedef struct _S_TIMING_SPECS { 249 int vga_width; 250 int vga_lines; 251 int tv_width; 252 int tv_lines; 253 int h_total; 254 int h_sync; 255 int v_total; 256 int v_sync; 257} S_TIMING_SPECS; 258 259/* Revision of Houston chip */ 260#define HOUSTON_REV_A 0 261#define HOUSTON_REV_B 1 262static int houston_Rev(void); 263 264/*========================================================================== 265 * Functions 266 *========================================================================== 267 */ 268static int houston_init(void); 269 270static unsigned char PLAL_FS450_i2c_address(void); 271static int PLAL_FS450_UIM_mode(void); 272static int PLAL_ReadRegister(S_REG_INFO * p_reg); 273static int PLAL_WriteRegister(const S_REG_INFO * p_reg); 274static int PLAL_IsTVOn(void); 275static int PLAL_EnableVga(void); 276static int PLAL_PrepForTVout(void); 277static int PLAL_SetTVTimingRegisters(const S_TIMING_SPECS * p_specs); 278static int PLAL_FinalEnableTVout(unsigned long vga_mode); 279 280/* Direct Memory Access Functions */ 281/* NOTE: Cx5530 is assumed hardcoded at 0x10000 offset from MediaGX base. 282 * F4Bar is bogus as described in the Cx5530 datasheet (actually points to GX 283 * frame buffer). */ 284static int 285DMAL_ReadUInt32(unsigned long phys_addr, unsigned long *p_data) 286{ 287 *p_data = READ_REG32(phys_addr); 288 return 0; 289} 290 291static int 292DMAL_WriteUInt32(unsigned long phys_addr, unsigned long data) 293{ 294 WRITE_REG32(phys_addr, data); 295 return 0; 296} 297 298/* Houston register access functions. */ 299static int 300houston_ReadReg(unsigned int reg, unsigned long *p_value, unsigned int bytes) 301{ 302 return gfx_i2c_read(1, PLAL_FS450_i2c_address(), (unsigned char) reg, 303 (unsigned char) bytes, (unsigned char *) p_value); 304} 305 306static int 307houston_WriteReg(unsigned int reg, unsigned long value, unsigned int bytes) 308{ 309 return gfx_i2c_write(1, PLAL_FS450_i2c_address(), (unsigned char) reg, 310 (unsigned char) bytes, (unsigned char *) &value); 311} 312 313/* TV configuration functions. */ 314static int config_init(void); 315static const S_TIMING_SPECS *p_specs(void); 316static void config_power(int on); 317static void config_vga_mode(unsigned long vga_mode); 318static void config_tv_std(unsigned long tv_std, unsigned int trigger_bits); 319static void conget_tv_std(unsigned long *p_tv_std); 320static unsigned long supported_standards(void); 321static void config_tvout_mode(unsigned long tvout_mode); 322static void conget_tvout_mode(unsigned long *p_tvout_mode); 323static void config_overscan_xy(unsigned long tv_std, unsigned long vga_mode, 324 int overscan_x, int overscan_y, int pos_x, 325 int pos_y); 326static void config_nco(unsigned long tv_std, unsigned long vga_mode); 327static void config_sharpness(int sharpness); 328static void conget_sharpness(int *p_sharpness); 329static void config_flicker(int flicker); 330static void conget_flicker(int *p_flicker); 331static void config_color(int color); 332static void conget_color(int *p_color); 333static void config_brightness_contrast(unsigned long tv_std, 334 unsigned int trigger_bits, 335 int brightness, int contrast); 336static void conget_brightness_contrast(unsigned long tv_std, 337 unsigned int trigger_bits, 338 int *p_brightness, int *p_contrast); 339static void config_yc_filter(unsigned long tv_std, int luma_filter, 340 int chroma_filter); 341static void conget_yc_filter(int *p_luma_filter, int *p_chroma_filter); 342static void config_macrovision(unsigned long tv_std, 343 unsigned int cp_trigger_bits); 344static void conget_macrovision(unsigned long tv_std, 345 unsigned int *p_cp_trigger_bits); 346 347/* Device settings. */ 348typedef struct _S_DEVICE_SETTINGS { 349 int tv_on; 350 unsigned long vga_mode; 351 unsigned long tv_std; 352 unsigned long tvout_mode; 353 int overscan_x; 354 int overscan_y; 355 int position_x; 356 int position_y; 357 int sharpness; 358 int flicker; 359 int color; 360 int brightness; 361 int contrast; 362 unsigned char yc_filter; 363 unsigned int aps_trigger_bits; 364 int last_overscan_y; 365} S_DEVICE_SETTINGS; 366 367static S_DEVICE_SETTINGS d; 368 369/*========================================================================== 370 * TV Setup Parameters 371 *========================================================================== 372 * */ 373 374static const struct { 375 unsigned long chroma_freq[5]; 376 unsigned short chroma_phase[5]; 377 unsigned short cphase_rst[5]; 378 unsigned short color[5]; 379 unsigned short cr_burst_level[5]; 380 unsigned short cb_burst_level[5]; 381 unsigned short sys625_50[5]; 382 unsigned short vsync5[5]; 383 unsigned short pal_mode[5]; 384 unsigned short hsync_width[5]; 385 unsigned short burst_width[5]; 386 unsigned short back_porch[5]; 387 unsigned short front_porch[5]; 388 unsigned short breeze_way[5]; 389 unsigned short activeline[5]; 390 unsigned short blank_level[5]; 391 unsigned short vbi_blank_level[5]; 392 unsigned short black_level[5]; 393 unsigned short white_level[5]; 394 unsigned short hamp_offset[5]; 395 unsigned short sync_level[5]; 396 unsigned short tv_lines[5]; 397 unsigned short tv_width[5]; 398 unsigned short tv_active_lines[5]; 399 unsigned short tv_active_width[5]; 400 unsigned char notch_filter[5]; 401 unsigned short houston_cr[5]; 402 unsigned short houston_ncodl[5]; 403 unsigned short houston_ncodh[5]; 404} tvsetup = { 405 /* ntsc, pal, ntsc-eij, pal-m, pal-n */ 406 { 407 0x1f7cf021, 0xcb8a092a, 0x1f7cf021, 0xe3efe621, 0xcb8a092a}, 408 /* chroma_freq */ 409 { 410 0, 0, 0, 0, 0}, 411 /* chroma_phase */ 412 { 413 2, 0, 2, 0, 0}, 414 /* cphase_rst */ 415 { 416 54, 43, 54, 43, 43}, 417 /* color */ 418 { 419 0, 31, 0, 29, 29}, 420 /* cr_burst_level */ 421 { 422 59, 44, 59, 41, 41}, 423 /* cb_burst_level */ 424 { 425 0, 1, 0, 0, 1}, 426 /* sys625_50 */ 427 { 428 0, 1, 0, 0, 0}, 429 /* vsync5 */ 430 { 431 0, 1, 0, 1, 1}, 432 /* pal_mode */ 433 { 434 0x7a, 0x7a, 0x7a, 0x7a, 0x7a}, 435 /* hsync_width */ 436 { 437 0x40, 0x3c, 0x40, 0x40, 0x3c}, 438 /* burst_width */ 439 { 440 0x80, 0x9a, 0x80, 0x80, 0x9a}, 441 /* back_porch */ 442 { 443 0x24, 0x1e, 0x24, 0x24, 0x1e}, 444 /* front_porch */ 445 { 446 0x19, 0x1a, 0x19, 0x12, 0x1a}, 447 /* breeze_way */ 448 { 449 0xb4, 0xb4, 0xb4, 0xb4, 0xb4}, 450 /* active_line */ 451 { 452 240, 251, 240, 240, 240}, 453 /* blank_level */ 454 { 455 240, 251, 240, 240, 240}, 456 /* vbi_blank_level */ 457 { 458 284, 252, 240, 252, 252}, 459 /* black_level */ 460 { 461 823, 821, 823, 821, 821}, 462 /* white_level */ 463 { 464 60, 48, 60, 48, 48}, 465 /* hamp_offset */ 466 { 467 0x08, 0x08, 0x08, 0x08, 0x08}, 468 /* sync_level */ 469 { 470 525, 625, 525, 525, 625}, 471 /* tv_lines */ 472 { 473 858, 864, 858, 858, 864}, 474 /* tv_width */ 475 { 476 487, 576, 487, 487, 576}, 477 /* tv_active_lines */ 478 { 479 800, 800, 800, 800, 800}, 480 /* tv_active_width */ 481 { 482 0x1a, 0x1d, 0x1a, 0x1d, 0x1d}, 483 /* notch filter enabled */ 484 { 485 0x0000, 0x0100, 0x0000, 0x0000, 0x0100}, 486 /* houston cr pal */ 487 { 488 0x7e48, 0xf580, 0x7e48, 0x7e48, 0xf580}, 489 /* houston ncodl */ 490 { 491 0x001b, 0x0020, 0x001b, 0x001b, 0x0020} 492 /* houston ncodh */ 493}; 494 495/* MediaGX default underscan and centered position setups. */ 496#define SCANTABLE_ENTRIES 5 497struct _scantable { 498 unsigned long mode; 499 unsigned short v_total[5]; 500 unsigned short v_sync[5]; 501 unsigned short iha[5]; 502 signed short iho[5]; 503 signed short hsc[5]; 504}; 505 506static struct _scantable scantable[SCANTABLE_ENTRIES] = { 507 { 508 GFX_VGA_MODE_640X480, 509 {617, 624, 617, 624, 624}, /* v_total */ 510 {69, 88, 69, 88, 88}, /* v_sync */ 511 {720, 720, 720, 720, 720}, /* iha */ 512 {0, 0, 0, 0, 0}, /* iho */ 513 {-12, 0, -6, 0, 0} /* hsc */ 514 }, 515 { 516 GFX_VGA_MODE_800X600, 517 {740, 740, 740, 740, 740}, /* v_total */ 518 {90, 88, 90, 88, 88}, /* v_sync */ 519 {720, 720, 508, 720, 720}, /* iha */ 520 {-8, 11, -8, -8, 11}, /* iho */ 521 {-27, -27, -27, -27, -27} /* hsc */ 522 }, 523 { 524 GFX_VGA_MODE_720X487, 525 {525, 720, 525, 720, 720}, /* v_total */ 526 {23, 230, 23, 230, 230}, /* v_sync */ 527 {720, 720, 720, 720, 720}, /* iha */ 528 {0xa2, 0xa2, 0xa2, 0xa2, 0xa2}, /* iho */ 529 {0, 0, 0, 0, 0} /* hsc */ 530 }, 531 { 532 GFX_VGA_MODE_720X576, 533 {720, 625, 720, 625, 625}, /* v_total */ 534 {129, 25, 129, 25, 25}, /* v_sync */ 535 {720, 720, 720, 720, 720}, /* iha */ 536 {0xaa, 0xaa, 0xaa, 0xaa, 0xaa}, /* iho */ 537 {0, 0, 0, 0, 0} /* hsc */ 538 }, 539 { 540 GFX_VGA_MODE_1024X768, 541 {933, 942, 933, 806, 806}, /* v_total */ 542 {121, 112, 121, 88, 88}, /* v_sync */ 543 {600, 600, 600, 600, 600}, /* iha */ 544 {0x3c, 0x23, 0x3c, 0x65, 0x65}, /* iho */ 545 {35, 26, 35, 26, 26} /* hsc */ 546 }, 547}; 548 549/* Houston fifo configuration constants. */ 550struct _ffolat { 551 int v_total; 552 unsigned short ffolat; 553}; 554 555struct _ffolativo { 556 int v_total; 557 unsigned short ivo; 558 unsigned short ffolat; 559}; 560 561/* h_total=832, ivo=40, tv_width=858, tv_lines=525, vga_lines=480 */ 562#define SIZE6X4NTSC 66 563static struct _ffolat ffo6x4ntsc[SIZE6X4NTSC + 1] = { 564 {541, 0x40}, {545, 0x40}, {549, 0x40}, {553, 0x40}, 565 {557, 0x58}, {561, 0x40}, {565, 0x40}, {569, 0x40}, 566 {573, 0x48}, {577, 0x40}, {581, 0x40}, {585, 0x40}, 567 {589, 0x40}, {593, 0x48}, {597, 0x40}, {601, 0x40}, 568 {605, 0x40}, {609, 0x40}, {613, 0x5b}, {617, 0x48}, 569 {621, 0x60}, {625, 0x48}, {629, 0x48}, {633, 0x40}, 570 {637, 0x5e}, {641, 0x40}, {645, 0x50}, {649, 0x56}, 571 {653, 0x58}, {657, 0x6c}, {661, 0x40}, {665, 0x40}, 572 {669, 0x40}, {673, 0x40}, {677, 0x40}, {681, 0x40}, 573 {685, 0x40}, {689, 0x40}, {693, 0x40}, {697, 0x40}, 574 {701, 0x40}, {705, 0x40}, {709, 0x40}, {713, 0x40}, 575 {717, 0x40}, {721, 0x40}, {725, 0x40}, {729, 0x40}, 576 {733, 0x40}, {737, 0x40}, {741, 0x40}, {745, 0x40}, 577 {749, 0x40}, {753, 0x40}, {757, 0x40}, {761, 0x40}, 578 {765, 0x40}, {769, 0x40}, {773, 0x40}, {777, 0x40}, 579 {781, 0x40}, {785, 0x40}, {789, 0x40}, {793, 0x40}, 580 {797, 0x30}, {801, 0x40}, 581 {-1, 0} 582}; 583 584#define SIZE6X4PAL 45 585static struct _ffolat ffo6x4pal[SIZE6X4PAL + 1] = { 586 {625, 0x60}, {629, 0x60}, {633, 0x60}, {637, 0x60}, 587 {641, 0x50}, {645, 0x60}, {649, 0x60}, {653, 0x60}, 588 {657, 0x60}, {661, 0x60}, {665, 0x60}, {669, 0x60}, 589 {673, 0x60}, {677, 0x60}, {681, 0x60}, {685, 0x60}, 590 {689, 0x60}, {693, 0x60}, {697, 0x60}, {701, 0x60}, 591 {705, 0x60}, {709, 0x60}, {713, 0x60}, {717, 0x60}, 592 {721, 0x60}, {725, 0x60}, {729, 0x60}, {733, 0x60}, 593 {737, 0x60}, {741, 0x60}, {745, 0x60}, {749, 0x60}, 594 {753, 0x60}, {757, 0x60}, {761, 0x60}, {765, 0x60}, 595 {769, 0x60}, {773, 0x60}, {777, 0x60}, {781, 0x60}, 596 {785, 0x60}, {789, 0x60}, {793, 0x60}, {797, 0x60}, 597 {801, 0x60}, 598 {-1, 0} 599}; 600 601#define SIZE7X4NTSC 40 602static struct _ffolat ffo7x4ntsc[SIZE7X4NTSC + 1] = { 603 {525, 0x52}, {529, 0x52}, {533, 0x52}, {537, 0x52}, 604 {541, 0x52}, {545, 0x40}, {549, 0x40}, {553, 0x40}, 605 {557, 0x58}, {561, 0x40}, {565, 0x58}, {569, 0x40}, 606 {573, 0x48}, {577, 0x40}, {581, 0x40}, {585, 0x40}, 607 {589, 0x40}, {593, 0x48}, {597, 0x40}, {601, 0x40}, 608 {605, 0x40}, {609, 0x40}, {613, 0x5b}, {617, 0x48}, 609 {621, 0x60}, {625, 0x48}, {629, 0x48}, {633, 0x40}, 610 {637, 0x5e}, {641, 0x40}, {645, 0x50}, {649, 0x56}, 611 {653, 0x58}, {657, 0x6c}, {661, 0x40}, {665, 0x40}, 612 {669, 0x40}, {673, 0x40}, {677, 0x40}, {681, 0x40}, 613 {-1, 0} 614}; 615 616#define SIZE7X4PAL 24 617static struct _ffolat ffo7x4pal[SIZE7X4PAL + 1] = { 618 {625, 0x60}, {629, 0x60}, {633, 0x60}, {637, 0x60}, 619 {641, 0x50}, {645, 0x60}, {649, 0x60}, {653, 0x60}, 620 {657, 0x60}, {661, 0x60}, {665, 0x60}, {669, 0x60}, 621 {673, 0x60}, {677, 0x60}, {681, 0x60}, {685, 0x60}, 622 {689, 0x60}, {693, 0x60}, {697, 0x60}, {701, 0x60}, 623 {705, 0x60}, {709, 0x60}, {713, 0x60}, {717, 0x60}, 624 {-1, 0} 625}; 626 627#define SIZE7X5NTSC 54 628static struct _ffolat ffo7x5ntsc[SIZE7X5NTSC + 1] = { 629 {590, 0x40}, {594, 0x48}, {598, 0x40}, {602, 0x40}, 630 {606, 0x40}, {610, 0x40}, {614, 0x5b}, {618, 0x48}, 631 {622, 0x60}, {626, 0x48}, {630, 0x48}, {634, 0x40}, 632 {638, 0x5e}, {642, 0x40}, {646, 0x50}, {650, 0x56}, 633 {654, 0x58}, {658, 0x6c}, {662, 0x40}, {666, 0x40}, 634 {670, 0x40}, {674, 0x40}, {678, 0x40}, {682, 0x40}, 635 {686, 0x40}, {690, 0x40}, {694, 0x40}, {698, 0x40}, 636 {702, 0x40}, {706, 0x40}, {710, 0x40}, {714, 0x40}, 637 {718, 0x40}, {722, 0x40}, {726, 0x40}, {730, 0x40}, 638 {734, 0x40}, {738, 0x40}, {742, 0x40}, {746, 0x40}, 639 {750, 0x40}, {754, 0x40}, {758, 0x40}, {762, 0x40}, 640 {766, 0x40}, {770, 0x40}, {774, 0x40}, {778, 0x40}, 641 {782, 0x40}, {786, 0x40}, {790, 0x40}, {794, 0x40}, 642 {798, 0x30}, {802, 0x40}, 643 {-1, 0} 644}; 645 646#define SIZE7X5PAL 45 647static struct _ffolat ffo7x5pal[SIZE7X5PAL + 1] = { 648 {625, 0x60}, {629, 0x60}, {633, 0x60}, {637, 0x60}, 649 {641, 0x50}, {645, 0x60}, {649, 0x60}, {653, 0x60}, 650 {657, 0x60}, {661, 0x60}, {665, 0x60}, {669, 0x60}, 651 {673, 0x60}, {677, 0x60}, {681, 0x60}, {685, 0x60}, 652 {689, 0x60}, {693, 0x60}, {697, 0x60}, {701, 0x60}, 653 {705, 0x60}, {709, 0x60}, {713, 0x60}, {717, 0x60}, 654 {721, 0x60}, {725, 0x60}, {729, 0x60}, {733, 0x60}, 655 {737, 0x60}, {741, 0x60}, {745, 0x60}, {749, 0x60}, 656 {753, 0x60}, {757, 0x60}, {761, 0x60}, {765, 0x60}, 657 {769, 0x60}, {773, 0x60}, {777, 0x60}, {781, 0x60}, 658 {785, 0x60}, {789, 0x60}, {793, 0x60}, {797, 0x60}, 659 {801, 0x60}, 660 {-1, 0} 661}; 662 663/* h_total=1056, vga_lines=600 */ 664#define SIZE8X6NTSC 37 665static struct _ffolat ffo8x6ntsc[SIZE8X6NTSC + 1] = { 666 {620, 0x40}, /* v_total_min >= vsync+10 >= vga_lines+10 = 610 */ 667 {625, 0x58}, {630, 0x40}, {635, 0x40}, {640, 0x40}, 668 {645, 0x46}, {650, 0x46}, {655, 0x4f}, {660, 0x4c}, 669 {665, 0x4a}, {670, 0x50}, {675, 0x2f}, {680, 0x48}, 670 {685, 0x38}, {690, 0x31}, {695, 0x40}, {700, 0x21}, 671 {705, 0x25}, {710, 0x40}, {715, 0x48}, {720, 0x50}, 672 {725, 0x30}, {730, 0x50}, {735, 0x50}, {740, 0x50}, 673 {745, 0x40}, {750, 0x38}, {755, 0x50}, {760, 0x50}, 674 {765, 0x40}, {770, 0x38}, {775, 0x40}, {780, 0x40}, 675 {785, 0x40}, {790, 0x38}, {795, 0x50}, {800, 0x50}, 676 {-1, 0} 677}; 678 679/* h_total=1056, vga_lines=600 */ 680#define SIZE8X6PAL 36 681static struct _ffolat ffo8x6pal[SIZE8X6PAL + 1] = { 682 {625, 0x80}, {630, 0x80}, {635, 0x5a}, {640, 0x55}, 683 {645, 0x48}, {650, 0x65}, {655, 0x65}, {660, 0x50}, 684 {665, 0x80}, {670, 0x70}, {675, 0x56}, {680, 0x80}, 685 {685, 0x58}, {690, 0x31}, {695, 0x80}, {700, 0x60}, 686 {705, 0x45}, {710, 0x4a}, {715, 0x50}, {720, 0x50}, 687 {725, 0x50}, {730, 0x45}, {735, 0x50}, {740, 0x50}, 688 {745, 0x50}, {750, 0x50}, {755, 0x50}, {760, 0x50}, 689 {765, 0x50}, {770, 0x50}, {775, 0x50}, {780, 0x50}, 690 {785, 0x50}, {790, 0x50}, {795, 0x50}, {800, 0x50}, 691 {-1, 0} 692}; 693 694/* h_total=1344, vga_lines=768 */ 695#define SIZE10X7NTSC 45 696static struct _ffolativo ffo10x7ntsc[SIZE10X7NTSC] = { 697 {783, 0x4d, 0x40}, 698 {789, 0x47, 0x14}, 699 {795, 0x47, 0x7f}, 700 {801, 0x47, 0x53}, 701 {807, 0x47, 0x11}, 702 {813, 0x47, 0x78}, 703 {819, 0x47, 0x54}, 704 {825, 0x47, 0x40}, 705 {831, 0x47, 0x0f}, 706 {837, 0x4d, 0x40}, 707 {843, 0x47, 0x5a}, 708 {849, 0x4d, 0x40}, 709 {855, 0x47, 0x4b}, 710 {861, 0x4d, 0x40}, 711 {867, 0x47, 0x4b}, 712 {873, 0x4d, 0x40}, 713 {879, 0x47, 0x07}, 714 {885, 0x48, 0x20}, 715 {891, 0x47, 0x82}, 716 {897, 0x47, 0x60}, 717 {903, 0x47, 0x7f}, 718 {909, 0x4d, 0x40}, 719 {915, 0x48, 0x40}, 720 {921, 0x4c, 0x40}, 721 {927, 0x49, 0x40}, 722 {933, 0x48, 0x40}, 723 {939, 0x4a, 0x40}, 724 {945, 0x46, 0x40}, 725 {951, 0x4a, 0x40}, 726 {957, 0x4a, 0x40}, 727 {963, 0x4b, 0x40}, 728 {969, 0x4b, 0x40}, 729 {975, 0x48, 0x40}, 730 {981, 0x47, 0x40}, 731 {987, 0x47, 0x40}, 732 {993, 0x47, 0x40}, 733 {999, 0x48, 0x40}, 734 {1005, 0x48, 0x40}, 735 {1011, 0x47, 0x40}, 736 {1017, 0x47, 0x40}, 737 {1023, 0x48, 0x40}, 738 {1029, 0x48, 0x40}, 739 {1035, 0x46, 0x40}, 740 {1041, 0x47, 0x40}, 741 {1047, 0x47, 0x40} 742}; 743 744/* h_total=1344, vga_lines=768 */ 745#define SIZE10X7PAL 46 746static struct _ffolativo ffo10x7pal[SIZE10X7PAL] = { 747 {781, 0x49, 0x40}, 748 {787, 0x46, 0x40}, 749 {793, 0x48, 0x40}, 750 {799, 0x46, 0x40}, 751 {805, 0x49, 0x40}, 752 {811, 0x47, 0x40}, 753 {817, 0x46, 0x40}, 754 {823, 0x46, 0x56}, 755 {829, 0x46, 0x2d}, 756 {835, 0x46, 0x40}, 757 {841, 0x46, 0x2d}, 758 {847, 0x46, 0x3f}, 759 {853, 0x46, 0x10}, 760 {859, 0x46, 0x86}, 761 {865, 0x46, 0xc9}, 762 {871, 0x46, 0x83}, 763 {877, 0x46, 0xa8}, 764 {883, 0x46, 0x81}, 765 {889, 0x46, 0xa5}, 766 {895, 0x46, 0xa9}, 767 {901, 0x46, 0x81}, 768 {907, 0x46, 0xa4}, 769 {913, 0x46, 0xa5}, 770 {919, 0x46, 0x7f}, 771 {925, 0x46, 0xa2}, 772 {931, 0x46, 0x9d}, 773 {937, 0x46, 0xc1}, 774 {943, 0x46, 0x96}, 775 {949, 0x46, 0xb7}, 776 {955, 0x46, 0xb1}, 777 {961, 0x46, 0x8a}, 778 {967, 0x46, 0xa9}, 779 {973, 0x46, 0xa0}, 780 {979, 0x46, 0x40}, 781 {985, 0x46, 0x97}, 782 {991, 0x46, 0xb5}, 783 {997, 0x46, 0xaa}, 784 {1003, 0x46, 0x83}, 785 {1009, 0x46, 0x9f}, 786 {1015, 0x47, 0x40}, 787 {1021, 0x46, 0xad}, 788 {1027, 0x46, 0x87}, 789 {1033, 0x46, 0xa2}, 790 {1039, 0x47, 0x40}, 791 {1045, 0x46, 0xac}, 792 {1051, 0x46, 0x86} 793}; 794 795/*==========================================================================*/ 796/*FS450 API Functions. */ 797/*==========================================================================*/ 798 799/* Initialize device settings */ 800static void 801initialize_houston_static_registers(void) 802{ 803 houston_WriteReg(HOUSTON_BYP, 0, 2); 804 houston_WriteReg(HOUSTON_APO, 0, 2); 805 houston_WriteReg(HOUSTON_ALO, 0, 2); 806 houston_WriteReg(HOUSTON_AFO, 0, 2); 807 houston_WriteReg(HOUSTON_BCONTL, 0, 2); 808 houston_WriteReg(HOUSTON_BCONTH, 0, 2); 809 houston_WriteReg(HOUSTON_BDONE, 0, 2); 810 houston_WriteReg(HOUSTON_BDIAGL, 0, 2); 811 houston_WriteReg(HOUSTON_BDIAGH, 0, 2); 812 houston_WriteReg(HOUSTON_MISC, 0, 2); 813} 814 815int 816FS450_init(void) 817{ 818 int err; 819 820 TRACE(("FS450_Init()\n")) 821 822 err = houston_init(); 823 if (err) 824 return err; 825 826 initialize_houston_static_registers(); 827 828 d.tv_on = PLAL_IsTVOn()? 1 : 0; 829 830 /* get the current tv standard */ 831 conget_tv_std(&d.tv_std); 832 833 d.vga_mode = 0; 834 835 /* default to VP_TVOUT_MODE_CVBS_YC */ 836 d.tvout_mode = GFX_TVOUT_MODE_CVBS_YC; 837 838 /* default to 1000 out of 1000 */ 839 d.sharpness = 1000; 840 config_sharpness(d.sharpness); 841 842 /* default to 800 out of 1000 */ 843 d.flicker = 800; 844 config_flicker(d.flicker); 845 846 /* default to zeros */ 847 d.overscan_x = 0; 848 d.overscan_y = 0; 849 d.position_x = 0; 850 d.position_y = 0; 851 852 d.color = 50; 853 /* d.color = tvsetup.color[k]; */ 854 config_color(d.color); 855 856 /* default */ 857 d.brightness = 50; 858 d.contrast = 60; 859 config_brightness_contrast(d.tv_std, d.aps_trigger_bits, d.brightness, 860 d.contrast); 861 862 /* get the current yc filtering */ 863 { 864 int luma_filter, chroma_filter; 865 866 conget_yc_filter(&luma_filter, &chroma_filter); 867 d.yc_filter = 0; 868 if (luma_filter) 869 d.yc_filter |= GFX_LUMA_FILTER; 870 if (chroma_filter) 871 d.yc_filter |= GFX_CHROMA_FILTER; 872 } 873 874 d.aps_trigger_bits = 0; 875 config_macrovision(d.tv_std, d.aps_trigger_bits); 876 877 d.last_overscan_y = -10000; 878 879 return 0; 880} 881 882void 883FS450_cleanup(void) 884{ 885} 886 887/*==========================================================================*/ 888/* Required configuration calls to write new settings to the device */ 889/*==========================================================================*/ 890 891#define REQ_TV_STANDARD_BIT 0x0002 892#define REQ_VGA_MODE_BIT 0x0004 893#define REQ_TVOUT_MODE_BIT 0x0008 894#define REQ_SHARPNESS_BIT 0x0010 895#define REQ_FLICKER_BIT 0x0020 896#define REQ_OVERSCAN_POSITION_BIT 0x0040 897#define REQ_COLOR_BIT 0x0080 898#define REQ_BRIGHTNESS_CONTRAST_BIT 0x0100 899#define REQ_YC_FILTER_BIT 0x0200 900#define REQ_MACROVISION_BIT 0x0400 901#define REQ_NCO_BIT 0x1000 902 903#define REQ_TV_STANDARD (REQ_TV_STANDARD_BIT | REQ_OVERSCAN_POSITION \ 904 | REQ_BRIGHTNESS_CONTRAST \ 905 | REQ_MACROVISION_BIT | REQ_YC_FILTER) 906#define REQ_VGA_MODE (REQ_VGA_MODE_BIT | REQ_OVERSCAN_POSITION) 907#define REQ_TVOUT_MODE (REQ_TVOUT_MODE_BIT) 908#define REQ_SHARPNESS (REQ_SHARPNESS_BIT) 909#define REQ_FLICKER (REQ_FLICKER_BIT) 910#define REQ_OVERSCAN_POSITION (REQ_OVERSCAN_POSITION_BIT | REQ_NCO) 911#define REQ_COLOR (REQ_COLOR_BIT) 912#define REQ_BRIGHTNESS_CONTRAST (REQ_BRIGHTNESS_CONTRAST_BIT) 913#define REQ_YC_FILTER (REQ_YC_FILTER_BIT) 914#define REQ_MACROVISION (REQ_TV_STANDARD_BIT | \ 915 REQ_BRIGHTNESS_CONTRAST_BIT | \ 916 REQ_MACROVISION_BIT) 917#define REQ_NCO (REQ_NCO_BIT) 918#define REQ_ENCODER (REQ_TV_STANDARD | REQ_COLOR | \ 919 REQ_BRIGHTNESS_CONTRAST | REQ_YC_FILTER) 920 921static int 922write_config(int req) 923{ 924 unsigned long reg, reg_encoder_reset = 0; 925 int reset; 926 927 /*if we're changing the nco, and the vertical scaling has changed... */ 928 reset = ((REQ_NCO_BIT & req) && (d.overscan_y != d.last_overscan_y)); 929 if (reset) { 930 /*put the encoder into reset while making changes */ 931 houston_ReadReg(ENC_RESET, ®, 1); 932 houston_WriteReg(ENC_RESET, reg | 0x01, 1); 933 reg_encoder_reset = reg & 0x01; 934 } 935 936 if (REQ_TV_STANDARD_BIT & req) 937 config_tv_std(d.tv_std, d.aps_trigger_bits); 938 939 if (REQ_VGA_MODE_BIT & req) 940 config_vga_mode(d.vga_mode); 941 942 if (REQ_TVOUT_MODE_BIT & req) 943 config_tvout_mode(d.tvout_mode); 944 945 if (REQ_OVERSCAN_POSITION_BIT & req) { 946 config_overscan_xy(d.tv_std, 947 d.vga_mode, 948 d.overscan_x, d.overscan_y, d.position_x, 949 d.position_y); 950 951 /*h_timing and v_timing and syncs. */ 952 if (PLAL_IsTVOn()) 953 PLAL_SetTVTimingRegisters(p_specs()); 954 } 955 956 if (REQ_NCO_BIT & req) 957 config_nco(d.tv_std, d.vga_mode); 958 959 if (REQ_SHARPNESS_BIT & req) 960 config_sharpness(d.sharpness); 961 962 if (REQ_FLICKER_BIT & req) 963 config_flicker(d.flicker); 964 965 if (REQ_COLOR_BIT & req) 966 config_color(d.color); 967 968 if (REQ_BRIGHTNESS_CONTRAST_BIT & req) { 969 config_brightness_contrast(d.tv_std, 970 d.aps_trigger_bits, d.brightness, 971 d.contrast); 972 } 973 974 if (REQ_YC_FILTER_BIT & req) { 975 config_yc_filter(d.tv_std, 976 (d.yc_filter & GFX_LUMA_FILTER), 977 (d.yc_filter & GFX_CHROMA_FILTER)); 978 } 979 980 if (REQ_MACROVISION_BIT & req) 981 config_macrovision(d.tv_std, d.aps_trigger_bits); 982 983 /*if we decided to put the encoder into reset, put it back */ 984 if (reset) { 985 houston_ReadReg(ENC_RESET, ®, 1); 986 houston_WriteReg(ENC_RESET, reg_encoder_reset | (reg & ~0x01), 1); 987 988 d.last_overscan_y = d.overscan_y; 989 } 990 return 0; 991} 992 993/*==========================================================================*/ 994/* TV On */ 995/*==========================================================================*/ 996 997#if GFX_TV_DYNAMIC 998int 999fs450_get_tv_enable(unsigned int *p_on) 1000#else 1001int 1002gfx_get_tv_enable(unsigned int *p_on) 1003#endif 1004{ 1005 if (!p_on) 1006 return ERR_INVALID_PARAMETER; 1007 1008 *p_on = d.tv_on; 1009 1010 return 0; 1011} 1012 1013/*//int FS450_set_tv_on(unsigned int on)*/ 1014#if GFX_TV_DYNAMIC 1015int 1016fs450_set_tv_enable(int on) 1017#else 1018int 1019gfx_set_tv_enable(int on) 1020#endif 1021{ 1022 unsigned long reg; 1023 1024 /*if not mode change, just return */ 1025 if ((d.tv_on && on) || (!d.tv_on && !on)) 1026 return 0; 1027 1028 /*if turning off... */ 1029 if (!on) { 1030 /*re-enable vga. */ 1031 PLAL_EnableVga(); 1032 1033 /*power down houston */ 1034 config_power(0); 1035 1036 d.tv_on = 0; 1037 1038 return 0; 1039 } 1040 1041 /*turning on... */ 1042 1043 /*power up houston */ 1044 config_power(1); 1045 1046 /*assert encoder reset. */ 1047 houston_WriteReg(ENC_RESET, 0x01, 1); 1048 1049 /*initial platform preparation */ 1050 PLAL_PrepForTVout(); 1051 1052 /*configure encoder and nco. */ 1053 write_config(REQ_VGA_MODE | 1054 REQ_TV_STANDARD | 1055 REQ_TVOUT_MODE | 1056 REQ_OVERSCAN_POSITION | REQ_YC_FILTER | REQ_MACROVISION); 1057 1058 /*set LP_EN and UIM */ 1059 houston_ReadReg(HOUSTON_CR, ®, 2); 1060 reg |= CR_LP_EN; 1061 reg &= ~(CR_UIM_MOD0 | CR_UIM_MOD1); 1062 reg |= (PLAL_FS450_UIM_mode() << 14); 1063 houston_WriteReg(HOUSTON_CR, reg, 2); 1064 1065 /*set platform timing registers */ 1066 PLAL_SetTVTimingRegisters(p_specs()); 1067 1068 PLAL_FinalEnableTVout(d.vga_mode); 1069 1070 /*sync bridge */ 1071 { 1072 int retry_count = 0; 1073 1074 /*sync 50 times */ 1075 while (retry_count++ < 50) { 1076 /*sync bridge. */ 1077 houston_ReadReg(HOUSTON_MISC, ®, 2); 1078 reg |= MISC_BRIDGE_SYNC; 1079 houston_WriteReg(HOUSTON_MISC, reg, 2); 1080 reg &= ~MISC_BRIDGE_SYNC; 1081 houston_WriteReg(HOUSTON_MISC, reg, 2); 1082 } 1083 } 1084 1085 /*deassert encoder reset. */ 1086 houston_WriteReg(ENC_RESET, 0x00, 1); 1087 1088 d.tv_on = 1; 1089 1090 return 0; 1091} 1092 1093#if GFX_TV_DYNAMIC 1094int 1095fs450_set_tv_defaults(int format) 1096#else 1097int 1098gfx_set_tv_defaults(int format) 1099#endif 1100{ 1101 return 0; 1102} 1103 1104/*==========================================================================*/ 1105/* TV standard */ 1106/*==========================================================================*/ 1107 1108#if GFX_TV_DYNAMIC 1109int 1110fs450_get_tv_standard(unsigned long *p_standard) 1111#else 1112int 1113gfx_get_tv_standard(unsigned long *p_standard) 1114#endif 1115{ 1116 if (!p_standard) 1117 return ERR_INVALID_PARAMETER; 1118 1119 *p_standard = d.tv_std; 1120 1121 return 0; 1122} 1123 1124#if GFX_TV_DYNAMIC 1125int 1126fs450_get_available_tv_standards(unsigned long *p_standards) 1127#else 1128int 1129gfx_get_available_tv_standards(unsigned long *p_standards) 1130#endif 1131{ 1132 if (!p_standards) 1133 return ERR_INVALID_PARAMETER; 1134 1135 *p_standards = supported_standards(); 1136 1137 return 0; 1138} 1139 1140#if GFX_TV_DYNAMIC 1141int 1142fs450_set_tv_standard(unsigned long standard) 1143#else 1144int 1145gfx_set_tv_standard(unsigned long standard) 1146#endif 1147{ 1148 /* verify supported standard. */ 1149 if (!(standard & supported_standards())) 1150 return ERR_INVALID_PARAMETER; 1151 1152 /* disallow if tv is on */ 1153 if (d.tv_on) 1154 return ERR_CANNOT_CHANGE_WHILE_TV_ON; 1155 1156 d.tv_std = standard; 1157 /* d.color = tvsetup.color[k]; */ 1158 1159 return write_config(REQ_TV_STANDARD); 1160} 1161 1162/*==========================================================================*/ 1163/* vga mode as known by the driver */ 1164/*==========================================================================*/ 1165 1166#if GFX_TV_DYNAMIC 1167int 1168fs450_get_tv_vga_mode(unsigned long *p_vga_mode) 1169#else 1170int 1171gfx_get_tv_vga_mode(unsigned long *p_vga_mode) 1172#endif 1173{ 1174 if (!p_vga_mode) 1175 return ERR_INVALID_PARAMETER; 1176 1177 *p_vga_mode = d.vga_mode; 1178 1179 return 0; 1180} 1181 1182#if GFX_TV_DYNAMIC 1183int 1184fs450_get_available_tv_vga_modes(unsigned long *p_vga_modes) 1185#else 1186int 1187gfx_get_available_tv_vga_modes(unsigned long *p_vga_modes) 1188#endif 1189{ 1190 if (!p_vga_modes) 1191 return ERR_INVALID_PARAMETER; 1192 1193 *p_vga_modes = 1194 GFX_VGA_MODE_640X480 | 1195 GFX_VGA_MODE_720X487 | GFX_VGA_MODE_720X576 | GFX_VGA_MODE_800X600; 1196 if (houston_Rev() >= HOUSTON_REV_B) 1197 *p_vga_modes |= GFX_VGA_MODE_1024X768; 1198 1199 return 0; 1200} 1201 1202#if GFX_TV_DYNAMIC 1203int 1204fs450_set_tv_vga_mode(unsigned long vga_mode) 1205#else 1206int 1207gfx_set_tv_vga_mode(unsigned long vga_mode) 1208#endif 1209{ 1210 /*reject if not a single valid VGA mode */ 1211 switch (vga_mode) { 1212 default: 1213 return ERR_INVALID_PARAMETER; 1214 case GFX_VGA_MODE_640X480: 1215 case GFX_VGA_MODE_720X487: 1216 case GFX_VGA_MODE_720X576: 1217 case GFX_VGA_MODE_800X600: 1218 break; 1219 case GFX_VGA_MODE_1024X768: 1220 if (houston_Rev() >= HOUSTON_REV_B) 1221 break; 1222 return ERR_INVALID_PARAMETER; 1223 } 1224 1225 /*if the mode has changed... */ 1226 if (vga_mode != d.vga_mode) { 1227 d.vga_mode = vga_mode; 1228 1229 return write_config(REQ_VGA_MODE); 1230 } 1231 1232 return 0; 1233} 1234 1235/*==========================================================================*/ 1236/* tvout mode */ 1237/*==========================================================================*/ 1238 1239#if GFX_TV_DYNAMIC 1240int 1241fs450_get_tvout_mode(unsigned long *p_tvout_mode) 1242#else 1243int 1244gfx_get_tvout_mode(unsigned long *p_tvout_mode) 1245#endif 1246{ 1247 if (!p_tvout_mode) 1248 return ERR_INVALID_PARAMETER; 1249 1250 *p_tvout_mode = d.tvout_mode; 1251 1252 return 0; 1253} 1254 1255#if GFX_TV_DYNAMIC 1256int 1257fs450_set_tvout_mode(unsigned long tvout_mode) 1258#else 1259int 1260gfx_set_tvout_mode(unsigned long tvout_mode) 1261#endif 1262{ 1263 d.tvout_mode = tvout_mode; 1264 1265 return write_config(REQ_TVOUT_MODE); 1266} 1267 1268/*==========================================================================*/ 1269/* Sharpness */ 1270/*==========================================================================*/ 1271 1272#if GFX_TV_DYNAMIC 1273int 1274fs450_get_sharpness(int *p_sharpness) 1275#else 1276int 1277gfx_get_sharpness(int *p_sharpness) 1278#endif 1279{ 1280 if (!p_sharpness) 1281 return ERR_INVALID_PARAMETER; 1282 1283 *p_sharpness = d.sharpness; 1284 1285 return 0; 1286} 1287 1288#if GFX_TV_DYNAMIC 1289int 1290fs450_set_sharpness(int sharpness) 1291#else 1292int 1293gfx_set_sharpness(int sharpness) 1294#endif 1295{ 1296 d.sharpness = range_limit(sharpness, 0, 1000); 1297 1298 return write_config(REQ_SHARPNESS); 1299} 1300 1301/*==========================================================================*/ 1302/* flicker filter control. */ 1303/*==========================================================================*/ 1304 1305#if GFX_TV_DYNAMIC 1306int 1307fs450_get_flicker_filter(int *p_flicker) 1308#else 1309int 1310gfx_get_flicker_filter(int *p_flicker) 1311#endif 1312{ 1313 if (!p_flicker) 1314 return ERR_INVALID_PARAMETER; 1315 1316 *p_flicker = d.flicker; 1317 1318 return 0; 1319} 1320 1321#if GFX_TV_DYNAMIC 1322int 1323fs450_set_flicker_filter(int flicker) 1324#else 1325int 1326gfx_set_flicker_filter(int flicker) 1327#endif 1328{ 1329 d.flicker = range_limit(flicker, 0, 1000); 1330 1331 return write_config(REQ_FLICKER); 1332} 1333 1334/*==========================================================================*/ 1335/* Overscan and Position */ 1336/*==========================================================================*/ 1337 1338#if GFX_TV_DYNAMIC 1339int 1340fs450_get_overscan(int *p_x, int *p_y) 1341#else 1342int 1343gfx_get_overscan(int *p_x, int *p_y) 1344#endif 1345{ 1346 if (!p_x || !p_y) 1347 return ERR_INVALID_PARAMETER; 1348 1349 *p_x = d.overscan_x; 1350 *p_y = d.overscan_y; 1351 1352 return 0; 1353} 1354 1355#if GFX_TV_DYNAMIC 1356int 1357fs450_set_overscan(int x, int y) 1358#else 1359int 1360gfx_set_overscan(int x, int y) 1361#endif 1362{ 1363 d.overscan_x = range_limit(x, -1000, 1000); 1364 d.overscan_y = range_limit(y, -1000, 1000); 1365 1366 return write_config(REQ_OVERSCAN_POSITION); 1367} 1368 1369#if GFX_TV_DYNAMIC 1370int 1371fs450_get_position(int *p_x, int *p_y) 1372#else 1373int 1374gfx_get_position(int *p_x, int *p_y) 1375#endif 1376{ 1377 if (!p_x || !p_y) 1378 return ERR_INVALID_PARAMETER; 1379 1380 *p_x = d.position_x; 1381 *p_y = d.position_y; 1382 1383 return 0; 1384} 1385 1386#if GFX_TV_DYNAMIC 1387int 1388fs450_set_position(int x, int y) 1389#else 1390int 1391gfx_set_position(int x, int y) 1392#endif 1393{ 1394 d.position_x = range_limit(x, -1000, 1000); 1395 d.position_y = range_limit(y, -1000, 1000); 1396 1397 return write_config(REQ_OVERSCAN_POSITION); 1398} 1399 1400/*==========================================================================*/ 1401/* Color, Brightness, and Contrast */ 1402/*==========================================================================*/ 1403 1404#if GFX_TV_DYNAMIC 1405int 1406fs450_get_color(int *p_color) 1407#else 1408int 1409gfx_get_color(int *p_color) 1410#endif 1411{ 1412 if (!p_color) 1413 return ERR_INVALID_PARAMETER; 1414 1415 *p_color = d.color; 1416 1417 return 0; 1418} 1419 1420#if GFX_TV_DYNAMIC 1421int 1422fs450_set_color(int color) 1423#else 1424int 1425gfx_set_color(int color) 1426#endif 1427{ 1428 d.color = range_limit(color, 0, 100); 1429 1430 return write_config(REQ_COLOR); 1431} 1432 1433#if GFX_TV_DYNAMIC 1434int 1435fs450_get_brightness(int *p_brightness) 1436#else 1437int 1438gfx_get_brightness(int *p_brightness) 1439#endif 1440{ 1441 if (!p_brightness) 1442 return ERR_INVALID_PARAMETER; 1443 1444 *p_brightness = d.brightness; 1445 1446 return 0; 1447} 1448 1449#if GFX_TV_DYNAMIC 1450int 1451fs450_set_brightness(int brightness) 1452#else 1453int 1454gfx_set_brightness(int brightness) 1455#endif 1456{ 1457 d.brightness = range_limit(brightness, 0, 100); 1458 1459 return write_config(REQ_BRIGHTNESS_CONTRAST); 1460} 1461 1462#if GFX_TV_DYNAMIC 1463int 1464fs450_get_contrast(int *p_contrast) 1465#else 1466int 1467gfx_get_contrast(int *p_contrast) 1468#endif 1469{ 1470 if (!p_contrast) 1471 return ERR_INVALID_PARAMETER; 1472 1473 *p_contrast = d.contrast; 1474 1475 return 0; 1476} 1477 1478#if GFX_TV_DYNAMIC 1479int 1480fs450_set_contrast(int contrast) 1481#else 1482int 1483gfx_set_contrast(int contrast) 1484#endif 1485{ 1486 d.contrast = range_limit(contrast, 0, 100); 1487 1488 return write_config(REQ_BRIGHTNESS_CONTRAST); 1489} 1490 1491/*==========================================================================*/ 1492/* YC filters */ 1493/*==========================================================================*/ 1494 1495#if GFX_TV_DYNAMIC 1496int 1497fs450_get_yc_filter(unsigned int *p_yc_filter) 1498#else 1499int 1500gfx_get_yc_filter(unsigned int *p_yc_filter) 1501#endif 1502{ 1503 if (!p_yc_filter) 1504 return ERR_INVALID_PARAMETER; 1505 1506 if (houston_Rev() < HOUSTON_REV_B) 1507 return ERR_NOT_SUPPORTED; 1508 1509 *p_yc_filter = d.yc_filter; 1510 1511 return 0; 1512} 1513 1514#if GFX_TV_DYNAMIC 1515int 1516fs450_set_yc_filter(unsigned int yc_filter) 1517#else 1518int 1519gfx_set_yc_filter(unsigned int yc_filter) 1520#endif 1521{ 1522 if (houston_Rev() < HOUSTON_REV_B) 1523 return ERR_NOT_SUPPORTED; 1524 1525 /*luma filter. */ 1526 if (yc_filter & GFX_LUMA_FILTER) 1527 d.yc_filter |= GFX_LUMA_FILTER; 1528 else 1529 d.yc_filter &= ~GFX_LUMA_FILTER; 1530 1531 /*chroma filter. */ 1532 if (yc_filter & GFX_CHROMA_FILTER) 1533 d.yc_filter |= GFX_CHROMA_FILTER; 1534 else 1535 d.yc_filter &= ~GFX_CHROMA_FILTER; 1536 1537 return write_config(REQ_YC_FILTER); 1538} 1539 1540#if GFX_TV_DYNAMIC 1541int 1542fs450_get_aps_trigger_bits(unsigned int *p_trigger_bits) 1543#else 1544int 1545gfx_get_aps_trigger_bits(unsigned int *p_trigger_bits) 1546#endif 1547{ 1548 if (!p_trigger_bits) 1549 return ERR_INVALID_PARAMETER; 1550 1551 *p_trigger_bits = d.aps_trigger_bits; 1552 1553 return 0; 1554} 1555 1556#if GFX_TV_DYNAMIC 1557int 1558fs450_set_aps_trigger_bits(unsigned int trigger_bits) 1559#else 1560int 1561gfx_set_aps_trigger_bits(unsigned int trigger_bits) 1562#endif 1563{ 1564 d.aps_trigger_bits = trigger_bits; 1565 1566 return write_config(REQ_MACROVISION); 1567} 1568 1569/*---------------------------------------------------------------------------- 1570 * gfx_set_tv_format 1571 * 1572 * This routine sets the TV encoder registers to the specified format 1573 * and resolution. 1574 * Currently only NTSC 640x480 is supported. 1575 *---------------------------------------------------------------------------- 1576 */ 1577#if GFX_TV_DYNAMIC 1578int 1579fs450_set_tv_format(TVStandardType format, GfxOnTVType resolution) 1580#else 1581int 1582gfx_set_tv_format(TVStandardType format, GfxOnTVType resolution) 1583#endif 1584{ 1585 /* ### ADD ### IMPLEMENTATION */ 1586 return (0); 1587} 1588 1589/*---------------------------------------------------------------------------- 1590 * gfx_set_tv_output 1591 * 1592 * This routine sets the TV encoder registers to the specified output type. 1593 * Supported output types are : S-VIDEO and Composite. 1594 *---------------------------------------------------------------------------- 1595 */ 1596#if GFX_TV_DYNAMIC 1597int 1598fs450_set_tv_output(int output) 1599#else 1600int 1601gfx_set_tv_output(int output) 1602#endif 1603{ 1604 /* ### ADD ### IMPLEMENTATION */ 1605 return (0); 1606} 1607 1608/*---------------------------------------------------------------------------- 1609 * gfx_set_tv_cc_enable 1610 * 1611 * This routine enables or disables the use of the hardware CC registers 1612 * in the TV encoder. 1613 *---------------------------------------------------------------------------- 1614 */ 1615#if GFX_TV_DYNAMIC 1616int 1617fs450_set_tv_cc_enable(int enable) 1618#else 1619int 1620gfx_set_tv_cc_enable(int enable) 1621#endif 1622{ 1623 /* ### ADD ### IMPLEMENTATION */ 1624 return (0); 1625} 1626 1627/*---------------------------------------------------------------------------- 1628 * gfx_set_tv_cc_data 1629 * 1630 * This routine writes the two specified characters to the CC data register 1631 * of the TV encoder. 1632 *---------------------------------------------------------------------------- 1633 */ 1634#if GFX_TV_DYNAMIC 1635int 1636fs450_set_tv_cc_data(unsigned char data1, unsigned char data2) 1637#else 1638int 1639gfx_set_tv_cc_data(unsigned char data1, unsigned char data2) 1640#endif 1641{ 1642 /* ### ADD ### IMPLEMENTATION */ 1643 return (0); 1644} 1645 1646#ifdef FS450_DIRECTREG 1647 1648/*==========================================================================*/ 1649/* Direct Read and Write registers */ 1650/*==========================================================================*/ 1651 1652int 1653FS450_ReadRegister(S_REG_INFO * p_reg) 1654{ 1655 unsigned long tmp; 1656 1657 if (PLAL_ReadRegister(p_reg)) 1658 return 0; 1659 1660 if (SOURCE_HOUSTON == p_reg->source) { 1661 switch (p_reg->size) { 1662 case 1: 1663 case 2: 1664 { 1665 houston_ReadReg((int) p_reg->offset, &tmp, (int) p_reg->size); 1666 p_reg->value = tmp; 1667 } 1668 return 0; 1669 1670 case 4: 1671 { 1672 houston_ReadReg((unsigned int) p_reg->offset, &tmp, 2); 1673 p_reg->value = (tmp << 16); 1674 houston_ReadReg((unsigned int) (p_reg->offset + 2), &tmp, 2); 1675 p_reg->value |= tmp; 1676 } 1677 return 0; 1678 } 1679 } 1680 1681 return ERR_INVALID_PARAMETER; 1682} 1683 1684int 1685FS450_WriteRegister(S_REG_INFO * p_reg) 1686{ 1687 if (PLAL_WriteRegister(p_reg)) 1688 return 0; 1689 1690 if (SOURCE_HOUSTON == p_reg->source) { 1691 houston_WriteReg((unsigned int) p_reg->offset, p_reg->value, 1692 p_reg->size); 1693 1694 return 0; 1695 } 1696 1697 return ERR_INVALID_PARAMETER; 1698} 1699 1700#endif 1701 1702/* Houston initialization function. */ 1703static int g_houston_rev = -1; 1704 1705static int 1706houston_init(void) 1707{ 1708 /*//int errc; */ 1709 unsigned long write, read; 1710 1711 TRACE(("houston_init()\n")) 1712 1713 /*Before we begin, we must enable power to the TFT */ 1714 read = READ_VID32(CS5530_DISPLAY_CONFIG); 1715 read |= CS5530_DCFG_FP_PWR_EN | CS5530_DCFG_FP_DATA_EN; 1716 WRITE_VID32(CS5530_DISPLAY_CONFIG, read); 1717 1718 /*simple w/r test. */ 1719 write = 0x0055; 1720 read = 0; 1721 1722 houston_WriteReg(HOUSTON_IHO, write, 2); 1723 houston_ReadReg(HOUSTON_IHO, &read, 2); 1724 if (read != write) { 1725 houston_WriteReg(HOUSTON_IHO, write, 2); 1726 houston_ReadReg(HOUSTON_IHO, &read, 2); 1727 if (read != write) { 1728 /*chip is not there, do something appropriate? */ 1729 TRACE(("wrote HOUSTON_IHO=0x0055, read 0x%04x\n", read)) 1730 return ERR_DEVICE_NOT_FOUND; 1731 } 1732 } 1733 1734 /*read chip revision. */ 1735 houston_ReadReg(HOUSTON_REV, &read, 2); 1736 g_houston_rev = (int) read; 1737 1738 /*ok. */ 1739 return 0; 1740} 1741 1742static int 1743houston_Rev(void) 1744{ 1745 return g_houston_rev; 1746} 1747 1748static S_TIMING_SPECS g_specs; 1749 1750static const S_TIMING_SPECS * 1751p_specs(void) 1752{ 1753 return &g_specs; 1754} 1755 1756/*==========================================================================*/ 1757/* FS450 configuration functions. */ 1758/*==========================================================================*/ 1759static int 1760config_init(void) 1761{ 1762 int err; 1763 1764 TRACE(("config_init()\n")) 1765 1766 err = houston_init(); 1767 if (err) 1768 return err; 1769 1770 return 0; 1771} 1772 1773/*==========================================================================*/ 1774/* convert word to encoder 10 bit value. */ 1775/*==========================================================================*/ 1776 1777static unsigned short 1778w10bit2z(unsigned short w) 1779{ 1780 return (w >> 2) | ((w & 0x03) << 8); 1781} 1782 1783static unsigned short 1784z2w10bit(unsigned short z) 1785{ 1786 return (0x03 & (z >> 8)) | ((0xFF & z) << 2); 1787} 1788 1789/*==========================================================================*/ 1790/* TV Standards */ 1791/*==========================================================================*/ 1792 1793static const struct { 1794 unsigned long standard; 1795 int tvsetup_index; 1796} g_tv_standards[] = { 1797 { 1798 GFX_TV_STANDARD_NTSC_M, 0}, { 1799 GFX_TV_STANDARD_NTSC_M_J, 2}, { 1800 GFX_TV_STANDARD_PAL_B, 1}, { 1801 GFX_TV_STANDARD_PAL_D, 1}, { 1802 GFX_TV_STANDARD_PAL_H, 1}, { 1803 GFX_TV_STANDARD_PAL_I, 1}, { 1804 GFX_TV_STANDARD_PAL_M, 3}, { 1805 GFX_TV_STANDARD_PAL_N, 4}, { 1806GFX_TV_STANDARD_PAL_G, 1},}; 1807 1808static int 1809map_tvstd_to_index(unsigned long tv_std) 1810{ 1811 unsigned int i; 1812 1813 for (i = 0; i < sizeof(g_tv_standards) / sizeof(*g_tv_standards); i++) { 1814 if (tv_std == g_tv_standards[i].standard) 1815 return g_tv_standards[i].tvsetup_index; 1816 } 1817 1818 return -1; 1819} 1820 1821static unsigned long 1822supported_standards(void) 1823{ 1824 unsigned long standards = 0; 1825 unsigned int i; 1826 1827 for (i = 0; i < sizeof(g_tv_standards) / sizeof(*g_tv_standards); i++) { 1828 if (g_tv_standards[i].tvsetup_index >= 0) 1829 standards |= g_tv_standards[i].standard; 1830 } 1831 1832 return standards; 1833} 1834 1835/*==========================================================================*/ 1836 1837static void 1838config_power(int on) 1839{ 1840 unsigned long reg; 1841 1842 if (houston_Rev() < HOUSTON_REV_B) { 1843 /* no power down supported, but still turn of clock in off mode */ 1844 if (on) { 1845 houston_ReadReg(HOUSTON_CR, ®, 2); 1846 reg &= ~(CR_CLKOFF | CR_RESET); 1847 houston_WriteReg(HOUSTON_CR, reg, 2); 1848 reg |= CR_RESET; 1849 houston_WriteReg(HOUSTON_CR, reg, 2); 1850 reg &= ~CR_RESET; 1851 houston_WriteReg(HOUSTON_CR, reg, 2); 1852 } 1853 else { 1854 houston_ReadReg(HOUSTON_CR, ®, 2); 1855 reg |= CR_CLKOFF; 1856 houston_WriteReg(HOUSTON_CR, reg, 2); 1857 } 1858 1859 return; 1860 } 1861 1862 if (on) { 1863 /* !CLKOFF, !COMPOFF, !YCOFF */ 1864 /* and reset Houston */ 1865 houston_ReadReg(HOUSTON_CR, ®, 2); 1866 reg &= ~(CR_CLKOFF | CR_RESET | CR_COMPOFF | CR_YCOFF); 1867 houston_WriteReg(HOUSTON_CR, reg, 2); 1868 reg |= CR_RESET; 1869 houston_WriteReg(HOUSTON_CR, reg, 2); 1870 reg &= ~CR_RESET; 1871 houston_WriteReg(HOUSTON_CR, reg, 2); 1872 1873 /* !GTLIO_PD */ 1874 houston_ReadReg(HOUSTON_MISC, ®, 2); 1875 reg &= ~MISC_GTLIO_PD; 1876 houston_WriteReg(HOUSTON_MISC, reg, 2); 1877 } 1878 else { 1879 /* CLKOFF, COMPOFF, YCOFF */ 1880 houston_ReadReg(HOUSTON_CR, ®, 2); 1881 reg |= (CR_CLKOFF | CR_COMPOFF | CR_YCOFF); 1882 houston_WriteReg(HOUSTON_CR, reg, 2); 1883 1884 /* GTLIO_PD */ 1885 houston_ReadReg(HOUSTON_MISC, ®, 2); 1886 reg |= MISC_GTLIO_PD; 1887 houston_WriteReg(HOUSTON_MISC, reg, 2); 1888 } 1889} 1890 1891/*==========================================================================*/ 1892/* VGA mode */ 1893/*==========================================================================*/ 1894 1895static void 1896config_vga_mode(unsigned long vga_mode) 1897{ 1898 /*h_total must be evenly divisible by 32? */ 1899 1900 static struct { 1901 unsigned long mode; 1902 int width; 1903 int lines; 1904 int h_total; 1905 } vgaparams[] = { 1906 { 1907 GFX_VGA_MODE_640X480, 640, 480, 1056}, { 1908 GFX_VGA_MODE_720X487, 720, 487, 1056}, { 1909 GFX_VGA_MODE_720X576, 720, 576, 1056}, { 1910 GFX_VGA_MODE_800X600, 800, 600, 1056}, { 1911 GFX_VGA_MODE_1024X768, 1024, 768, 1344},}; 1912 1913 unsigned long cr, misc, byp; 1914 unsigned int i; 1915 1916 g_specs.vga_width = 0; 1917 g_specs.vga_lines = 0; 1918 g_specs.h_total = 0; 1919 1920 for (i = 0; i < sizeof(vgaparams) / sizeof(*vgaparams); i++) { 1921 if (vga_mode == vgaparams[i].mode) { 1922 g_specs.vga_width = vgaparams[i].width; 1923 g_specs.vga_lines = vgaparams[i].lines; 1924 g_specs.h_total = vgaparams[i].h_total; 1925 break; 1926 } 1927 } 1928 if (!g_specs.h_total) 1929 return; 1930 1931 /*clock mux decimator and vga dual. */ 1932 houston_ReadReg(HOUSTON_CR, &cr, 2); 1933 houston_ReadReg(HOUSTON_MISC, &misc, 2); 1934 houston_ReadReg(HOUSTON_BYP, &byp, 2); 1935 1936 if (vga_mode == GFX_VGA_MODE_1024X768) { 1937 /*XGA*/ cr |= CR_UIM_DEC; 1938 misc |= MISC_VGACKDIV; 1939 byp |= (BYP_HDS_BYPASS | BYP_CAC_BYPASS); 1940 } 1941 else { 1942 /*VGA,SVGA */ 1943 cr &= ~CR_UIM_DEC; 1944 misc &= ~MISC_VGACKDIV; 1945 byp &= ~(BYP_HDS_BYPASS | BYP_CAC_BYPASS); 1946 } 1947 1948 houston_WriteReg(HOUSTON_CR, cr, 2); 1949 houston_WriteReg(HOUSTON_MISC, misc, 2); 1950 houston_WriteReg(HOUSTON_BYP, byp, 2); 1951} 1952 1953/*==========================================================================*/ 1954/* Write settings for TV standard to device */ 1955/*==========================================================================*/ 1956 1957static void 1958config_tv_std(unsigned long tv_std, unsigned int trigger_bits) 1959{ 1960 int k; 1961 unsigned short reg34; 1962 unsigned long cr, w; 1963 unsigned long l; 1964 1965 /*verify supported standard. */ 1966 k = map_tvstd_to_index(tv_std); 1967 if (k < 0) 1968 return; 1969 1970 /*store tv width and lines */ 1971 g_specs.tv_width = tvsetup.tv_width[k]; 1972 g_specs.tv_lines = tvsetup.tv_lines[k]; 1973 1974 /*houston CR register. */ 1975 houston_ReadReg(HOUSTON_CR, &cr, 2); 1976 cr &= ~CR_656_PAL_NTSC; 1977 cr |= tvsetup.houston_cr[k]; 1978 houston_WriteReg(HOUSTON_CR, cr, 2); 1979 1980 /*setup the encoder. */ 1981 l = tvsetup.chroma_freq[k]; 1982 houston_WriteReg(ENC_CHROMA_FREQ, (int) (l & 0x00ff), 1); 1983 houston_WriteReg(ENC_CHROMA_FREQ + 1, (int) ((l >> 8) & 0x00ff), 1); 1984 houston_WriteReg(ENC_CHROMA_FREQ + 2, (int) ((l >> 16) & 0x00ff), 1); 1985 houston_WriteReg(ENC_CHROMA_FREQ + 3, (int) ((l >> 24) & 0x00ff), 1); 1986 1987 houston_WriteReg(ENC_CHROMA_PHASE, tvsetup.chroma_phase[k], 1); 1988 houston_WriteReg(ENC_REG05, 0x00, 1); /*reg 0x05 */ 1989 houston_WriteReg(ENC_REG06, 0x89, 1); /*reg 0x06 */ 1990 houston_WriteReg(ENC_REG07, 0x00, 1); /*reg 0x07 */ 1991 houston_WriteReg(ENC_HSYNC_WIDTH, tvsetup.hsync_width[k], 1); 1992 houston_WriteReg(ENC_BURST_WIDTH, tvsetup.burst_width[k], 1); 1993 houston_WriteReg(ENC_BACK_PORCH, tvsetup.back_porch[k], 1); 1994 houston_WriteReg(ENC_CB_BURST_LEVEL, tvsetup.cb_burst_level[k], 1); 1995 houston_WriteReg(ENC_CR_BURST_LEVEL, tvsetup.cr_burst_level[k], 1); 1996 houston_WriteReg(ENC_SLAVE_MODE, 0x01, 1); /*slave mode */ 1997 if (trigger_bits == 0) 1998 w = w10bit2z(tvsetup.blank_level[k]); /*blank level */ 1999 else 2000 w = w10bit2z((unsigned short) (tvsetup.blank_level[k] - 2001 tvsetup.hamp_offset[k])); 2002 houston_WriteReg(ENC_BLANK_LEVEL, w & 0x00ff, 1); 2003 houston_WriteReg(ENC_BLANK_LEVEL + 1, w >> 8, 1); 2004 w = w10bit2z(tvsetup.tv_lines[k]); /*num_lines */ 2005 houston_WriteReg(ENC_NUM_LINES, w & 0x00ff, 1); 2006 houston_WriteReg(ENC_NUM_LINES + 1, w >> 8, 1); 2007 2008 houston_WriteReg(ENC_TINT, 0x00, 1); /*tint */ 2009 houston_WriteReg(ENC_BREEZE_WAY, tvsetup.breeze_way[k], 1); 2010 houston_WriteReg(ENC_FRONT_PORCH, tvsetup.front_porch[k], 1); 2011 houston_WriteReg(ENC_ACTIVELINE, tvsetup.activeline[k], 1); 2012 houston_WriteReg(ENC_FIRST_LINE, 0x15, 1); /*firstvideoline */ 2013 reg34 = 2014 0x80 | 2015 (tvsetup.pal_mode[k] << 6) | 2016 (tvsetup.sys625_50[k] << 3) | 2017 (tvsetup.cphase_rst[k] << 1) | (tvsetup.vsync5[k]); 2018 houston_WriteReg(ENC_REG34, reg34, 1); /*reg 0x34 */ 2019 houston_WriteReg(ENC_SYNC_LEVEL, tvsetup.sync_level[k], 1); 2020 if (trigger_bits == 0) 2021 w = w10bit2z(tvsetup.vbi_blank_level[k]); /*blank level */ 2022 else 2023 w = w10bit2z((unsigned short) (tvsetup.vbi_blank_level[k] - 1)); 2024 houston_WriteReg(ENC_VBI_BLANK_LEVEL, w & 0x00ff, 1); 2025 houston_WriteReg(ENC_VBI_BLANK_LEVEL + 1, w >> 8, 1); 2026} 2027 2028static void 2029conget_tv_std(unsigned long *p_tv_standard) 2030{ 2031 unsigned long cr; 2032 2033 if (!p_tv_standard) 2034 return; 2035 2036 /*just pick between NTSC and PAL */ 2037 houston_ReadReg(HOUSTON_CR, &cr, 2); 2038 if (CR_656_PAL_NTSC & cr) 2039 *p_tv_standard = GFX_TV_STANDARD_PAL_B; 2040 else 2041 *p_tv_standard = GFX_TV_STANDARD_NTSC_M; 2042} 2043 2044/*==========================================================================*/ 2045/* TVout mode */ 2046/*==========================================================================*/ 2047 2048static void 2049config_tvout_mode(unsigned long tvout_mode) 2050{ 2051 unsigned long cr; 2052 2053 houston_ReadReg(HOUSTON_CR, &cr, 2); 2054 2055 /*all dacs off */ 2056 cr |= (CR_COMPOFF | CR_YCOFF); 2057 /*not rgb */ 2058 cr &= ~CR_OFMT; 2059 2060 /*turn on requested output */ 2061 if (GFX_TVOUT_MODE_CVBS & tvout_mode) 2062 cr &= ~CR_COMPOFF; 2063 if (GFX_TVOUT_MODE_YC & tvout_mode) 2064 cr &= ~CR_YCOFF; 2065 if (GFX_TVOUT_MODE_RGB & tvout_mode) { 2066 cr &= ~(CR_COMPOFF | CR_YCOFF); 2067 cr |= CR_OFMT; 2068 } 2069 2070 houston_WriteReg(HOUSTON_CR, cr, 2); 2071} 2072 2073static void 2074conget_tvout_mode(unsigned long *p_tvout_mode) 2075{ 2076 unsigned long cr; 2077 2078 if (!p_tvout_mode) 2079 return; 2080 2081 houston_ReadReg(HOUSTON_CR, &cr, 2); 2082 2083 if (CR_OFMT & cr) 2084 *p_tvout_mode = GFX_TVOUT_MODE_RGB; 2085 else { 2086 *p_tvout_mode = 0; 2087 if (!(CR_YCOFF & cr)) 2088 *p_tvout_mode |= GFX_TVOUT_MODE_YC; 2089 if (!(CR_COMPOFF & cr)) 2090 *p_tvout_mode |= GFX_TVOUT_MODE_CVBS; 2091 } 2092} 2093 2094/*==========================================================================*/ 2095/* Size & Position */ 2096/*==========================================================================*/ 2097 2098#define IS_NTSC(tv_std) \ 2099 (tv_std & ( \ 2100 GFX_TV_STANDARD_NTSC_M | \ 2101 GFX_TV_STANDARD_NTSC_M_J | \ 2102 GFX_TV_STANDARD_PAL_M)) 2103#define IS_PAL(tv_std) \ 2104 (tv_std & ( \ 2105 GFX_TV_STANDARD_PAL_B | \ 2106 GFX_TV_STANDARD_PAL_D | \ 2107 GFX_TV_STANDARD_PAL_H | \ 2108 GFX_TV_STANDARD_PAL_I | \ 2109 GFX_TV_STANDARD_PAL_N | \ 2110 GFX_TV_STANDARD_PAL_G)) 2111 2112/*return fifo delay setting for mode, std, and total lines.*/ 2113 2114static void 2115get_ffolat_ivo(unsigned long vga_mode, 2116 unsigned long tv_std, long i, unsigned short *ffolat, 2117 unsigned short *ivo) 2118{ 2119 switch (vga_mode) { 2120 case GFX_VGA_MODE_640X480: 2121 if (IS_NTSC(tv_std)) { 2122 if (i > SIZE6X4NTSC - 1) 2123 i = SIZE6X4NTSC - 1; 2124 *ffolat = ffo6x4ntsc[i].ffolat; 2125 *ivo = 0x20; 2126 } 2127 else { 2128 if (i > SIZE6X4PAL - 1) 2129 i = SIZE6X4PAL - 1; 2130 *ffolat = ffo6x4pal[i].ffolat; 2131 *ivo = 0x28; 2132 } 2133 break; 2134 2135 case GFX_VGA_MODE_800X600: 2136 if (IS_NTSC(tv_std)) { 2137 if (i > SIZE8X6NTSC - 1) 2138 i = SIZE8X6NTSC - 1; 2139 *ffolat = ffo8x6ntsc[i].ffolat; 2140 *ivo = 0x3a; 2141 } 2142 else { 2143 if (i > SIZE8X6PAL - 1) 2144 i = SIZE8X6PAL - 1; 2145 *ffolat = ffo8x6pal[i].ffolat; 2146 *ivo = 0x39; 2147 } 2148 break; 2149 2150 case GFX_VGA_MODE_720X487: 2151 *ffolat = 0x40; /*FFO7x4; */ 2152 *ivo = 0x1a; 2153 break; 2154 2155 case GFX_VGA_MODE_720X576: 2156 *ffolat = 0x40; /*FFO7x5; */ 2157 *ivo = 0x1a; 2158 break; 2159 2160 case GFX_VGA_MODE_1024X768: 2161 default: 2162 if (IS_NTSC(tv_std)) { 2163 if (i > SIZE10X7NTSC - 1) 2164 i = SIZE10X7NTSC - 1; 2165 *ffolat = ffo10x7ntsc[i].ffolat; 2166 *ivo = ffo10x7ntsc[i].ivo; 2167 } 2168 else { 2169 if (i > SIZE10X7PAL - 1) 2170 i = SIZE10X7PAL - 1; 2171 *ffolat = ffo10x7pal[i].ffolat; 2172 *ivo = ffo10x7pal[i].ivo; 2173 } 2174 break; 2175 } 2176} 2177 2178/*get vertical line min and max for mode and std.*/ 2179 2180static void 2181get_vtotal_min_max(unsigned long vga_mode, 2182 unsigned long tv_std, int *v_total_min, int *v_total_max, 2183 int *v_step) 2184{ 2185 int k = map_tvstd_to_index(tv_std); 2186 2187 switch (vga_mode) { 2188 case GFX_VGA_MODE_640X480: 2189 if (IS_NTSC(tv_std)) { 2190 *v_total_min = ffo6x4ntsc[0].v_total; 2191 *v_total_max = ffo6x4ntsc[SIZE6X4NTSC - 1].v_total; 2192 } 2193 else { 2194 *v_total_min = ffo6x4pal[0].v_total; 2195 *v_total_max = ffo6x4pal[SIZE6X4PAL - 1].v_total; 2196 } 2197 *v_step = 4; 2198 break; 2199 2200 case GFX_VGA_MODE_800X600: 2201 if (IS_NTSC(tv_std)) { 2202 *v_total_min = ffo8x6ntsc[0].v_total; 2203 *v_total_max = ffo8x6ntsc[SIZE8X6NTSC - 1].v_total; 2204 } 2205 else { 2206 *v_total_min = ffo8x6pal[0].v_total; 2207 *v_total_max = ffo8x6pal[SIZE8X6PAL - 1].v_total; 2208 } 2209 *v_step = 5; 2210 break; 2211 2212 case GFX_VGA_MODE_720X487: 2213 case GFX_VGA_MODE_720X576: 2214 *v_total_min = tvsetup.tv_lines[k]; 2215 *v_total_max = tvsetup.tv_lines[k]; 2216 *v_step = 4; 2217 break; 2218 2219 case GFX_VGA_MODE_1024X768: 2220 if (IS_NTSC(tv_std)) { 2221 *v_total_min = ffo10x7ntsc[0].v_total; 2222 *v_total_max = ffo10x7ntsc[SIZE10X7NTSC - 1].v_total; 2223 } 2224 else { 2225 *v_total_min = ffo10x7pal[0].v_total; 2226 *v_total_max = ffo10x7pal[SIZE10X7PAL - 1].v_total; 2227 } 2228 *v_step = 6; 2229 break; 2230 } 2231} 2232 2233static void 2234config_overscan_xy(unsigned long tv_std, 2235 unsigned long vga_mode, 2236 int overscan_x, int overscan_y, int pos_x, int pos_y) 2237{ 2238 unsigned int vga_index; 2239 unsigned long reg; 2240 double vsc; 2241 int k; 2242 unsigned short ffolat, ivo; 2243 int base_v_total, range, v_offset; 2244 int v_total_min, v_total_max, v_step; 2245 float r, f; 2246 int vga_pixels, pre_pixels; 2247 float hscale, hscale_min, hscale_max; 2248 int hsc; 2249 int iho, iho_max, ihw; 2250 2251 /*tv_std is valid. */ 2252 k = map_tvstd_to_index(tv_std); 2253 2254 /*store tv width and lines */ 2255 g_specs.tv_width = tvsetup.tv_width[k]; 2256 g_specs.tv_lines = tvsetup.tv_lines[k]; 2257 2258 /*determine vga mode index */ 2259 for (vga_index = 0; vga_index < SCANTABLE_ENTRIES; vga_index++) { 2260 if (scantable[vga_index].mode == vga_mode) 2261 break; 2262 } 2263 if (vga_index >= SCANTABLE_ENTRIES) 2264 return; 2265 2266 /*vertical scaling (v_total setup). */ 2267 /*calculate vertical range. */ 2268 get_vtotal_min_max(vga_mode, tv_std, &v_total_min, &v_total_max, &v_step); 2269 TRACE(("v_total min=%d, max=%d\n", v_total_min, v_total_max)) 2270 base_v_total = scantable[vga_index].v_total[k]; 2271 range = fsmax(base_v_total - v_total_min, v_total_max - base_v_total); 2272 TRACE(("v_total range = %d\n", range)) 2273 2274 /*map +/-1000 overscan y into +/-range. */ 2275 v_offset = (int) ((((float) overscan_y * range) / 1000.f) + .5f); 2276 TRACE(("v_offset = %d\n", v_offset)) 2277 2278 /*range limit v_total. */ 2279 g_specs.v_total = 2280 range_limit(base_v_total + v_offset, v_total_min, v_total_max); 2281 2282 /*round to calibrated value. */ 2283 v_offset = (g_specs.v_total - v_total_min + (v_step / 2)) / v_step; 2284 g_specs.v_total = v_total_min + v_offset * v_step; 2285 TRACE(("desired v_total=%d\n", g_specs.v_total)) 2286 2287 /*vertical positioning (vsync setup). */ 2288 get_ffolat_ivo(vga_mode, tv_std, v_offset, &ffolat, &ivo); 2289 houston_WriteReg(HOUSTON_IVO, ivo, 2); 2290 2291 /*scale base sync offset by scaling ratio. */ 2292 r = (float) g_specs.v_total / (float) base_v_total; 2293 v_offset = (int) (r * (float) scantable[vga_index].v_sync[k]); 2294 2295 /*scale ivo. */ 2296 f = (float) ivo; 2297 v_offset -= (int) (f - f / r); 2298 2299 /*compensate for center screen. */ 2300 f = (float) tvsetup.tv_active_lines[k] / 2.f; 2301 v_offset += (int) (f * r - f); 2302 2303 /*calculate vsync. */ 2304 g_specs.v_sync = g_specs.v_total - v_offset + pos_y; 2305 TRACE(("desired v_total=%d, desired v_sync=%d\n", g_specs.v_total, 2306 g_specs.v_sync)) 2307 if (g_specs.v_sync < g_specs.vga_lines + 10) { 2308 TRACE(("vsync too low\n")) 2309 /*d.v_total += d.vga_lines+10-d.v_sync; */ 2310 g_specs.v_sync = g_specs.vga_lines + 10; 2311 } 2312 else if (g_specs.v_sync > g_specs.v_total - 10) { 2313 TRACE(("vsync too high\n")) 2314 g_specs.v_sync = g_specs.v_total - 10; 2315 } 2316 TRACE(("v_total=%d v_sync=%d\n", g_specs.v_total, g_specs.v_sync)) 2317 2318 /* FFOLAT. */ 2319 houston_WriteReg(HOUSTON_FFO_LAT, ffolat, 2); 2320 2321 /* VSC. */ 2322 vsc = 2323 (65536.0f * (1.0f - 2324 (double) g_specs.tv_lines / (double) g_specs.v_total)) + 2325 0.5f; 2326 reg = ((unsigned long) -vsc) & 0xffff; 2327 TRACE(("vsc=%04x, tv_lines=%d, v_total=%d\n", reg, g_specs.tv_lines, 2328 g_specs.v_total)) 2329 houston_WriteReg(HOUSTON_VSC, (int) reg, 2); 2330 2331 /* horizontal scaling. */ 2332 2333 /* vga pixels is vga width, except in 1024x768, where it's half that. */ 2334 vga_pixels = g_specs.vga_width; 2335 if (1024 == vga_pixels) 2336 vga_pixels /= 2; 2337 2338 /* maximum scaling coefficient is tv_width / vga_pixels */ 2339 /* minimum is about 1/2, but that is quite small. arbitrarily set 2340 * minimum at 75% maximum. */ 2341 hscale_max = (720.0f / vga_pixels); 2342 hscale_min = fsmax((0.75f * hscale_max), (1.0f - (63.0f / 128.0f))); 2343 TRACE(("hscale_min = %u.%u, hscale_max = %u.%u\n", 2344 (int) hscale_min, 2345 (int) ((hscale_min - (int) hscale_min) * 1000), 2346 (int) hscale_max, (int) ((hscale_max - (int) hscale_max) * 1000))) 2347 2348 /* map overscan_x into min to max. */ 2349 hscale = 2350 hscale_min + ((overscan_x + 1000.0f) / 2000.0f) * (hscale_max - 2351 hscale_min); 2352 TRACE(("hscale = %u.%u\n", (int) hscale, 2353 (int) ((hscale - (int) hscale) * 1000))) 2354 2355 /* determine hsc where hscale = (1 + hsc/128) */ 2356 if (hscale >= 1.0f) 2357 hsc = (int) (128.f * (hscale - 1.0f) + .5f); 2358 else 2359 hsc = (int) (128.f * (hscale - 1.0f) - .5f); 2360 2361 TRACE(("hsc = %d\n", hsc)) 2362 if (hsc >= 0) 2363 houston_WriteReg(HOUSTON_HSC, hsc << 8, 2); 2364 else 2365 houston_WriteReg(HOUSTON_HSC, hsc & 0xFF, 2); 2366 2367 /* recalculate hscale for future formulas */ 2368 hscale = 1.0f + (hsc / 128.0f); 2369 TRACE(("recalculated hscale = %u.%u\n", (int) hscale, 2370 (int) ((hscale - (int) hscale) * 1000))) 2371 2372 /* horizontal offset. */ 2373 /* place hsync 40 before halfway from vga_width to htotal */ 2374 /* but not less than vga_width + 10 */ 2375 g_specs.h_sync = 2376 fsmax((g_specs.h_total + g_specs.vga_width) / 2 - 40, 2377 g_specs.vga_width + 10); 2378 /* also, make it even */ 2379 g_specs.h_sync &= ~1; 2380 TRACE(("hsync = %u\n", g_specs.h_sync)) 2381 2382 /* iho range is 0 to iho_max. */ 2383 /* iho_max is 2 * iho_center. */ 2384 /* iho_center is pre_pixels - (tvwidth / hscale - vga pixels) / 2. */ 2385 /* pre_pixels = (htotal - hsync) * (vga_pixels / vga_width) */ 2386 /* note that the range is inverted also, because it specifies the number 2387 * of pixels */ 2388 /* to skip, or subtract. iho=0 maps to farthest right. */ 2389 /* map -pos_x = +/-1000 into (0 to iho_max) */ 2390 pre_pixels = 2391 (int) ((long) (g_specs.h_total - 2392 g_specs.h_sync) * vga_pixels / g_specs.vga_width); 2393 iho_max = (2 * pre_pixels) - ((int) (720.0f / hscale + 0.5f) - vga_pixels); 2394 TRACE(("iho_max = %u\n", iho_max)) 2395 iho = 2396 (int) range_limit(((long) (1000 - pos_x) * iho_max / 2000) + 2397 scantable[vga_index].iho[k], 0, iho_max); 2398 TRACE(("iho = %u\n", iho)) 2399 houston_WriteReg(HOUSTON_IHO, iho, 2); 2400 2401 /* input horizontal width. */ 2402 2403 /* input horizontal width is vga pixels + pre_pixels - iho */ 2404 /* additionally, ihw cannot exceed tv width / hscale */ 2405 /* and if hsc is negative, (ihw)(-hsc/128) cannot exceed ~250. */ 2406 /* and ihw should be even. */ 2407 ihw = fsmin(vga_pixels + pre_pixels - iho, (int) (720.0f / hscale)); 2408 if (hsc < 0) 2409 ihw = (int) fsmin(ihw, 253L * 128 / (-hsc)); 2410 ihw &= ~1; 2411 TRACE(("ihw = %u\n", ihw)) 2412 houston_WriteReg(HOUSTON_IHA, ihw, 2); 2413 2414 f = (((float) g_specs.h_total * g_specs.v_total) * 27.f) / 2415 ((float) g_specs.tv_width * g_specs.tv_lines); 2416 2417 TRACE(("freq=%u.%uMHz\n", (int) f, (int) ((f - (int) f) * 1000))) 2418} 2419 2420/*==========================================================================*/ 2421/* configure houston nco. */ 2422/*==========================================================================*/ 2423 2424static void 2425config_nco(unsigned long tv_std, unsigned long vga_mode) 2426{ 2427 unsigned long cr, misc; 2428 unsigned long reg; 2429 int k = map_tvstd_to_index(tv_std); 2430 2431 /*read and store CR. */ 2432 houston_ReadReg(HOUSTON_CR, &cr, 2); 2433 2434 /*make sure NCO_EN (enable latch) bit is clear */ 2435 cr &= ~CR_NCO_EN; 2436 houston_WriteReg(HOUSTON_CR, cr, 2); 2437 2438 /*clear NCO_LOADX. */ 2439 houston_ReadReg(HOUSTON_MISC, &misc, 2); 2440 misc &= ~(MISC_NCO_LOAD1 + MISC_NCO_LOAD0); 2441 houston_WriteReg(HOUSTON_MISC, misc, 2); 2442 2443 if (vga_mode == GFX_VGA_MODE_1024X768) { 2444 /*setup for M and N load (Nco_load=1). */ 2445 misc |= (MISC_NCO_LOAD0); 2446 houston_WriteReg(HOUSTON_MISC, misc, 2); 2447 2448 /*M and N. */ 2449 houston_WriteReg(HOUSTON_NCONL, 1024 - 2, 2); 2450 houston_WriteReg(HOUSTON_NCODL, 128 - 1, 2); 2451 2452 /*latch M/N in. */ 2453 cr |= CR_NCO_EN; 2454 houston_WriteReg(HOUSTON_CR, cr, 2); 2455 cr &= ~CR_NCO_EN; 2456 houston_WriteReg(HOUSTON_CR, cr, 2); 2457 2458 /*setup ncon and ncod load (Nco_load=0). */ 2459 misc &= ~(MISC_NCO_LOAD1 + MISC_NCO_LOAD0); 2460 houston_WriteReg(HOUSTON_MISC, misc, 2); 2461 2462 /*NCON. */ 2463 reg = ((unsigned long) g_specs.v_total * g_specs.h_total) / 2; 2464 houston_WriteReg(HOUSTON_NCONH, reg >> 16, 2); 2465 houston_WriteReg(HOUSTON_NCONL, reg & 0xffff, 2); 2466 2467 /*NCOD. */ 2468 houston_WriteReg(HOUSTON_NCODL, tvsetup.houston_ncodl[k], 2); 2469 houston_WriteReg(HOUSTON_NCODH, tvsetup.houston_ncodh[k], 2); 2470 } 2471 else { 2472 /*setup for M and N load (Nco_load=2). */ 2473 misc |= (MISC_NCO_LOAD1); 2474 houston_WriteReg(HOUSTON_MISC, misc, 2); 2475 2476 /*NCON. */ 2477 reg = (unsigned long) g_specs.v_total * g_specs.h_total; 2478 houston_WriteReg(HOUSTON_NCONH, reg >> 16, 2); 2479 houston_WriteReg(HOUSTON_NCONL, reg & 0xffff, 2); 2480 2481 /*NCOD. */ 2482 houston_WriteReg(HOUSTON_NCODL, tvsetup.houston_ncodl[k], 2); 2483 houston_WriteReg(HOUSTON_NCODH, tvsetup.houston_ncodh[k], 2); 2484 2485 TRACE(("NCON = %lu (0x%08lx), NCOD = %lu (0x%08lx)\n", 2486 reg, 2487 reg, 2488 ((unsigned long) tvsetup.houston_ncodh[k] << 16) + 2489 tvsetup.houston_ncodl[k], 2490 ((unsigned long) tvsetup.houston_ncodh[k] << 16) + 2491 tvsetup.houston_ncodl[k])) 2492 } 2493 2494 /*latch M/N and NCON/NCOD in. */ 2495 cr |= CR_NCO_EN; 2496 houston_WriteReg(HOUSTON_CR, cr, 2); 2497 cr &= ~CR_NCO_EN; 2498 houston_WriteReg(HOUSTON_CR, cr, 2); 2499} 2500 2501/*==========================================================================*/ 2502/* Write sharpness settings to device */ 2503/*==========================================================================*/ 2504 2505static void 2506config_sharpness(int sharpness) 2507{ 2508 unsigned int shp; 2509 2510 /*map 0-1000 to 0-20. */ 2511 shp = (unsigned int) (0.5f + ((float) sharpness * 20.0f / 1000.0f)); 2512 shp = range_limit(shp, 0, 20); 2513 2514 houston_WriteReg(HOUSTON_SHP, shp, 2); 2515} 2516 2517static void 2518conget_sharpness(int *p_sharpness) 2519{ 2520 unsigned long shp; 2521 2522 if (!p_sharpness) 2523 return; 2524 2525 houston_ReadReg(HOUSTON_SHP, &shp, 2); 2526 2527 /*map 0-20 to 0-1000. */ 2528 *p_sharpness = (int) (0.5f + ((float) shp * 1000.0f / 20.0f)); 2529} 2530 2531/*==========================================================================*/ 2532/* Write flicker settings to device */ 2533/*==========================================================================*/ 2534 2535static void 2536config_flicker(int flicker) 2537{ 2538 unsigned int flk; 2539 2540 /*map 0-1000 to 0-16. */ 2541 flk = (unsigned int) (0.5f + ((float) flicker * 16.0f / 1000.0f)); 2542 flk = range_limit(flk, 0, 16); 2543 2544 houston_WriteReg(HOUSTON_FLK, flk, 2); 2545} 2546 2547static void 2548conget_flicker(int *p_flicker) 2549{ 2550 unsigned long flk; 2551 2552 if (!p_flicker) 2553 return; 2554 2555 houston_ReadReg(HOUSTON_FLK, &flk, 2); 2556 2557 /*map 0-16 to 0-1000. */ 2558 *p_flicker = (int) (0.5f + ((float) flk * 1000.0f / 16.0f)); 2559} 2560 2561/*==========================================================================*/ 2562/* Write color settings to device */ 2563/*==========================================================================*/ 2564 2565static void 2566config_color(int color) 2567{ 2568 unsigned long clr; 2569 2570 /*map 0-100 to 0-255. */ 2571 /*montreal production test needs 169 to be mappable, so */ 2572 /*use .8 rounding factor, 169=(int)(66.*2.55+.8). */ 2573 clr = (unsigned long) (0.8f + ((float) color * 255.0f / 100.0f)); 2574 clr = range_limit(clr, 0, 255); 2575 2576 houston_WriteReg(ENC_CR_GAIN, clr, 1); 2577 houston_WriteReg(ENC_CB_GAIN, clr, 1); 2578} 2579 2580static void 2581conget_color(int *p_color) 2582{ 2583 unsigned long cr_gain; 2584 2585 if (!p_color) 2586 return; 2587 2588 /*just get CR GAIN, CB GAIN should match. */ 2589 houston_ReadReg(ENC_CR_GAIN, &cr_gain, 1); 2590 2591 /*map 0-255 to 0-100. */ 2592 *p_color = (int) (0.5f + ((float) cr_gain * 100.0f / 255.0f)); 2593} 2594 2595/*==========================================================================*/ 2596/* Write brightness and contrast settings to device */ 2597/*==========================================================================*/ 2598 2599#define NTSC_BLANK_LEVEL 240 2600 2601static const int min_black_level = NTSC_BLANK_LEVEL + 1; 2602static const int max_white_level = 1023; 2603 2604static void 2605config_brightness_contrast(unsigned long tv_std, unsigned int trigger_bits, 2606 int brightness, int contrast) 2607{ 2608 int brightness_off; 2609 float contrast_mult; 2610 int black, white; 2611 unsigned short w; 2612 int k = map_tvstd_to_index(tv_std); 2613 2614 /*0-100 maps to +/-220. */ 2615 brightness_off = 2616 (int) (0.5f + ((float) brightness * 440.0f / 100.0f)) - 220; 2617 2618 /*0-100 maps to .75-1.25. */ 2619 contrast_mult = ((float) contrast * 0.5f / 100.0f) + 0.75f; 2620 2621 black = tvsetup.black_level[k]; 2622 if (trigger_bits != 0) 2623 black -= tvsetup.hamp_offset[k]; 2624 2625 white = tvsetup.white_level[k]; 2626 if (trigger_bits != 0) 2627 white -= tvsetup.hamp_offset[k]; 2628 2629 black = (int) ((float) (black + brightness_off) * contrast_mult); 2630 white = (int) ((float) (white + brightness_off) * contrast_mult); 2631 if (black < min_black_level) 2632 black = min_black_level; 2633 if (white > max_white_level) 2634 white = max_white_level; 2635 2636 w = w10bit2z((unsigned short) black); 2637 houston_WriteReg(ENC_BLACK_LEVEL, w & 0x00ff, 1); 2638 houston_WriteReg(ENC_BLACK_LEVEL + 1, w >> 8, 1); 2639 w = w10bit2z((unsigned short) white); 2640 houston_WriteReg(ENC_WHITE_LEVEL, w & 0x00ff, 1); 2641 houston_WriteReg(ENC_WHITE_LEVEL + 1, w >> 8, 1); 2642} 2643 2644static void 2645conget_brightness_contrast(unsigned long tv_std, unsigned int trigger_bits, 2646 int *p_brightness, int *p_contrast) 2647{ 2648 int brightness_off; 2649 float contrast_mult; 2650 unsigned short black, white; 2651 unsigned long zh, zl; 2652 int k; 2653 2654 if (!p_brightness || !p_contrast) 2655 return; 2656 2657 k = map_tvstd_to_index(tv_std); 2658 2659 houston_ReadReg(ENC_BLACK_LEVEL, &zl, 1); 2660 houston_ReadReg(ENC_BLACK_LEVEL + 1, &zh, 1); 2661 black = z2w10bit((unsigned short) (zl + (zh << 8))); 2662 if (trigger_bits != 0) 2663 black += tvsetup.hamp_offset[k]; 2664 houston_ReadReg(ENC_WHITE_LEVEL, &zl, 1); 2665 houston_ReadReg(ENC_WHITE_LEVEL + 1, &zh, 1); 2666 white = z2w10bit((unsigned short) (zl + (zh << 8))); 2667 if (trigger_bits != 0) 2668 white += tvsetup.hamp_offset[k]; 2669 2670 /*this reverse computation does not account for clipping, but should */ 2671 /*provide somewhat reasonable numbers */ 2672 contrast_mult = 2673 ((float) white - (float) black) / ((float) tvsetup.white_level[k] - 2674 (float) tvsetup.black_level[k]); 2675 brightness_off = 2676 (int) (((float) black / contrast_mult) - tvsetup.black_level[k]); 2677 2678 /*+/-220 maps to 0-100. */ 2679 *p_brightness = 2680 range_limit((int) (0.5f + ((float) (brightness_off + 2681 220) * 100.0f / 440.0f)), 0, 100); 2682 2683 /*.75-1.25 maps to 0-100. */ 2684 *p_contrast = 2685 range_limit((int) (0.5f + ((float) (contrast_mult - 2686 0.75f) * 100.0f / 0.5f)), 0, 100); 2687} 2688 2689/*==========================================================================*/ 2690/* configure luma/chroma filters. */ 2691/*==========================================================================*/ 2692 2693static void 2694config_yc_filter(unsigned long tv_std, int luma_filter, int chroma_filter) 2695{ 2696 unsigned long reg, reg07, reg34; 2697 2698 if (houston_Rev() < HOUSTON_REV_B) 2699 return; 2700 2701 /*luma filter. */ 2702 if (luma_filter) 2703 reg = tvsetup.notch_filter[map_tvstd_to_index(tv_std)]; 2704 else 2705 reg = 0; 2706 houston_WriteReg(ENC_NOTCH_FILTER, reg, 1); 2707 2708 /*chroma filter. */ 2709 houston_ReadReg(ENC_REG07, ®07, 1); 2710 houston_ReadReg(ENC_REG34, ®34, 1); 2711 if (chroma_filter) { 2712 reg07 &= ~0x08; 2713 reg34 &= ~0x20; 2714 } 2715 else { 2716 reg07 |= 0x08; 2717 reg34 |= 0x20; 2718 } 2719 houston_WriteReg(ENC_REG07, reg07, 1); 2720 houston_WriteReg(ENC_REG34, reg34, 1); 2721} 2722 2723static void 2724conget_yc_filter(int *p_luma_filter, int *p_chroma_filter) 2725{ 2726 unsigned long reg, reg07, reg34; 2727 2728 if (!p_luma_filter || !p_chroma_filter) 2729 return; 2730 2731 if (houston_Rev() < HOUSTON_REV_B) { 2732 *p_luma_filter = 0; 2733 *p_chroma_filter = 0; 2734 return; 2735 } 2736 2737 /*luma filter. */ 2738 houston_ReadReg(ENC_NOTCH_FILTER, ®, 1); 2739 *p_luma_filter = (reg ? 1 : 0); 2740 2741 /*chroma filter. */ 2742 houston_ReadReg(ENC_REG07, ®07, 1); 2743 houston_ReadReg(ENC_REG34, ®34, 1); 2744 *p_chroma_filter = !((0x08 & reg07) || (0x20 & reg34)); 2745} 2746 2747/*==========================================================================*/ 2748/* Macrovision */ 2749/*==========================================================================*/ 2750 2751static void 2752config_macrovision(unsigned long tv_std, unsigned int trigger_bits) 2753{ 2754/*Constants to index into mvsetup columns.*/ 2755#define nNTSC_APS00 0 /*ntsc mv off. */ 2756#define nNTSC_APS01 1 /*ntsc AGC only. */ 2757#define nNTSC_APS10 2 /*ntsc AGC + 2-line CS. */ 2758#define nNTSC_APS11 3 /*ntsc AGC + 4-line CS. */ 2759#define nPAL_APS00 4 /*pal mv off. */ 2760#define nPAL_APSXX 5 /*pal mv on. */ 2761#define nMVModes 6 2762 2763 /*Macrovision setup table. */ 2764 static const struct mvparms { 2765 unsigned short n0[nMVModes]; 2766 unsigned short n1[nMVModes]; 2767 unsigned short n2[nMVModes]; 2768 unsigned short n3[nMVModes]; 2769 unsigned short n4[nMVModes]; 2770 unsigned short n5[nMVModes]; 2771 unsigned short n6[nMVModes]; 2772 unsigned short n7[nMVModes]; 2773 unsigned short n8[nMVModes]; 2774 unsigned short n9[nMVModes]; 2775 unsigned short n10[nMVModes]; 2776 unsigned short n11[nMVModes]; 2777 unsigned short n12[nMVModes]; 2778 unsigned short n13[nMVModes]; 2779 unsigned short n14[nMVModes]; 2780 unsigned short n15[nMVModes]; 2781 unsigned short n16[nMVModes]; 2782 unsigned short n17[nMVModes]; 2783 unsigned short n18[nMVModes]; 2784 unsigned short n19[nMVModes]; 2785 unsigned short n20[nMVModes]; 2786 unsigned short n21[nMVModes]; 2787 unsigned short n22[nMVModes]; 2788 unsigned short agc_pulse_level[nMVModes]; 2789 unsigned short bp_pulse_level[nMVModes]; 2790 } mvsetup = { 2791 /* ntsc ntsc ntsc ntsc pal pal */ 2792 /* MV AGC AGC + AGC + MV MV */ 2793 /* off. only 2-line 4-line off. on. */ 2794 /* CS. CS. */ 2795 { 2796 0x00, 0x36, 0x3e, 0x3e, 0x00, 0x3e}, /*n0 */ 2797 { 2798 0x1d, 0x1d, 0x1d, 0x17, 0x1a, 0x1a}, /*n1 */ 2799 { 2800 0x11, 0x11, 0x11, 0x15, 0x22, 0x22}, /*n2 */ 2801 { 2802 0x25, 0x25, 0x25, 0x21, 0x2a, 0x2a}, /*n3 */ 2803 { 2804 0x11, 0x11, 0x11, 0x15, 0x22, 0x22}, /*n4 */ 2805 { 2806 0x01, 0x01, 0x01, 0x05, 0x05, 0x05}, /*n5 */ 2807 { 2808 0x07, 0x07, 0x07, 0x05, 0x02, 0x02}, /*n6 */ 2809 { 2810 0x00, 0x00, 0x00, 0x02, 0x00, 0x00}, /*n7 */ 2811 { 2812 0x1b, 0x1b, 0x1b, 0x1b, 0x1c, 0x1c}, /*n8 */ 2813 { 2814 0x1b, 0x1b, 0x1b, 0x1b, 0x3d, 0x3d}, /*n9 */ 2815 { 2816 0x24, 0x24, 0x24, 0x24, 0x14, 0x14}, /*n10 */ 2817 { 2818 0x780f, 0x780f, 0x780f, 0x780f, 0x7e07, 0x7e07}, /*n11 */ 2819 { 2820 0x0000, 0x0000, 0x0000, 0x0000, 0x5402, 0x5402}, /*n12 */ 2821 { 2822 0x0f, 0x0f, 0x0f, 0x0f, 0xfe, 0xfe}, /*n13 */ 2823 { 2824 0x0f, 0x0f, 0x0f, 0x0f, 0x7e, 0x7e}, /*n14 */ 2825 { 2826 0x60, 0x60, 0x60, 0x60, 0x60, 0x60}, /*n15 */ 2827 { 2828 0x01, 0x01, 0x01, 0x01, 0x00, 0x00}, /*n16 */ 2829 { 2830 0x0a, 0x0a, 0x0a, 0x0a, 0x08, 0x08}, /*n17 */ 2831 { 2832 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*n18 */ 2833 { 2834 0x05, 0x05, 0x05, 0x05, 0x04, 0x04}, /*n19 */ 2835 { 2836 0x04, 0x04, 0x04, 0x04, 0x07, 0x07}, /*n20 */ 2837 { 2838 0x03ff, 0x03ff, 0x03ff, 0x03ff, 0x0155, 0x0155}, /*n21 */ 2839 { 2840 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*n22 */ 2841 { 2842 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3}, /*agc_pulse_level */ 2843 { 2844 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8}, /*bp_pulse_level */ 2845 }; 2846 2847 int nMode; 2848 unsigned long misc; 2849 unsigned short n0; 2850 2851 trigger_bits &= 0x3; 2852 2853 /*Determine the OEM Macrovision Program Mode and Register 0 Data. */ 2854 if (IS_NTSC(tv_std)) { 2855 /*NTSC TV Standard. */ 2856 if (trigger_bits == 0) { 2857 /*turn Macrovision OFF. */ 2858 nMode = nNTSC_APS00; 2859 } 2860 else if (trigger_bits == 1) { 2861 /*AGC Only. */ 2862 nMode = nNTSC_APS01; 2863 } 2864 else if (trigger_bits == 2) { 2865 /*AGC + 2-line CS. */ 2866 nMode = nNTSC_APS10; 2867 } 2868 else { 2869 /*AGC + 4-line CS. */ 2870 nMode = nNTSC_APS11; 2871 } 2872 } 2873 else { 2874 /*PAL TV Standard. */ 2875 if (trigger_bits == 0) { 2876 /*turn Macrovision OFF. */ 2877 nMode = nPAL_APS00; 2878 } 2879 else { 2880 /*APS 01, 10, or 11. */ 2881 nMode = nPAL_APSXX; 2882 } 2883 } 2884 2885 /*Retrieve the Macrovision Program Mode Data */ 2886 if (tv_std != GFX_TV_STANDARD_PAL_M) 2887 n0 = mvsetup.n0[nMode]; 2888 else { 2889 /*PAL-M sets up like NTSC except for n0. */ 2890 if ((trigger_bits & 0x03) == 0) 2891 n0 = mvsetup.n0[nPAL_APS00]; 2892 else 2893 n0 = mvsetup.n0[nPAL_APSXX]; 2894 } 2895 2896 /*download settings now. */ 2897 houston_WriteReg(MV_N0, n0, 1); 2898 houston_WriteReg(MV_N1, mvsetup.n1[nMode], 1); 2899 houston_WriteReg(MV_N2, mvsetup.n2[nMode], 1); 2900 houston_WriteReg(MV_N3, mvsetup.n3[nMode], 1); 2901 houston_WriteReg(MV_N4, mvsetup.n4[nMode], 1); 2902 houston_WriteReg(MV_N5, mvsetup.n5[nMode], 1); 2903 houston_WriteReg(MV_N6, mvsetup.n6[nMode], 1); 2904 houston_WriteReg(MV_N7, mvsetup.n7[nMode], 1); 2905 houston_WriteReg(MV_N8, mvsetup.n8[nMode], 1); 2906 houston_WriteReg(MV_N9, mvsetup.n9[nMode], 1); 2907 houston_WriteReg(MV_N10, mvsetup.n10[nMode], 1); 2908 houston_WriteReg(MV_N11, mvsetup.n11[nMode] & 0xff, 1); 2909 houston_WriteReg(MV_N11 + 1, mvsetup.n11[nMode] >> 8, 1); 2910 houston_WriteReg(MV_N12, mvsetup.n12[nMode] & 0xff, 1); 2911 houston_WriteReg(MV_N12 + 1, mvsetup.n12[nMode] >> 8, 1); 2912 houston_WriteReg(MV_N13, mvsetup.n13[nMode], 1); 2913 houston_WriteReg(MV_N14, mvsetup.n14[nMode], 1); 2914 houston_WriteReg(MV_N15, mvsetup.n15[nMode], 1); 2915 houston_WriteReg(MV_N16, mvsetup.n16[nMode], 1); 2916 houston_WriteReg(MV_N17, mvsetup.n17[nMode], 1); 2917 houston_WriteReg(MV_N18, mvsetup.n18[nMode], 1); 2918 houston_WriteReg(MV_N19, mvsetup.n19[nMode], 1); 2919 houston_WriteReg(MV_N20, mvsetup.n20[nMode], 1); 2920 houston_WriteReg(MV_N21, mvsetup.n21[nMode] & 0xff, 1); 2921 houston_WriteReg(MV_N21 + 1, mvsetup.n21[nMode] >> 8, 1); 2922 houston_WriteReg(MV_N22, mvsetup.n22[nMode], 1); 2923 houston_WriteReg(MV_AGC_PULSE_LEVEL, mvsetup.agc_pulse_level[nMode], 1); 2924 houston_WriteReg(MV_BP_PULSE_LEVEL, mvsetup.bp_pulse_level[nMode], 1); 2925 2926 houston_ReadReg(HOUSTON_MISC, &misc, 2); 2927 if (trigger_bits == 0) 2928 misc &= ~MISC_MV_SOFT_EN; 2929 else 2930 misc |= MISC_MV_SOFT_EN; 2931 houston_WriteReg(HOUSTON_MISC, misc, 2); 2932} 2933 2934static void 2935conget_macrovision(unsigned long tv_std, unsigned int *p_cp_trigger_bits) 2936{ 2937 unsigned long n0, n1; 2938 2939 if (!p_cp_trigger_bits) 2940 return; 2941 2942 houston_ReadReg(MV_N0, &n0, 1); 2943 houston_ReadReg(MV_N1, &n1, 1); 2944 2945 *p_cp_trigger_bits = 0; 2946 2947 if (IS_NTSC(tv_std)) { 2948 switch (n0) { 2949 case 0: 2950 *p_cp_trigger_bits = 0; 2951 break; 2952 2953 case 0x36: 2954 *p_cp_trigger_bits = 1; 2955 break; 2956 2957 case 0x3E: 2958 { 2959 if (0x1D == n1) 2960 *p_cp_trigger_bits = 2; 2961 else 2962 *p_cp_trigger_bits = 3; 2963 } 2964 break; 2965 } 2966 } 2967 else if (IS_PAL(tv_std)) { 2968 if (0 == n0) 2969 *p_cp_trigger_bits = 0; 2970 else { 2971 /*don't know here what the non-zero trigger bits were */ 2972 *p_cp_trigger_bits = 1; 2973 } 2974 } 2975} 2976 2977/* PLAL_MediaGX.cpp */ 2978/*==========================================================================*/ 2979/* These functions provides implementation of platform-specific functions */ 2980/* MediaGX platform. */ 2981/*==========================================================================*/ 2982 2983/*MediaGX control registers.*/ 2984#define CCR3 0xC3 2985#define GCR 0xb8 2986 2987/*Media GX general config register.*/ 2988#define GX_DCLK_MUL 0x00c0 2989#define GX_DCLKx1 0x0040 2990#define GX_DCLKx2 0x0080 2991#define GX_DCLKx4 0x00c0 2992 2993/*Media GX timing config register.*/ 2994#define GX_TGEN 0x0020 2995 2996/*Cx5530 register offsets (from GX_BASE).*/ 2997#define CX_DISPLAY_CONFIG 0x10004 2998#define CX_DOT_CLK 0x10024 2999#define CX_TV_CONFIG 0x10028 3000 3001/*Cx5530 display configuration register.*/ 3002#define CX_FPVSYNC_POL 0x0800 3003#define CX_FPHSYNC_POL 0x0400 3004#define CX_FPDATA_ENB 0x0080 3005#define CX_FPPOWER_ENB 0x0040 3006#define CX_CRTVSYNC_POL 0x0200 3007#define CX_CRTHSYNC_POL 0x0100 3008 3009/*Cx5530 dot clock configuration register.*/ 3010#define CX_TVCLK_SELECT 0x0400 3011 3012/*Cx5530 tv configuration register*/ 3013#define CX_INVERT_FPCLK (1 << 6) 3014 3015/*========================================================================== 3016 * FS450 I2C Address 3017 * There are two possible 7-bit addresses, 0x4A and 0x6A. 3018 * The address if selectable via pins on the FS450. 3019 * There are also two possible 10-bit addresses, 0x224 and 0x276, but this 3020 * source is not designed to use them. 3021 *==========================================================================*/ 3022 3023#define FS450_I2C_ADDRESS (0x4A) 3024 3025static unsigned char 3026PLAL_FS450_i2c_address(void) 3027{ 3028 return FS450_I2C_ADDRESS; 3029} 3030 3031/*========================================================================== 3032 * FS450 UIM mode 3033 * This mode is programmed in the FS450 command register when enabling TV 3034 * out. 3035 *========================================================================== 3036 */ 3037static int 3038PLAL_FS450_UIM_mode(void) 3039{ 3040 return 3; 3041} 3042 3043/*==========================================================================*/ 3044/* Read and Write MediaGX registers */ 3045/*==========================================================================*/ 3046static unsigned long 3047ReadGx(unsigned long inRegAddr) 3048{ 3049 unsigned long data; 3050 3051 DMAL_ReadUInt32(inRegAddr, &data); 3052 3053 return data; 3054} 3055 3056static void 3057WriteGx(unsigned long inRegAddr, unsigned long inData) 3058{ 3059 int is_timing_register; 3060 unsigned long reg_timing_cfg; 3061 3062 /*because the unlock register for the MediaGx video registers may not */ 3063 /*persist, we will write the unlock code before every write. */ 3064 DMAL_WriteUInt32(DC_UNLOCK, 0x4758); 3065 3066 /*see if register is a timing register */ 3067 is_timing_register = 3068 (DC_H_TIMING_1 == inRegAddr) || 3069 (DC_H_TIMING_2 == inRegAddr) || 3070 (DC_H_TIMING_3 == inRegAddr) || 3071 (DC_FP_H_TIMING == inRegAddr) || 3072 (DC_V_TIMING_1 == inRegAddr) || 3073 (DC_V_TIMING_2 == inRegAddr) || 3074 (DC_V_TIMING_3 == inRegAddr) || (DC_FP_V_TIMING == inRegAddr); 3075 3076 /*if the register is a timing register, clear the TGEN bit to allow 3077 * modification */ 3078 if (is_timing_register) { 3079 DMAL_ReadUInt32(DC_TIMING_CFG, ®_timing_cfg); 3080 DMAL_WriteUInt32(DC_TIMING_CFG, reg_timing_cfg & ~GX_TGEN); 3081 } 3082 3083 /*write the requested register */ 3084 DMAL_WriteUInt32(inRegAddr, inData); 3085 3086 /*reset the TGEN bit to previous state */ 3087 if (is_timing_register) { 3088 DMAL_WriteUInt32(DC_TIMING_CFG, reg_timing_cfg); 3089 } 3090} 3091 3092#ifdef FS450_DIRECTREG 3093 3094/*==========================================================================*/ 3095/* Platform-specific processing for a Read or Write Register calls. */ 3096/* The functions should return true if the specified register belongs to */ 3097/* this platform. */ 3098/*==========================================================================*/ 3099 3100static int 3101PLAL_ReadRegister(S_REG_INFO * p_reg) 3102{ 3103 if (!p_reg) 3104 return 0; 3105 3106 if (SOURCE_GCC == p_reg->source) { 3107 p_reg->value = ReadGx(p_reg->offset); 3108 3109 return 1; 3110 } 3111 3112 return 0; 3113} 3114 3115static int 3116PLAL_WriteRegister(const S_REG_INFO * p_reg) 3117{ 3118 if (!p_reg) 3119 return 0; 3120 3121 if (SOURCE_GCC == p_reg->source) { 3122 WriteGx(p_reg->offset, p_reg->value); 3123 3124 return 1; 3125 } 3126 3127 return 0; 3128} 3129 3130#endif 3131 3132/*========================================================================== 3133 * Determine if TV is on 3134 *==========================================================================*/ 3135static int 3136PLAL_IsTVOn(void) 3137{ 3138 unsigned long reg; 3139 3140 /*check Cx5530 dot clock */ 3141 reg = ReadGx(CX_DOT_CLK); 3142 return (reg & CX_TVCLK_SELECT) ? 1 : 0; 3143} 3144 3145/*========================================================================== 3146 * Platform-specific actions to reset to VGA mode 3147 *==========================================================================*/ 3148 3149static int 3150PLAL_EnableVga(void) 3151{ 3152 unsigned long reg; 3153 3154 /*2 x dclk */ 3155 reg = ReadGx(DC_GENERAL_CFG); 3156 reg &= ~GX_DCLK_MUL; 3157 reg |= GX_DCLKx2; 3158 WriteGx(DC_GENERAL_CFG, reg); 3159 3160 /*select pll dot clock. */ 3161 reg = ReadGx(CX_DOT_CLK); 3162 reg &= ~CX_TVCLK_SELECT; 3163 WriteGx(CX_DOT_CLK, reg); 3164 3165 /*timing config, reset everything on dclk. */ 3166 reg = ReadGx(DC_TIMING_CFG); 3167 reg &= ~GX_TGEN; 3168 WriteGx(DC_TIMING_CFG, reg); 3169 reg |= GX_TGEN; 3170 WriteGx(DC_TIMING_CFG, reg); 3171 3172 /*un-invert FP clock */ 3173 reg = ReadGx(CX_TV_CONFIG); 3174 reg &= ~CX_INVERT_FPCLK; 3175 WriteGx(CX_TV_CONFIG, reg); 3176 3177 return 0; 3178} 3179 3180/*==========================================================================*/ 3181/*Platform-specific actions to enter TVout mode */ 3182/*==========================================================================*/ 3183 3184static int 3185PLAL_PrepForTVout(void) 3186{ 3187 unsigned int reg; 3188 3189 /*Cx5530 tv config. */ 3190 reg = 0; 3191 WriteGx(CX_TV_CONFIG, reg); 3192 3193 /*invert FP clock */ 3194 reg = (int) ReadGx(CX_TV_CONFIG); 3195 reg |= CX_INVERT_FPCLK; 3196 WriteGx(CX_TV_CONFIG, reg); 3197 3198 return 0; 3199} 3200 3201static int 3202PLAL_SetTVTimingRegisters(const S_TIMING_SPECS * p_specs) 3203{ 3204 unsigned long reg; 3205 3206 /*timing config, reset everything on dclk. */ 3207 reg = ReadGx(DC_TIMING_CFG); 3208 reg &= ~GX_TGEN; 3209 WriteGx(DC_TIMING_CFG, reg); 3210 3211 /*htotal and hactive. */ 3212 reg = ((p_specs->h_total - 1) << 16) | (p_specs->vga_width - 1); 3213 WriteGx(DC_H_TIMING_1, reg); 3214 3215 /*hblank. */ 3216 reg = ((p_specs->h_total - 1) << 16) | (p_specs->vga_width - 1); 3217 WriteGx(DC_H_TIMING_2, reg); 3218 3219 /*hsync. */ 3220 reg = ((p_specs->h_sync + 63) << 16) | p_specs->h_sync; 3221 WriteGx(DC_H_TIMING_3, reg); 3222 3223 /*fp hsync. */ 3224 WriteGx(DC_FP_H_TIMING, reg); 3225 3226 /*vtotal and vactive. */ 3227 reg = ((p_specs->v_total - 1) << 16) | (p_specs->vga_lines - 1); 3228 WriteGx(DC_V_TIMING_1, reg); 3229 3230 /*vblank. */ 3231 reg = ((p_specs->v_total - 1) << 16) | (p_specs->vga_lines - 1); 3232 WriteGx(DC_V_TIMING_2, reg); 3233 3234 /*vsync. */ 3235 reg = ((p_specs->v_sync) << 16) | (p_specs->v_sync - 1); 3236 WriteGx(DC_V_TIMING_3, reg); 3237 3238 /*fp vsync. */ 3239 reg = ((p_specs->v_sync - 1) << 16) | (p_specs->v_sync - 2); 3240 WriteGx(DC_FP_V_TIMING, reg); 3241 3242 /*timing config, re-enable all dclk stuff. */ 3243 reg = ReadGx(DC_TIMING_CFG); 3244 reg |= GX_TGEN; 3245 WriteGx(DC_TIMING_CFG, reg); 3246 3247 return 0; 3248} 3249 3250static int 3251PLAL_FinalEnableTVout(unsigned long vga_mode) 3252{ 3253 unsigned int reg; 3254 3255 /*Cx5530 select tv dot clock. */ 3256 reg = (int) ReadGx(CX_DOT_CLK); 3257 reg |= CX_TVCLK_SELECT; 3258 WriteGx(CX_DOT_CLK, reg); 3259 3260 /*2 x dclk (actually 1x) */ 3261 reg = (int) ReadGx(DC_GENERAL_CFG); 3262 reg &= ~GX_DCLK_MUL; 3263 WriteGx(DC_GENERAL_CFG, reg); 3264 3265 reg |= GX_DCLKx2; 3266 WriteGx(DC_GENERAL_CFG, reg); 3267 3268 /*Cx5530 display configuration register. */ 3269 reg = (int) ReadGx(CX_DISPLAY_CONFIG); 3270 reg |= (CX_FPVSYNC_POL | CX_FPHSYNC_POL | CX_FPDATA_ENB | CX_FPPOWER_ENB); 3271 WriteGx(CX_DISPLAY_CONFIG, reg); 3272 3273 return 0; 3274} 3275