brintos

brintos / linux-shallow public Read only

0
0
Text · 5.9 KiB · 8c49d4e Raw
260 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 *   Copyright (C) 2007 Advanced Micro Devices, Inc.4 *   Copyright (C) 2008 Andres Salomon <dilinger@debian.org>5 */6#include <linux/fb.h>7#include <asm/io.h>8#include <asm/msr.h>9#include <linux/cs5535.h>10#include <asm/delay.h>11 12#include "gxfb.h"13 14static void gx_save_regs(struct gxfb_par *par)15{16	int i;17 18	/* wait for the BLT engine to stop being busy */19	do {20		i = read_gp(par, GP_BLT_STATUS);21	} while (i & (GP_BLT_STATUS_BLT_PENDING | GP_BLT_STATUS_BLT_BUSY));22 23	/* save MSRs */24	rdmsrl(MSR_GX_MSR_PADSEL, par->msr.padsel);25	rdmsrl(MSR_GLCP_DOTPLL, par->msr.dotpll);26 27	write_dc(par, DC_UNLOCK, DC_UNLOCK_UNLOCK);28 29	/* save registers */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));34 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);39}40 41static void gx_set_dotpll(uint32_t dotpll_hi)42{43	uint32_t dotpll_lo;44	int i;45 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);50 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)55			break;56		udelay(1);57	}58 59	/* PLL set, unlock */60	dotpll_lo &= ~MSR_GLCP_DOTPLL_DOTRESET;61	wrmsr(MSR_GLCP_DOTPLL, dotpll_lo, dotpll_hi);62}63 64static void gx_restore_gfx_proc(struct gxfb_par *par)65{66	int i;67 68	for (i = 0; i < ARRAY_SIZE(par->gp); i++) {69		switch (i) {70		case GP_VECTOR_MODE:71		case GP_BLT_MODE:72		case GP_BLT_STATUS:73		case GP_HST_SRC:74			/* don't restore these registers */75			break;76		default:77			write_gp(par, i, par->gp[i]);78		}79	}80}81 82static void gx_restore_display_ctlr(struct gxfb_par *par)83{84	int i;85 86	for (i = 0; i < ARRAY_SIZE(par->dc); i++) {87		switch (i) {88		case DC_UNLOCK:89			/* unlock the DC; runs first */90			write_dc(par, DC_UNLOCK, DC_UNLOCK_UNLOCK);91			break;92 93		case DC_GENERAL_CFG:94			/* write without the enables */95			write_dc(par, i, par->dc[i] & ~(DC_GENERAL_CFG_VIDE |96					DC_GENERAL_CFG_ICNE |97					DC_GENERAL_CFG_CURE |98					DC_GENERAL_CFG_DFLE));99			break;100 101		case DC_DISPLAY_CFG: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));106			break;107 108		case DC_RSVD_0:109		case DC_RSVD_1:110		case DC_RSVD_2:111		case DC_RSVD_3:112		case DC_RSVD_4:113		case DC_LINE_CNT:114		case DC_PAL_ADDRESS:115		case DC_PAL_DATA:116		case DC_DFIFO_DIAG:117		case DC_CFIFO_DIAG:118		case DC_RSVD_5:119			/* don't restore these registers */120			break;121		default:122			write_dc(par, i, par->dc[i]);123		}124	}125 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]);130}131 132static void gx_restore_video_proc(struct gxfb_par *par)133{134	int i;135 136	wrmsrl(MSR_GX_MSR_PADSEL, par->msr.padsel);137 138	for (i = 0; i < ARRAY_SIZE(par->vp); i++) {139		switch (i) {140		case VP_VCFG:141			/* don't enable video yet */142			write_vp(par, i, par->vp[i] & ~VP_VCFG_VID_EN);143			break;144 145		case VP_DCFG: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));150			break;151 152		case VP_GAR:153		case VP_GDR:154		case VP_RSVD_0:155		case VP_RSVD_1:156		case VP_RSVD_2:157		case VP_RSVD_3:158		case VP_CRC32:159		case VP_AWT:160		case VP_VTM:161			/* don't restore these registers */162			break;163		default:164			write_vp(par, i, par->vp[i]);165		}166	}167}168 169static void gx_restore_regs(struct gxfb_par *par)170{171	int i;172 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);177 178	/* Flat Panel */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]);182	}183}184 185static void gx_disable_graphics(struct gxfb_par *par)186{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));191 192	/* turn off the flat panel */193	write_fp(par, FP_PM, par->fp[FP_PM] & ~FP_PM_P);194 195 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);205}206 207static void gx_enable_graphics(struct gxfb_par *par)208{209	uint32_t fp;210 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]);216	} else {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]);220	}221 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]);228 229	/* lock the door behind us */230	write_dc(par, DC_UNLOCK, DC_UNLOCK_LOCK);231}232 233int gx_powerdown(struct fb_info *info)234{235	struct gxfb_par *par = info->par;236 237	if (par->powered_down)238		return 0;239 240	gx_save_regs(par);241	gx_disable_graphics(par);242 243	par->powered_down = 1;244	return 0;245}246 247int gx_powerup(struct fb_info *info)248{249	struct gxfb_par *par = info->par;250 251	if (!par->powered_down)252		return 0;253 254	gx_restore_regs(par);255	gx_enable_graphics(par);256 257	par->powered_down  = 0;258	return 0;259}260