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