0001
0002
0003
0004
0005
0006 #include <linux/fb.h>
0007 #include <asm/io.h>
0008 #include <asm/msr.h>
0009 #include <linux/cs5535.h>
0010 #include <asm/delay.h>
0011
0012 #include "gxfb.h"
0013
0014 static void gx_save_regs(struct gxfb_par *par)
0015 {
0016 int i;
0017
0018
0019 do {
0020 i = read_gp(par, GP_BLT_STATUS);
0021 } while (i & (GP_BLT_STATUS_BLT_PENDING | GP_BLT_STATUS_BLT_BUSY));
0022
0023
0024 rdmsrl(MSR_GX_MSR_PADSEL, par->msr.padsel);
0025 rdmsrl(MSR_GLCP_DOTPLL, par->msr.dotpll);
0026
0027 write_dc(par, DC_UNLOCK, DC_UNLOCK_UNLOCK);
0028
0029
0030 memcpy(par->gp, par->gp_regs, sizeof(par->gp));
0031 memcpy(par->dc, par->dc_regs, sizeof(par->dc));
0032 memcpy(par->vp, par->vid_regs, sizeof(par->vp));
0033 memcpy(par->fp, par->vid_regs + VP_FP_START, sizeof(par->fp));
0034
0035
0036 write_dc(par, DC_PAL_ADDRESS, 0);
0037 for (i = 0; i < ARRAY_SIZE(par->pal); i++)
0038 par->pal[i] = read_dc(par, DC_PAL_DATA);
0039 }
0040
0041 static void gx_set_dotpll(uint32_t dotpll_hi)
0042 {
0043 uint32_t dotpll_lo;
0044 int i;
0045
0046 rdmsrl(MSR_GLCP_DOTPLL, dotpll_lo);
0047 dotpll_lo |= MSR_GLCP_DOTPLL_DOTRESET;
0048 dotpll_lo &= ~MSR_GLCP_DOTPLL_BYPASS;
0049 wrmsr(MSR_GLCP_DOTPLL, dotpll_lo, dotpll_hi);
0050
0051
0052 for (i = 0; i < 200; i++) {
0053 rdmsrl(MSR_GLCP_DOTPLL, dotpll_lo);
0054 if (dotpll_lo & MSR_GLCP_DOTPLL_LOCK)
0055 break;
0056 udelay(1);
0057 }
0058
0059
0060 dotpll_lo &= ~MSR_GLCP_DOTPLL_DOTRESET;
0061 wrmsr(MSR_GLCP_DOTPLL, dotpll_lo, dotpll_hi);
0062 }
0063
0064 static void gx_restore_gfx_proc(struct gxfb_par *par)
0065 {
0066 int i;
0067
0068 for (i = 0; i < ARRAY_SIZE(par->gp); i++) {
0069 switch (i) {
0070 case GP_VECTOR_MODE:
0071 case GP_BLT_MODE:
0072 case GP_BLT_STATUS:
0073 case GP_HST_SRC:
0074
0075 break;
0076 default:
0077 write_gp(par, i, par->gp[i]);
0078 }
0079 }
0080 }
0081
0082 static void gx_restore_display_ctlr(struct gxfb_par *par)
0083 {
0084 int i;
0085
0086 for (i = 0; i < ARRAY_SIZE(par->dc); i++) {
0087 switch (i) {
0088 case DC_UNLOCK:
0089
0090 write_dc(par, DC_UNLOCK, DC_UNLOCK_UNLOCK);
0091 break;
0092
0093 case DC_GENERAL_CFG:
0094
0095 write_dc(par, i, par->dc[i] & ~(DC_GENERAL_CFG_VIDE |
0096 DC_GENERAL_CFG_ICNE |
0097 DC_GENERAL_CFG_CURE |
0098 DC_GENERAL_CFG_DFLE));
0099 break;
0100
0101 case DC_DISPLAY_CFG:
0102
0103 write_dc(par, i, par->dc[i] & ~(DC_DISPLAY_CFG_VDEN |
0104 DC_DISPLAY_CFG_GDEN |
0105 DC_DISPLAY_CFG_TGEN));
0106 break;
0107
0108 case DC_RSVD_0:
0109 case DC_RSVD_1:
0110 case DC_RSVD_2:
0111 case DC_RSVD_3:
0112 case DC_RSVD_4:
0113 case DC_LINE_CNT:
0114 case DC_PAL_ADDRESS:
0115 case DC_PAL_DATA:
0116 case DC_DFIFO_DIAG:
0117 case DC_CFIFO_DIAG:
0118 case DC_RSVD_5:
0119
0120 break;
0121 default:
0122 write_dc(par, i, par->dc[i]);
0123 }
0124 }
0125
0126
0127 write_dc(par, DC_PAL_ADDRESS, 0);
0128 for (i = 0; i < ARRAY_SIZE(par->pal); i++)
0129 write_dc(par, DC_PAL_DATA, par->pal[i]);
0130 }
0131
0132 static void gx_restore_video_proc(struct gxfb_par *par)
0133 {
0134 int i;
0135
0136 wrmsrl(MSR_GX_MSR_PADSEL, par->msr.padsel);
0137
0138 for (i = 0; i < ARRAY_SIZE(par->vp); i++) {
0139 switch (i) {
0140 case VP_VCFG:
0141
0142 write_vp(par, i, par->vp[i] & ~VP_VCFG_VID_EN);
0143 break;
0144
0145 case VP_DCFG:
0146
0147 write_vp(par, i, par->vp[i] &
0148 ~(VP_DCFG_DAC_BL_EN | VP_DCFG_VSYNC_EN |
0149 VP_DCFG_HSYNC_EN | VP_DCFG_CRT_EN));
0150 break;
0151
0152 case VP_GAR:
0153 case VP_GDR:
0154 case VP_RSVD_0:
0155 case VP_RSVD_1:
0156 case VP_RSVD_2:
0157 case VP_RSVD_3:
0158 case VP_CRC32:
0159 case VP_AWT:
0160 case VP_VTM:
0161
0162 break;
0163 default:
0164 write_vp(par, i, par->vp[i]);
0165 }
0166 }
0167 }
0168
0169 static void gx_restore_regs(struct gxfb_par *par)
0170 {
0171 int i;
0172
0173 gx_set_dotpll((uint32_t) (par->msr.dotpll >> 32));
0174 gx_restore_gfx_proc(par);
0175 gx_restore_display_ctlr(par);
0176 gx_restore_video_proc(par);
0177
0178
0179 for (i = 0; i < ARRAY_SIZE(par->fp); i++) {
0180 if (i != FP_PM && i != FP_RSVD_0)
0181 write_fp(par, i, par->fp[i]);
0182 }
0183 }
0184
0185 static void gx_disable_graphics(struct gxfb_par *par)
0186 {
0187
0188 write_vp(par, VP_VCFG, par->vp[VP_VCFG] & ~VP_VCFG_VID_EN);
0189 write_vp(par, VP_DCFG, par->vp[VP_DCFG] & ~(VP_DCFG_DAC_BL_EN |
0190 VP_DCFG_VSYNC_EN | VP_DCFG_HSYNC_EN | VP_DCFG_CRT_EN));
0191
0192
0193 write_fp(par, FP_PM, par->fp[FP_PM] & ~FP_PM_P);
0194
0195
0196
0197 write_dc(par, DC_UNLOCK, DC_UNLOCK_UNLOCK);
0198 write_dc(par, DC_GENERAL_CFG, par->dc[DC_GENERAL_CFG] &
0199 ~(DC_GENERAL_CFG_VIDE | DC_GENERAL_CFG_ICNE |
0200 DC_GENERAL_CFG_CURE | DC_GENERAL_CFG_DFLE));
0201 write_dc(par, DC_DISPLAY_CFG, par->dc[DC_DISPLAY_CFG] &
0202 ~(DC_DISPLAY_CFG_VDEN | DC_DISPLAY_CFG_GDEN |
0203 DC_DISPLAY_CFG_TGEN));
0204 write_dc(par, DC_UNLOCK, DC_UNLOCK_LOCK);
0205 }
0206
0207 static void gx_enable_graphics(struct gxfb_par *par)
0208 {
0209 uint32_t fp;
0210
0211 fp = read_fp(par, FP_PM);
0212 if (par->fp[FP_PM] & FP_PM_P) {
0213
0214 if (!(fp & (FP_PM_PANEL_ON|FP_PM_PANEL_PWR_UP)))
0215 write_fp(par, FP_PM, par->fp[FP_PM]);
0216 } else {
0217
0218 if (!(fp & (FP_PM_PANEL_OFF|FP_PM_PANEL_PWR_DOWN)))
0219 write_fp(par, FP_PM, par->fp[FP_PM]);
0220 }
0221
0222
0223 write_vp(par, VP_VCFG, par->vp[VP_VCFG]);
0224 write_vp(par, VP_DCFG, par->vp[VP_DCFG]);
0225 write_dc(par, DC_DISPLAY_CFG, par->dc[DC_DISPLAY_CFG]);
0226
0227 write_dc(par, DC_GENERAL_CFG, par->dc[DC_GENERAL_CFG]);
0228
0229
0230 write_dc(par, DC_UNLOCK, DC_UNLOCK_LOCK);
0231 }
0232
0233 int gx_powerdown(struct fb_info *info)
0234 {
0235 struct gxfb_par *par = info->par;
0236
0237 if (par->powered_down)
0238 return 0;
0239
0240 gx_save_regs(par);
0241 gx_disable_graphics(par);
0242
0243 par->powered_down = 1;
0244 return 0;
0245 }
0246
0247 int gx_powerup(struct fb_info *info)
0248 {
0249 struct gxfb_par *par = info->par;
0250
0251 if (!par->powered_down)
0252 return 0;
0253
0254 gx_restore_regs(par);
0255 gx_enable_graphics(par);
0256
0257 par->powered_down = 0;
0258 return 0;
0259 }