提交 81dee67e 编写于 作者: S Sudip Mukherjee 提交者: Greg Kroah-Hartman

staging: sm750fb: add sm750 to staging

sm750 of Silicon Motion is pci-e display controller device and has
features like dual display and 2D acceleration. This patch adds the
driver to staging.
Signed-off-by: NSudip Mukherjee <sudip@vectorindia.org>
Signed-off-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
上级 c3d6047d
......@@ -58,6 +58,8 @@ source "drivers/staging/iio/Kconfig"
source "drivers/staging/sm7xxfb/Kconfig"
source "drivers/staging/sm750fb/Kconfig"
source "drivers/staging/xgifb/Kconfig"
source "drivers/staging/emxx_udc/Kconfig"
......
......@@ -23,6 +23,7 @@ obj-$(CONFIG_VT6656) += vt6656/
obj-$(CONFIG_VME_BUS) += vme/
obj-$(CONFIG_IIO) += iio/
obj-$(CONFIG_FB_SM7XX) += sm7xxfb/
obj-$(CONFIG_FB_SM7XX) += sm750fb/
obj-$(CONFIG_FB_XGI) += xgifb/
obj-$(CONFIG_USB_EMXX) += emxx_udc/
obj-$(CONFIG_FT1000) += ft1000/
......
config FB_SM750
tristate "Silicon Motion SM750 framebuffer support"
depends on FB && PCI
help
Frame buffer driver for the Silicon Motion SM750 chip
with 2D accelearion and dual head support.
This driver is also available as a module. The module will be
called sm750fb. If you want to compile it as a module, say M
here and read <file:Documentation/kbuild/modules.txt>.
obj-$(CONFIG_FB_SM750) += sm750fb.o
sm750fb-objs := sm750.o sm750_hw.o sm750_accel.o sm750_cursor.o ddk750_chip.o ddk750_power.o ddk750_mode.o
sm750fb-objs += ddk750_display.o ddk750_help.o ddk750_swi2c.o ddk750_sii164.o ddk750_dvi.o ddk750_hwi2c.o
TODO:
- lots of clechpatch cleanup
- use kernel coding style
- refine the code and remove unused code
- check on hardware effects of removal of USE_HW_I2C and USE_DVICHIP (these two
are supposed to be sample code which is given here if someone wants to
use those functionalities)
- move it to drivers/video/fbdev
- modify the code for drm framework
Please send any patches to
Greg Kroah-Hartman <greg@kroah.com>
Sudip Mukherjee <sudipm.mukherjee@gmail.com>
Teddy Wang <teddy.wang@siliconmotion.com>
Sudip Mukherjee <sudip@vectorindia.org>
#ifndef DDK750_H__
#define DDK750_H__
/*******************************************************************
*
* Copyright (c) 2007 by Silicon Motion, Inc. (SMI)
*
* All rights are reserved. Reproduction or in part is prohibited
* without the written consent of the copyright owner.
*
* RegSC.h --- SM718 SDK
* This file contains the definitions for the System Configuration registers.
*
*******************************************************************/
#include "ddk750_reg.h"
#include "ddk750_mode.h"
#include "ddk750_chip.h"
#include "ddk750_display.h"
#include "ddk750_power.h"
#include "ddk750_help.h"
#ifdef USE_HW_I2C
#include "ddk750_hwi2c.h"
#endif
#include "ddk750_swi2c.h"
#endif
#include "ddk750_help.h"
#include "ddk750_reg.h"
#include "ddk750_chip.h"
#include "ddk750_power.h"
typedef struct _pllcalparam{
unsigned char power;/* d : 0~ 6*/
unsigned char pod;
unsigned char od;
unsigned char value;/* value of 2 power d (2^d) */
}
pllcalparam;
logical_chip_type_t getChipType()
{
unsigned short physicalID;
char physicalRev;
logical_chip_type_t chip;
physicalID = devId750;//either 0x718 or 0x750
physicalRev = revId750;
if (physicalID == 0x718)
{
chip = SM718;
}
else if (physicalID == 0x750)
{
chip = SM750;
/* SM750 and SM750LE are different in their revision ID only. */
if (physicalRev == SM750LE_REVISION_ID){
chip = SM750LE;
}
}
else
{
chip = SM_UNKNOWN;
}
return chip;
}
inline unsigned int twoToPowerOfx(unsigned long x)
{
unsigned long i;
unsigned long result = 1;
for (i=1; i<=x; i++)
result *= 2;
return result;
}
inline unsigned int calcPLL(pll_value_t *pPLL)
{
return (pPLL->inputFreq * pPLL->M / pPLL->N / twoToPowerOfx(pPLL->OD) / twoToPowerOfx(pPLL->POD));
}
unsigned int getPllValue(clock_type_t clockType, pll_value_t *pPLL)
{
unsigned int ulPllReg = 0;
pPLL->inputFreq = DEFAULT_INPUT_CLOCK;
pPLL->clockType = clockType;
switch (clockType)
{
case MXCLK_PLL:
ulPllReg = PEEK32(MXCLK_PLL_CTRL);
break;
case PRIMARY_PLL:
ulPllReg = PEEK32(PANEL_PLL_CTRL);
break;
case SECONDARY_PLL:
ulPllReg = PEEK32(CRT_PLL_CTRL);
break;
case VGA0_PLL:
ulPllReg = PEEK32(VGA_PLL0_CTRL);
break;
case VGA1_PLL:
ulPllReg = PEEK32(VGA_PLL1_CTRL);
break;
}
pPLL->M = FIELD_GET(ulPllReg, PANEL_PLL_CTRL, M);
pPLL->N = FIELD_GET(ulPllReg, PANEL_PLL_CTRL, N);
pPLL->OD = FIELD_GET(ulPllReg, PANEL_PLL_CTRL, OD);
pPLL->POD = FIELD_GET(ulPllReg, PANEL_PLL_CTRL, POD);
return calcPLL(pPLL);
}
unsigned int getChipClock()
{
pll_value_t pll;
#if 1
if(getChipType() == SM750LE)
return MHz(130);
#endif
return getPllValue(MXCLK_PLL, &pll);
}
/*
* This function set up the main chip clock.
*
* Input: Frequency to be set.
*/
void setChipClock(unsigned int frequency)
{
pll_value_t pll;
unsigned int ulActualMxClk;
#if 1
/* Cheok_0509: For SM750LE, the chip clock is fixed. Nothing to set. */
if (getChipType() == SM750LE)
return;
#endif
if (frequency != 0)
{
/*
* Set up PLL, a structure to hold the value to be set in clocks.
*/
pll.inputFreq = DEFAULT_INPUT_CLOCK; /* Defined in CLOCK.H */
pll.clockType = MXCLK_PLL;
/*
* Call calcPllValue() to fill up the other fields for PLL structure.
* Sometime, the chip cannot set up the exact clock required by User.
* Return value from calcPllValue() gives the actual possible clock.
*/
ulActualMxClk = calcPllValue(frequency, &pll);
/* Master Clock Control: MXCLK_PLL */
POKE32(MXCLK_PLL_CTRL, formatPllReg(&pll));
}
}
void setMemoryClock(unsigned int frequency)
{
unsigned int ulReg, divisor;
#if 1
/* Cheok_0509: For SM750LE, the memory clock is fixed. Nothing to set. */
if (getChipType() == SM750LE)
return;
#endif
if (frequency != 0)
{
/* Set the frequency to the maximum frequency that the DDR Memory can take
which is 336MHz. */
if (frequency > MHz(336))
frequency = MHz(336);
/* Calculate the divisor */
divisor = (unsigned int) roundedDiv(getChipClock(), frequency);
/* Set the corresponding divisor in the register. */
ulReg = PEEK32(CURRENT_GATE);
switch(divisor)
{
default:
case 1:
ulReg = FIELD_SET(ulReg, CURRENT_GATE, M2XCLK, DIV_1);
break;
case 2:
ulReg = FIELD_SET(ulReg, CURRENT_GATE, M2XCLK, DIV_2);
break;
case 3:
ulReg = FIELD_SET(ulReg, CURRENT_GATE, M2XCLK, DIV_3);
break;
case 4:
ulReg = FIELD_SET(ulReg, CURRENT_GATE, M2XCLK, DIV_4);
break;
}
setCurrentGate(ulReg);
}
}
/*
* This function set up the master clock (MCLK).
*
* Input: Frequency to be set.
*
* NOTE:
* The maximum frequency the engine can run is 168MHz.
*/
void setMasterClock(unsigned int frequency)
{
unsigned int ulReg, divisor;
#if 1
/* Cheok_0509: For SM750LE, the memory clock is fixed. Nothing to set. */
if (getChipType() == SM750LE)
return;
#endif
if (frequency != 0)
{
/* Set the frequency to the maximum frequency that the SM750 engine can
run, which is about 190 MHz. */
if (frequency > MHz(190))
frequency = MHz(190);
/* Calculate the divisor */
divisor = (unsigned int) roundedDiv(getChipClock(), frequency);
/* Set the corresponding divisor in the register. */
ulReg = PEEK32(CURRENT_GATE);
switch(divisor)
{
default:
case 3:
ulReg = FIELD_SET(ulReg, CURRENT_GATE, MCLK, DIV_3);
break;
case 4:
ulReg = FIELD_SET(ulReg, CURRENT_GATE, MCLK, DIV_4);
break;
case 6:
ulReg = FIELD_SET(ulReg, CURRENT_GATE, MCLK, DIV_6);
break;
case 8:
ulReg = FIELD_SET(ulReg, CURRENT_GATE, MCLK, DIV_8);
break;
}
setCurrentGate(ulReg);
}
}
unsigned int ddk750_getVMSize()
{
unsigned int reg;
unsigned int data;
/* sm750le only use 64 mb memory*/
if(getChipType() == SM750LE)
return MB(64);
/* for 750,always use power mode0*/
reg = PEEK32(MODE0_GATE);
reg = FIELD_SET(reg,MODE0_GATE,GPIO,ON);
POKE32(MODE0_GATE,reg);
/* get frame buffer size from GPIO */
reg = FIELD_GET(PEEK32(MISC_CTRL),MISC_CTRL,LOCALMEM_SIZE);
switch(reg){
case MISC_CTRL_LOCALMEM_SIZE_8M: data = MB(8); break; /* 8 Mega byte */
case MISC_CTRL_LOCALMEM_SIZE_16M: data = MB(16); break; /* 16 Mega byte */
case MISC_CTRL_LOCALMEM_SIZE_32M: data = MB(32); break; /* 32 Mega byte */
case MISC_CTRL_LOCALMEM_SIZE_64M: data = MB(64); break; /* 64 Mega byte */
default: data = 0;break;
}
return data;
}
int ddk750_initHw(initchip_param_t * pInitParam)
{
unsigned int ulReg;
#if 0
//move the code to map regiter function.
if(getChipType() == SM718){
/* turn on big endian bit*/
ulReg = PEEK32(0x74);
/* now consider register definition in a big endian pattern*/
POKE32(0x74,ulReg|0x80000000);
}
#endif
if (pInitParam->powerMode != 0 )
pInitParam->powerMode = 0;
setPowerMode(pInitParam->powerMode);
/* Enable display power gate & LOCALMEM power gate*/
ulReg = PEEK32(CURRENT_GATE);
ulReg = FIELD_SET(ulReg, CURRENT_GATE, DISPLAY, ON);
ulReg = FIELD_SET(ulReg,CURRENT_GATE,LOCALMEM,ON);
setCurrentGate(ulReg);
if(getChipType() != SM750LE){
/* set panel pll and graphic mode via mmio_88 */
ulReg = PEEK32(VGA_CONFIGURATION);
ulReg = FIELD_SET(ulReg,VGA_CONFIGURATION,PLL,PANEL);
ulReg = FIELD_SET(ulReg,VGA_CONFIGURATION,MODE,GRAPHIC);
POKE32(VGA_CONFIGURATION,ulReg);
}else{
#if defined(__i386__) || defined( __x86_64__)
/* set graphic mode via IO method */
outb_p(0x88,0x3d4);
outb_p(0x06,0x3d5);
#endif
}
/* Set the Main Chip Clock */
setChipClock(MHz((unsigned int)pInitParam->chipClock));
/* Set up memory clock. */
setMemoryClock(MHz(pInitParam->memClock));
/* Set up master clock */
setMasterClock(MHz(pInitParam->masterClock));
/* Reset the memory controller. If the memory controller is not reset in SM750,
the system might hang when sw accesses the memory.
The memory should be resetted after changing the MXCLK.
*/
if (pInitParam->resetMemory == 1)
{
ulReg = PEEK32(MISC_CTRL);
ulReg = FIELD_SET(ulReg, MISC_CTRL, LOCALMEM_RESET, RESET);
POKE32(MISC_CTRL, ulReg);
ulReg = FIELD_SET(ulReg, MISC_CTRL, LOCALMEM_RESET, NORMAL);
POKE32(MISC_CTRL, ulReg);
}
if (pInitParam->setAllEngOff == 1)
{
enable2DEngine(0);
/* Disable Overlay, if a former application left it on */
ulReg = PEEK32(VIDEO_DISPLAY_CTRL);
ulReg = FIELD_SET(ulReg, VIDEO_DISPLAY_CTRL, PLANE, DISABLE);
POKE32(VIDEO_DISPLAY_CTRL, ulReg);
/* Disable video alpha, if a former application left it on */
ulReg = PEEK32(VIDEO_ALPHA_DISPLAY_CTRL);
ulReg = FIELD_SET(ulReg, VIDEO_ALPHA_DISPLAY_CTRL, PLANE, DISABLE);
POKE32(VIDEO_ALPHA_DISPLAY_CTRL, ulReg);
/* Disable alpha plane, if a former application left it on */
ulReg = PEEK32(ALPHA_DISPLAY_CTRL);
ulReg = FIELD_SET(ulReg, ALPHA_DISPLAY_CTRL, PLANE, DISABLE);
POKE32(ALPHA_DISPLAY_CTRL, ulReg);
#if 0
/* Disable LCD hardware cursor, if a former application left it on */
ulReg = PEEK32(PANEL_HWC_ADDRESS);
ulReg = FIELD_SET(ulReg, PANEL_HWC_ADDRESS, ENABLE, DISABLE);
POKE32(PANEL_HWC_ADDRESS, ulReg);
/* Disable CRT hardware cursor, if a former application left it on */
ulReg = PEEK32(CRT_HWC_ADDRESS);
ulReg = FIELD_SET(ulReg, CRT_HWC_ADDRESS, ENABLE, DISABLE);
POKE32(CRT_HWC_ADDRESS, ulReg);
/* Disable ZV Port 0, if a former application left it on */
ulReg = PEEK32(ZV0_CAPTURE_CTRL);
ulReg = FIELD_SET(ulReg, ZV0_CAPTURE_CTRL, CAP, DISABLE);
POKE32(ZV0_CAPTURE_CTRL, ulReg);
/* Disable ZV Port 1, if a former application left it on */
ulReg = PEEK32(ZV1_CAPTURE_CTRL);
ulReg = FIELD_SET(ulReg, ZV1_CAPTURE_CTRL, CAP, DISABLE);
POKE32(ZV1_CAPTURE_CTRL, ulReg);
/* Disable ZV Port Power, if a former application left it on */
enableZVPort(0);
/* Disable DMA Channel, if a former application left it on */
ulReg = PEEK32(DMA_ABORT_INTERRUPT);
ulReg = FIELD_SET(ulReg, DMA_ABORT_INTERRUPT, ABORT_1, ABORT);
POKE32(DMA_ABORT_INTERRUPT, ulReg);
/* Disable i2c */
enableI2C(0);
#endif
/* Disable DMA Channel, if a former application left it on */
ulReg = PEEK32(DMA_ABORT_INTERRUPT);
ulReg = FIELD_SET(ulReg, DMA_ABORT_INTERRUPT, ABORT_1, ABORT);
POKE32(DMA_ABORT_INTERRUPT, ulReg);
/* Disable DMA Power, if a former application left it on */
enableDMA(0);
}
/* We can add more initialization as needed. */
return 0;
}
#if 0
unsigned int absDiff(unsigned int a, unsigned int b)
{
if ( a > b )
return(a - b);
else
return(b - a);
}
#endif
/*
monk liu @ 4/6/2011:
re-write the calculatePLL function of ddk750.
the original version function does not use some mathematics tricks and shortcut
when it doing the calculation of the best N,M,D combination
I think this version gives a little upgrade in speed
750 pll clock formular:
Request Clock = (Input Clock * M )/(N * X)
Input Clock = 14318181 hz
X = 2 power D
D ={0,1,2,3,4,5,6}
M = {1,...,255}
N = {2,...,15}
*/
unsigned int calcPllValue(unsigned int request_orig,pll_value_t *pll)
{
/* used for primary and secondary channel pixel clock pll */
static pllcalparam xparm_PIXEL[] = {
/* 2^0 = 1*/ {0,0,0,1},
/* 2^ 1 =2*/ {1,0,1,2},
/* 2^ 2 = 4*/ {2,0,2,4},
{3,0,3,8},
{4,1,3,16},
{5,2,3,32},
/* 2^6 = 64 */ {6,3,3,64},
};
/* used for MXCLK (chip clock) */
static pllcalparam xparm_MXCLK[] = {
/* 2^0 = 1*/ {0,0,0,1},
/* 2^ 1 =2*/ {1,0,1,2},
/* 2^ 2 = 4*/ {2,0,2,4},
{3,0,3,8},
};
/* as sm750 register definition, N located in 2,15 and M located in 1,255 */
int N,M,X,d;
int xcnt;
int miniDiff;
unsigned int RN,quo,rem,fl_quo;
unsigned int input,request;
unsigned int tmpClock,ret;
pllcalparam * xparm;
#if 1
if (getChipType() == SM750LE)
{
/* SM750LE don't have prgrammable PLL and M/N values to work on.
Just return the requested clock. */
return request_orig;
}
#endif
ret = 0;
miniDiff = ~0;
request = request_orig / 1000;
input = pll->inputFreq / 1000;
/* for MXCLK register , no POD provided, so need be treated differently */
if(pll->clockType != MXCLK_PLL){
xparm = &xparm_PIXEL[0];
xcnt = sizeof(xparm_PIXEL)/sizeof(xparm_PIXEL[0]);
}else{
xparm = &xparm_MXCLK[0];
xcnt = sizeof(xparm_MXCLK)/sizeof(xparm_MXCLK[0]);
}
for(N = 15;N>1;N--)
{
/* RN will not exceed maximum long if @request <= 285 MHZ (for 32bit cpu) */
RN = N * request;
quo = RN / input;
rem = RN % input;/* rem always small than 14318181 */
fl_quo = (rem * 10000 /input);
for(d = xcnt - 1;d >= 0;d--){
X = xparm[d].value;
M = quo*X;
M += fl_quo * X / 10000;
/* round step */
M += (fl_quo*X % 10000)>5000?1:0;
if(M < 256 && M > 0)
{
unsigned int diff;
tmpClock = pll->inputFreq *M / N / X;
diff = absDiff(tmpClock,request_orig);
if(diff < miniDiff)
{
pll->M = M;
pll->N = N;
pll->OD = xparm[d].od;
pll->POD = xparm[d].pod;
miniDiff = diff;
ret = tmpClock;
}
}
}
}
//printk("Finally: pll->n[%lu],m[%lu],od[%lu],pod[%lu]\n",pll->N,pll->M,pll->OD,pll->POD);
return ret;
}
unsigned int calcPllValue2(
unsigned int ulRequestClk, /* Required pixel clock in Hz unit */
pll_value_t *pPLL /* Structure to hold the value to be set in PLL */
)
{
unsigned int M, N, OD, POD = 0, diff, pllClk, odPower, podPower;
unsigned int bestDiff = 0xffffffff; /* biggest 32 bit unsigned number */
unsigned int ret;
/* Init PLL structure to know states */
pPLL->M = 0;
pPLL->N = 0;
pPLL->OD = 0;
pPLL->POD = 0;
/* Sanity check: None at the moment */
/* Convert everything in Khz range in order to avoid calculation overflow */
pPLL->inputFreq /= 1000;
ulRequestClk /= 1000;
#ifndef VALIDATION_CHIP
/* The maximum of post divider is 8. */
for (POD=0; POD<=3; POD++)
#endif
{
#ifndef VALIDATION_CHIP
/* MXCLK_PLL does not have post divider. */
if ((POD > 0) && (pPLL->clockType == MXCLK_PLL))
break;
#endif
/* Work out 2 to the power of POD */
podPower = twoToPowerOfx(POD);
/* OD has only 2 bits [15:14] and its value must between 0 to 3 */
for (OD=0; OD<=3; OD++)
{
/* Work out 2 to the power of OD */
odPower = twoToPowerOfx(OD);
#ifdef VALIDATION_CHIP
if (odPower > 4)
podPower = 4;
else
podPower = odPower;
#endif
/* N has 4 bits [11:8] and its value must between 2 and 15.
The N == 1 will behave differently --> Result is not correct. */
for (N=2; N<=15; N++)
{
/* The formula for PLL is ulRequestClk = inputFreq * M / N / (2^OD)
In the following steps, we try to work out a best M value given the others are known.
To avoid decimal calculation, we use 1000 as multiplier for up to 3 decimal places of accuracy.
*/
M = ulRequestClk * N * odPower * 1000 / pPLL->inputFreq;
M = roundedDiv(M, 1000);
/* M field has only 8 bits, reject value bigger than 8 bits */
if (M < 256)
{
/* Calculate the actual clock for a given M & N */
pllClk = pPLL->inputFreq * M / N / odPower / podPower;
/* How much are we different from the requirement */
diff = absDiff(pllClk, ulRequestClk);
if (diff < bestDiff)
{
bestDiff = diff;
/* Store M and N values */
pPLL->M = M;
pPLL->N = N;
pPLL->OD = OD;
#ifdef VALIDATION_CHIP
if (OD > 2)
POD = 2;
else
POD = OD;
#endif
pPLL->POD = POD;
}
}
}
}
}
/* Restore input frequency from Khz to hz unit */
// pPLL->inputFreq *= 1000;
ulRequestClk *= 1000;
pPLL->inputFreq = DEFAULT_INPUT_CLOCK; /* Default reference clock */
/* Output debug information */
//DDKDEBUGPRINT((DISPLAY_LEVEL, "calcPllValue: Requested Frequency = %d\n", ulRequestClk));
//DDKDEBUGPRINT((DISPLAY_LEVEL, "calcPllValue: Input CLK = %dHz, M=%d, N=%d, OD=%d, POD=%d\n", pPLL->inputFreq, pPLL->M, pPLL->N, pPLL->OD, pPLL->POD));
/* Return actual frequency that the PLL can set */
ret = calcPLL(pPLL);
return ret;
}
unsigned int formatPllReg(pll_value_t *pPLL)
{
unsigned int ulPllReg = 0;
/* Note that all PLL's have the same format. Here, we just use Panel PLL parameter
to work out the bit fields in the register.
On returning a 32 bit number, the value can be applied to any PLL in the calling function.
*/
ulPllReg =
FIELD_SET( 0, PANEL_PLL_CTRL, BYPASS, OFF)
| FIELD_SET( 0, PANEL_PLL_CTRL, POWER, ON)
| FIELD_SET( 0, PANEL_PLL_CTRL, INPUT, OSC)
#ifndef VALIDATION_CHIP
| FIELD_VALUE(0, PANEL_PLL_CTRL, POD, pPLL->POD)
#endif
| FIELD_VALUE(0, PANEL_PLL_CTRL, OD, pPLL->OD)
| FIELD_VALUE(0, PANEL_PLL_CTRL, N, pPLL->N)
| FIELD_VALUE(0, PANEL_PLL_CTRL, M, pPLL->M);
return(ulPllReg);
}
#ifndef DDK750_CHIP_H__
#define DDK750_CHIP_H__
#define DEFAULT_INPUT_CLOCK 14318181 /* Default reference clock */
#define SM750LE_REVISION_ID (char)0xfe
/* This is all the chips recognized by this library */
typedef enum _logical_chip_type_t
{
SM_UNKNOWN,
SM718,
SM750,
SM750LE,
}
logical_chip_type_t;
typedef enum _clock_type_t
{
MXCLK_PLL,
PRIMARY_PLL,
SECONDARY_PLL,
VGA0_PLL,
VGA1_PLL,
}
clock_type_t;
typedef struct _pll_value_t
{
clock_type_t clockType;
unsigned long inputFreq; /* Input clock frequency to the PLL */
/* Use this when clockType = PANEL_PLL */
unsigned long M;
unsigned long N;
unsigned long OD;
unsigned long POD;
}
pll_value_t;
/* input struct to initChipParam() function */
typedef struct _initchip_param_t
{
unsigned short powerMode; /* Use power mode 0 or 1 */
unsigned short chipClock; /* Speed of main chip clock in MHz unit
0 = keep the current clock setting
Others = the new main chip clock
*/
unsigned short memClock; /* Speed of memory clock in MHz unit
0 = keep the current clock setting
Others = the new memory clock
*/
unsigned short masterClock; /* Speed of master clock in MHz unit
0 = keep the current clock setting
Others = the new master clock
*/
unsigned short setAllEngOff; /* 0 = leave all engine state untouched.
1 = make sure they are off: 2D, Overlay,
video alpha, alpha, hardware cursors
*/
unsigned char resetMemory; /* 0 = Do not reset the memory controller
1 = Reset the memory controller
*/
/* More initialization parameter can be added if needed */
}
initchip_param_t;
logical_chip_type_t getChipType(void);
unsigned int calcPllValue(unsigned int request,pll_value_t *pll);
unsigned int calcPllValue2(unsigned int,pll_value_t *);
unsigned int formatPllReg(pll_value_t *pPLL);
void ddk750_set_mmio(volatile unsigned char *,unsigned short,char);
unsigned int ddk750_getVMSize(void);
int ddk750_initHw(initchip_param_t *);
unsigned int getPllValue(clock_type_t clockType, pll_value_t *pPLL);
unsigned int getChipClock(void);
void setChipClock(unsigned int);
void setMemoryClock(unsigned int frequency);
void setMasterClock(unsigned int frequency);
#endif
#include "ddk750_reg.h"
#include "ddk750_help.h"
#include "ddk750_display.h"
#include "ddk750_power.h"
#include "ddk750_dvi.h"
#define primaryWaitVerticalSync(delay) waitNextVerticalSync(0,delay)
static void setDisplayControl(int ctrl,int dispState)
{
/* state != 0 means turn on both timing & plane en_bit */
unsigned long ulDisplayCtrlReg, ulReservedBits;
int cnt;
cnt = 0;
/* Set the primary display control */
if (!ctrl)
{
ulDisplayCtrlReg = PEEK32(PANEL_DISPLAY_CTRL);
/* Turn on/off the Panel display control */
if (dispState)
{
/* Timing should be enabled first before enabling the plane
* because changing at the same time does not guarantee that
* the plane will also enabled or disabled.
*/
ulDisplayCtrlReg = FIELD_SET(ulDisplayCtrlReg,
PANEL_DISPLAY_CTRL, TIMING, ENABLE);
POKE32(PANEL_DISPLAY_CTRL, ulDisplayCtrlReg);
ulDisplayCtrlReg = FIELD_SET(ulDisplayCtrlReg,
PANEL_DISPLAY_CTRL, PLANE, ENABLE);
/* Added some masks to mask out the reserved bits.
* Sometimes, the reserved bits are set/reset randomly when
* writing to the PRIMARY_DISPLAY_CTRL, therefore, the register
* reserved bits are needed to be masked out.
*/
ulReservedBits = FIELD_SET(0, PANEL_DISPLAY_CTRL, RESERVED_1_MASK, ENABLE) |
FIELD_SET(0, PANEL_DISPLAY_CTRL, RESERVED_2_MASK, ENABLE) |
FIELD_SET(0, PANEL_DISPLAY_CTRL, RESERVED_3_MASK, ENABLE);
/* Somehow the register value on the plane is not set
* until a few delay. Need to write
* and read it a couple times
*/
do
{
cnt++;
POKE32(PANEL_DISPLAY_CTRL, ulDisplayCtrlReg);
} while((PEEK32(PANEL_DISPLAY_CTRL) & ~ulReservedBits) !=
(ulDisplayCtrlReg & ~ulReservedBits));
printk("Set Panel Plane enbit:after tried %d times\n",cnt);
}
else
{
/* When turning off, there is no rule on the programming
* sequence since whenever the clock is off, then it does not
* matter whether the plane is enabled or disabled.
* Note: Modifying the plane bit will take effect on the
* next vertical sync. Need to find out if it is necessary to
* wait for 1 vsync before modifying the timing enable bit.
* */
ulDisplayCtrlReg = FIELD_SET(ulDisplayCtrlReg,
PANEL_DISPLAY_CTRL, PLANE, DISABLE);
POKE32(PANEL_DISPLAY_CTRL, ulDisplayCtrlReg);
ulDisplayCtrlReg = FIELD_SET(ulDisplayCtrlReg,
PANEL_DISPLAY_CTRL, TIMING, DISABLE);
POKE32(PANEL_DISPLAY_CTRL, ulDisplayCtrlReg);
}
}
/* Set the secondary display control */
else
{
ulDisplayCtrlReg = PEEK32(CRT_DISPLAY_CTRL);
if (dispState)
{
/* Timing should be enabled first before enabling the plane because changing at the
same time does not guarantee that the plane will also enabled or disabled.
*/
ulDisplayCtrlReg = FIELD_SET(ulDisplayCtrlReg,
CRT_DISPLAY_CTRL, TIMING, ENABLE);
POKE32(CRT_DISPLAY_CTRL, ulDisplayCtrlReg);
ulDisplayCtrlReg = FIELD_SET(ulDisplayCtrlReg,
CRT_DISPLAY_CTRL, PLANE, ENABLE);
/* Added some masks to mask out the reserved bits.
* Sometimes, the reserved bits are set/reset randomly when
* writing to the PRIMARY_DISPLAY_CTRL, therefore, the register
* reserved bits are needed to be masked out.
*/
ulReservedBits = FIELD_SET(0, CRT_DISPLAY_CTRL, RESERVED_1_MASK, ENABLE) |
FIELD_SET(0, CRT_DISPLAY_CTRL, RESERVED_2_MASK, ENABLE) |
FIELD_SET(0, CRT_DISPLAY_CTRL, RESERVED_3_MASK, ENABLE) |
FIELD_SET(0, CRT_DISPLAY_CTRL, RESERVED_4_MASK, ENABLE);
do
{
cnt++;
POKE32(CRT_DISPLAY_CTRL, ulDisplayCtrlReg);
} while((PEEK32(CRT_DISPLAY_CTRL) & ~ulReservedBits) !=
(ulDisplayCtrlReg & ~ulReservedBits));
printk("Set Crt Plane enbit:after tried %d times\n",cnt);
}
else
{
/* When turning off, there is no rule on the programming
* sequence since whenever the clock is off, then it does not
* matter whether the plane is enabled or disabled.
* Note: Modifying the plane bit will take effect on the next
* vertical sync. Need to find out if it is necessary to
* wait for 1 vsync before modifying the timing enable bit.
*/
ulDisplayCtrlReg = FIELD_SET(ulDisplayCtrlReg,
CRT_DISPLAY_CTRL, PLANE, DISABLE);
POKE32(CRT_DISPLAY_CTRL, ulDisplayCtrlReg);
ulDisplayCtrlReg = FIELD_SET(ulDisplayCtrlReg,
CRT_DISPLAY_CTRL, TIMING, DISABLE);
POKE32(CRT_DISPLAY_CTRL, ulDisplayCtrlReg);
}
}
}
static void waitNextVerticalSync(int ctrl,int delay)
{
unsigned int status;
if(!ctrl){
/* primary controller */
/* Do not wait when the Primary PLL is off or display control is already off.
This will prevent the software to wait forever. */
if ((FIELD_GET(PEEK32(PANEL_PLL_CTRL), PANEL_PLL_CTRL, POWER) ==
PANEL_PLL_CTRL_POWER_OFF) ||
(FIELD_GET(PEEK32(PANEL_DISPLAY_CTRL), PANEL_DISPLAY_CTRL, TIMING) ==
PANEL_DISPLAY_CTRL_TIMING_DISABLE))
{
return;
}
while (delay-- > 0)
{
/* Wait for end of vsync. */
do
{
status = FIELD_GET(PEEK32(SYSTEM_CTRL),
SYSTEM_CTRL,
PANEL_VSYNC);
}
while (status == SYSTEM_CTRL_PANEL_VSYNC_ACTIVE);
/* Wait for start of vsync. */
do
{
status = FIELD_GET(PEEK32(SYSTEM_CTRL),
SYSTEM_CTRL,
PANEL_VSYNC);
}
while (status == SYSTEM_CTRL_PANEL_VSYNC_INACTIVE);
}
}else{
/* Do not wait when the Primary PLL is off or display control is already off.
This will prevent the software to wait forever. */
if ((FIELD_GET(PEEK32(CRT_PLL_CTRL), CRT_PLL_CTRL, POWER) ==
CRT_PLL_CTRL_POWER_OFF) ||
(FIELD_GET(PEEK32(CRT_DISPLAY_CTRL), CRT_DISPLAY_CTRL, TIMING) ==
CRT_DISPLAY_CTRL_TIMING_DISABLE))
{
return;
}
while (delay-- > 0)
{
/* Wait for end of vsync. */
do
{
status = FIELD_GET(PEEK32(SYSTEM_CTRL),
SYSTEM_CTRL,
CRT_VSYNC);
}
while (status == SYSTEM_CTRL_CRT_VSYNC_ACTIVE);
/* Wait for start of vsync. */
do
{
status = FIELD_GET(PEEK32(SYSTEM_CTRL),
SYSTEM_CTRL,
CRT_VSYNC);
}
while (status == SYSTEM_CTRL_CRT_VSYNC_INACTIVE);
}
}
}
static void swPanelPowerSequence_sm750le(int disp,int delay)
{
unsigned int reg;
reg = PEEK32(DISPLAY_CONTROL_750LE);
if(disp)
reg |= 0xf;
else
reg &= ~0xf;
POKE32(DISPLAY_CONTROL_750LE,reg);
}
static void swPanelPowerSequence(int disp,int delay)
{
unsigned int reg;
/* disp should be 1 to open sequence */
reg = PEEK32(PANEL_DISPLAY_CTRL);
reg = FIELD_VALUE(reg,PANEL_DISPLAY_CTRL,FPEN,disp);
POKE32(PANEL_DISPLAY_CTRL,reg);
primaryWaitVerticalSync(delay);
reg = PEEK32(PANEL_DISPLAY_CTRL);
reg = FIELD_VALUE(reg,PANEL_DISPLAY_CTRL,DATA,disp);
POKE32(PANEL_DISPLAY_CTRL,reg);
primaryWaitVerticalSync(delay);
reg = PEEK32(PANEL_DISPLAY_CTRL);
reg = FIELD_VALUE(reg,PANEL_DISPLAY_CTRL,VBIASEN,disp);
POKE32(PANEL_DISPLAY_CTRL,reg);
primaryWaitVerticalSync(delay);
reg = PEEK32(PANEL_DISPLAY_CTRL);
reg = FIELD_VALUE(reg,PANEL_DISPLAY_CTRL,FPEN,disp);
POKE32(PANEL_DISPLAY_CTRL,reg);
primaryWaitVerticalSync(delay);
}
void ddk750_setLogicalDispOut(disp_output_t output)
{
unsigned int reg;
if(output & PNL_2_USAGE){
/* set panel path controller select */
reg = PEEK32(PANEL_DISPLAY_CTRL);
reg = FIELD_VALUE(reg,PANEL_DISPLAY_CTRL,SELECT,(output & PNL_2_MASK)>>PNL_2_OFFSET);
POKE32(PANEL_DISPLAY_CTRL,reg);
}
if(output & CRT_2_USAGE){
/* set crt path controller select */
reg = PEEK32(CRT_DISPLAY_CTRL);
reg = FIELD_VALUE(reg,CRT_DISPLAY_CTRL,SELECT,(output & CRT_2_MASK)>>CRT_2_OFFSET);
/*se blank off */
reg = FIELD_SET(reg,CRT_DISPLAY_CTRL,BLANK,OFF);
POKE32(CRT_DISPLAY_CTRL,reg);
}
if(output & PRI_TP_USAGE){
/* set primary timing and plane en_bit */
setDisplayControl(0,(output&PRI_TP_MASK)>>PRI_TP_OFFSET);
}
if(output & SEC_TP_USAGE){
/* set secondary timing and plane en_bit*/
setDisplayControl(1,(output&SEC_TP_MASK)>>SEC_TP_OFFSET);
}
if(output & PNL_SEQ_USAGE){
/* set panel sequence */
swPanelPowerSequence((output&PNL_SEQ_MASK)>>PNL_SEQ_OFFSET,4);
}
if(output & DAC_USAGE)
setDAC((output & DAC_MASK)>>DAC_OFFSET);
if(output & DPMS_USAGE)
ddk750_setDPMS((output & DPMS_MASK) >> DPMS_OFFSET);
}
int ddk750_initDVIDisp()
{
/* Initialize DVI. If the dviInit fail and the VendorID or the DeviceID are
not zeroed, then set the failure flag. If it is zeroe, it might mean
that the system is in Dual CRT Monitor configuration. */
/* De-skew enabled with default 111b value.
This will fix some artifacts problem in some mode on board 2.2.
Somehow this fix does not affect board 2.1.
*/
if ((dviInit(1, /* Select Rising Edge */
1, /* Select 24-bit bus */
0, /* Select Single Edge clock */
1, /* Enable HSync as is */
1, /* Enable VSync as is */
1, /* Enable De-skew */
7, /* Set the de-skew setting to maximum setup */
1, /* Enable continuous Sync */
1, /* Enable PLL Filter */
4 /* Use the recommended value for PLL Filter value */
) != 0) && (dviGetVendorID() != 0x0000) && (dviGetDeviceID() != 0x0000))
{
return (-1);
}
/* TODO: Initialize other display component */
/* Success */
return 0;
}
#ifndef DDK750_DISPLAY_H__
#define DDK750_DISPLAY_H__
/* panel path select
80000[29:28]
*/
#define PNL_2_OFFSET 0
#define PNL_2_MASK (3 << PNL_2_OFFSET)
#define PNL_2_USAGE (PNL_2_MASK << 16)
#define PNL_2_PRI ((0 << PNL_2_OFFSET)|PNL_2_USAGE)
#define PNL_2_SEC ((2 << PNL_2_OFFSET)|PNL_2_USAGE)
/* primary timing & plane enable bit
1: 80000[8] & 80000[2] on
0: both off
*/
#define PRI_TP_OFFSET 4
#define PRI_TP_MASK (1 << PRI_TP_OFFSET)
#define PRI_TP_USAGE (PRI_TP_MASK << 16)
#define PRI_TP_ON ((0x1 << PRI_TP_OFFSET)|PRI_TP_USAGE)
#define PRI_TP_OFF ((0x0 << PRI_TP_OFFSET)|PRI_TP_USAGE)
/* panel sequency status
80000[27:24]
*/
#define PNL_SEQ_OFFSET 6
#define PNL_SEQ_MASK (1 << PNL_SEQ_OFFSET)
#define PNL_SEQ_USAGE (PNL_SEQ_MASK << 16)
#define PNL_SEQ_ON ((1 << PNL_SEQ_OFFSET)|PNL_SEQ_USAGE)
#define PNL_SEQ_OFF ((0 << PNL_SEQ_OFFSET)|PNL_SEQ_USAGE)
/* dual digital output
80000[19]
*/
#define DUAL_TFT_OFFSET 8
#define DUAL_TFT_MASK (1 << DUAL_TFT_OFFSET)
#define DUAL_TFT_USAGE (DUAL_TFT_MASK << 16)
#define DUAL_TFT_ON ((1 << DUAL_TFT_OFFSET)|DUAL_TFT_USAGE)
#define DUAL_TFT_OFF ((0 << DUAL_TFT_OFFSET)|DUAL_TFT_USAGE)
/* secondary timing & plane enable bit
1:80200[8] & 80200[2] on
0: both off
*/
#define SEC_TP_OFFSET 5
#define SEC_TP_MASK (1<< SEC_TP_OFFSET)
#define SEC_TP_USAGE (SEC_TP_MASK << 16)
#define SEC_TP_ON ((0x1 << SEC_TP_OFFSET)|SEC_TP_USAGE)
#define SEC_TP_OFF ((0x0 << SEC_TP_OFFSET)|SEC_TP_USAGE)
/* crt path select
80200[19:18]
*/
#define CRT_2_OFFSET 2
#define CRT_2_MASK (3 << CRT_2_OFFSET)
#define CRT_2_USAGE (CRT_2_MASK << 16)
#define CRT_2_PRI ((0x0 << CRT_2_OFFSET)|CRT_2_USAGE)
#define CRT_2_SEC ((0x2 << CRT_2_OFFSET)|CRT_2_USAGE)
/* DAC affect both DVI and DSUB
4[20]
*/
#define DAC_OFFSET 7
#define DAC_MASK (1 << DAC_OFFSET)
#define DAC_USAGE (DAC_MASK << 16)
#define DAC_ON ((0x0<< DAC_OFFSET)|DAC_USAGE)
#define DAC_OFF ((0x1 << DAC_OFFSET)|DAC_USAGE)
/* DPMS only affect D-SUB head
0[31:30]
*/
#define DPMS_OFFSET 9
#define DPMS_MASK (3 << DPMS_OFFSET)
#define DPMS_USAGE (DPMS_MASK << 16)
#define DPMS_OFF ((3 << DPMS_OFFSET)|DPMS_USAGE)
#define DPMS_ON ((0 << DPMS_OFFSET)|DPMS_USAGE)
/*
LCD1 means panel path TFT1 & panel path DVI (so enable DAC)
CRT means crt path DSUB
*/
#if 0
typedef enum _disp_output_t
{
NO_DISPLAY = DPMS_OFF,
LCD1_PRI = PNL_2_PRI|PRI_TP_ON|PNL_SEQ_ON|DPMS_OFF|DAC_ON,
LCD1_SEC = PNL_2_SEC|SEC_TP_ON|PNL_SEQ_ON|DPMS_OFF|DAC_ON,
LCD2_PRI = CRT_2_PRI|PRI_TP_ON|DUAL_TFT_ON|DPMS_OFF,
LCD2_SEC = CRT_2_SEC|SEC_TP_ON|DUAL_TFT_ON|DPMS_OFF,
DSUB_PRI = CRT_2_PRI|PRI_TP_ON|DAC_ON,
DSUB_SEC = CRT_2_SEC|SEC_TP_ON|DAC_ON,
LCD1_DSUB_PRI = PNL_2_PRI|PRI_TP_ON|PNL_SEQ_ON|
CRT_2_PRI|SEC_TP_OFF|DAC_ON,
LCD1_DSUB_SEC = PNL_2_SEC|SEC_TP_ON|PNL_SEQ_ON|
CRT_2_SEC|PRI_TP_OFF|DAC_ON,
/* LCD1 show primary and DSUB show secondary */
LCD1_DSUB_DUAL = PNL_2_PRI|PRI_TP_ON|PNL_SEQ_ON|
CRT_2_SEC|SEC_TP_ON|DAC_ON,
/* LCD1 show secondary and DSUB show primary */
LCD1_DSUB_DUAL_SWAP = PNL_2_SEC|SEC_TP_ON|PNL_SEQ_ON|
CRT_2_PRI|PRI_TP_ON|DAC_ON,
LCD1_LCD2_PRI = PNL_2_PRI|PRI_TP_ON|PNL_SEQ_ON|
CRT_2_PRI|SEC_TP_OFF|DPMS_OFF|DUAL_TFT_ON,
LCD1_LCD2_SEC = PNL_2_SEC|SEC_TP_ON|PNL_SEQ_ON|
CRT_2_SEC|PRI_TP_OFF|DPMS_OFF|DUAL_TFT_ON,
LCD1_LCD2_DSUB_PRI = PNL_2_PRI|PRI_TP_ON|PNL_SEQ_ON|DAC_ON|
CRT_2_PRI|SEC_TP_OFF|DPMS_ON|DUAL_TFT_ON,
LCD1_LCD2_DSUB_SEC = PNL_2_SEC|SEC_TP_ON|PNL_SEQ_ON|DAC_ON|
CRT_2_SEC|PRI_TP_OFF|DPMS_ON|DUAL_TFT_ON,
}
disp_output_t;
#else
typedef enum _disp_output_t{
do_LCD1_PRI = PNL_2_PRI|PRI_TP_ON|PNL_SEQ_ON|DAC_ON,
do_LCD1_SEC = PNL_2_SEC|SEC_TP_ON|PNL_SEQ_ON|DAC_ON,
#if 0
do_LCD2_PRI = CRT_2_PRI|PRI_TP_ON,
do_LCD2_SEC = CRT_2_SEC|SEC_TP_ON,
#else
do_LCD2_PRI = CRT_2_PRI|PRI_TP_ON|DUAL_TFT_ON,
do_LCD2_SEC = CRT_2_SEC|SEC_TP_ON|DUAL_TFT_ON,
#endif
/*
do_DSUB_PRI = CRT_2_PRI|PRI_TP_ON|DPMS_ON|DAC_ON,
do_DSUB_SEC = CRT_2_SEC|SEC_TP_ON|DPMS_ON|DAC_ON,
*/
#if 0
do_CRT_PRI = CRT_2_PRI|PRI_TP_ON,
do_CRT_SEC = CRT_2_SEC|SEC_TP_ON,
#else
do_CRT_PRI = CRT_2_PRI|PRI_TP_ON|DPMS_ON|DAC_ON,
do_CRT_SEC = CRT_2_SEC|SEC_TP_ON|DPMS_ON|DAC_ON,
#endif
}
disp_output_t;
#endif
void ddk750_setLogicalDispOut(disp_output_t);
int ddk750_initDVIDisp(void);
#endif
#define USE_DVICHIP
#ifdef USE_DVICHIP
#include "ddk750_help.h"
#include "ddk750_reg.h"
#include "ddk750_dvi.h"
#include "ddk750_sii164.h"
/* This global variable contains all the supported driver and its corresponding
function API. Please set the function pointer to NULL whenever the function
is not supported. */
static dvi_ctrl_device_t g_dcftSupportedDviController[] =
{
#ifdef DVI_CTRL_SII164
{
.pfnInit = sii164InitChip,
.pfnGetVendorId = sii164GetVendorID,
.pfnGetDeviceId = sii164GetDeviceID,
#ifdef SII164_FULL_FUNCTIONS
.pfnResetChip = sii164ResetChip,
.pfnGetChipString = sii164GetChipString,
.pfnSetPower = sii164SetPower,
.pfnEnableHotPlugDetection = sii164EnableHotPlugDetection,
.pfnIsConnected = sii164IsConnected,
.pfnCheckInterrupt = sii164CheckInterrupt,
.pfnClearInterrupt = sii164ClearInterrupt,
#endif
},
#endif
};
int dviInit(
unsigned char edgeSelect,
unsigned char busSelect,
unsigned char dualEdgeClkSelect,
unsigned char hsyncEnable,
unsigned char vsyncEnable,
unsigned char deskewEnable,
unsigned char deskewSetting,
unsigned char continuousSyncEnable,
unsigned char pllFilterEnable,
unsigned char pllFilterValue
)
{
dvi_ctrl_device_t *pCurrentDviCtrl;
pCurrentDviCtrl = g_dcftSupportedDviController;
if(pCurrentDviCtrl->pfnInit != NULL)
{
return pCurrentDviCtrl->pfnInit(edgeSelect, busSelect, dualEdgeClkSelect, hsyncEnable,
vsyncEnable, deskewEnable, deskewSetting, continuousSyncEnable,
pllFilterEnable, pllFilterValue);
}
return -1;//error
}
/*
* dviGetVendorID
* This function gets the vendor ID of the DVI controller chip.
*
* Output:
* Vendor ID
*/
unsigned short dviGetVendorID()
{
dvi_ctrl_device_t *pCurrentDviCtrl;
//pCurrentDviCtrl = getDviCtrl();
pCurrentDviCtrl = g_dcftSupportedDviController;
if (pCurrentDviCtrl != (dvi_ctrl_device_t *)0)
return pCurrentDviCtrl->pfnGetVendorId();
return 0x0000;
}
/*
* dviGetDeviceID
* This function gets the device ID of the DVI controller chip.
*
* Output:
* Device ID
*/
unsigned short dviGetDeviceID()
{
dvi_ctrl_device_t *pCurrentDviCtrl;
// pCurrentDviCtrl = getDviCtrl();
pCurrentDviCtrl = g_dcftSupportedDviController;
if (pCurrentDviCtrl != (dvi_ctrl_device_t *)0)
return pCurrentDviCtrl->pfnGetDeviceId();
return 0x0000;
}
#endif
#ifndef DDK750_DVI_H__
#define DDK750_DVI_H__
/* dvi chip stuffs structros */
typedef long (*PFN_DVICTRL_INIT)(
unsigned char edgeSelect,
unsigned char busSelect,
unsigned char dualEdgeClkSelect,
unsigned char hsyncEnable,
unsigned char vsyncEnable,
unsigned char deskewEnable,
unsigned char deskewSetting,
unsigned char continuousSyncEnable,
unsigned char pllFilterEnable,
unsigned char pllFilterValue);
typedef void (*PFN_DVICTRL_RESETCHIP)(void);
typedef char* (*PFN_DVICTRL_GETCHIPSTRING)(void);
typedef unsigned short (*PFN_DVICTRL_GETVENDORID)(void);
typedef unsigned short (*PFN_DVICTRL_GETDEVICEID)(void);
typedef void (*PFN_DVICTRL_SETPOWER)(unsigned char powerUp);
typedef void (*PFN_DVICTRL_HOTPLUGDETECTION)(unsigned char enableHotPlug);
typedef unsigned char (*PFN_DVICTRL_ISCONNECTED)(void);
typedef unsigned char (*PFN_DVICTRL_CHECKINTERRUPT)(void);
typedef void (*PFN_DVICTRL_CLEARINTERRUPT)(void);
/* Structure to hold all the function pointer to the DVI Controller. */
typedef struct _dvi_ctrl_device_t
{
PFN_DVICTRL_INIT pfnInit;
PFN_DVICTRL_RESETCHIP pfnResetChip;
PFN_DVICTRL_GETCHIPSTRING pfnGetChipString;
PFN_DVICTRL_GETVENDORID pfnGetVendorId;
PFN_DVICTRL_GETDEVICEID pfnGetDeviceId;
PFN_DVICTRL_SETPOWER pfnSetPower;
PFN_DVICTRL_HOTPLUGDETECTION pfnEnableHotPlugDetection;
PFN_DVICTRL_ISCONNECTED pfnIsConnected;
PFN_DVICTRL_CHECKINTERRUPT pfnCheckInterrupt;
PFN_DVICTRL_CLEARINTERRUPT pfnClearInterrupt;
} dvi_ctrl_device_t;
#define DVI_CTRL_SII164
/* dvi functions prototype */
int dviInit(
unsigned char edgeSelect,
unsigned char busSelect,
unsigned char dualEdgeClkSelect,
unsigned char hsyncEnable,
unsigned char vsyncEnable,
unsigned char deskewEnable,
unsigned char deskewSetting,
unsigned char continuousSyncEnable,
unsigned char pllFilterEnable,
unsigned char pllFilterValue
);
unsigned short dviGetVendorID(void);
unsigned short dviGetDeviceID(void);
#endif
//#include "ddk750_reg.h"
//#include "ddk750_chip.h"
#include "ddk750_help.h"
volatile unsigned char __iomem * mmio750 = NULL;
char revId750 = 0;
unsigned short devId750 = 0;
/* after driver mapped io registers, use this function first */
void ddk750_set_mmio(volatile unsigned char * addr,unsigned short devId,char revId)
{
mmio750 = addr;
devId750 = devId;
revId750 = revId;
if(revId == 0xfe)
printk("found sm750le\n");
}
#ifndef DDK750_HELP_H__
#define DDK750_HELP_H__
#include "ddk750_chip.h"
#ifndef USE_INTERNAL_REGISTER_ACCESS
#include <linux/ioport.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include "sm750_help.h"
#if 0
/* if 718 big endian turned on,be aware that don't use this driver for general use,only for ppc big-endian */
#warning "big endian on target cpu and enable nature big endian support of 718 capability !"
#define PEEK32(addr) __raw_readl((void __iomem *)(mmio750)+(addr))
#define POKE32(addr,data) __raw_writel((data),(void __iomem*)(mmio750)+(addr))
#else /* software control endianess */
#define PEEK32(addr) readl((addr)+mmio750)
#define POKE32(addr,data) writel((data),(addr)+mmio750)
#endif
extern volatile unsigned char __iomem * mmio750;
extern char revId750;
extern unsigned short devId750;
#else
/* implement if you want use it*/
#endif
#endif
#define USE_HW_I2C
#ifdef USE_HW_I2C
#include "ddk750_help.h"
#include "ddk750_reg.h"
#include "ddk750_hwi2c.h"
#include "ddk750_power.h"
#define MAX_HWI2C_FIFO 16
#define HWI2C_WAIT_TIMEOUT 0xF0000
int hwI2CInit(
unsigned char busSpeedMode
)
{
unsigned int value;
/* Enable GPIO 30 & 31 as IIC clock & data */
value = PEEK32(GPIO_MUX);
value = FIELD_SET(value, GPIO_MUX, 30, I2C) |
FIELD_SET(0, GPIO_MUX, 31, I2C);
POKE32(GPIO_MUX, value);
/* Enable Hardware I2C power.
TODO: Check if we need to enable GPIO power?
*/
enableI2C(1);
/* Enable the I2C Controller and set the bus speed mode */
value = PEEK32(I2C_CTRL);
if (busSpeedMode == 0)
value = FIELD_SET(value, I2C_CTRL, MODE, STANDARD);
else
value = FIELD_SET(value, I2C_CTRL, MODE, FAST);
value = FIELD_SET(value, I2C_CTRL, EN, ENABLE);
POKE32(I2C_CTRL, value);
return 0;
}
void hwI2CClose(void)
{
unsigned int value;
/* Disable I2C controller */
value = PEEK32(I2C_CTRL);
value = FIELD_SET(value, I2C_CTRL, EN, DISABLE);
POKE32(I2C_CTRL, value);
/* Disable I2C Power */
enableI2C(0);
/* Set GPIO 30 & 31 back as GPIO pins */
value = PEEK32(GPIO_MUX);
value = FIELD_SET(value, GPIO_MUX, 30, GPIO);
value = FIELD_SET(value, GPIO_MUX, 31, GPIO);
POKE32(GPIO_MUX, value);
}
long hwI2CWaitTXDone(void)
{
unsigned int timeout;
/* Wait until the transfer is completed. */
timeout = HWI2C_WAIT_TIMEOUT;
while ((FIELD_GET(PEEK32(I2C_STATUS), I2C_STATUS, TX) != I2C_STATUS_TX_COMPLETED) &&
(timeout != 0))
timeout--;
if (timeout == 0)
return (-1);
return 0;
}
/*
* This function writes data to the i2c slave device registers.
*
* Parameters:
* deviceAddress - i2c Slave device address
* length - Total number of bytes to be written to the device
* pBuffer - The buffer that contains the data to be written to the
* i2c device.
*
* Return Value:
* Total number of bytes those are actually written.
*/
unsigned int hwI2CWriteData(
unsigned char deviceAddress,
unsigned int length,
unsigned char *pBuffer
)
{
unsigned char count, i;
unsigned int totalBytes = 0;
/* Set the Device Address */
POKE32(I2C_SLAVE_ADDRESS, deviceAddress & ~0x01);
/* Write data.
* Note:
* Only 16 byte can be accessed per i2c start instruction.
*/
do
{
/* Reset I2C by writing 0 to I2C_RESET register to clear the previous status. */
POKE32(I2C_RESET, 0);
/* Set the number of bytes to be written */
if (length < MAX_HWI2C_FIFO)
count = length - 1;
else
count = MAX_HWI2C_FIFO - 1;
POKE32(I2C_BYTE_COUNT, count);
/* Move the data to the I2C data register */
for (i = 0; i <= count; i++)
POKE32(I2C_DATA0 + i, *pBuffer++);
/* Start the I2C */
POKE32(I2C_CTRL, FIELD_SET(PEEK32(I2C_CTRL), I2C_CTRL, CTRL, START));
/* Wait until the transfer is completed. */
if (hwI2CWaitTXDone() != 0)
break;
/* Substract length */
length -= (count + 1);
/* Total byte written */
totalBytes += (count + 1);
} while (length > 0);
return totalBytes;
}
/*
* This function reads data from the slave device and stores them
* in the given buffer
*
* Parameters:
* deviceAddress - i2c Slave device address
* length - Total number of bytes to be read
* pBuffer - Pointer to a buffer to be filled with the data read
* from the slave device. It has to be the same size as the
* length to make sure that it can keep all the data read.
*
* Return Value:
* Total number of actual bytes read from the slave device
*/
unsigned int hwI2CReadData(
unsigned char deviceAddress,
unsigned int length,
unsigned char *pBuffer
)
{
unsigned char count, i;
unsigned int totalBytes = 0;
/* Set the Device Address */
POKE32(I2C_SLAVE_ADDRESS, deviceAddress | 0x01);
/* Read data and save them to the buffer.
* Note:
* Only 16 byte can be accessed per i2c start instruction.
*/
do
{
/* Reset I2C by writing 0 to I2C_RESET register to clear all the status. */
POKE32(I2C_RESET, 0);
/* Set the number of bytes to be read */
if (length <= MAX_HWI2C_FIFO)
count = length - 1;
else
count = MAX_HWI2C_FIFO - 1;
POKE32(I2C_BYTE_COUNT, count);
/* Start the I2C */
POKE32(I2C_CTRL, FIELD_SET(PEEK32(I2C_CTRL), I2C_CTRL, CTRL, START));
/* Wait until transaction done. */
if (hwI2CWaitTXDone() != 0)
break;
/* Save the data to the given buffer */
for (i = 0; i <= count; i++)
*pBuffer++ = PEEK32(I2C_DATA0 + i);
/* Substract length by 16 */
length -= (count + 1);
/* Number of bytes read. */
totalBytes += (count + 1);
} while (length > 0);
return totalBytes;
}
/*
* This function reads the slave device's register
*
* Parameters:
* deviceAddress - i2c Slave device address which register
* to be read from
* registerIndex - Slave device's register to be read
*
* Return Value:
* Register value
*/
unsigned char hwI2CReadReg(
unsigned char deviceAddress,
unsigned char registerIndex
)
{
unsigned char value = (0xFF);
if (hwI2CWriteData(deviceAddress, 1, &registerIndex) == 1)
hwI2CReadData(deviceAddress, 1, &value);
return value;
}
/*
* This function writes a value to the slave device's register
*
* Parameters:
* deviceAddress - i2c Slave device address which register
* to be written
* registerIndex - Slave device's register to be written
* data - Data to be written to the register
*
* Result:
* 0 - Success
* -1 - Fail
*/
int hwI2CWriteReg(
unsigned char deviceAddress,
unsigned char registerIndex,
unsigned char data
)
{
unsigned char value[2];
value[0] = registerIndex;
value[1] = data;
if (hwI2CWriteData(deviceAddress, 2, value) == 2)
return 0;
return (-1);
}
#endif
#ifndef DDK750_HWI2C_H__
#define DDK750_HWI2C_H__
/* hwi2c functions */
int hwI2CInit(unsigned char busSpeedMode);
void hwI2CClose(void);
unsigned char hwI2CReadReg(unsigned char deviceAddress,unsigned char registerIndex);
int hwI2CWriteReg(unsigned char deviceAddress,unsigned char registerIndex,unsigned char data);
#endif
#include "ddk750_help.h"
#include "ddk750_reg.h"
#include "ddk750_mode.h"
#include "ddk750_chip.h"
/*
SM750LE only:
This function takes care extra registers and bit fields required to set
up a mode in SM750LE
Explanation about Display Control register:
HW only supports 7 predefined pixel clocks, and clock select is
in bit 29:27 of Display Control register.
*/
static unsigned long displayControlAdjust_SM750LE(mode_parameter_t *pModeParam, unsigned long dispControl)
{
unsigned long x, y;
x = pModeParam->horizontal_display_end;
y = pModeParam->vertical_display_end;
/* SM750LE has to set up the top-left and bottom-right
registers as well.
Note that normal SM750/SM718 only use those two register for
auto-centering mode.
*/
POKE32(CRT_AUTO_CENTERING_TL,
FIELD_VALUE(0, CRT_AUTO_CENTERING_TL, TOP, 0)
| FIELD_VALUE(0, CRT_AUTO_CENTERING_TL, LEFT, 0));
POKE32(CRT_AUTO_CENTERING_BR,
FIELD_VALUE(0, CRT_AUTO_CENTERING_BR, BOTTOM, y-1)
| FIELD_VALUE(0, CRT_AUTO_CENTERING_BR, RIGHT, x-1));
/* Assume common fields in dispControl have been properly set before
calling this function.
This function only sets the extra fields in dispControl.
*/
/* Clear bit 29:27 of display control register */
dispControl &= FIELD_CLEAR(CRT_DISPLAY_CTRL, CLK);
/* Set bit 29:27 of display control register for the right clock */
/* Note that SM750LE only need to supported 7 resoluitons. */
if ( x == 800 && y == 600 )
dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL41);
else if (x == 1024 && y == 768)
dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL65);
else if (x == 1152 && y == 864)
dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL80);
else if (x == 1280 && y == 768)
dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL80);
else if (x == 1280 && y == 720)
dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL74);
else if (x == 1280 && y == 960)
dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL108);
else if (x == 1280 && y == 1024)
dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL108);
else /* default to VGA clock */
dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL25);
/* Set bit 25:24 of display controller */
dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CRTSELECT, CRT);
dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, RGBBIT, 24BIT);
/* Set bit 14 of display controller */
dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLOCK_PHASE, ACTIVE_LOW);
POKE32(CRT_DISPLAY_CTRL, dispControl);
return dispControl;
}
/* only timing related registers will be programed */
static int programModeRegisters(mode_parameter_t * pModeParam,pll_value_t * pll)
{
int ret = 0;
int cnt = 0;
unsigned int ulTmpValue,ulReg;
if(pll->clockType == SECONDARY_PLL)
{
/* programe secondary pixel clock */
POKE32(CRT_PLL_CTRL,formatPllReg(pll));
POKE32(CRT_HORIZONTAL_TOTAL,
FIELD_VALUE(0, CRT_HORIZONTAL_TOTAL, TOTAL, pModeParam->horizontal_total - 1)
| FIELD_VALUE(0, CRT_HORIZONTAL_TOTAL, DISPLAY_END, pModeParam->horizontal_display_end - 1));
POKE32(CRT_HORIZONTAL_SYNC,
FIELD_VALUE(0, CRT_HORIZONTAL_SYNC, WIDTH, pModeParam->horizontal_sync_width)
| FIELD_VALUE(0, CRT_HORIZONTAL_SYNC, START, pModeParam->horizontal_sync_start - 1));
POKE32(CRT_VERTICAL_TOTAL,
FIELD_VALUE(0, CRT_VERTICAL_TOTAL, TOTAL, pModeParam->vertical_total - 1)
| FIELD_VALUE(0, CRT_VERTICAL_TOTAL, DISPLAY_END, pModeParam->vertical_display_end - 1));
POKE32(CRT_VERTICAL_SYNC,
FIELD_VALUE(0, CRT_VERTICAL_SYNC, HEIGHT, pModeParam->vertical_sync_height)
| FIELD_VALUE(0, CRT_VERTICAL_SYNC, START, pModeParam->vertical_sync_start - 1));
ulTmpValue = FIELD_VALUE(0,CRT_DISPLAY_CTRL,VSYNC_PHASE,pModeParam->vertical_sync_polarity)|
FIELD_VALUE(0,CRT_DISPLAY_CTRL,HSYNC_PHASE,pModeParam->horizontal_sync_polarity)|
FIELD_SET(0,CRT_DISPLAY_CTRL,TIMING,ENABLE)|
FIELD_SET(0,CRT_DISPLAY_CTRL,PLANE,ENABLE);
if(getChipType() == SM750LE){
displayControlAdjust_SM750LE(pModeParam,ulTmpValue);
}else{
ulReg = PEEK32(CRT_DISPLAY_CTRL)
& FIELD_CLEAR(CRT_DISPLAY_CTRL,VSYNC_PHASE)
& FIELD_CLEAR(CRT_DISPLAY_CTRL,HSYNC_PHASE)
& FIELD_CLEAR(CRT_DISPLAY_CTRL,TIMING)
& FIELD_CLEAR(CRT_DISPLAY_CTRL,PLANE);
POKE32(CRT_DISPLAY_CTRL,ulTmpValue|ulReg);
}
}
else if(pll->clockType == PRIMARY_PLL)
{
unsigned int ulReservedBits;
POKE32(PANEL_PLL_CTRL,formatPllReg(pll));
POKE32(PANEL_HORIZONTAL_TOTAL,
FIELD_VALUE(0, PANEL_HORIZONTAL_TOTAL, TOTAL, pModeParam->horizontal_total - 1)
| FIELD_VALUE(0, PANEL_HORIZONTAL_TOTAL, DISPLAY_END, pModeParam->horizontal_display_end - 1));
POKE32(PANEL_HORIZONTAL_SYNC,
FIELD_VALUE(0, PANEL_HORIZONTAL_SYNC, WIDTH, pModeParam->horizontal_sync_width)
| FIELD_VALUE(0, PANEL_HORIZONTAL_SYNC, START, pModeParam->horizontal_sync_start - 1));
POKE32(PANEL_VERTICAL_TOTAL,
FIELD_VALUE(0, PANEL_VERTICAL_TOTAL, TOTAL, pModeParam->vertical_total - 1)
| FIELD_VALUE(0, PANEL_VERTICAL_TOTAL, DISPLAY_END, pModeParam->vertical_display_end - 1));
POKE32(PANEL_VERTICAL_SYNC,
FIELD_VALUE(0, PANEL_VERTICAL_SYNC, HEIGHT, pModeParam->vertical_sync_height)
| FIELD_VALUE(0, PANEL_VERTICAL_SYNC, START, pModeParam->vertical_sync_start - 1));
ulTmpValue = FIELD_VALUE(0,PANEL_DISPLAY_CTRL,VSYNC_PHASE,pModeParam->vertical_sync_polarity)|
FIELD_VALUE(0,PANEL_DISPLAY_CTRL,HSYNC_PHASE,pModeParam->horizontal_sync_polarity)|
FIELD_VALUE(0,PANEL_DISPLAY_CTRL,CLOCK_PHASE,pModeParam->clock_phase_polarity)|
FIELD_SET(0,PANEL_DISPLAY_CTRL,TIMING,ENABLE)|
FIELD_SET(0,PANEL_DISPLAY_CTRL,PLANE,ENABLE);
ulReservedBits = FIELD_SET(0, PANEL_DISPLAY_CTRL, RESERVED_1_MASK, ENABLE) |
FIELD_SET(0, PANEL_DISPLAY_CTRL, RESERVED_2_MASK, ENABLE) |
FIELD_SET(0, PANEL_DISPLAY_CTRL, RESERVED_3_MASK, ENABLE)|
FIELD_SET(0,PANEL_DISPLAY_CTRL,VSYNC,ACTIVE_LOW);
ulReg = (PEEK32(PANEL_DISPLAY_CTRL) & ~ulReservedBits)
& FIELD_CLEAR(PANEL_DISPLAY_CTRL, CLOCK_PHASE)
& FIELD_CLEAR(PANEL_DISPLAY_CTRL, VSYNC_PHASE)
& FIELD_CLEAR(PANEL_DISPLAY_CTRL, HSYNC_PHASE)
& FIELD_CLEAR(PANEL_DISPLAY_CTRL, TIMING)
& FIELD_CLEAR(PANEL_DISPLAY_CTRL, PLANE);
/* May a hardware bug or just my test chip (not confirmed).
* PANEL_DISPLAY_CTRL register seems requiring few writes
* before a value can be succesfully written in.
* Added some masks to mask out the reserved bits.
* Note: This problem happens by design. The hardware will wait for the
* next vertical sync to turn on/off the plane.
*/
POKE32(PANEL_DISPLAY_CTRL,ulTmpValue|ulReg);
#if 1
while((PEEK32(PANEL_DISPLAY_CTRL) & ~ulReservedBits) != (ulTmpValue|ulReg))
{
cnt++;
if(cnt > 1000)
break;
POKE32(PANEL_DISPLAY_CTRL,ulTmpValue|ulReg);
}
#endif
}
else{
ret = -1;
}
return ret;
}
int ddk750_setModeTiming(mode_parameter_t * parm,clock_type_t clock)
{
pll_value_t pll;
unsigned int uiActualPixelClk;
pll.inputFreq = DEFAULT_INPUT_CLOCK;
pll.clockType = clock;
uiActualPixelClk = calcPllValue(parm->pixel_clock,&pll);
if(getChipType() == SM750LE){
/* set graphic mode via IO method */
outb_p(0x88,0x3d4);
outb_p(0x06,0x3d5);
}
programModeRegisters(parm,&pll);
return 0;
}
#ifndef DDK750_MODE_H__
#define DDK750_MODE_H__
#include "ddk750_chip.h"
typedef enum _spolarity_t
{
POS = 0, /* positive */
NEG, /* negative */
}
spolarity_t;
typedef struct _mode_parameter_t
{
/* Horizontal timing. */
unsigned long horizontal_total;
unsigned long horizontal_display_end;
unsigned long horizontal_sync_start;
unsigned long horizontal_sync_width;
spolarity_t horizontal_sync_polarity;
/* Vertical timing. */
unsigned long vertical_total;
unsigned long vertical_display_end;
unsigned long vertical_sync_start;
unsigned long vertical_sync_height;
spolarity_t vertical_sync_polarity;
/* Refresh timing. */
unsigned long pixel_clock;
unsigned long horizontal_frequency;
unsigned long vertical_frequency;
/* Clock Phase. This clock phase only applies to Panel. */
spolarity_t clock_phase_polarity;
}
mode_parameter_t;
int ddk750_setModeTiming(mode_parameter_t *,clock_type_t);
#endif
#include "ddk750_help.h"
#include "ddk750_reg.h"
#include "ddk750_power.h"
void ddk750_setDPMS(DPMS_t state)
{
unsigned int value;
if(getChipType() == SM750LE){
value = PEEK32(CRT_DISPLAY_CTRL);
POKE32(CRT_DISPLAY_CTRL,FIELD_VALUE(value,CRT_DISPLAY_CTRL,DPMS,state));
}else{
value = PEEK32(SYSTEM_CTRL);
value= FIELD_VALUE(value,SYSTEM_CTRL,DPMS,state);
POKE32(SYSTEM_CTRL, value);
}
}
unsigned int getPowerMode()
{
if(getChipType() == SM750LE)
return 0;
return (FIELD_GET(PEEK32(POWER_MODE_CTRL), POWER_MODE_CTRL, MODE));
}
/*
* SM50x can operate in one of three modes: 0, 1 or Sleep.
* On hardware reset, power mode 0 is default.
*/
void setPowerMode(unsigned int powerMode)
{
unsigned int control_value = 0;
control_value = PEEK32(POWER_MODE_CTRL);
if(getChipType() == SM750LE)
return;
switch (powerMode)
{
case POWER_MODE_CTRL_MODE_MODE0:
control_value = FIELD_SET(control_value, POWER_MODE_CTRL, MODE, MODE0);
break;
case POWER_MODE_CTRL_MODE_MODE1:
control_value = FIELD_SET(control_value, POWER_MODE_CTRL, MODE, MODE1);
break;
case POWER_MODE_CTRL_MODE_SLEEP:
control_value = FIELD_SET(control_value, POWER_MODE_CTRL, MODE, SLEEP);
break;
default:
break;
}
/* Set up other fields in Power Control Register */
if (powerMode == POWER_MODE_CTRL_MODE_SLEEP)
{
control_value =
#ifdef VALIDATION_CHIP
FIELD_SET( control_value, POWER_MODE_CTRL, 336CLK, OFF) |
#endif
FIELD_SET( control_value, POWER_MODE_CTRL, OSC_INPUT, OFF);
}
else
{
control_value =
#ifdef VALIDATION_CHIP
FIELD_SET( control_value, POWER_MODE_CTRL, 336CLK, ON) |
#endif
FIELD_SET( control_value, POWER_MODE_CTRL, OSC_INPUT, ON);
}
/* Program new power mode. */
POKE32(POWER_MODE_CTRL, control_value);
}
void setCurrentGate(unsigned int gate)
{
unsigned int gate_reg;
unsigned int mode;
/* Get current power mode. */
mode = getPowerMode();
switch (mode)
{
case POWER_MODE_CTRL_MODE_MODE0:
gate_reg = MODE0_GATE;
break;
case POWER_MODE_CTRL_MODE_MODE1:
gate_reg = MODE1_GATE;
break;
default:
gate_reg = MODE0_GATE;
break;
}
POKE32(gate_reg, gate);
}
/*
* This function enable/disable the 2D engine.
*/
void enable2DEngine(unsigned int enable)
{
uint32_t gate;
gate = PEEK32(CURRENT_GATE);
if (enable)
{
gate = FIELD_SET(gate, CURRENT_GATE, DE, ON);
gate = FIELD_SET(gate, CURRENT_GATE, CSC, ON);
}
else
{
gate = FIELD_SET(gate, CURRENT_GATE, DE, OFF);
gate = FIELD_SET(gate, CURRENT_GATE, CSC, OFF);
}
setCurrentGate(gate);
}
/*
* This function enable/disable the ZV Port.
*/
void enableZVPort(unsigned int enable)
{
uint32_t gate;
/* Enable ZV Port Gate */
gate = PEEK32(CURRENT_GATE);
if (enable)
{
gate = FIELD_SET(gate, CURRENT_GATE, ZVPORT, ON);
#if 1
/* Using Software I2C */
gate = FIELD_SET(gate, CURRENT_GATE, GPIO, ON);
#else
/* Using Hardware I2C */
gate = FIELD_SET(gate, CURRENT_GATE, I2C, ON);
#endif
}
else
{
/* Disable ZV Port Gate. There is no way to know whether the GPIO pins are being used
or not. Therefore, do not disable the GPIO gate. */
gate = FIELD_SET(gate, CURRENT_GATE, ZVPORT, OFF);
}
setCurrentGate(gate);
}
void enableSSP(unsigned int enable)
{
uint32_t gate;
/* Enable SSP Gate */
gate = PEEK32(CURRENT_GATE);
if (enable)
gate = FIELD_SET(gate, CURRENT_GATE, SSP, ON);
else
gate = FIELD_SET(gate, CURRENT_GATE, SSP, OFF);
setCurrentGate(gate);
}
void enableDMA(unsigned int enable)
{
uint32_t gate;
/* Enable DMA Gate */
gate = PEEK32(CURRENT_GATE);
if (enable)
gate = FIELD_SET(gate, CURRENT_GATE, DMA, ON);
else
gate = FIELD_SET(gate, CURRENT_GATE, DMA, OFF);
setCurrentGate(gate);
}
/*
* This function enable/disable the GPIO Engine
*/
void enableGPIO(unsigned int enable)
{
uint32_t gate;
/* Enable GPIO Gate */
gate = PEEK32(CURRENT_GATE);
if (enable)
gate = FIELD_SET(gate, CURRENT_GATE, GPIO, ON);
else
gate = FIELD_SET(gate, CURRENT_GATE, GPIO, OFF);
setCurrentGate(gate);
}
/*
* This function enable/disable the PWM Engine
*/
void enablePWM(unsigned int enable)
{
uint32_t gate;
/* Enable PWM Gate */
gate = PEEK32(CURRENT_GATE);
if (enable)
gate = FIELD_SET(gate, CURRENT_GATE, PWM, ON);
else
gate = FIELD_SET(gate, CURRENT_GATE, PWM, OFF);
setCurrentGate(gate);
}
/*
* This function enable/disable the I2C Engine
*/
void enableI2C(unsigned int enable)
{
uint32_t gate;
/* Enable I2C Gate */
gate = PEEK32(CURRENT_GATE);
if (enable)
gate = FIELD_SET(gate, CURRENT_GATE, I2C, ON);
else
gate = FIELD_SET(gate, CURRENT_GATE, I2C, OFF);
setCurrentGate(gate);
}
#ifndef DDK750_POWER_H__
#define DDK750_POWER_H__
typedef enum _DPMS_t
{
crtDPMS_ON = 0x0,
crtDPMS_STANDBY = 0x1,
crtDPMS_SUSPEND = 0x2,
crtDPMS_OFF = 0x3,
}
DPMS_t;
#define setDAC(off) \
{ \
POKE32(MISC_CTRL,FIELD_VALUE(PEEK32(MISC_CTRL), \
MISC_CTRL, \
DAC_POWER, \
off)); \
}
void ddk750_setDPMS(DPMS_t);
unsigned int getPowerMode(void);
/*
* This function sets the current power mode
*/
void setPowerMode(unsigned int powerMode);
/*
* This function sets current gate
*/
void setCurrentGate(unsigned int gate);
/*
* This function enable/disable the 2D engine.
*/
void enable2DEngine(unsigned int enable);
/*
* This function enable/disable the ZV Port
*/
void enableZVPort(unsigned int enable);
/*
* This function enable/disable the DMA Engine
*/
void enableDMA(unsigned int enable);
/*
* This function enable/disable the GPIO Engine
*/
void enableGPIO(unsigned int enable);
/*
* This function enable/disable the PWM Engine
*/
void enablePWM(unsigned int enable);
/*
* This function enable/disable the I2C Engine
*/
void enableI2C(unsigned int enable);
/*
* This function enable/disable the SSP.
*/
void enableSSP(unsigned int enable);
#endif
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Introduction:
SM750 of Silicon MOtion is pci express display controller device.
The SM750 embedded graphics features include:
- dual display
- 2D acceleration
- 16MB integrated video memory
About the kernel module paramter of driver:
Use 1280,8bpp index color and 60 hz mode:
insmod ./sm750fb.ko g_option="1280x1024-8@60"
Disable MTRR,Disable 2d acceleration,Disable hardware cursor,
and use a 800x600 mode :
insmod ./sm750fb.ko g_option="noaccel:nomtrr:nohwc:800x600"
dual frame buffer for driver with "dual" parameter
insmod ./sm750fb.ko g_option="dual,800x600:1024x768"
it will create fb0 and fb1 (or fb1,fb2 if fb0 already exist) under /dev
and user can use con2fb to link fbX and ttyX
Notes:
1) if you build the driver with built-in method, the paramter
you edited in the grub config file will be also the
same format as above modular method,but additionaly add
"video=sm750fb:"
ahead of parameters,so,it looks like:
video=sm750fb:noaccel,1280x1024@60,otherparam,etc...
it equal to modular method with below command:
insmod ./sm750fb.ko g_option="noaccel:1280x1024@60:otherparm:etc..."
2) if you put 800x600 into the paramter without bpp and
refresh rate, kernel driver will defaulty use 16bpp and 60hz
Important:
if you have vesafb enabled in your config then /dev/fb0 will be created by vesafb
and this driver will use fb1, fb2. In that case, you need to configure your X-server
to use fb1. Another simple althernative is to disable vesafb from your config.
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
#ifndef LYNX_CURSOR_H__
#define LYNX_CURSOR_H__
/* hw_cursor_xxx works for voyager,718 and 750 */
void hw_cursor_enable(struct lynx_cursor * cursor);
void hw_cursor_disable(struct lynx_cursor * cursor);
void hw_cursor_setSize(struct lynx_cursor * cursor,
int w,int h);
void hw_cursor_setPos(struct lynx_cursor * cursor,
int x,int y);
void hw_cursor_setColor(struct lynx_cursor * cursor,
u32 fg,u32 bg);
void hw_cursor_setData(struct lynx_cursor * cursor,
u16 rop,const u8* data,const u8* mask);
void hw_cursor_setData2(struct lynx_cursor * cursor,
u16 rop,const u8* data,const u8* mask);
#endif
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册