Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  *   Copyright (C) 2007 Advanced Micro Devices, Inc.
0004  *   Copyright (C) 2008 Andres Salomon <dilinger@debian.org>
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     /* wait for the BLT engine to stop being busy */
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     /* save MSRs */
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     /* save registers */
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     /* save the palette */
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     /* wait for the PLL to lock */
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     /* PLL set, unlock */
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             /* don't restore these registers */
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             /* unlock the DC; runs first */
0090             write_dc(par, DC_UNLOCK, DC_UNLOCK_UNLOCK);
0091             break;
0092 
0093         case DC_GENERAL_CFG:
0094             /* write without the enables */
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             /* write without the enables */
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             /* don't restore these registers */
0120             break;
0121         default:
0122             write_dc(par, i, par->dc[i]);
0123         }
0124     }
0125 
0126     /* restore the palette */
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             /* don't enable video yet */
0142             write_vp(par, i, par->vp[i] & ~VP_VCFG_VID_EN);
0143             break;
0144 
0145         case VP_DCFG:
0146             /* don't enable CRT yet */
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             /* don't restore these registers */
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     /* Flat Panel */
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     /* shut down the engine */
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     /* turn off the flat panel */
0193     write_fp(par, FP_PM, par->fp[FP_PM] & ~FP_PM_P);
0194 
0195 
0196     /* turn off display */
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         /* power on the panel if not already power{ed,ing} on */
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         /* power down the panel if not already power{ed,ing} down */
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     /* turn everything on */
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     /* do this last; it will enable the FIFO load */
0227     write_dc(par, DC_GENERAL_CFG, par->dc[DC_GENERAL_CFG]);
0228 
0229     /* lock the door behind us */
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 }