2 * Copyright (C) 2007 Advanced Micro Devices, Inc.
3 * Copyright (C) 2008 Andres Salomon <dilinger@debian.org>
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version.
13 #include <asm/geode.h>
14 #include <asm/delay.h>
20 static void gx_save_regs(struct gxfb_par
*par
)
24 /* wait for the BLT engine to stop being busy */
26 i
= read_gp(par
, GP_BLT_STATUS
);
27 } while (i
& (GP_BLT_STATUS_BLT_PENDING
| GP_BLT_STATUS_BLT_BUSY
));
30 rdmsrl(MSR_GX_MSR_PADSEL
, par
->msr
.padsel
);
31 rdmsrl(MSR_GLCP_DOTPLL
, par
->msr
.dotpll
);
33 write_dc(par
, DC_UNLOCK
, DC_UNLOCK_UNLOCK
);
36 memcpy(par
->gp
, par
->gp_regs
, sizeof(par
->gp
));
37 memcpy(par
->dc
, par
->dc_regs
, sizeof(par
->dc
));
38 memcpy(par
->vp
, par
->vid_regs
, sizeof(par
->vp
));
39 memcpy(par
->fp
, par
->vid_regs
+ VP_FP_START
, sizeof(par
->fp
));
41 /* save the palette */
42 write_dc(par
, DC_PAL_ADDRESS
, 0);
43 for (i
= 0; i
< ARRAY_SIZE(par
->pal
); i
++)
44 par
->pal
[i
] = read_dc(par
, DC_PAL_DATA
);
47 static void gx_set_dotpll(uint32_t dotpll_hi
)
52 rdmsrl(MSR_GLCP_DOTPLL
, dotpll_lo
);
53 dotpll_lo
|= MSR_GLCP_DOTPLL_DOTRESET
;
54 dotpll_lo
&= ~MSR_GLCP_DOTPLL_BYPASS
;
55 wrmsr(MSR_GLCP_DOTPLL
, dotpll_lo
, dotpll_hi
);
57 /* wait for the PLL to lock */
58 for (i
= 0; i
< 200; i
++) {
59 rdmsrl(MSR_GLCP_DOTPLL
, dotpll_lo
);
60 if (dotpll_lo
& MSR_GLCP_DOTPLL_LOCK
)
66 dotpll_lo
&= ~MSR_GLCP_DOTPLL_DOTRESET
;
67 wrmsr(MSR_GLCP_DOTPLL
, dotpll_lo
, dotpll_hi
);
70 static void gx_restore_gfx_proc(struct gxfb_par
*par
)
74 for (i
= 0; i
< ARRAY_SIZE(par
->gp
); i
++) {
80 /* don't restore these registers */
83 write_gp(par
, i
, par
->gp
[i
]);
88 static void gx_restore_display_ctlr(struct gxfb_par
*par
)
92 for (i
= 0; i
< ARRAY_SIZE(par
->dc
); i
++) {
95 /* unlock the DC; runs first */
96 write_dc(par
, DC_UNLOCK
, DC_UNLOCK_UNLOCK
);
100 /* write without the enables */
101 write_dc(par
, i
, par
->dc
[i
] & ~(DC_GENERAL_CFG_VIDE
|
102 DC_GENERAL_CFG_ICNE
|
103 DC_GENERAL_CFG_CURE
|
104 DC_GENERAL_CFG_DFLE
));
108 /* write without the enables */
109 write_dc(par
, i
, par
->dc
[i
] & ~(DC_DISPLAY_CFG_VDEN
|
110 DC_DISPLAY_CFG_GDEN
|
111 DC_DISPLAY_CFG_TGEN
));
125 /* don't restore these registers */
128 write_dc(par
, i
, par
->dc
[i
]);
132 /* restore the palette */
133 write_dc(par
, DC_PAL_ADDRESS
, 0);
134 for (i
= 0; i
< ARRAY_SIZE(par
->pal
); i
++)
135 write_dc(par
, DC_PAL_DATA
, par
->pal
[i
]);
138 static void gx_restore_video_proc(struct gxfb_par
*par
)
142 wrmsrl(MSR_GX_MSR_PADSEL
, par
->msr
.padsel
);
144 for (i
= 0; i
< ARRAY_SIZE(par
->vp
); i
++) {
147 /* don't enable video yet */
148 write_vp(par
, i
, par
->vp
[i
] & ~VP_VCFG_VID_EN
);
152 /* don't enable CRT yet */
153 write_vp(par
, i
, par
->vp
[i
] &
154 ~(VP_DCFG_DAC_BL_EN
| VP_DCFG_VSYNC_EN
|
155 VP_DCFG_HSYNC_EN
| VP_DCFG_CRT_EN
));
167 /* don't restore these registers */
170 write_vp(par
, i
, par
->vp
[i
]);
175 static void gx_restore_regs(struct gxfb_par
*par
)
179 gx_set_dotpll((uint32_t) (par
->msr
.dotpll
>> 32));
180 gx_restore_gfx_proc(par
);
181 gx_restore_display_ctlr(par
);
182 gx_restore_video_proc(par
);
185 for (i
= 0; i
< ARRAY_SIZE(par
->fp
); i
++) {
186 if (i
!= FP_PM
&& i
!= FP_RSVD_0
)
187 write_fp(par
, i
, par
->fp
[i
]);
191 static void gx_disable_graphics(struct gxfb_par
*par
)
193 /* shut down the engine */
194 write_vp(par
, VP_VCFG
, par
->vp
[VP_VCFG
] & ~VP_VCFG_VID_EN
);
195 write_vp(par
, VP_DCFG
, par
->vp
[VP_DCFG
] & ~(VP_DCFG_DAC_BL_EN
|
196 VP_DCFG_VSYNC_EN
| VP_DCFG_HSYNC_EN
| VP_DCFG_CRT_EN
));
198 /* turn off the flat panel */
199 write_fp(par
, FP_PM
, par
->fp
[FP_PM
] & ~FP_PM_P
);
202 /* turn off display */
203 write_dc(par
, DC_UNLOCK
, DC_UNLOCK_UNLOCK
);
204 write_dc(par
, DC_GENERAL_CFG
, par
->dc
[DC_GENERAL_CFG
] &
205 ~(DC_GENERAL_CFG_VIDE
| DC_GENERAL_CFG_ICNE
|
206 DC_GENERAL_CFG_CURE
| DC_GENERAL_CFG_DFLE
));
207 write_dc(par
, DC_DISPLAY_CFG
, par
->dc
[DC_DISPLAY_CFG
] &
208 ~(DC_DISPLAY_CFG_VDEN
| DC_DISPLAY_CFG_GDEN
|
209 DC_DISPLAY_CFG_TGEN
));
210 write_dc(par
, DC_UNLOCK
, DC_UNLOCK_LOCK
);
213 static void gx_enable_graphics(struct gxfb_par
*par
)
217 fp
= read_fp(par
, FP_PM
);
218 if (par
->fp
[FP_PM
] & FP_PM_P
) {
219 /* power on the panel if not already power{ed,ing} on */
220 if (!(fp
& (FP_PM_PANEL_ON
|FP_PM_PANEL_PWR_UP
)))
221 write_fp(par
, FP_PM
, par
->fp
[FP_PM
]);
223 /* power down the panel if not already power{ed,ing} down */
224 if (!(fp
& (FP_PM_PANEL_OFF
|FP_PM_PANEL_PWR_DOWN
)))
225 write_fp(par
, FP_PM
, par
->fp
[FP_PM
]);
228 /* turn everything on */
229 write_vp(par
, VP_VCFG
, par
->vp
[VP_VCFG
]);
230 write_vp(par
, VP_DCFG
, par
->vp
[VP_DCFG
]);
231 write_dc(par
, DC_DISPLAY_CFG
, par
->dc
[DC_DISPLAY_CFG
]);
232 /* do this last; it will enable the FIFO load */
233 write_dc(par
, DC_GENERAL_CFG
, par
->dc
[DC_GENERAL_CFG
]);
235 /* lock the door behind us */
236 write_dc(par
, DC_UNLOCK
, DC_UNLOCK_LOCK
);
239 int gx_powerdown(struct fb_info
*info
)
241 struct gxfb_par
*par
= info
->par
;
243 if (par
->powered_down
)
247 gx_disable_graphics(par
);
249 par
->powered_down
= 1;
253 int gx_powerup(struct fb_info
*info
)
255 struct gxfb_par
*par
= info
->par
;
257 if (!par
->powered_down
)
260 gx_restore_regs(par
);
261 gx_enable_graphics(par
);
263 par
->powered_down
= 0;