/* Copyright (c) 2005 Advanced Micro Devices, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to * deal in the Software without restriction, including without limitation the * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or * sell copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS * IN THE SOFTWARE. * * Neither the name of the Advanced Micro Devices, Inc. nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * */ /* * File Contents: This file contains the panel library files to the * GX2 platforms with 9211 support. * * SubModule: Geode FlatPanel library * */ #include "92xx.h" #include "gx2_9211.h" #include "pnl_defs.h" #if defined(_WIN32) /* windows */ #include "gfx_defs.h" extern DEV_STATUS gfx_msr_read(unsigned int device, unsigned int msrRegister, Q_WORD * msrValue); extern DEV_STATUS gfx_msr_write(unsigned int device, unsigned int msrRegister, Q_WORD * msrValue); #endif static unsigned long FPBaseAddr; void SetFPBaseAddr(unsigned long addr) { FPBaseAddr = addr; } /**************************************************************************** * protected_mode_access( unsigned long mode, unsigned long width, * unsigned long addr, unsigned char* pdata ) * This function provides access to physical memory at the requested address. * * mode is: * GX2_READ or GX2_WRITE (accesses a single byte, word or double word * depending on the value of "width". Only 1, 2 or 4 supported). * READ_BYTES, WRITE_BYTES accesses "width" number of bytes (8 bits) * READ_WORDS, WRITE_WORDS accesses "width" number of words (16 bits) * READ_DWORDS, WRITE_DWORDS accesses "width" number of dwords (32 * bits) * * width is: * The size of the access. For READ or WRITE, only 1, 2 and 4 are * supported. For other modes, width is not limited but will cause * paging if the block traverses page boundaries. * * addr is: * The physical address being accessed * * pdata is: * A pointer to the data to be read or written into. * * NOTE! WORD or DWORD accesses can only be made on WORD or DWORD boundaries! ****************************************************************************/ void protected_mode_access(unsigned long mode, unsigned long width, unsigned long addr, char *pdata) { void *ptr = (void *)(FPBaseAddr + addr); /* type specific buffer pointers */ char *byte_data = (char *)pdata; unsigned long *word_data = (unsigned long *)pdata; unsigned long *dword_data = (unsigned long *)pdata; if (mode == GX2_READ) { switch (width) { case FOUR_BYTES: *(dword_data) = (unsigned long)(*(unsigned long *)ptr); break; case TWO_BYTES: *(word_data) = (unsigned long)(*(unsigned long *)ptr); break; default: *(byte_data) = (char)(*(char *)ptr); break; } } /* end GX2_READ */ else if (mode == GX2_WRITE) { switch (width) { case FOUR_BYTES: *(unsigned long *)ptr = *dword_data; break; case TWO_BYTES: *(unsigned long *)ptr = *word_data; break; default: *(char *)ptr = *byte_data; break; } /* end switch(mode) */ } /* end case GX2_WRITE */ return; } /* End of protected_mode_access. */ /************************************************************************* * void write_video_reg64_low( unsigned long offset, unsigned long value ) * * Writes value to the low 32 bits of the 64 bit memory mapped video * register indicated by offset. * This function uses Sys_info.video_reg_base as the base address, so * the value of offset should be with respect to this base. *************************************************************************/ void write_video_reg64_low(unsigned long offset, unsigned long value) { protected_mode_access(GX2_WRITE, FOUR_BYTES, FPBaseAddr + offset, (char *)&value); } /*end write_video_reg64_low() */ /************************************************************************* * unsigned long read_video_reg64_low( unsigned long offset ) * * Returns the contents of the low 32 bits of the 64 bit memory mapped * video register indicated by offset. * This function uses Sys_info.video_reg_base as the base address, so * the value of offset should be with respect to this base. *************************************************************************/ unsigned long read_video_reg64_low(unsigned long offset) { unsigned long data; protected_mode_access(GX2_READ, FOUR_BYTES, FPBaseAddr + offset, (char *)&data); return (data); } /*end read_video_reg64_low() */ /***************************************************************************** * void Redcloud_fp_reg(int mode, unsigned long address, unsigned long *data) * * Writes and reads dwords to the Redcloud flat panel registers in the * Redcloud Display Filter. There's no clock control, chip select or timing * to deal with. * This routine expects the actual GX2 macro definitions for the address. * * Parameters: * mode: An integer value for a GX2_READ or GX2_WRITE operation * 0 = GX2_Read and 1 = GX2_Write * address: A dword value representing the offset of the register. * data: A pointer to a dword value that is to be written in to * the required register. In case of a Read operation * this will point to the result of the Read operation. ****************************************************************************/ void Redcloud_fp_reg(int mode, unsigned long address, unsigned long *data) { if (mode == GX2_READ) { *data = read_video_reg64_low(address); } else { write_video_reg64_low(address, *data); } } /* End of Redcloud_fp_reg() */ /*------------------------------------------------------------------- * * SET_92XX_MODE_PARAMS * This routine sets the 9211 mode parameters. * *-------------------------------------------------------------------*/ void set_Redcloud_92xx_mode_params(int mode) { CS92xx_MODE *pMode = &FPModeParams[mode]; unsigned long temp_data = 0; unsigned long base_data; QQ_WORD msrValue; /* on a Redcloud, we need to set up the DF pad select MSR */ if (gfx_msr_read(RC_ID_DF, GX2_VP_MSR_PAD_SELECT, &msrValue) == FOUND) { msrValue.low &= ~GX2_VP_PAD_SELECT_MASK; if (pMode->panel_type == PNL_TFT || pMode->panel_type == PNL_TWOP) { msrValue.low = GX2_VP_PAD_SELECT_TFT; } else { msrValue.low = GX2_VP_PAD_SELECT_DSTN; } gfx_msr_write(RC_ID_DF, GX2_VP_MSR_PAD_SELECT, &msrValue); } /* Turn the 92xx power off before setting any new parameters. */ temp_data = pMode->power_management & ~GX2_FP_PM_PWR_ON; Redcloud_fp_reg(GX2_WRITE, GX2_FP_PWR_MAN, (unsigned long *)&temp_data); /* Set 9211 registers using the desired panel settings */ Redcloud_fp_reg(GX2_WRITE, GX2_FP_PAN_TIMING1, (unsigned long *)&pMode->panel_timing1); /* On Redcloud, bit 31 is now reserved. */ temp_data = pMode->panel_timing2 & 0x7FFFFFFF; Redcloud_fp_reg(GX2_WRITE, GX2_FP_PAN_TIMING2, (unsigned long *)&temp_data); /* On Redcloud TFT parts, set this to 0x70 so all 8 bits per color run * thru fp crc but only non-TFT parts. Otherwise, set it to be 0x50. * (source: Larry G.). */ if (pMode->panel_type == PNL_TFT || pMode->panel_type == PNL_TWOP) { temp_data = GX2_FP_CRC_PASS_THRU_MASK; } else { temp_data = pMode->rev_C_dither_frc; } Redcloud_fp_reg(GX2_WRITE, GX2_FP_DITH_FR_CNTRL, (unsigned long *)&temp_data); Redcloud_fp_reg(GX2_WRITE, GX2_FP_BLFSR, (unsigned long *)&pMode->blue_lsfr_seed); Redcloud_fp_reg(GX2_WRITE, GX2_FP_RLFSR, (unsigned long *)&pMode->red_green_lsfr_seed); /* Set the memory information, then the power register last. * This will turn the panel on at the 9211. */ Redcloud_fp_reg(GX2_READ, GX2_FP_FBB, (unsigned long *)&base_data); if (base_data != 0x41780000) { base_data = 0x41780000; Redcloud_fp_reg(GX2_WRITE, GX2_FP_FBB, (unsigned long *)&base_data); } Redcloud_fp_reg(GX2_WRITE, GX2_FP_PWR_MAN, (unsigned long *)&pMode->power_management); } /*end set_92xx_mode_params() */ /* ----------------------------------------------------------------------- * SET_FLAT_PANEL_MODE * * This routine sets the specified flat panel moden parameters in * the 9211. * Returns PASS if successful, FAIL if the mode parameters could * not be set. *------------------------------------------------------------------------*/ unsigned char set_Redcloud_92xx_mode(Pnl_PanelStat * pstat) { int mode; /* LOOP THROUGH THE AVAILABLE MODES TO FIND A MATCH */ for (mode = 0; mode < NUM_92XX_MODES; mode++) { if ((FPModeParams[mode].xres == pstat->XRes) && (FPModeParams[mode].yres == pstat->YRes) && (FPModeParams[mode].bpp == pstat->Depth) && (FPModeParams[mode].panel_type == pstat->Type) && (FPModeParams[mode].color_type == pstat->MonoColor)) { /* SET THE 92xx FOR THE SELECTED MODE */ set_Redcloud_92xx_mode_params(mode); return TRUE; } /* end if() */ } /* end for() */ return FALSE; } /* end set_Centaurus_92xx_mode() */ void Redcloud_9211init(Pnl_PanelStat * pstat) { set_Redcloud_92xx_mode(pstat); }