162306a36Sopenharmony_ci/*
262306a36Sopenharmony_ci *  linux/drivers/video/kyro/STG4000Ramdac.c
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci *  Copyright (C) 2002 STMicroelectronics
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci * This file is subject to the terms and conditions of the GNU General Public
762306a36Sopenharmony_ci * License.  See the file COPYING in the main directory of this archive
862306a36Sopenharmony_ci * for more details.
962306a36Sopenharmony_ci */
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci#include <linux/kernel.h>
1262306a36Sopenharmony_ci#include <linux/errno.h>
1362306a36Sopenharmony_ci#include <linux/types.h>
1462306a36Sopenharmony_ci#include <video/kyro.h>
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci#include "STG4000Reg.h"
1762306a36Sopenharmony_ci#include "STG4000Interface.h"
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_cistatic u32 STG_PIXEL_BUS_WIDTH = 128;	/* 128 bit bus width      */
2062306a36Sopenharmony_cistatic u32 REF_CLOCK = 14318;
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ciint InitialiseRamdac(volatile STG4000REG __iomem * pSTGReg,
2362306a36Sopenharmony_ci		     u32 displayDepth,
2462306a36Sopenharmony_ci		     u32 displayWidth,
2562306a36Sopenharmony_ci		     u32 displayHeight,
2662306a36Sopenharmony_ci		     s32 HSyncPolarity,
2762306a36Sopenharmony_ci		     s32 VSyncPolarity, u32 * pixelClock)
2862306a36Sopenharmony_ci{
2962306a36Sopenharmony_ci	u32 tmp = 0;
3062306a36Sopenharmony_ci	u32 F = 0, R = 0, P = 0;
3162306a36Sopenharmony_ci	u32 stride = 0;
3262306a36Sopenharmony_ci	u32 ulPdiv = 0;
3362306a36Sopenharmony_ci	u32 physicalPixelDepth = 0;
3462306a36Sopenharmony_ci	/* Make sure DAC is in Reset */
3562306a36Sopenharmony_ci	tmp = STG_READ_REG(SoftwareReset);
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci	if (tmp & 0x1) {
3862306a36Sopenharmony_ci		CLEAR_BIT(1);
3962306a36Sopenharmony_ci		STG_WRITE_REG(SoftwareReset, tmp);
4062306a36Sopenharmony_ci	}
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci	/* Set Pixel Format */
4362306a36Sopenharmony_ci	tmp = STG_READ_REG(DACPixelFormat);
4462306a36Sopenharmony_ci	CLEAR_BITS_FRM_TO(0, 2);
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci	/* Set LUT not used from 16bpp to 32 bpp ??? */
4762306a36Sopenharmony_ci	CLEAR_BITS_FRM_TO(8, 9);
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci	switch (displayDepth) {
5062306a36Sopenharmony_ci	case 16:
5162306a36Sopenharmony_ci		{
5262306a36Sopenharmony_ci			physicalPixelDepth = 16;
5362306a36Sopenharmony_ci			tmp |= _16BPP;
5462306a36Sopenharmony_ci			break;
5562306a36Sopenharmony_ci		}
5662306a36Sopenharmony_ci	case 32:
5762306a36Sopenharmony_ci		{
5862306a36Sopenharmony_ci			/* Set for 32 bits per pixel */
5962306a36Sopenharmony_ci			physicalPixelDepth = 32;
6062306a36Sopenharmony_ci			tmp |= _32BPP;
6162306a36Sopenharmony_ci			break;
6262306a36Sopenharmony_ci		}
6362306a36Sopenharmony_ci	default:
6462306a36Sopenharmony_ci		return -EINVAL;
6562306a36Sopenharmony_ci	}
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ci	STG_WRITE_REG(DACPixelFormat, tmp);
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ci	/* Workout Bus transfer bandwidth according to pixel format */
7062306a36Sopenharmony_ci	ulPdiv = STG_PIXEL_BUS_WIDTH / physicalPixelDepth;
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ci	/* Get Screen Stride in pixels */
7362306a36Sopenharmony_ci	stride = displayWidth;
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_ci	/* Set Primary size info */
7662306a36Sopenharmony_ci	tmp = STG_READ_REG(DACPrimSize);
7762306a36Sopenharmony_ci	CLEAR_BITS_FRM_TO(0, 10);
7862306a36Sopenharmony_ci	CLEAR_BITS_FRM_TO(12, 31);
7962306a36Sopenharmony_ci	tmp |=
8062306a36Sopenharmony_ci	    ((((displayHeight - 1) << 12) | (((displayWidth / ulPdiv) -
8162306a36Sopenharmony_ci					      1) << 23))
8262306a36Sopenharmony_ci	     | (stride / ulPdiv));
8362306a36Sopenharmony_ci	STG_WRITE_REG(DACPrimSize, tmp);
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ci	/* Set Pixel Clock */
8762306a36Sopenharmony_ci	*pixelClock = ProgramClock(REF_CLOCK, *pixelClock, &F, &R, &P);
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ci	/* Set DAC PLL Mode */
9062306a36Sopenharmony_ci	tmp = STG_READ_REG(DACPLLMode);
9162306a36Sopenharmony_ci	CLEAR_BITS_FRM_TO(0, 15);
9262306a36Sopenharmony_ci	/* tmp |= ((P-1) | ((F-2) << 2) | ((R-2) << 11)); */
9362306a36Sopenharmony_ci	tmp |= ((P) | ((F - 2) << 2) | ((R - 2) << 11));
9462306a36Sopenharmony_ci	STG_WRITE_REG(DACPLLMode, tmp);
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_ci	/* Set Prim Address */
9762306a36Sopenharmony_ci	tmp = STG_READ_REG(DACPrimAddress);
9862306a36Sopenharmony_ci	CLEAR_BITS_FRM_TO(0, 20);
9962306a36Sopenharmony_ci	CLEAR_BITS_FRM_TO(20, 31);
10062306a36Sopenharmony_ci	STG_WRITE_REG(DACPrimAddress, tmp);
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_ci	/* Set Cursor details with HW Cursor disabled */
10362306a36Sopenharmony_ci	tmp = STG_READ_REG(DACCursorCtrl);
10462306a36Sopenharmony_ci	tmp &= ~SET_BIT(31);
10562306a36Sopenharmony_ci	STG_WRITE_REG(DACCursorCtrl, tmp);
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_ci	tmp = STG_READ_REG(DACCursorAddr);
10862306a36Sopenharmony_ci	CLEAR_BITS_FRM_TO(0, 20);
10962306a36Sopenharmony_ci	STG_WRITE_REG(DACCursorAddr, tmp);
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ci	/* Set Video Window */
11262306a36Sopenharmony_ci	tmp = STG_READ_REG(DACVidWinStart);
11362306a36Sopenharmony_ci	CLEAR_BITS_FRM_TO(0, 10);
11462306a36Sopenharmony_ci	CLEAR_BITS_FRM_TO(16, 26);
11562306a36Sopenharmony_ci	STG_WRITE_REG(DACVidWinStart, tmp);
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_ci	tmp = STG_READ_REG(DACVidWinEnd);
11862306a36Sopenharmony_ci	CLEAR_BITS_FRM_TO(0, 10);
11962306a36Sopenharmony_ci	CLEAR_BITS_FRM_TO(16, 26);
12062306a36Sopenharmony_ci	STG_WRITE_REG(DACVidWinEnd, tmp);
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_ci	/* Set DAC Border Color to default */
12362306a36Sopenharmony_ci	tmp = STG_READ_REG(DACBorderColor);
12462306a36Sopenharmony_ci	CLEAR_BITS_FRM_TO(0, 23);
12562306a36Sopenharmony_ci	STG_WRITE_REG(DACBorderColor, tmp);
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci	/* Set Graphics and Overlay Burst Control */
12862306a36Sopenharmony_ci	STG_WRITE_REG(DACBurstCtrl, 0x0404);
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_ci	/* Set CRC Trigger to default */
13162306a36Sopenharmony_ci	tmp = STG_READ_REG(DACCrcTrigger);
13262306a36Sopenharmony_ci	CLEAR_BIT(0);
13362306a36Sopenharmony_ci	STG_WRITE_REG(DACCrcTrigger, tmp);
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_ci	/* Set Video Port Control to default */
13662306a36Sopenharmony_ci	tmp = STG_READ_REG(DigVidPortCtrl);
13762306a36Sopenharmony_ci	CLEAR_BIT(8);
13862306a36Sopenharmony_ci	CLEAR_BITS_FRM_TO(16, 27);
13962306a36Sopenharmony_ci	CLEAR_BITS_FRM_TO(1, 3);
14062306a36Sopenharmony_ci	CLEAR_BITS_FRM_TO(10, 11);
14162306a36Sopenharmony_ci	STG_WRITE_REG(DigVidPortCtrl, tmp);
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_ci	return 0;
14462306a36Sopenharmony_ci}
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_ci/* Ramdac control, turning output to the screen on and off */
14762306a36Sopenharmony_civoid DisableRamdacOutput(volatile STG4000REG __iomem * pSTGReg)
14862306a36Sopenharmony_ci{
14962306a36Sopenharmony_ci	u32 tmp;
15062306a36Sopenharmony_ci
15162306a36Sopenharmony_ci	/* Disable DAC for Graphics Stream Control */
15262306a36Sopenharmony_ci	tmp = (STG_READ_REG(DACStreamCtrl)) & ~SET_BIT(0);
15362306a36Sopenharmony_ci	STG_WRITE_REG(DACStreamCtrl, tmp);
15462306a36Sopenharmony_ci}
15562306a36Sopenharmony_ci
15662306a36Sopenharmony_civoid EnableRamdacOutput(volatile STG4000REG __iomem * pSTGReg)
15762306a36Sopenharmony_ci{
15862306a36Sopenharmony_ci	u32 tmp;
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_ci	/* Enable DAC for Graphics Stream Control */
16162306a36Sopenharmony_ci	tmp = (STG_READ_REG(DACStreamCtrl)) | SET_BIT(0);
16262306a36Sopenharmony_ci	STG_WRITE_REG(DACStreamCtrl, tmp);
16362306a36Sopenharmony_ci}
164