1/* Copyright (c) 2005 Advanced Micro Devices, Inc.
2 *
3 * Permission is hereby granted, free of charge, to any person obtaining a copy
4 * of this software and associated documentation files (the "Software"), to
5 * deal in the Software without restriction, including without limitation the
6 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7 * sell copies of the Software, and to permit persons to whom the Software is
8 * furnished to do so, subject to the following conditions:
9 *
10 * The above copyright notice and this permission notice shall be included in
11 * all copies or substantial portions of the Software.
12 *
13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19 * IN THE SOFTWARE.
20 *
21 * Neither the name of the Advanced Micro Devices, Inc. nor the names of its
22 * contributors may be used to endorse or promote products derived from this
23 * software without specific prior written permission.
24 * */
25
26/*
27 * File Contents:   This file contains the panel library files to the
28 *                  GX2 platforms with 9211 support.
29 *
30 * SubModule:       Geode FlatPanel library
31 * */
32
33#include "92xx.h"
34#include "gx2_9211.h"
35#include "pnl_defs.h"
36
37#if defined(_WIN32)             /* windows */
38#include "gfx_defs.h"
39
40extern DEV_STATUS gfx_msr_read(unsigned int device, unsigned int msrRegister,
41                               Q_WORD * msrValue);
42extern DEV_STATUS gfx_msr_write(unsigned int device, unsigned int msrRegister,
43                                Q_WORD * msrValue);
44#endif
45
46static unsigned long FPBaseAddr;
47
48void
49SetFPBaseAddr(unsigned long addr)
50{
51
52    FPBaseAddr = addr;
53}
54
55/****************************************************************************
56 * protected_mode_access( unsigned long mode, unsigned long width,
57 * 		unsigned long addr, unsigned char* pdata )
58 * This function provides access to physical memory at the requested address.
59 *
60 * mode is:
61 *        GX2_READ or GX2_WRITE (accesses a single byte, word or double word
62 *        	depending on the value of "width".  Only 1, 2 or 4 supported).
63 *        READ_BYTES, WRITE_BYTES accesses "width" number of bytes (8 bits)
64 *        READ_WORDS, WRITE_WORDS accesses "width" number of words (16 bits)
65 *        READ_DWORDS, WRITE_DWORDS accesses "width" number of dwords (32
66 *        	bits)
67 *
68 * width is:
69 * 		  The size of the access.  For READ or WRITE, only 1, 2 and 4 are
70 *        	supported.  For other modes, width is not limited but will cause
71 *        	paging if the block traverses page boundaries.
72 *
73 * addr is:
74 * 		  The physical address being accessed
75 *
76 * pdata is:
77 * 		  A pointer to the data to be read or written into.
78 *
79 * NOTE! WORD or DWORD accesses can only be made on WORD or DWORD boundaries!
80 ****************************************************************************/
81void
82protected_mode_access(unsigned long mode,
83                      unsigned long width, unsigned long addr, char *pdata)
84{
85    void *ptr = (void *) (FPBaseAddr + addr);
86
87    /* type specific buffer pointers */
88    char *byte_data = (char *) pdata;
89    unsigned long *word_data = (unsigned long *) pdata;
90    unsigned long *dword_data = (unsigned long *) pdata;
91
92    if (mode == GX2_READ) {
93        switch (width) {
94        case FOUR_BYTES:
95            *(dword_data) = (unsigned long) (*(unsigned long *) ptr);
96            break;
97        case TWO_BYTES:
98            *(word_data) = (unsigned long) (*(unsigned long *) ptr);
99            break;
100        default:
101            *(byte_data) = (char) (*(char *) ptr);
102            break;
103        }
104    }                           /* end  GX2_READ */
105    else if (mode == GX2_WRITE) {
106        switch (width) {
107        case FOUR_BYTES:
108            *(unsigned long *) ptr = *dword_data;
109            break;
110        case TWO_BYTES:
111            *(unsigned long *) ptr = *word_data;
112            break;
113        default:
114            *(char *) ptr = *byte_data;
115            break;
116        }                       /* end switch(mode) */
117    }
118    /* end case GX2_WRITE */
119    return;
120
121}                               /* End of protected_mode_access. */
122
123/*************************************************************************
124 * void write_video_reg64_low( unsigned long offset, unsigned long value )
125 *
126 * Writes value to the low 32 bits of the 64 bit memory mapped video
127 * register indicated by offset.
128 * This function uses Sys_info.video_reg_base as the base address, so
129 * the value of offset should be with respect to this base.
130 *************************************************************************/
131void
132write_video_reg64_low(unsigned long offset, unsigned long value)
133{
134    protected_mode_access(GX2_WRITE, FOUR_BYTES,
135                          FPBaseAddr + offset, (char *) &value);
136}                               /*end write_video_reg64_low() */
137
138/*************************************************************************
139 * unsigned long read_video_reg64_low( unsigned long offset )
140 *
141 * Returns the contents of the low 32 bits of the 64 bit memory mapped
142 * video register indicated by offset.
143 * This function uses Sys_info.video_reg_base as the base address, so
144 * the value of offset should be with respect to this base.
145 *************************************************************************/
146unsigned long
147read_video_reg64_low(unsigned long offset)
148{
149    unsigned long data;
150
151    protected_mode_access(GX2_READ, FOUR_BYTES,
152                          FPBaseAddr + offset, (char *) &data);
153    return (data);
154}                               /*end read_video_reg64_low() */
155
156/*****************************************************************************
157 * void Redcloud_fp_reg(int mode, unsigned long address, unsigned long *data)
158 *
159 * Writes and reads dwords to the Redcloud flat panel registers in the
160 * Redcloud Display Filter.  There's no clock control, chip select or timing
161 * to deal with.
162 * This routine expects the actual GX2 macro definitions for the address.
163 *
164 * Parameters:
165 *			mode:		An integer value for a GX2_READ or GX2_WRITE operation
166 *						0 = GX2_Read and 1 = GX2_Write
167 *			address:	A dword value representing the offset of the register.
168 *			data:		A pointer to a dword value that is to be written in to
169 *						the required register.  In case of a Read operation
170 *						this will point to the result of the Read operation.
171 ****************************************************************************/
172void
173Redcloud_fp_reg(int mode, unsigned long address, unsigned long *data)
174{
175    if (mode == GX2_READ) {
176        *data = read_video_reg64_low(address);
177    }
178    else {
179        write_video_reg64_low(address, *data);
180    }
181
182}                               /* End of Redcloud_fp_reg() */
183
184/*-------------------------------------------------------------------
185 *
186 * SET_92XX_MODE_PARAMS
187 * This routine sets the 9211 mode parameters.
188 *
189 *-------------------------------------------------------------------*/
190
191void
192set_Redcloud_92xx_mode_params(int mode)
193{
194    CS92xx_MODE *pMode = &FPModeParams[mode];
195    unsigned long temp_data = 0;
196    unsigned long base_data;
197    QQ_WORD msrValue;
198
199    /* on a Redcloud, we need to set up the DF pad select MSR */
200    if (gfx_msr_read(RC_ID_DF, GX2_VP_MSR_PAD_SELECT, &msrValue) == FOUND) {
201        msrValue.low &= ~GX2_VP_PAD_SELECT_MASK;
202        if (pMode->panel_type == PNL_TFT || pMode->panel_type == PNL_TWOP) {
203            msrValue.low = GX2_VP_PAD_SELECT_TFT;
204        }
205        else {
206            msrValue.low = GX2_VP_PAD_SELECT_DSTN;
207        }
208        gfx_msr_write(RC_ID_DF, GX2_VP_MSR_PAD_SELECT, &msrValue);
209    }
210
211    /* Turn the 92xx power off before setting any new parameters. */
212    temp_data = pMode->power_management & ~GX2_FP_PM_PWR_ON;
213    Redcloud_fp_reg(GX2_WRITE, GX2_FP_PWR_MAN, (unsigned long *) &temp_data);
214
215    /* Set 9211 registers using the desired panel settings */
216
217    Redcloud_fp_reg(GX2_WRITE, GX2_FP_PAN_TIMING1,
218                    (unsigned long *) &pMode->panel_timing1);
219
220    /* On Redcloud, bit 31 is now reserved. */
221    temp_data = pMode->panel_timing2 & 0x7FFFFFFF;
222    Redcloud_fp_reg(GX2_WRITE, GX2_FP_PAN_TIMING2,
223                    (unsigned long *) &temp_data);
224
225    /* On Redcloud TFT parts, set this to 0x70 so all 8 bits per color run
226     * thru fp crc but only non-TFT parts.  Otherwise, set it to be 0x50.
227     * (source: Larry G.).
228     */
229    if (pMode->panel_type == PNL_TFT || pMode->panel_type == PNL_TWOP) {
230        temp_data = GX2_FP_CRC_PASS_THRU_MASK;
231    }
232    else {
233        temp_data = pMode->rev_C_dither_frc;
234    }
235    Redcloud_fp_reg(GX2_WRITE, GX2_FP_DITH_FR_CNTRL,
236                    (unsigned long *) &temp_data);
237    Redcloud_fp_reg(GX2_WRITE, GX2_FP_BLFSR,
238                    (unsigned long *) &pMode->blue_lsfr_seed);
239    Redcloud_fp_reg(GX2_WRITE, GX2_FP_RLFSR,
240                    (unsigned long *) &pMode->red_green_lsfr_seed);
241
242    /* Set the memory information, then the power register last.
243     * This will turn the panel on at the 9211.
244     */
245
246    Redcloud_fp_reg(GX2_READ, GX2_FP_FBB, (unsigned long *) &base_data);
247    if (base_data != 0x41780000) {
248        base_data = 0x41780000;
249        Redcloud_fp_reg(GX2_WRITE, GX2_FP_FBB, (unsigned long *) &base_data);
250    }
251
252    Redcloud_fp_reg(GX2_WRITE, GX2_FP_PWR_MAN,
253                    (unsigned long *) &pMode->power_management);
254
255}                               /*end set_92xx_mode_params() */
256
257/* -----------------------------------------------------------------------
258 * SET_FLAT_PANEL_MODE
259 *
260 * This routine sets the specified flat panel moden parameters in
261 * the 9211.
262 * Returns PASS if successful, FAIL if the mode parameters could
263 * not be set.
264 *------------------------------------------------------------------------*/
265
266unsigned char
267set_Redcloud_92xx_mode(Pnl_PanelStat * pstat)
268{
269    int mode;
270
271    /* LOOP THROUGH THE AVAILABLE MODES TO FIND A MATCH */
272
273    for (mode = 0; mode < NUM_92XX_MODES; mode++) {
274        if ((FPModeParams[mode].xres == pstat->XRes) &&
275            (FPModeParams[mode].yres == pstat->YRes) &&
276            (FPModeParams[mode].bpp == pstat->Depth) &&
277            (FPModeParams[mode].panel_type == pstat->Type) &&
278            (FPModeParams[mode].color_type == pstat->MonoColor)) {
279
280            /* SET THE 92xx FOR THE SELECTED MODE */
281            set_Redcloud_92xx_mode_params(mode);
282            return TRUE;
283        }                       /* end if() */
284    }                           /* end for() */
285    return FALSE;
286
287}                               /* end set_Centaurus_92xx_mode() */
288
289void
290Redcloud_9211init(Pnl_PanelStat * pstat)
291{
292
293    set_Redcloud_92xx_mode(pstat);
294
295}
296