18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci *  linux/drivers/video/kyro/STG4000VTG.c
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci *  Copyright (C) 2002 STMicroelectronics
58c2ecf20Sopenharmony_ci *
68c2ecf20Sopenharmony_ci * This file is subject to the terms and conditions of the GNU General Public
78c2ecf20Sopenharmony_ci * License.  See the file COPYING in the main directory of this archive
88c2ecf20Sopenharmony_ci * for more details.
98c2ecf20Sopenharmony_ci */
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci#include <linux/types.h>
128c2ecf20Sopenharmony_ci#include <video/kyro.h>
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ci#include "STG4000Reg.h"
158c2ecf20Sopenharmony_ci#include "STG4000Interface.h"
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_civoid DisableVGA(volatile STG4000REG __iomem *pSTGReg)
188c2ecf20Sopenharmony_ci{
198c2ecf20Sopenharmony_ci	u32 tmp;
208c2ecf20Sopenharmony_ci	volatile u32 count = 0, i;
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci	/* Reset the VGA registers */
238c2ecf20Sopenharmony_ci	tmp = STG_READ_REG(SoftwareReset);
248c2ecf20Sopenharmony_ci	CLEAR_BIT(8);
258c2ecf20Sopenharmony_ci	STG_WRITE_REG(SoftwareReset, tmp);
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_ci	/* Just for Delay */
288c2ecf20Sopenharmony_ci	for (i = 0; i < 1000; i++) {
298c2ecf20Sopenharmony_ci		count++;
308c2ecf20Sopenharmony_ci	}
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_ci	/* Pull-out the VGA registers from reset */
338c2ecf20Sopenharmony_ci	tmp = STG_READ_REG(SoftwareReset);
348c2ecf20Sopenharmony_ci	tmp |= SET_BIT(8);
358c2ecf20Sopenharmony_ci	STG_WRITE_REG(SoftwareReset, tmp);
368c2ecf20Sopenharmony_ci}
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_civoid StopVTG(volatile STG4000REG __iomem *pSTGReg)
398c2ecf20Sopenharmony_ci{
408c2ecf20Sopenharmony_ci	u32 tmp = 0;
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ci	/* Stop Ver and Hor Sync Generator */
438c2ecf20Sopenharmony_ci	tmp = (STG_READ_REG(DACSyncCtrl)) | SET_BIT(0) | SET_BIT(2);
448c2ecf20Sopenharmony_ci	CLEAR_BIT(31);
458c2ecf20Sopenharmony_ci	STG_WRITE_REG(DACSyncCtrl, tmp);
468c2ecf20Sopenharmony_ci}
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_civoid StartVTG(volatile STG4000REG __iomem *pSTGReg)
498c2ecf20Sopenharmony_ci{
508c2ecf20Sopenharmony_ci	u32 tmp = 0;
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ci	/* Start Ver and Hor Sync Generator */
538c2ecf20Sopenharmony_ci	tmp = ((STG_READ_REG(DACSyncCtrl)) | SET_BIT(31));
548c2ecf20Sopenharmony_ci	CLEAR_BIT(0);
558c2ecf20Sopenharmony_ci	CLEAR_BIT(2);
568c2ecf20Sopenharmony_ci	STG_WRITE_REG(DACSyncCtrl, tmp);
578c2ecf20Sopenharmony_ci}
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_civoid SetupVTG(volatile STG4000REG __iomem *pSTGReg,
608c2ecf20Sopenharmony_ci	      const struct kyrofb_info * pTiming)
618c2ecf20Sopenharmony_ci{
628c2ecf20Sopenharmony_ci	u32 tmp = 0;
638c2ecf20Sopenharmony_ci	u32 margins = 0;
648c2ecf20Sopenharmony_ci	u32 ulBorder;
658c2ecf20Sopenharmony_ci	u32 xRes = pTiming->XRES;
668c2ecf20Sopenharmony_ci	u32 yRes = pTiming->YRES;
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_ci	/* Horizontal */
698c2ecf20Sopenharmony_ci	u32 HAddrTime, HRightBorder, HLeftBorder;
708c2ecf20Sopenharmony_ci	u32 HBackPorcStrt, HFrontPorchStrt, HTotal,
718c2ecf20Sopenharmony_ci	    HLeftBorderStrt, HRightBorderStrt, HDisplayStrt;
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ci	/* Vertical */
748c2ecf20Sopenharmony_ci	u32 VDisplayStrt, VBottomBorder, VTopBorder;
758c2ecf20Sopenharmony_ci	u32 VBackPorchStrt, VTotal, VTopBorderStrt,
768c2ecf20Sopenharmony_ci	    VFrontPorchStrt, VBottomBorderStrt, VAddrTime;
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ci	/* Need to calculate the right border */
798c2ecf20Sopenharmony_ci	if ((xRes == 640) && (yRes == 480)) {
808c2ecf20Sopenharmony_ci		if ((pTiming->VFREQ == 60) || (pTiming->VFREQ == 72)) {
818c2ecf20Sopenharmony_ci			margins = 8;
828c2ecf20Sopenharmony_ci		}
838c2ecf20Sopenharmony_ci	}
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_ci	/* Work out the Border */
868c2ecf20Sopenharmony_ci	ulBorder =
878c2ecf20Sopenharmony_ci	    (pTiming->HTot -
888c2ecf20Sopenharmony_ci	     (pTiming->HST + (pTiming->HBP - margins) + xRes +
898c2ecf20Sopenharmony_ci	      (pTiming->HFP - margins))) >> 1;
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_ci	/* Border the same for Vertical and Horizontal */
928c2ecf20Sopenharmony_ci	VBottomBorder = HLeftBorder = VTopBorder = HRightBorder = ulBorder;
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_ci    /************ Get Timing values for Horizontal ******************/
958c2ecf20Sopenharmony_ci	HAddrTime = xRes;
968c2ecf20Sopenharmony_ci	HBackPorcStrt = pTiming->HST;
978c2ecf20Sopenharmony_ci	HTotal = pTiming->HTot;
988c2ecf20Sopenharmony_ci	HDisplayStrt =
998c2ecf20Sopenharmony_ci	    pTiming->HST + (pTiming->HBP - margins) + HLeftBorder;
1008c2ecf20Sopenharmony_ci	HLeftBorderStrt = HDisplayStrt - HLeftBorder;
1018c2ecf20Sopenharmony_ci	HFrontPorchStrt =
1028c2ecf20Sopenharmony_ci	    pTiming->HST + (pTiming->HBP - margins) + HLeftBorder +
1038c2ecf20Sopenharmony_ci	    HAddrTime + HRightBorder;
1048c2ecf20Sopenharmony_ci	HRightBorderStrt = HFrontPorchStrt - HRightBorder;
1058c2ecf20Sopenharmony_ci
1068c2ecf20Sopenharmony_ci    /************ Get Timing values for Vertical ******************/
1078c2ecf20Sopenharmony_ci	VAddrTime = yRes;
1088c2ecf20Sopenharmony_ci	VBackPorchStrt = pTiming->VST;
1098c2ecf20Sopenharmony_ci	VTotal = pTiming->VTot;
1108c2ecf20Sopenharmony_ci	VDisplayStrt =
1118c2ecf20Sopenharmony_ci	    pTiming->VST + (pTiming->VBP - margins) + VTopBorder;
1128c2ecf20Sopenharmony_ci	VTopBorderStrt = VDisplayStrt - VTopBorder;
1138c2ecf20Sopenharmony_ci	VFrontPorchStrt =
1148c2ecf20Sopenharmony_ci	    pTiming->VST + (pTiming->VBP - margins) + VTopBorder +
1158c2ecf20Sopenharmony_ci	    VAddrTime + VBottomBorder;
1168c2ecf20Sopenharmony_ci	VBottomBorderStrt = VFrontPorchStrt - VBottomBorder;
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_ci	/* Set Hor Timing 1, 2, 3 */
1198c2ecf20Sopenharmony_ci	tmp = STG_READ_REG(DACHorTim1);
1208c2ecf20Sopenharmony_ci	CLEAR_BITS_FRM_TO(0, 11);
1218c2ecf20Sopenharmony_ci	CLEAR_BITS_FRM_TO(16, 27);
1228c2ecf20Sopenharmony_ci	tmp |= (HTotal) | (HBackPorcStrt << 16);
1238c2ecf20Sopenharmony_ci	STG_WRITE_REG(DACHorTim1, tmp);
1248c2ecf20Sopenharmony_ci
1258c2ecf20Sopenharmony_ci	tmp = STG_READ_REG(DACHorTim2);
1268c2ecf20Sopenharmony_ci	CLEAR_BITS_FRM_TO(0, 11);
1278c2ecf20Sopenharmony_ci	CLEAR_BITS_FRM_TO(16, 27);
1288c2ecf20Sopenharmony_ci	tmp |= (HDisplayStrt << 16) | HLeftBorderStrt;
1298c2ecf20Sopenharmony_ci	STG_WRITE_REG(DACHorTim2, tmp);
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_ci	tmp = STG_READ_REG(DACHorTim3);
1328c2ecf20Sopenharmony_ci	CLEAR_BITS_FRM_TO(0, 11);
1338c2ecf20Sopenharmony_ci	CLEAR_BITS_FRM_TO(16, 27);
1348c2ecf20Sopenharmony_ci	tmp |= (HFrontPorchStrt << 16) | HRightBorderStrt;
1358c2ecf20Sopenharmony_ci	STG_WRITE_REG(DACHorTim3, tmp);
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_ci	/* Set Ver Timing 1, 2, 3 */
1388c2ecf20Sopenharmony_ci	tmp = STG_READ_REG(DACVerTim1);
1398c2ecf20Sopenharmony_ci	CLEAR_BITS_FRM_TO(0, 11);
1408c2ecf20Sopenharmony_ci	CLEAR_BITS_FRM_TO(16, 27);
1418c2ecf20Sopenharmony_ci	tmp |= (VBackPorchStrt << 16) | (VTotal);
1428c2ecf20Sopenharmony_ci	STG_WRITE_REG(DACVerTim1, tmp);
1438c2ecf20Sopenharmony_ci
1448c2ecf20Sopenharmony_ci	tmp = STG_READ_REG(DACVerTim2);
1458c2ecf20Sopenharmony_ci	CLEAR_BITS_FRM_TO(0, 11);
1468c2ecf20Sopenharmony_ci	CLEAR_BITS_FRM_TO(16, 27);
1478c2ecf20Sopenharmony_ci	tmp |= (VDisplayStrt << 16) | VTopBorderStrt;
1488c2ecf20Sopenharmony_ci	STG_WRITE_REG(DACVerTim2, tmp);
1498c2ecf20Sopenharmony_ci
1508c2ecf20Sopenharmony_ci	tmp = STG_READ_REG(DACVerTim3);
1518c2ecf20Sopenharmony_ci	CLEAR_BITS_FRM_TO(0, 11);
1528c2ecf20Sopenharmony_ci	CLEAR_BITS_FRM_TO(16, 27);
1538c2ecf20Sopenharmony_ci	tmp |= (VFrontPorchStrt << 16) | VBottomBorderStrt;
1548c2ecf20Sopenharmony_ci	STG_WRITE_REG(DACVerTim3, tmp);
1558c2ecf20Sopenharmony_ci
1568c2ecf20Sopenharmony_ci	/* Set Verical and Horizontal Polarity */
1578c2ecf20Sopenharmony_ci	tmp = STG_READ_REG(DACSyncCtrl) | SET_BIT(3) | SET_BIT(1);
1588c2ecf20Sopenharmony_ci
1598c2ecf20Sopenharmony_ci	if ((pTiming->HSP > 0) && (pTiming->VSP < 0)) {	/* +hsync -vsync */
1608c2ecf20Sopenharmony_ci		tmp &= ~0x8;
1618c2ecf20Sopenharmony_ci	} else if ((pTiming->HSP < 0) && (pTiming->VSP > 0)) {	/* -hsync +vsync */
1628c2ecf20Sopenharmony_ci		tmp &= ~0x2;
1638c2ecf20Sopenharmony_ci	} else if ((pTiming->HSP < 0) && (pTiming->VSP < 0)) {	/* -hsync -vsync */
1648c2ecf20Sopenharmony_ci		tmp &= ~0xA;
1658c2ecf20Sopenharmony_ci	} else if ((pTiming->HSP > 0) && (pTiming->VSP > 0)) {	/* +hsync -vsync */
1668c2ecf20Sopenharmony_ci		tmp &= ~0x0;
1678c2ecf20Sopenharmony_ci	}
1688c2ecf20Sopenharmony_ci
1698c2ecf20Sopenharmony_ci	STG_WRITE_REG(DACSyncCtrl, tmp);
1708c2ecf20Sopenharmony_ci}
171