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