xref: /linux/drivers/video/fbdev/kyro/STG4000VTG.c (revision e5451c8f8330e03ad3cfa16048b4daf961af434f)
1*f7018c21STomi Valkeinen /*
2*f7018c21STomi Valkeinen  *  linux/drivers/video/kyro/STG4000VTG.c
3*f7018c21STomi Valkeinen  *
4*f7018c21STomi Valkeinen  *  Copyright (C) 2002 STMicroelectronics
5*f7018c21STomi Valkeinen  *
6*f7018c21STomi Valkeinen  * This file is subject to the terms and conditions of the GNU General Public
7*f7018c21STomi Valkeinen  * License.  See the file COPYING in the main directory of this archive
8*f7018c21STomi Valkeinen  * for more details.
9*f7018c21STomi Valkeinen  */
10*f7018c21STomi Valkeinen 
11*f7018c21STomi Valkeinen #include <linux/types.h>
12*f7018c21STomi Valkeinen #include <video/kyro.h>
13*f7018c21STomi Valkeinen 
14*f7018c21STomi Valkeinen #include "STG4000Reg.h"
15*f7018c21STomi Valkeinen #include "STG4000Interface.h"
16*f7018c21STomi Valkeinen 
DisableVGA(volatile STG4000REG __iomem * pSTGReg)17*f7018c21STomi Valkeinen void DisableVGA(volatile STG4000REG __iomem *pSTGReg)
18*f7018c21STomi Valkeinen {
19*f7018c21STomi Valkeinen 	u32 tmp;
20*f7018c21STomi Valkeinen 	volatile u32 count = 0, i;
21*f7018c21STomi Valkeinen 
22*f7018c21STomi Valkeinen 	/* Reset the VGA registers */
23*f7018c21STomi Valkeinen 	tmp = STG_READ_REG(SoftwareReset);
24*f7018c21STomi Valkeinen 	CLEAR_BIT(8);
25*f7018c21STomi Valkeinen 	STG_WRITE_REG(SoftwareReset, tmp);
26*f7018c21STomi Valkeinen 
27*f7018c21STomi Valkeinen 	/* Just for Delay */
28*f7018c21STomi Valkeinen 	for (i = 0; i < 1000; i++) {
29*f7018c21STomi Valkeinen 		count++;
30*f7018c21STomi Valkeinen 	}
31*f7018c21STomi Valkeinen 
32*f7018c21STomi Valkeinen 	/* Pull-out the VGA registers from reset */
33*f7018c21STomi Valkeinen 	tmp = STG_READ_REG(SoftwareReset);
34*f7018c21STomi Valkeinen 	tmp |= SET_BIT(8);
35*f7018c21STomi Valkeinen 	STG_WRITE_REG(SoftwareReset, tmp);
36*f7018c21STomi Valkeinen }
37*f7018c21STomi Valkeinen 
StopVTG(volatile STG4000REG __iomem * pSTGReg)38*f7018c21STomi Valkeinen void StopVTG(volatile STG4000REG __iomem *pSTGReg)
39*f7018c21STomi Valkeinen {
40*f7018c21STomi Valkeinen 	u32 tmp = 0;
41*f7018c21STomi Valkeinen 
42*f7018c21STomi Valkeinen 	/* Stop Ver and Hor Sync Generator */
43*f7018c21STomi Valkeinen 	tmp = (STG_READ_REG(DACSyncCtrl)) | SET_BIT(0) | SET_BIT(2);
44*f7018c21STomi Valkeinen 	CLEAR_BIT(31);
45*f7018c21STomi Valkeinen 	STG_WRITE_REG(DACSyncCtrl, tmp);
46*f7018c21STomi Valkeinen }
47*f7018c21STomi Valkeinen 
StartVTG(volatile STG4000REG __iomem * pSTGReg)48*f7018c21STomi Valkeinen void StartVTG(volatile STG4000REG __iomem *pSTGReg)
49*f7018c21STomi Valkeinen {
50*f7018c21STomi Valkeinen 	u32 tmp = 0;
51*f7018c21STomi Valkeinen 
52*f7018c21STomi Valkeinen 	/* Start Ver and Hor Sync Generator */
53*f7018c21STomi Valkeinen 	tmp = ((STG_READ_REG(DACSyncCtrl)) | SET_BIT(31));
54*f7018c21STomi Valkeinen 	CLEAR_BIT(0);
55*f7018c21STomi Valkeinen 	CLEAR_BIT(2);
56*f7018c21STomi Valkeinen 	STG_WRITE_REG(DACSyncCtrl, tmp);
57*f7018c21STomi Valkeinen }
58*f7018c21STomi Valkeinen 
SetupVTG(volatile STG4000REG __iomem * pSTGReg,const struct kyrofb_info * pTiming)59*f7018c21STomi Valkeinen void SetupVTG(volatile STG4000REG __iomem *pSTGReg,
60*f7018c21STomi Valkeinen 	      const struct kyrofb_info * pTiming)
61*f7018c21STomi Valkeinen {
62*f7018c21STomi Valkeinen 	u32 tmp = 0;
63*f7018c21STomi Valkeinen 	u32 margins = 0;
64*f7018c21STomi Valkeinen 	u32 ulBorder;
65*f7018c21STomi Valkeinen 	u32 xRes = pTiming->XRES;
66*f7018c21STomi Valkeinen 	u32 yRes = pTiming->YRES;
67*f7018c21STomi Valkeinen 
68*f7018c21STomi Valkeinen 	/* Horizontal */
69*f7018c21STomi Valkeinen 	u32 HAddrTime, HRightBorder, HLeftBorder;
70*f7018c21STomi Valkeinen 	u32 HBackPorcStrt, HFrontPorchStrt, HTotal,
71*f7018c21STomi Valkeinen 	    HLeftBorderStrt, HRightBorderStrt, HDisplayStrt;
72*f7018c21STomi Valkeinen 
73*f7018c21STomi Valkeinen 	/* Vertical */
74*f7018c21STomi Valkeinen 	u32 VDisplayStrt, VBottomBorder, VTopBorder;
75*f7018c21STomi Valkeinen 	u32 VBackPorchStrt, VTotal, VTopBorderStrt,
76*f7018c21STomi Valkeinen 	    VFrontPorchStrt, VBottomBorderStrt, VAddrTime;
77*f7018c21STomi Valkeinen 
78*f7018c21STomi Valkeinen 	/* Need to calculate the right border */
79*f7018c21STomi Valkeinen 	if ((xRes == 640) && (yRes == 480)) {
80*f7018c21STomi Valkeinen 		if ((pTiming->VFREQ == 60) || (pTiming->VFREQ == 72)) {
81*f7018c21STomi Valkeinen 			margins = 8;
82*f7018c21STomi Valkeinen 		}
83*f7018c21STomi Valkeinen 	}
84*f7018c21STomi Valkeinen 
85*f7018c21STomi Valkeinen 	/* Work out the Border */
86*f7018c21STomi Valkeinen 	ulBorder =
87*f7018c21STomi Valkeinen 	    (pTiming->HTot -
88*f7018c21STomi Valkeinen 	     (pTiming->HST + (pTiming->HBP - margins) + xRes +
89*f7018c21STomi Valkeinen 	      (pTiming->HFP - margins))) >> 1;
90*f7018c21STomi Valkeinen 
91*f7018c21STomi Valkeinen 	/* Border the same for Vertical and Horizontal */
92*f7018c21STomi Valkeinen 	VBottomBorder = HLeftBorder = VTopBorder = HRightBorder = ulBorder;
93*f7018c21STomi Valkeinen 
94*f7018c21STomi Valkeinen     /************ Get Timing values for Horizontal ******************/
95*f7018c21STomi Valkeinen 	HAddrTime = xRes;
96*f7018c21STomi Valkeinen 	HBackPorcStrt = pTiming->HST;
97*f7018c21STomi Valkeinen 	HTotal = pTiming->HTot;
98*f7018c21STomi Valkeinen 	HDisplayStrt =
99*f7018c21STomi Valkeinen 	    pTiming->HST + (pTiming->HBP - margins) + HLeftBorder;
100*f7018c21STomi Valkeinen 	HLeftBorderStrt = HDisplayStrt - HLeftBorder;
101*f7018c21STomi Valkeinen 	HFrontPorchStrt =
102*f7018c21STomi Valkeinen 	    pTiming->HST + (pTiming->HBP - margins) + HLeftBorder +
103*f7018c21STomi Valkeinen 	    HAddrTime + HRightBorder;
104*f7018c21STomi Valkeinen 	HRightBorderStrt = HFrontPorchStrt - HRightBorder;
105*f7018c21STomi Valkeinen 
106*f7018c21STomi Valkeinen     /************ Get Timing values for Vertical ******************/
107*f7018c21STomi Valkeinen 	VAddrTime = yRes;
108*f7018c21STomi Valkeinen 	VBackPorchStrt = pTiming->VST;
109*f7018c21STomi Valkeinen 	VTotal = pTiming->VTot;
110*f7018c21STomi Valkeinen 	VDisplayStrt =
111*f7018c21STomi Valkeinen 	    pTiming->VST + (pTiming->VBP - margins) + VTopBorder;
112*f7018c21STomi Valkeinen 	VTopBorderStrt = VDisplayStrt - VTopBorder;
113*f7018c21STomi Valkeinen 	VFrontPorchStrt =
114*f7018c21STomi Valkeinen 	    pTiming->VST + (pTiming->VBP - margins) + VTopBorder +
115*f7018c21STomi Valkeinen 	    VAddrTime + VBottomBorder;
116*f7018c21STomi Valkeinen 	VBottomBorderStrt = VFrontPorchStrt - VBottomBorder;
117*f7018c21STomi Valkeinen 
118*f7018c21STomi Valkeinen 	/* Set Hor Timing 1, 2, 3 */
119*f7018c21STomi Valkeinen 	tmp = STG_READ_REG(DACHorTim1);
120*f7018c21STomi Valkeinen 	CLEAR_BITS_FRM_TO(0, 11);
121*f7018c21STomi Valkeinen 	CLEAR_BITS_FRM_TO(16, 27);
122*f7018c21STomi Valkeinen 	tmp |= (HTotal) | (HBackPorcStrt << 16);
123*f7018c21STomi Valkeinen 	STG_WRITE_REG(DACHorTim1, tmp);
124*f7018c21STomi Valkeinen 
125*f7018c21STomi Valkeinen 	tmp = STG_READ_REG(DACHorTim2);
126*f7018c21STomi Valkeinen 	CLEAR_BITS_FRM_TO(0, 11);
127*f7018c21STomi Valkeinen 	CLEAR_BITS_FRM_TO(16, 27);
128*f7018c21STomi Valkeinen 	tmp |= (HDisplayStrt << 16) | HLeftBorderStrt;
129*f7018c21STomi Valkeinen 	STG_WRITE_REG(DACHorTim2, tmp);
130*f7018c21STomi Valkeinen 
131*f7018c21STomi Valkeinen 	tmp = STG_READ_REG(DACHorTim3);
132*f7018c21STomi Valkeinen 	CLEAR_BITS_FRM_TO(0, 11);
133*f7018c21STomi Valkeinen 	CLEAR_BITS_FRM_TO(16, 27);
134*f7018c21STomi Valkeinen 	tmp |= (HFrontPorchStrt << 16) | HRightBorderStrt;
135*f7018c21STomi Valkeinen 	STG_WRITE_REG(DACHorTim3, tmp);
136*f7018c21STomi Valkeinen 
137*f7018c21STomi Valkeinen 	/* Set Ver Timing 1, 2, 3 */
138*f7018c21STomi Valkeinen 	tmp = STG_READ_REG(DACVerTim1);
139*f7018c21STomi Valkeinen 	CLEAR_BITS_FRM_TO(0, 11);
140*f7018c21STomi Valkeinen 	CLEAR_BITS_FRM_TO(16, 27);
141*f7018c21STomi Valkeinen 	tmp |= (VBackPorchStrt << 16) | (VTotal);
142*f7018c21STomi Valkeinen 	STG_WRITE_REG(DACVerTim1, tmp);
143*f7018c21STomi Valkeinen 
144*f7018c21STomi Valkeinen 	tmp = STG_READ_REG(DACVerTim2);
145*f7018c21STomi Valkeinen 	CLEAR_BITS_FRM_TO(0, 11);
146*f7018c21STomi Valkeinen 	CLEAR_BITS_FRM_TO(16, 27);
147*f7018c21STomi Valkeinen 	tmp |= (VDisplayStrt << 16) | VTopBorderStrt;
148*f7018c21STomi Valkeinen 	STG_WRITE_REG(DACVerTim2, tmp);
149*f7018c21STomi Valkeinen 
150*f7018c21STomi Valkeinen 	tmp = STG_READ_REG(DACVerTim3);
151*f7018c21STomi Valkeinen 	CLEAR_BITS_FRM_TO(0, 11);
152*f7018c21STomi Valkeinen 	CLEAR_BITS_FRM_TO(16, 27);
153*f7018c21STomi Valkeinen 	tmp |= (VFrontPorchStrt << 16) | VBottomBorderStrt;
154*f7018c21STomi Valkeinen 	STG_WRITE_REG(DACVerTim3, tmp);
155*f7018c21STomi Valkeinen 
156*f7018c21STomi Valkeinen 	/* Set Verical and Horizontal Polarity */
157*f7018c21STomi Valkeinen 	tmp = STG_READ_REG(DACSyncCtrl) | SET_BIT(3) | SET_BIT(1);
158*f7018c21STomi Valkeinen 
159*f7018c21STomi Valkeinen 	if ((pTiming->HSP > 0) && (pTiming->VSP < 0)) {	/* +hsync -vsync */
160*f7018c21STomi Valkeinen 		tmp &= ~0x8;
161*f7018c21STomi Valkeinen 	} else if ((pTiming->HSP < 0) && (pTiming->VSP > 0)) {	/* -hsync +vsync */
162*f7018c21STomi Valkeinen 		tmp &= ~0x2;
163*f7018c21STomi Valkeinen 	} else if ((pTiming->HSP < 0) && (pTiming->VSP < 0)) {	/* -hsync -vsync */
164*f7018c21STomi Valkeinen 		tmp &= ~0xA;
165*f7018c21STomi Valkeinen 	} else if ((pTiming->HSP > 0) && (pTiming->VSP > 0)) {	/* +hsync -vsync */
166*f7018c21STomi Valkeinen 		tmp &= ~0x0;
167*f7018c21STomi Valkeinen 	}
168*f7018c21STomi Valkeinen 
169*f7018c21STomi Valkeinen 	STG_WRITE_REG(DACSyncCtrl, tmp);
170*f7018c21STomi Valkeinen }
171