1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2007 Advanced Micro Devices, Inc.
9 #include <linux/cs5535.h>
10 #include <asm/delay.h>
14 static void gx_save_regs(struct gxfb_par *par)
18 /* wait for the BLT engine to stop being busy */
20 i = read_gp(par, GP_BLT_STATUS);
21 } while (i & (GP_BLT_STATUS_BLT_PENDING | GP_BLT_STATUS_BLT_BUSY));
24 rdmsrl(MSR_GX_MSR_PADSEL, par->msr.padsel);
25 rdmsrl(MSR_GLCP_DOTPLL, par->msr.dotpll);
27 write_dc(par, DC_UNLOCK, DC_UNLOCK_UNLOCK);
30 memcpy(par->gp, par->gp_regs, sizeof(par->gp));
31 memcpy(par->dc, par->dc_regs, sizeof(par->dc));
32 memcpy(par->vp, par->vid_regs, sizeof(par->vp));
33 memcpy(par->fp, par->vid_regs + VP_FP_START, sizeof(par->fp));
35 /* save the palette */
36 write_dc(par, DC_PAL_ADDRESS, 0);
37 for (i = 0; i < ARRAY_SIZE(par->pal); i++)
38 par->pal[i] = read_dc(par, DC_PAL_DATA);
41 static void gx_set_dotpll(uint32_t dotpll_hi)
46 rdmsrl(MSR_GLCP_DOTPLL, dotpll_lo);
47 dotpll_lo |= MSR_GLCP_DOTPLL_DOTRESET;
48 dotpll_lo &= ~MSR_GLCP_DOTPLL_BYPASS;
49 wrmsr(MSR_GLCP_DOTPLL, dotpll_lo, dotpll_hi);
51 /* wait for the PLL to lock */
52 for (i = 0; i < 200; i++) {
53 rdmsrl(MSR_GLCP_DOTPLL, dotpll_lo);
54 if (dotpll_lo & MSR_GLCP_DOTPLL_LOCK)
60 dotpll_lo &= ~MSR_GLCP_DOTPLL_DOTRESET;
61 wrmsr(MSR_GLCP_DOTPLL, dotpll_lo, dotpll_hi);
64 static void gx_restore_gfx_proc(struct gxfb_par *par)
68 for (i = 0; i < ARRAY_SIZE(par->gp); i++) {
74 /* don't restore these registers */
77 write_gp(par, i, par->gp[i]);
82 static void gx_restore_display_ctlr(struct gxfb_par *par)
86 for (i = 0; i < ARRAY_SIZE(par->dc); i++) {
89 /* unlock the DC; runs first */
90 write_dc(par, DC_UNLOCK, DC_UNLOCK_UNLOCK);
94 /* write without the enables */
95 write_dc(par, i, par->dc[i] & ~(DC_GENERAL_CFG_VIDE |
98 DC_GENERAL_CFG_DFLE));
102 /* write without the enables */
103 write_dc(par, i, par->dc[i] & ~(DC_DISPLAY_CFG_VDEN |
104 DC_DISPLAY_CFG_GDEN |
105 DC_DISPLAY_CFG_TGEN));
119 /* don't restore these registers */
122 write_dc(par, i, par->dc[i]);
126 /* restore the palette */
127 write_dc(par, DC_PAL_ADDRESS, 0);
128 for (i = 0; i < ARRAY_SIZE(par->pal); i++)
129 write_dc(par, DC_PAL_DATA, par->pal[i]);
132 static void gx_restore_video_proc(struct gxfb_par *par)
136 wrmsrl(MSR_GX_MSR_PADSEL, par->msr.padsel);
138 for (i = 0; i < ARRAY_SIZE(par->vp); i++) {
141 /* don't enable video yet */
142 write_vp(par, i, par->vp[i] & ~VP_VCFG_VID_EN);
146 /* don't enable CRT yet */
147 write_vp(par, i, par->vp[i] &
148 ~(VP_DCFG_DAC_BL_EN | VP_DCFG_VSYNC_EN |
149 VP_DCFG_HSYNC_EN | VP_DCFG_CRT_EN));
161 /* don't restore these registers */
164 write_vp(par, i, par->vp[i]);
169 static void gx_restore_regs(struct gxfb_par *par)
173 gx_set_dotpll((uint32_t) (par->msr.dotpll >> 32));
174 gx_restore_gfx_proc(par);
175 gx_restore_display_ctlr(par);
176 gx_restore_video_proc(par);
179 for (i = 0; i < ARRAY_SIZE(par->fp); i++) {
180 if (i != FP_PM && i != FP_RSVD_0)
181 write_fp(par, i, par->fp[i]);
185 static void gx_disable_graphics(struct gxfb_par *par)
187 /* shut down the engine */
188 write_vp(par, VP_VCFG, par->vp[VP_VCFG] & ~VP_VCFG_VID_EN);
189 write_vp(par, VP_DCFG, par->vp[VP_DCFG] & ~(VP_DCFG_DAC_BL_EN |
190 VP_DCFG_VSYNC_EN | VP_DCFG_HSYNC_EN | VP_DCFG_CRT_EN));
192 /* turn off the flat panel */
193 write_fp(par, FP_PM, par->fp[FP_PM] & ~FP_PM_P);
196 /* turn off display */
197 write_dc(par, DC_UNLOCK, DC_UNLOCK_UNLOCK);
198 write_dc(par, DC_GENERAL_CFG, par->dc[DC_GENERAL_CFG] &
199 ~(DC_GENERAL_CFG_VIDE | DC_GENERAL_CFG_ICNE |
200 DC_GENERAL_CFG_CURE | DC_GENERAL_CFG_DFLE));
201 write_dc(par, DC_DISPLAY_CFG, par->dc[DC_DISPLAY_CFG] &
202 ~(DC_DISPLAY_CFG_VDEN | DC_DISPLAY_CFG_GDEN |
203 DC_DISPLAY_CFG_TGEN));
204 write_dc(par, DC_UNLOCK, DC_UNLOCK_LOCK);
207 static void gx_enable_graphics(struct gxfb_par *par)
211 fp = read_fp(par, FP_PM);
212 if (par->fp[FP_PM] & FP_PM_P) {
213 /* power on the panel if not already power{ed,ing} on */
214 if (!(fp & (FP_PM_PANEL_ON|FP_PM_PANEL_PWR_UP)))
215 write_fp(par, FP_PM, par->fp[FP_PM]);
217 /* power down the panel if not already power{ed,ing} down */
218 if (!(fp & (FP_PM_PANEL_OFF|FP_PM_PANEL_PWR_DOWN)))
219 write_fp(par, FP_PM, par->fp[FP_PM]);
222 /* turn everything on */
223 write_vp(par, VP_VCFG, par->vp[VP_VCFG]);
224 write_vp(par, VP_DCFG, par->vp[VP_DCFG]);
225 write_dc(par, DC_DISPLAY_CFG, par->dc[DC_DISPLAY_CFG]);
226 /* do this last; it will enable the FIFO load */
227 write_dc(par, DC_GENERAL_CFG, par->dc[DC_GENERAL_CFG]);
229 /* lock the door behind us */
230 write_dc(par, DC_UNLOCK, DC_UNLOCK_LOCK);
233 int gx_powerdown(struct fb_info *info)
235 struct gxfb_par *par = info->par;
237 if (par->powered_down)
241 gx_disable_graphics(par);
243 par->powered_down = 1;
247 int gx_powerup(struct fb_info *info)
249 struct gxfb_par *par = info->par;
251 if (!par->powered_down)
254 gx_restore_regs(par);
255 gx_enable_graphics(par);
257 par->powered_down = 0;