Commit d2d4d371 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] kyrofb support

From: Paul Mundt <lethal@linux-sh.org>

This patch adds support for the Kyro graphics boards (STG4000/PowerVR
3/etc= .) to 2.6.  This is a direct port and substantial cleanup / rewrite
of the 2.4 driver that's available in the sh64 tree at linux-sh.bkbits.net.

Some of the overlay code and the STG4000 bits are still a bit ugly, so be
forewarned.
parent 43450275
......@@ -726,6 +726,16 @@ config FB_NEOMAGIC
To compile this driver as a module, choose M here: the
module will be called neofb.
config FB_KYRO
tristate "IMG Kyro support"
depends on FB && PCI
help
Say Y here if you have a STG4000 / Kyro / PowerVR 3 based
graphics board.
To compile this driver as a module, choose M here: the
module will be called kyrofb.
config FB_3DFX
tristate "3Dfx Banshee/Voodoo3 display support"
depends on FB && PCI
......
......@@ -70,6 +70,7 @@ obj-$(CONFIG_FB_VIRTUAL) += vfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt
obj-$(CONFIG_FB_HIT) += hitfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
obj-$(CONFIG_FB_E1355) += epson1355fb.o
obj-$(CONFIG_FB_PVR2) += pvr2fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
obj-$(CONFIG_FB_KYRO) += kyro/ cfbfillrect.o cfbcopyarea.o cfbimgblt.o
obj-$(CONFIG_FB_VOODOO1) += sstfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
obj-$(CONFIG_FB_FFB) += ffb.o sbuslib.o cfbimgblt.o cfbcopyarea.o
......
......@@ -159,6 +159,8 @@ extern int tcx_init(void);
extern int tcx_setup(char*);
extern int leo_init(void);
extern int leo_setup(char*);
extern int kyrofb_init(void);
extern int kyrofb_setup(char*);
static struct {
const char *name;
......@@ -360,6 +362,10 @@ static struct {
#ifdef CONFIG_FB_VOODOO1
{ "sstfb", sstfb_init, sstfb_setup },
#endif
#ifdef CONFIG_FB_KYRO
{ "kyrofb", kyrofb_init, kyrofb_setup },
#endif
/*
* Generic drivers that don't use resource management (yet)
*/
......
#
# Makefile for the Kyro framebuffer driver
#
# Note! Dependencies are done automagically by 'make dep', which also
# removes any old dependencies. DON'T put your own dependencies here
# unless it's something special (ie not a .c file).
#
# Note 2! The CFLAGS definitions are now in the main makefile...
obj-$(CONFIG_FB_KYRO) += kyrofb.o
kyrofb-objs := STG4000Ramdac.o STG4000VTG.o STG4000OverlayDevice.o \
STG4000InitDevice.o fbdev.o
/*
* linux/drivers/video/kyro/STG4000InitDevice.c
*
* Copyright (C) 2000 Imagination Technologies Ltd
* Copyright (C) 2002 STMicroelectronics
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file COPYING in the main directory of this archive
* for more details.
*/
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/pci.h>
#include "STG4000Reg.h"
/* SDRAM fixed settings */
#define SDRAM_CFG_0 0x49A1
#define SDRAM_CFG_1 0xA732
#define SDRAM_CFG_2 0x31
#define SDRAM_ARB_CFG 0xA0
#define SDRAM_REFRESH 0x20
/* Reset values */
#define PMX2_SOFTRESET_DAC_RST 0x0001
#define PMX2_SOFTRESET_C1_RST 0x0004
#define PMX2_SOFTRESET_C2_RST 0x0008
#define PMX2_SOFTRESET_3D_RST 0x0010
#define PMX2_SOFTRESET_VIDIN_RST 0x0020
#define PMX2_SOFTRESET_TLB_RST 0x0040
#define PMX2_SOFTRESET_SD_RST 0x0080
#define PMX2_SOFTRESET_VGA_RST 0x0100
#define PMX2_SOFTRESET_ROM_RST 0x0200 /* reserved bit, do not reset */
#define PMX2_SOFTRESET_TA_RST 0x0400
#define PMX2_SOFTRESET_REG_RST 0x4000
#define PMX2_SOFTRESET_ALL 0x7fff
/* Core clock freq */
#define CORE_PLL_FREQ 1000000
/* Reference Clock freq */
#define REF_FREQ 14318
/* PCI Registers */
static u16 CorePllControl = 0x70;
#define PCI_CONFIG_SUBSYS_ID 0x2e
/* Misc */
#define CORE_PLL_MODE_REG_0_7 3
#define CORE_PLL_MODE_REG_8_15 2
#define CORE_PLL_MODE_CONFIG_REG 1
#define DAC_PLL_CONFIG_REG 0
#define STG_MAX_VCO 500000
#define STG_MIN_VCO 100000
/* PLL Clock */
#define STG4K3_PLL_SCALER 8 /* scale numbers by 2^8 for fixed point calc */
#define STG4K3_PLL_MIN_R 2 /* Minimum multiplier */
#define STG4K3_PLL_MAX_R 33 /* Max */
#define STG4K3_PLL_MIN_F 2 /* Minimum divisor */
#define STG4K3_PLL_MAX_F 513 /* Max */
#define STG4K3_PLL_MIN_OD 0 /* Min output divider (shift) */
#define STG4K3_PLL_MAX_OD 2 /* Max */
#define STG4K3_PLL_MIN_VCO_SC (100000000 >> STG4K3_PLL_SCALER) /* Min VCO rate */
#define STG4K3_PLL_MAX_VCO_SC (500000000 >> STG4K3_PLL_SCALER) /* Max VCO rate */
#define STG4K3_PLL_MINR_VCO_SC (100000000 >> STG4K3_PLL_SCALER) /* Min VCO rate (restricted) */
#define STG4K3_PLL_MAXR_VCO_SC (500000000 >> STG4K3_PLL_SCALER) /* Max VCO rate (restricted) */
#define STG4K3_PLL_MINR_VCO 100000000 /* Min VCO rate (restricted) */
#define STG4K3_PLL_MAX_VCO 500000000 /* Max VCO rate */
#define STG4K3_PLL_MAXR_VCO 500000000 /* Max VCO rate (restricted) */
#define OS_DELAY(X) \
{ \
volatile u32 i,count=0; \
for(i=0;i<X;i++) count++; \
}
u32 InitSDRAMRegisters(volatile STG4000REG * pSTGReg, u32 dwSubSysID,
u32 dwRevID)
{
u32 adwSDRAMArgCfg0[] = { 0xa0, 0x80, 0xa0, 0xa0, 0xa0 };
u32 adwSDRAMCfg1[] = { 0x8732, 0x8732, 0xa732, 0xa732, 0x8732 };
u32 adwSDRAMCfg2[] = { 0x87d2, 0x87d2, 0xa7d2, 0x87d2, 0xa7d2 };
u32 adwSDRAMRsh[] = { 36, 39, 40 };
u32 adwChipSpeed[] = { 110, 120, 125 };
u32 dwMemTypeIdx;
u32 dwChipSpeedIdx;
/* Get memory tpye and chip speed indexs from the SubSysDevID */
dwMemTypeIdx = (dwSubSysID & 0x70) >> 4;
dwChipSpeedIdx = (dwSubSysID & 0x180) >> 7;
if (dwMemTypeIdx > 4 || dwChipSpeedIdx > 2)
return 0;
/* Program SD-RAM interface */
STG_WRITE_REG(SDRAMArbiterConf, adwSDRAMArgCfg0[dwMemTypeIdx]);
if (dwRevID < 5) {
STG_WRITE_REG(SDRAMConf0, 0x49A1);
STG_WRITE_REG(SDRAMConf1, adwSDRAMCfg1[dwMemTypeIdx]);
} else {
STG_WRITE_REG(SDRAMConf0, 0x4DF1);
STG_WRITE_REG(SDRAMConf1, adwSDRAMCfg2[dwMemTypeIdx]);
}
STG_WRITE_REG(SDRAMConf2, 0x31);
STG_WRITE_REG(SDRAMRefresh, adwSDRAMRsh[dwChipSpeedIdx]);
return adwChipSpeed[dwChipSpeedIdx] * 10000;
}
u32 ProgramClock(u32 refClock,
u32 coreClock,
u32 * FOut, u32 * ROut, u32 * POut)
{
u32 R = 0, F = 0, OD = 0, ODIndex = 0;
u32 ulBestR = 0, ulBestF = 0, ulBestOD = 0;
u32 ulBestVCO = 0, ulBestClk = 0, ulBestScore = 0;
u32 ulScore, ulPhaseScore, ulVcoScore;
u32 ulTmp = 0, ulVCO;
u32 ulScaleClockReq, ulMinClock, ulMaxClock;
u32 ODValues[] = { 1, 2, 0 };
/* Translate clock in Hz */
coreClock *= 100; /* in Hz */
refClock *= 1000; /* in Hz */
/* Work out acceptable clock
* The method calculates ~ +- 0.4% (1/256)
*/
ulMinClock = coreClock - (coreClock >> 8);
ulMaxClock = coreClock + (coreClock >> 8);
/* Scale clock required for use in calculations */
ulScaleClockReq = coreClock >> STG4K3_PLL_SCALER;
/* Iterate through post divider values */
for (ODIndex = 0; ODIndex < 3; ODIndex++) {
OD = ODValues[ODIndex];
R = STG4K3_PLL_MIN_R;
/* loop for pre-divider from min to max */
while (R <= STG4K3_PLL_MAX_R) {
/* estimate required feedback multiplier */
ulTmp = R * (ulScaleClockReq << OD);
/* F = ClkRequired * R * (2^OD) / Fref */
F = (u32)(ulTmp / (refClock >> STG4K3_PLL_SCALER));
/* compensate for accuracy */
if (F > STG4K3_PLL_MIN_F)
F--;
/*
* We should be close to our target frequency (if it's
* achievable with current OD & R) let's iterate
* through F for best fit
*/
while ((F >= STG4K3_PLL_MIN_F) &&
(F <= STG4K3_PLL_MAX_F)) {
/* Calc VCO at full accuracy */
ulVCO = refClock / R;
ulVCO = F * ulVCO;
/*
* Check it's within restricted VCO range
* unless of course the desired frequency is
* above the restricted range, then test
* against VCO limit
*/
if ((ulVCO >= STG4K3_PLL_MINR_VCO) &&
((ulVCO <= STG4K3_PLL_MAXR_VCO) ||
((coreClock > STG4K3_PLL_MAXR_VCO)
&& (ulVCO <= STG4K3_PLL_MAX_VCO)))) {
ulTmp = (ulVCO >> OD); /* Clock = VCO / (2^OD) */
/* Is this clock good enough? */
if ((ulTmp >= ulMinClock)
&& (ulTmp <= ulMaxClock)) {
ulPhaseScore = (((refClock / R) - (refClock / STG4K3_PLL_MAX_R))) / ((refClock - (refClock / STG4K3_PLL_MAX_R)) >> 10);
ulVcoScore = ((ulVCO - STG4K3_PLL_MINR_VCO)) / ((STG4K3_PLL_MAXR_VCO - STG4K3_PLL_MINR_VCO) >> 10);
ulScore = ulPhaseScore + ulVcoScore;
if (!ulBestScore) {
ulBestVCO = ulVCO;
ulBestOD = OD;
ulBestF = F;
ulBestR = R;
ulBestClk = ulTmp;
ulBestScore =
ulScore;
}
/* is this better, ( aim for highest Score) */
/*--------------------------------------------------------------------------
Here we want to use a scoring system which will take account of both the
value at the phase comparater and the VCO output
to do this we will use a cumulative score between the two
The way this ends up is that we choose the first value in the loop anyway
but we shall keep this code in case new restrictions come into play
--------------------------------------------------------------------------*/
if ((ulScore >= ulBestScore) && (OD > 0)) {
ulBestVCO = ulVCO;
ulBestOD = OD;
ulBestF = F;
ulBestR = R;
ulBestClk = ulTmp;
ulBestScore =
ulScore;
}
}
}
F++;
}
R++;
}
}
/*
did we find anything?
Then return RFOD
*/
if (ulBestScore) {
*ROut = ulBestR;
*FOut = ulBestF;
if ((ulBestOD == 2) || (ulBestOD == 3)) {
*POut = 3;
} else
*POut = ulBestOD;
}
return (ulBestClk);
}
int SetCoreClockPLL(volatile STG4000REG * pSTGReg, struct pci_dev *pDev)
{
u32 F, R, P;
u16 core_pll = 0, sub;
u32 ulCoreClock;
u32 tmp;
u32 ulChipSpeed;
u8 rev;
STG_WRITE_REG(IntMask, 0xFFFF);
/* Disable Primary Core Thread0 */
tmp = STG_READ_REG(Thread0Enable);
CLEAR_BIT(0);
STG_WRITE_REG(Thread0Enable, tmp);
/* Disable Primary Core Thread1 */
tmp = STG_READ_REG(Thread1Enable);
CLEAR_BIT(0);
STG_WRITE_REG(Thread1Enable, tmp);
STG_WRITE_REG(SoftwareReset,
PMX2_SOFTRESET_REG_RST | PMX2_SOFTRESET_ROM_RST);
STG_WRITE_REG(SoftwareReset,
PMX2_SOFTRESET_REG_RST | PMX2_SOFTRESET_TA_RST |
PMX2_SOFTRESET_ROM_RST);
/* Need to play around to reset TA */
STG_WRITE_REG(TAConfiguration, 0);
STG_WRITE_REG(SoftwareReset,
PMX2_SOFTRESET_REG_RST | PMX2_SOFTRESET_ROM_RST);
STG_WRITE_REG(SoftwareReset,
PMX2_SOFTRESET_REG_RST | PMX2_SOFTRESET_TA_RST |
PMX2_SOFTRESET_ROM_RST);
pci_read_config_word(pDev, PCI_CONFIG_SUBSYS_ID, &sub);
pci_read_config_byte(pDev, PCI_REVISION_ID, &rev);
ulChipSpeed = InitSDRAMRegisters(pSTGReg, (u32)sub, (u32)rev);
if (ulChipSpeed == 0)
return -EINVAL;
ulCoreClock = ProgramClock(REF_FREQ, CORE_PLL_FREQ, &F, &R, &P);
core_pll |= ((P) | ((F - 2) << 2) | ((R - 2) << 11));
/* Set Core PLL Control to Core PLL Mode */
/* Send bits 0:7 of the Core PLL Mode register */
tmp = ((CORE_PLL_MODE_REG_0_7 << 8) | (core_pll & 0x00FF));
pci_write_config_word(pDev, CorePllControl, tmp);
/* Without some delay between the PCI config writes the clock does
not reliably set when the code is compiled -O3
*/
OS_DELAY(1000000);
tmp |= SET_BIT(14);
pci_write_config_word(pDev, CorePllControl, tmp);
OS_DELAY(1000000);
/* Send bits 8:15 of the Core PLL Mode register */
tmp =
((CORE_PLL_MODE_REG_8_15 << 8) | ((core_pll & 0xFF00) >> 8));
pci_write_config_word(pDev, CorePllControl, tmp);
OS_DELAY(1000000);
tmp |= SET_BIT(14);
pci_write_config_word(pDev, CorePllControl, tmp);
OS_DELAY(1000000);
STG_WRITE_REG(SoftwareReset, PMX2_SOFTRESET_ALL);
#if 0
/* Enable Primary Core Thread0 */
tmp = ((STG_READ_REG(Thread0Enable)) | SET_BIT(0));
STG_WRITE_REG(Thread0Enable, tmp);
/* Enable Primary Core Thread1 */
tmp = ((STG_READ_REG(Thread1Enable)) | SET_BIT(0));
STG_WRITE_REG(Thread1Enable, tmp);
#endif
return 0;
}
/*
* linux/drivers/video/kyro/STG4000Interface.h
*
* Copyright (C) 2002 STMicroelectronics
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file COPYING in the main directory of this archive
* for more details.
*/
#ifndef _STG4000INTERFACE_H
#define _STG4000INTERFACE_H
struct pci_dev;
/*
* Ramdac Setup
*/
extern int InitialiseRamdac(volatile STG4000REG *pSTGReg, u32 displayDepth,
u32 displayWidth, u32 displayHeight,
s32 HSyncPolarity, s32 VSyncPolarity,
u32 *pixelClock);
extern void DisableRamdacOutput(volatile STG4000REG * pSTGReg);
extern void EnableRamdacOutput(volatile STG4000REG * pSTGReg);
/*
* Timing generator setup
*/
extern void DisableVGA(volatile STG4000REG * pSTGReg);
extern void StopVTG(volatile STG4000REG * pSTGReg);
extern void StartVTG(volatile STG4000REG * pSTGReg);
extern void SetupVTG(volatile STG4000REG * pSTGReg,
const struct kyrofb_info * pTiming);
extern u32 ProgramClock(u32 refClock, u32 coreClock, u32 *FOut, u32 *ROut, u32 *POut);
extern int SetCoreClockPLL(volatile STG4000REG * pSTGReg, struct pci_dev *pDev);
/*
* Overlay setup
*/
extern void ResetOverlayRegisters(volatile STG4000REG * pSTGReg);
extern int CreateOverlaySurface(volatile STG4000REG * pSTGReg,
u32 ulWidth, u32 ulHeight,
int bLinear,
u32 ulOverlayOffset,
u32 * retStride, u32 * retUVStride);
extern int SetOverlayBlendMode(volatile STG4000REG * pSTGReg,
OVRL_BLEND_MODE mode,
u32 ulAlpha, u32 ulColorKey);
extern int SetOverlayViewPort(volatile STG4000REG * pSTGReg,
u32 left, u32 top,
u32 right, u32 bottom);
extern void EnableOverlayPlane(volatile STG4000REG * pSTGReg);
#endif /* _STG4000INTERFACE_H */
This diff is collapsed.
/*
* linux/drivers/video/kyro/STG4000Ramdac.c
*
* Copyright (C) 2002 STMicroelectronics
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file COPYING in the main directory of this archive
* for more details.
*/
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <video/kyro.h>
#include "STG4000Reg.h"
#include "STG4000Interface.h"
static u32 STG_PIXEL_BUS_WIDTH = 128; /* 128 bit bus width */
static u32 REF_CLOCK = 14318;
STG4000REG *pSTGReg;
int InitialiseRamdac(volatile STG4000REG * pSTGReg,
u32 displayDepth,
u32 displayWidth,
u32 displayHeight,
s32 HSyncPolarity,
s32 VSyncPolarity, u32 * pixelClock)
{
u32 tmp = 0;
u32 F = 0, R = 0, P = 0;
u32 stride = 0;
u32 ulPdiv = 0;
u32 physicalPixelDepth = 0;
/* Make sure DAC is in Reset */
tmp = STG_READ_REG(SoftwareReset);
if (tmp & 0x1) {
CLEAR_BIT(1);
STG_WRITE_REG(SoftwareReset, tmp);
}
/* Set Pixel Format */
tmp = STG_READ_REG(DACPixelFormat);
CLEAR_BITS_FRM_TO(0, 2);
/* Set LUT not used from 16bpp to 32 bpp ??? */
CLEAR_BITS_FRM_TO(8, 9);
switch (displayDepth) {
case 16:
{
physicalPixelDepth = 16;
tmp |= _16BPP;
break;
}
case 32:
{
/* Set for 32 bits per pixel */
physicalPixelDepth = 32;
tmp |= _32BPP;
break;
}
default:
return -EINVAL;
}
STG_WRITE_REG(DACPixelFormat, tmp);
/* Workout Bus transfer bandwidth according to pixel format */
ulPdiv = STG_PIXEL_BUS_WIDTH / physicalPixelDepth;
/* Get Screen Stride in pixels */
stride = displayWidth;
/* Set Primary size info */
tmp = STG_READ_REG(DACPrimSize);
CLEAR_BITS_FRM_TO(0, 10);
CLEAR_BITS_FRM_TO(12, 31);
tmp |=
((((displayHeight - 1) << 12) | (((displayWidth / ulPdiv) -
1) << 23))
| (stride / ulPdiv));
STG_WRITE_REG(DACPrimSize, tmp);
/* Set Pixel Clock */
*pixelClock = ProgramClock(REF_CLOCK, *pixelClock, &F, &R, &P);
/* Set DAC PLL Mode */
tmp = STG_READ_REG(DACPLLMode);
CLEAR_BITS_FRM_TO(0, 15);
/* tmp |= ((P-1) | ((F-2) << 2) | ((R-2) << 11)); */
tmp |= ((P) | ((F - 2) << 2) | ((R - 2) << 11));
STG_WRITE_REG(DACPLLMode, tmp);
/* Set Prim Address */
tmp = STG_READ_REG(DACPrimAddress);
CLEAR_BITS_FRM_TO(0, 20);
CLEAR_BITS_FRM_TO(20, 31);
STG_WRITE_REG(DACPrimAddress, tmp);
/* Set Cursor details with HW Cursor disabled */
tmp = STG_READ_REG(DACCursorCtrl);
tmp &= ~SET_BIT(31);
STG_WRITE_REG(DACCursorCtrl, tmp);
tmp = STG_READ_REG(DACCursorAddr);
CLEAR_BITS_FRM_TO(0, 20);
STG_WRITE_REG(DACCursorAddr, tmp);
/* Set Video Window */
tmp = STG_READ_REG(DACVidWinStart);
CLEAR_BITS_FRM_TO(0, 10);
CLEAR_BITS_FRM_TO(16, 26);
STG_WRITE_REG(DACVidWinStart, tmp);
tmp = STG_READ_REG(DACVidWinEnd);
CLEAR_BITS_FRM_TO(0, 10);
CLEAR_BITS_FRM_TO(16, 26);
STG_WRITE_REG(DACVidWinEnd, tmp);
/* Set DAC Border Color to default */
tmp = STG_READ_REG(DACBorderColor);
CLEAR_BITS_FRM_TO(0, 23);
STG_WRITE_REG(DACBorderColor, tmp);
/* Set Graphics and Overlay Burst Control */
STG_WRITE_REG(DACBurstCtrl, 0x0404);
/* Set CRC Trigger to default */
tmp = STG_READ_REG(DACCrcTrigger);
CLEAR_BIT(0);
STG_WRITE_REG(DACCrcTrigger, tmp);
/* Set Video Port Control to default */
tmp = STG_READ_REG(DigVidPortCtrl);
CLEAR_BIT(8);
CLEAR_BITS_FRM_TO(16, 27);
CLEAR_BITS_FRM_TO(1, 3);
CLEAR_BITS_FRM_TO(10, 11);
STG_WRITE_REG(DigVidPortCtrl, tmp);
return 0;
}
/* Ramdac control, turning output to the screen on and off */
void DisableRamdacOutput(volatile STG4000REG * pSTGReg)
{
u32 tmp;
/* Disable DAC for Graphics Stream Control */
tmp = (STG_READ_REG(DACStreamCtrl)) & ~SET_BIT(0);
STG_WRITE_REG(DACStreamCtrl, tmp);
}
void EnableRamdacOutput(volatile STG4000REG * pSTGReg)
{
u32 tmp;
/* Enable DAC for Graphics Stream Control */
tmp = (STG_READ_REG(DACStreamCtrl)) | SET_BIT(0);
STG_WRITE_REG(DACStreamCtrl, tmp);
}
This diff is collapsed.
/*
* linux/drivers/video/kyro/STG4000VTG.c
*
* Copyright (C) 2002 STMicroelectronics
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file COPYING in the main directory of this archive
* for more details.
*/
#include <linux/types.h>
#include <video/kyro.h>
#include "STG4000Reg.h"
#include "STG4000Interface.h"
void DisableVGA(volatile STG4000REG * pSTGReg)
{
u32 tmp;
volatile u32 count, i;
/* Reset the VGA registers */
tmp = STG_READ_REG(SoftwareReset);
CLEAR_BIT(8);
STG_WRITE_REG(SoftwareReset, tmp);
/* Just for Delay */
for (i = 0; i < 1000; i++) {
count++;
}
/* Pull-out the VGA registers from reset */
tmp = STG_READ_REG(SoftwareReset);
tmp |= SET_BIT(8);
STG_WRITE_REG(SoftwareReset, tmp);
}
void StopVTG(volatile STG4000REG * pSTGReg)
{
u32 tmp = 0;
/* Stop Ver and Hor Sync Generator */
tmp = (STG_READ_REG(DACSyncCtrl)) | SET_BIT(0) | SET_BIT(2);
CLEAR_BIT(31);
STG_WRITE_REG(DACSyncCtrl, tmp);
}
void StartVTG(volatile STG4000REG * pSTGReg)
{
u32 tmp = 0;
/* Start Ver and Hor Sync Generator */
tmp = ((STG_READ_REG(DACSyncCtrl)) | SET_BIT(31));
CLEAR_BIT(0);
CLEAR_BIT(2);
STG_WRITE_REG(DACSyncCtrl, tmp);
}
void SetupVTG(volatile STG4000REG * pSTGReg,
const struct kyrofb_info * pTiming)
{
u32 tmp = 0;
u32 margins = 0;
u32 ulBorder;
u32 xRes = pTiming->XRES;
u32 yRes = pTiming->YRES;
/* Horizontal */
u32 HAddrTime, HRightBorder, HLeftBorder;
u32 HBackPorcStrt, HFrontPorchStrt, HTotal,
HLeftBorderStrt, HRightBorderStrt, HDisplayStrt;
/* Vertical */
u32 VDisplayStrt, VBottomBorder, VTopBorder;
u32 VBackPorchStrt, VTotal, VTopBorderStrt,
VFrontPorchStrt, VBottomBorderStrt, VAddrTime;
/* Need to calculate the right border */
if ((xRes == 640) && (yRes == 480)) {
if ((pTiming->VFREQ == 60) || (pTiming->VFREQ == 72)) {
margins = 8;
}
}
/* Work out the Border */
ulBorder =
(pTiming->HTot -
(pTiming->HST + (pTiming->HBP - margins) + xRes +
(pTiming->HFP - margins))) >> 1;
/* Border the same for Vertical and Horizontal */
VBottomBorder = HLeftBorder = VTopBorder = HRightBorder = ulBorder;
/************ Get Timing values for Horizontal ******************/
HAddrTime = xRes;
HBackPorcStrt = pTiming->HST;
HTotal = pTiming->HTot;
HDisplayStrt =
pTiming->HST + (pTiming->HBP - margins) + HLeftBorder;
HLeftBorderStrt = HDisplayStrt - HLeftBorder;
HFrontPorchStrt =
pTiming->HST + (pTiming->HBP - margins) + HLeftBorder +
HAddrTime + HRightBorder;
HRightBorderStrt = HFrontPorchStrt - HRightBorder;
/************ Get Timing values for Vertical ******************/
VAddrTime = yRes;
VBackPorchStrt = pTiming->VST;
VTotal = pTiming->VTot;
VDisplayStrt =
pTiming->VST + (pTiming->VBP - margins) + VTopBorder;
VTopBorderStrt = VDisplayStrt - VTopBorder;
VFrontPorchStrt =
pTiming->VST + (pTiming->VBP - margins) + VTopBorder +
VAddrTime + VBottomBorder;
VBottomBorderStrt = VFrontPorchStrt - VBottomBorder;
/* Set Hor Timing 1, 2, 3 */
tmp = STG_READ_REG(DACHorTim1);
CLEAR_BITS_FRM_TO(0, 11);
CLEAR_BITS_FRM_TO(16, 27);
tmp |= (HTotal) | (HBackPorcStrt << 16);
STG_WRITE_REG(DACHorTim1, tmp);
tmp = STG_READ_REG(DACHorTim2);
CLEAR_BITS_FRM_TO(0, 11);
CLEAR_BITS_FRM_TO(16, 27);
tmp |= (HDisplayStrt << 16) | HLeftBorderStrt;
STG_WRITE_REG(DACHorTim2, tmp);
tmp = STG_READ_REG(DACHorTim3);
CLEAR_BITS_FRM_TO(0, 11);
CLEAR_BITS_FRM_TO(16, 27);
tmp |= (HFrontPorchStrt << 16) | HRightBorderStrt;
STG_WRITE_REG(DACHorTim3, tmp);
/* Set Ver Timing 1, 2, 3 */
tmp = STG_READ_REG(DACVerTim1);
CLEAR_BITS_FRM_TO(0, 11);
CLEAR_BITS_FRM_TO(16, 27);
tmp |= (VBackPorchStrt << 16) | (VTotal);
STG_WRITE_REG(DACVerTim1, tmp);
tmp = STG_READ_REG(DACVerTim2);
CLEAR_BITS_FRM_TO(0, 11);
CLEAR_BITS_FRM_TO(16, 27);
tmp |= (VDisplayStrt << 16) | VTopBorderStrt;
STG_WRITE_REG(DACVerTim2, tmp);
tmp = STG_READ_REG(DACVerTim3);
CLEAR_BITS_FRM_TO(0, 11);
CLEAR_BITS_FRM_TO(16, 27);
tmp |= (VFrontPorchStrt << 16) | VBottomBorderStrt;
STG_WRITE_REG(DACVerTim3, tmp);
/* Set Verical and Horizontal Polarity */
tmp = STG_READ_REG(DACSyncCtrl) | SET_BIT(3) | SET_BIT(1);
if ((pTiming->HSP > 0) && (pTiming->VSP < 0)) { /* +hsync -vsync */
tmp &= ~0x8;
} else if ((pTiming->HSP < 0) && (pTiming->VSP > 0)) { /* -hsync +vsync */
tmp &= ~0x2;
} else if ((pTiming->HSP < 0) && (pTiming->VSP < 0)) { /* -hsync -vsync */
tmp &= ~0xA;
} else if ((pTiming->HSP > 0) && (pTiming->VSP > 0)) { /* +hsync -vsync */
tmp &= ~0x0;
}
STG_WRITE_REG(DACSyncCtrl, tmp);
}
This diff is collapsed.
/*
* linux/drivers/video/kyro/kryo.h
*
* Copyright (C) 2002 STMicroelectronics
* Copyright (C) 2004 Paul Mundt
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file COPYING in the main directory of this archive
* for more details.
*/
#ifndef _KYRO_H
#define _KYRO_H
struct kyrofb_info {
void *regbase;
u32 HTot; /* Hor Total Time */
u32 HFP; /* Hor Front Porch */
u32 HST; /* Hor Sync Time */
u32 HBP; /* Hor Back Porch */
s32 HSP; /* Hor Sync Polarity */
u32 VTot; /* Ver Total Time */
u32 VFP; /* Ver Front Porch */
u32 VST; /* Ver Sync Time */
u32 VBP; /* Ver Back Porch */
s32 VSP; /* Ver Sync Polarity */
u32 XRES; /* X Resolution */
u32 YRES; /* Y Resolution */
u32 VFREQ; /* Ver Frequency */
u32 PIXCLK; /* Pixel Clock */
u32 HCLK; /* Hor Clock */
/* Usefull to hold depth here for Linux */
u8 PIXDEPTH;
#ifdef CONFIG_MTRR
int mtrr_handle;
#endif
};
extern int kyro_dev_init(void);
extern void kyro_dev_reset(void);
extern unsigned char *kyro_dev_physical_fb_ptr(void);
extern unsigned char *kyro_dev_virtual_fb_ptr(void);
extern void *kyro_dev_physical_regs_ptr(void);
extern void *kyro_dev_virtual_regs_ptr(void);
extern unsigned int kyro_dev_fb_size(void);
extern unsigned int kyro_dev_regs_size(void);
extern int kyro_dev_overlay_create(u32 width, u32 height, int bLinear);
extern u32 kyro_dev_overlay_offset(void);
extern int kyro_dev_overlay_viewport_set(u32 x, u32 y, u32 width, u32 height);
/*
* benedict.gaster@superh.com
* Added the follow IOCTLS for the creation of overlay services...
*/
#define KYRO_IOC_MAGIC 'k'
#define KYRO_IOCTL_OVERLAY_CREATE _IO(KYRO_IOC_MAGIC, 0)
#define KYRO_IOCTL_OVERLAY_VIEWPORT_SET _IO(KYRO_IOC_MAGIC, 1)
#define KYRO_IOCTL_SET_VIDEO_MODE _IO(KYRO_IOC_MAGIC, 2)
#define KYRO_IOCTL_UVSTRIDE _IO(KYRO_IOC_MAGIC, 3)
#define KYRO_IOCTL_OVERLAY_OFFSET _IO(KYRO_IOC_MAGIC, 4)
#define KYRO_IOCTL_STRIDE _IO(KYRO_IOC_MAGIC, 5)
/*
* The follow 3 structures are used to pass data from user space into the kernel
* for the creation of overlay surfaces and setting the video mode.
*/
typedef struct _OVERLAY_CREATE {
u32 ulWidth;
u32 ulHeight;
int bLinear;
} overlay_create;
typedef struct _OVERLAY_VIEWPORT_SET {
u32 xOrgin;
u32 yOrgin;
u32 xSize;
u32 ySize;
} overlay_viewport_set;
typedef struct _SET_VIDEO_MODE {
u32 ulWidth;
u32 ulHeight;
u32 ulScan;
u8 displayDepth;
int bLinear;
} set_video_mode;
#endif /* _KYRO_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment