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