答复: 转发: Siliconmotion new kernel driver initial patch

Konrad Rzeszutek Wilk konrad at kernel.org
Fri Sep 21 08:36:08 PDT 2012


On Fri, Aug 24, 2012 at 10:35:00AM +0800, Aaron.Chen  陈俊杰 wrote:
> Hi,
> 
> >What's with the #ifdef 0 or #ifdef 1?
> 
> >Why is there a bunch of ddkxxx something? Can those header files be squashed together?
> 
> We have deleted all the "#ifdef 0 or #ifdef 1" and cut our codes into smaller parts in order to get reviewed easier. There are less ddkxxx something in this patch.

Please next time post it inline, not as attachment.

Also explain why/where what machines this runs on.

>From 35c8c1675e2bf6d8e7a702d61558b99316aaeabe Mon Sep 17 00:00:00 2001
>From: Aaron Chen <aaron.chen at siliconmotion.com>
>Date: Fri, 24 Aug 2012 10:03:54 +0800
>Subject: [PATCH] siliconmotion kernel driver initial patch
>
>This is the initial patch for siliconmotion kernel driver. It can support SM750 and SM718. It is a framebuffer driver.
>
>Signed-off-by: Aaron Chen <aaron.chen at siliconmotion.com>
>---
> drivers/video/Kconfig                 |   13 +
> drivers/video/Makefile                |    1 +
> drivers/video/lynxfb/Makefile         |   63 ++
> drivers/video/lynxfb/ddk750.h         |   31 +
> drivers/video/lynxfb/ddk750_chip.c    |  586 ++++++++++++
> drivers/video/lynxfb/ddk750_chip.h    |   97 ++
> drivers/video/lynxfb/ddk750_display.c |  295 ++++++
> drivers/video/lynxfb/ddk750_display.h |  124 +++
> drivers/video/lynxfb/ddk750_dvi.c     |  114 +++
> drivers/video/lynxfb/ddk750_dvi.h     |   84 ++
> drivers/video/lynxfb/ddk750_help.c    |   37 +
> drivers/video/lynxfb/ddk750_help.h    |   42 +
> drivers/video/lynxfb/ddk750_hwi2c.c   |  290 ++++++
> drivers/video/lynxfb/ddk750_hwi2c.h   |   28 +
> drivers/video/lynxfb/ddk750_mode.c    |  213 +++++
> drivers/video/lynxfb/ddk750_mode.h    |   59 ++
> drivers/video/lynxfb/ddk750_power.c   |  243 +++++
> drivers/video/lynxfb/ddk750_power.h   |   85 ++
> drivers/video/lynxfb/ddk750_reg.h     |  362 +++++++
> drivers/video/lynxfb/ddk750_sii164.c  |  435 +++++++++
> drivers/video/lynxfb/ddk750_sii164.h  |  187 ++++
> drivers/video/lynxfb/ddk750_swi2c.c   |  522 ++++++++++
> drivers/video/lynxfb/ddk750_swi2c.h   |   98 ++
> drivers/video/lynxfb/lynx_accel.c     |  417 ++++++++
> drivers/video/lynxfb/lynx_accel.h     |  161 ++++
> drivers/video/lynxfb/lynx_cursor.c    |  223 +++++
> drivers/video/lynxfb/lynx_cursor.h    |   36 +
> drivers/video/lynxfb/lynx_drv.c       | 1688 +++++++++++++++++++++++++++++++++
> drivers/video/lynxfb/lynx_drv.h       |  271 ++++++
> drivers/video/lynxfb/lynx_help.h      |  115 +++
> drivers/video/lynxfb/lynx_hw750.c     |  633 +++++++++++++
> drivers/video/lynxfb/lynx_hw750.h     |  120 +++
> drivers/video/lynxfb/modedb.c         |  238 +++++
> drivers/video/lynxfb/ver.h            |   38 +
> 34 files changed, 7949 insertions(+)
> create mode 100644 drivers/video/lynxfb/Makefile
> create mode 100644 drivers/video/lynxfb/ddk750.h
> create mode 100644 drivers/video/lynxfb/ddk750_chip.c
> create mode 100644 drivers/video/lynxfb/ddk750_chip.h
> create mode 100644 drivers/video/lynxfb/ddk750_display.c
> create mode 100644 drivers/video/lynxfb/ddk750_display.h
> create mode 100644 drivers/video/lynxfb/ddk750_dvi.c
> create mode 100644 drivers/video/lynxfb/ddk750_dvi.h
> create mode 100644 drivers/video/lynxfb/ddk750_help.c
> create mode 100644 drivers/video/lynxfb/ddk750_help.h
> create mode 100644 drivers/video/lynxfb/ddk750_hwi2c.c
> create mode 100644 drivers/video/lynxfb/ddk750_hwi2c.h
> create mode 100644 drivers/video/lynxfb/ddk750_mode.c
> create mode 100644 drivers/video/lynxfb/ddk750_mode.h
> create mode 100644 drivers/video/lynxfb/ddk750_power.c
> create mode 100644 drivers/video/lynxfb/ddk750_power.h
> create mode 100644 drivers/video/lynxfb/ddk750_reg.h
> create mode 100644 drivers/video/lynxfb/ddk750_sii164.c
> create mode 100644 drivers/video/lynxfb/ddk750_sii164.h
> create mode 100644 drivers/video/lynxfb/ddk750_swi2c.c
> create mode 100644 drivers/video/lynxfb/ddk750_swi2c.h
> create mode 100644 drivers/video/lynxfb/lynx_accel.c
> create mode 100644 drivers/video/lynxfb/lynx_accel.h
> create mode 100644 drivers/video/lynxfb/lynx_cursor.c
> create mode 100644 drivers/video/lynxfb/lynx_cursor.h
> create mode 100644 drivers/video/lynxfb/lynx_drv.c
> create mode 100644 drivers/video/lynxfb/lynx_drv.h
> create mode 100644 drivers/video/lynxfb/lynx_help.h
> create mode 100644 drivers/video/lynxfb/lynx_hw750.c
> create mode 100644 drivers/video/lynxfb/lynx_hw750.h
> create mode 100644 drivers/video/lynxfb/modedb.c
> create mode 100644 drivers/video/lynxfb/ver.h
>
>diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
>index 0217f74..8c52b1a 100644
>--- a/drivers/video/Kconfig
>+++ b/drivers/video/Kconfig
>@@ -2444,6 +2444,19 @@ config FB_PUV3_UNIGFX
> 	  Choose this option if you want to use the Unigfx device as a
> 	  framebuffer device. Without the support of PCI & AGP.
> 
>+config FB_LYNXFB
>+	tristate "SMI lynx sm750/718/712/722/502 display support"
>+	depends on FB && PCI
>+	select FB_CFB_IMAGEBLIT
>+	select FB_CFB_FILLRECT
>+	select FB_CFB_COPYAREA
>+	---help---
>+	  This driver supports graphic board with the siliconmotion
>+	  sm750/sm718/sm712/sm722/sm502. Say Y if you have such a
>+	  graphic board.
>+	  To compile this driver as a module, choose M here: the
>+	  module will be called lynxfb.
>+
> source "drivers/video/omap/Kconfig"
> source "drivers/video/omap2/Kconfig"
> source "drivers/video/exynos/Kconfig"
>diff --git a/drivers/video/Makefile b/drivers/video/Makefile
>index ee8dafb..b402bfb 100644
>--- a/drivers/video/Makefile
>+++ b/drivers/video/Makefile
>@@ -149,6 +149,7 @@ obj-$(CONFIG_FB_MSM)              += msm/
> obj-$(CONFIG_FB_NUC900)           += nuc900fb.o
> obj-$(CONFIG_FB_JZ4740)		  += jz4740_fb.o
> obj-$(CONFIG_FB_PUV3_UNIGFX)      += fb-puv3.o
>+obj-$(CONFIG_FB_LYNXFB)		  += lynxfb/
> 
> # Platform or fallback drivers go here
> obj-$(CONFIG_FB_UVESA)            += uvesafb.o
>diff --git a/drivers/video/lynxfb/Makefile b/drivers/video/lynxfb/Makefile
>new file mode 100644
>index 0000000..8853097
>--- /dev/null
>+++ b/drivers/video/lynxfb/Makefile
>@@ -0,0 +1,63 @@
>+#
>+# Makefile for lynx frame buffer
>+# 					-by Monk.liu
>+#
>+ifeq ($(KERNELRELEASE),)
>+
>+ifeq ($(kernel),)
>+# build the driver with kernel version currerntly using
>+knv :=$(shell uname -r)
>+else
>+# user want to build the driver based on specific kernel version
>+knv :=$(kernel)
>+endif
>+
>+KERNELDIR :=/lib/modules/$(knv)/build
>+PWD := $(shell pwd)
>+
>+default:
>+	$(MAKE) -C $(KERNELDIR) M=$(PWD) CONFIG_FB_LYNXFB=m modules
>+install:default
>+	$(MAKE) -C $(KERNELDIR) M=$(PWD) CONFIG_FB_LYNXFB=m modules_install
>+clean:
>+	$(MAKE) -C $(KERNELDIR) M=$(PWD) clean
>+else
>+

You don't need all of that.

>+obj-$(CONFIG_FB_LYNXFB) += lynxfb.o
>+
>+lynxfb-y := lynx_drv.o lynx_hw750.o lynx_accel.o lynx_cursor.o
>+lynxfb-y += ddk750_chip.o ddk750_power.o ddk750_mode.o ddk750_display.o ddk750_help.o
>+lynxfb-y +=  ddk750_swi2c.o

Those should suffice. Or perhaps:
obj-$(CONFIG_FB_LYNXFB) += lynxfb.o lynx_drv.o lynx_hw750.o lynx_accel.o lynx_cursor.o
			ddk750_chip.o ddk750_power.o ddk750_mode.o ddk750_display.o ddk750_help.o

and that is it.

>+
>+
>+EXTRA_CFLAGS += -DOPENSOURCE
>+
>+ifneq ($(nodvi),1)
>+lynxfb-y += ddk750_sii164.o
>+lynxfb-y += ddk750_dvi.o
>+EXTRA_CFLAGS += -DUSE_DVICHIP
>+else
>+endif
>+
>+# if user define swi2c=1,then for sm750/sm718,its dvi chip (sii164) will be initilized by swi2c
>+# but for 750le, always swi2c used to setup its 7301 dvi chip
>+ifneq ($(swi2c),1)
>+lynxfb-y += ddk750_hwi2c.o
>+EXTRA_CFLAGS += -DUSE_HW_I2C
>+endif
>+
>+lynxfb-objs := $(lynxfb-y)
>+
>+ifeq ($(debug),1)
>+#CONFIG_FB_LYNXFB_DEBUG=y
>+EXTRA_CFLAGS += -DDEBUG=1
>+endif
>+
>+ifeq ($(debug),2)
>+EXTRA_CFLAGS += -DDEBUG=2
>+endif
>+
>+#ifdef CONFIG_FB_LYNXFB_DEBUG
>+#endif
>+
>+endif
>diff --git a/drivers/video/lynxfb/ddk750.h b/drivers/video/lynxfb/ddk750.h
>new file mode 100644
>index 0000000..fd3e279
>--- /dev/null
>+++ b/drivers/video/lynxfb/ddk750.h
>@@ -0,0 +1,31 @@
>+/*******************************************************************
>+*Copyright (c) 2012 by Silicon Motion, Inc. (SMI)
>+*Permission is hereby granted, free of charge, to any person obtaining a copy
>+*of this software and associated documentation files (the "Software"), to deal
>+*in the Software without restriction, including without limitation the rights to
>+*use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
>+*of the Software, and to permit persons to whom the Software is furnished to
>+*do so, subject to the following conditions:
>+*
>+*THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
>+*EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
>+*OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
>+*NONINFRINGEMENT.  IN NO EVENT SHALL Mill.Chen and Monk.Liu OR COPYRIGHT
>+*HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
>+*WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
>+*FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
>+*OTHER DEALINGS IN THE SOFTWARE.
>+*******************************************************************/
>+#ifndef DDK750_H__
>+#define DDK750_H__
>+#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

This header file is not adding anyting to the driver. Why don't you just
include those #includes in the C code?

>diff --git a/drivers/video/lynxfb/ddk750_chip.c b/drivers/video/lynxfb/ddk750_chip.c
>new file mode 100644
>index 0000000..4eff5c6
>--- /dev/null
>+++ b/drivers/video/lynxfb/ddk750_chip.c
>@@ -0,0 +1,586 @@
>+/*******************************************************************
>+*Copyright (c) 2012 by Silicon Motion, Inc. (SMI)
>+*Permission is hereby granted, free of charge, to any person obtaining a copy
>+*of this software and associated documentation files (the "Software"), to deal
>+*in the Software without restriction, including without limitation the rights to
>+*use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
>+*of the Software, and to permit persons to whom the Software is furnished to
>+*do so, subject to the following conditions:
>+*
>+*THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
>+*EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
>+*OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
>+*NONINFRINGEMENT.  IN NO EVENT SHALL Mill.Chen and Monk.Liu OR COPYRIGHT
>+*HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
>+*WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
>+*FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
>+*OTHER DEALINGS IN THE SOFTWARE.
>+*******************************************************************/
>+#include "ddk750_help.h"
>+#include "ddk750_reg.h"
>+#include "ddk750_chip.h"
>+#include "ddk750_power.h"
>+typedef struct _pllcalparam{

You didn't run cleanpatch on this patch series at all did you? Please
do that and then repost it.
>+	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)

I think there is a nice macro for this. Did you search in the 
code already for this?

>+{
>+	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 = 255&(ulPllReg >> PANEL_PLL_CTRL_M_LSB);
>+	pPLL->N = 15&(ulPllReg >> PANEL_PLL_CTRL_N_LSB);
>+	pPLL->OD = 3&(ulPllReg >> PANEL_PLL_CTRL_OD_LSB);
>+	pPLL->POD = 3&(ulPllReg >> PANEL_PLL_CTRL_POD_LSB);
>+
>+	return calcPLL(pPLL);
>+}
>+
>+
>+unsigned int getChipClock()
>+{
>+	pll_value_t pll;
>+	if (getChipType() == SM750LE)
>+		return MHz(130);
>+
>+	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;
>+
>+	/* Cheok_0509: For SM750LE, the chip clock is fixed. Nothing to set. */
>+	if (getChipType() == SM750LE)
>+		return;
>+
>+
>+	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 */

I don't think the 'CLOCK.H' file is present there.
>+		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.

So an estimation then? 
>+		 */
>+		ulActualMxClk = calcPllValue(frequency, &pll);
>+
>+		/* Master Clock Control: MXCLK_PLL */
>+		POKE32(MXCLK_PLL_CTRL, formatPllReg(&pll));
>+	}
>+}
>+
>+
>+
>+void setMemoryClock(unsigned int frequency)
>+{
>+	unsigned int ulReg, divisor;
>+
>+	/* Cheok_0509: For SM750LE, the memory clock is fixed. Nothing to set. */
>+	if (getChipType() == SM750LE)
>+		return;
>+
>+	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 = ulReg&(~(1 << CURRENT_GATE_M2XCLK_LSB));
>+			break;
>+		case 2:
>+			ulReg = ulReg|(1 << CURRENT_GATE_M2XCLK_LSB);
>+			break;
>+		case 3:
>+			ulReg = ulReg&(~(3 << CURRENT_GATE_M2XCLK_LSB));
>+			ulReg = ulReg|(2 << CURRENT_GATE_M2XCLK_LSB);
>+			break;
>+		case 4:
>+			ulReg = ulReg|(3 << CURRENT_GATE_M2XCLK_LSB);
>+			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;
>+
>+	/* Cheok_0509: For SM750LE, the memory clock is fixed. Nothing to set. */
>+	if (getChipType() == SM750LE)
>+		return;
>+
>+	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 = ulReg&(~(1 << CURRENT_GATE_MCLK_LSB));
>+			break;
>+		case 4:
>+			ulReg = ulReg|(1 << CURRENT_GATE_MCLK_LSB);
>+			break;
>+		case 6:
>+			ulReg = ulReg&(~(3 << CURRENT_GATE_MCLK_LSB));
>+			ulReg = ulReg|(2 << CURRENT_GATE_MCLK_LSB);
>+			break;
>+		case 8:
>+			ulReg = ulReg|(3 << CURRENT_GATE_MCLK_LSB);
>+			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 = reg|(1 << MODE0_GATE_GPIO_LSB);
>+	POKE32(MODE0_GATE, reg);
>+
>+	/* get frame buffer size from GPIO */
>+	reg = 3&(PEEK32(MISC_CTRL) >> MISC_CTRL_LOCALMEM_SIZE_LSB);
>+	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 (pInitParam->powerMode != 0)
>+		pInitParam->powerMode = 0;
>+	setPowerMode(pInitParam->powerMode);
>+
>+	/* Enable display power gate & LOCALMEM power gate*/
>+	ulReg = PEEK32(CURRENT_GATE);
>+	ulReg = ulReg|(1 << CURRENT_GATE_DISPLAY_LSB);
>+	ulReg = ulReg|(1 << CURRENT_GATE_LOCALMEM_LSB);
>+	setCurrentGate(ulReg);
>+
>+	if (getChipType() != SM750LE) {
>+		/*	set panel pll and graphic mode via mmio_88 */
>+		ulReg = PEEK32(VGA_CONFIGURATION);
>+		ulReg = ulReg|(1 << VGA_CONFIGURATION_PLL_LSB);
>+		ulReg = ulReg|(1 << VGA_CONFIGURATION_MODE_LSB);
>+
>+		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 = ulReg&(~(1 << MISC_CTRL_LOCALMEM_RESET_LSB));
>+		POKE32(MISC_CTRL, ulReg);
>+
>+		ulReg = ulReg|(1 << MISC_CTRL_LOCALMEM_RESET_LSB);
>+		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 = ulReg&(~(1 << VIDEO_DISPLAY_CTRL_PLANE_LSB));
>+		POKE32(VIDEO_DISPLAY_CTRL, ulReg);
>+
>+		/* Disable video alpha, if a former application left it on */
>+		ulReg = PEEK32(VIDEO_ALPHA_DISPLAY_CTRL);
>+		ulReg = ulReg&(~(1 << VIDEO_ALPHA_DISPLAY_CTRL_PLANE_LSB));
>+		POKE32(VIDEO_ALPHA_DISPLAY_CTRL, ulReg);
>+
>+		/* Disable alpha plane, if a former application left it on */
>+		ulReg = PEEK32(ALPHA_DISPLAY_CTRL);
>+		ulReg = ulReg&(~(1 << ALPHA_DISPLAY_CTRL_PLANE_LSB));
>+		POKE32(ALPHA_DISPLAY_CTRL, ulReg);
>+
>+		/* Disable DMA Channel, if a former application left it on */
>+		ulReg = PEEK32(DMA_ABORT_INTERRUPT);
>+		ulReg = ulReg|(1 << DMA_ABORT_INTERRUPT_ABORT_1_LSB);
>+		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;
>+}
>+
>+/*
>+   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 (getChipType() == SM750LE) {
>+		/* SM750LE don't have prgrammable PLL and M/N values to work on.
>+		   Just return the requested clock. */
>+		return request_orig;
>+	}
>+
>+
>+	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

So.. what are those? Should these #ifdef's be removed?

I stopped here.. You should read the Documentation/Submitting* files and
follow what they mention there. Please fix the syntax, remove the usage
of templates, and user 'pr_info' instead of 'printk'.


>+	/* 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));i
>+	   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));i */
>+
>+	/* 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 =
>+		(0 << PANEL_PLL_CTRL_BYPASS_LSB)
>+		| (1 << PANEL_PLL_CTRL_POWER_LSB)
>+		| (0 << PANEL_PLL_CTRL_INPUT_LSB)
>+#ifndef VALIDATION_CHIP
>+		| (pPLL->POD << PANEL_PLL_CTRL_POD_LSB)
>+#endif
>+		| (pPLL->OD << PANEL_PLL_CTRL_OD_LSB)
>+		| (pPLL->N << PANEL_PLL_CTRL_N_LSB)
>+		| (pPLL->M << PANEL_PLL_CTRL_M_LSB);
>+	return ulPllReg;
>+}
>+
>+
>diff --git a/drivers/video/lynxfb/ddk750_chip.h b/drivers/video/lynxfb/ddk750_chip.h
>new file mode 100644
>index 0000000..f24af16
>--- /dev/null
>+++ b/drivers/video/lynxfb/ddk750_chip.h
>@@ -0,0 +1,97 @@
>+/*******************************************************************
>+*Copyright (c) 2012 by Silicon Motion, Inc. (SMI)
>+*Permission is hereby granted, free of charge, to any person obtaining a copy
>+*of this software and associated documentation files (the "Software"), to deal
>+*in the Software without restriction, including without limitation the rights to
>+*use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
>+*of the Software, and to permit persons to whom the Software is furnished to
>+*do so, subject to the following conditions:
>+*
>+*THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
>+*EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
>+*OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
>+*NONINFRINGEMENT.  IN NO EVENT SHALL Mill.Chen and Monk.Liu OR COPYRIGHT
>+*HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
>+*WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
>+*FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
>+*OTHER DEALINGS IN THE SOFTWARE.
>+*******************************************************************/
>+#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
>diff --git a/drivers/video/lynxfb/ddk750_display.c b/drivers/video/lynxfb/ddk750_display.c
>new file mode 100644
>index 0000000..6e973cc
>--- /dev/null
>+++ b/drivers/video/lynxfb/ddk750_display.c
>@@ -0,0 +1,295 @@
>+/*******************************************************************
>+*Copyright (c) 2012 by Silicon Motion, Inc. (SMI)
>+*Permission is hereby granted, free of charge, to any person obtaining a copy
>+*of this software and associated documentation files (the "Software"), to deal
>+*in the Software without restriction, including without limitation the rights to
>+*use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
>+*of the Software, and to permit persons to whom the Software is furnished to
>+*do so, subject to the following conditions:
>+*
>+*THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
>+*EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
>+*OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
>+*NONINFRINGEMENT.  IN NO EVENT SHALL Mill.Chen and Monk.Liu OR COPYRIGHT
>+*HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
>+*WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
>+*FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
>+*OTHER DEALINGS IN THE SOFTWARE.
>+*******************************************************************/
>+#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 = 0;
>+	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 = ulDisplayCtrlReg|(1 << PANEL_DISPLAY_CTRL_TIMING_LSB);
>+			POKE32(PANEL_DISPLAY_CTRL, ulDisplayCtrlReg);
>+
>+			ulDisplayCtrlReg = ulDisplayCtrlReg|(1 << PANEL_DISPLAY_CTRL_PLANE_LSB);
>+			/* 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 = (3 << PANEL_DISPLAY_CTRL_RESERVED_1_MASK_LSB)|
>+					(15 << PANEL_DISPLAY_CTRL_RESERVED_2_MASK_LSB)|
>+					(1 << PANEL_DISPLAY_CTRL_RESERVED_3_MASK_LSB);
>+
>+			/* 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 = ulDisplayCtrlReg&(~(1 << PANEL_DISPLAY_CTRL_PLANE_LSB));
>+			POKE32(PANEL_DISPLAY_CTRL, ulDisplayCtrlReg);
>+
>+			ulDisplayCtrlReg = ulDisplayCtrlReg&(~(1 << PANEL_DISPLAY_CTRL_TIMING_LSB));
>+			POKE32(PANEL_DISPLAY_CTRL, ulDisplayCtrlReg);
>+		}
>+
>+	} else{
>+		/* Set the secondary display control */
>+		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 = ulDisplayCtrlReg|(1 << CRT_DISPLAY_CTRL_TIMING_LSB);
>+			POKE32(CRT_DISPLAY_CTRL, ulDisplayCtrlReg);
>+
>+			ulDisplayCtrlReg = ulDisplayCtrlReg|(1 << CRT_DISPLAY_CTRL_PLANE_LSB);
>+
>+			/* 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 = (0X1F << CRT_DISPLAY_CTRL_RESERVED_1_MASK_LSB)|
>+					(3 << CRT_DISPLAY_CTRL_RESERVED_2_MASK_LSB)|
>+					(1 << CRT_DISPLAY_CTRL_RESERVED_3_MASK_LSB)|
>+					(1 << CRT_DISPLAY_CTRL_RESERVED_4_MASK_LSB);
>+			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 = ulDisplayCtrlReg&(~(1 << CRT_DISPLAY_CTRL_PLANE_LSB));
>+			POKE32(CRT_DISPLAY_CTRL, ulDisplayCtrlReg);
>+
>+			ulDisplayCtrlReg = ulDisplayCtrlReg&(~(1 << CRT_DISPLAY_CTRL_TIMING_LSB));
>+			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 (((1&(PEEK32(PANEL_PLL_CTRL) >> PANEL_PLL_CTRL_POWER_LSB)) ==
>+					PANEL_PLL_CTRL_POWER_OFF) ||
>+				((1&(PEEK32(PANEL_DISPLAY_CTRL) >> PANEL_DISPLAY_CTRL_TIMING_LSB)) ==
>+				 PANEL_DISPLAY_CTRL_TIMING_DISABLE)) {
>+			return;
>+		}
>+		while (delay-- > 0) {
>+			/* Wait for end of vsync. */
>+			do {
>+				status = 1&(PEEK32(SYSTEM_CTRL) >> SYSTEM_CTRL_PANEL_VSYNC_LSB);
>+			} while (status == SYSTEM_CTRL_PANEL_VSYNC_ACTIVE);
>+
>+			/* Wait for start of vsync. */
>+			do {
>+				status = 1&(PEEK32(SYSTEM_CTRL) >> SYSTEM_CTRL_PANEL_VSYNC_LSB);
>+			} 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 ((1&(PEEK32(CRT_PLL_CTRL) >> CRT_PLL_CTRL_POWER_LSB) ==
>+					CRT_PLL_CTRL_POWER_OFF) ||
>+				(1&(PEEK32(CRT_DISPLAY_CTRL) >> CRT_DISPLAY_CTRL_TIMING_LSB) ==
>+				 CRT_DISPLAY_CTRL_TIMING_DISABLE)) {
>+			return;
>+		}
>+
>+		while (delay-- > 0) {
>+			/* Wait for end of vsync. */
>+			do {
>+				status = 1&(PEEK32(SYSTEM_CTRL) >> SYSTEM_CTRL_CRT_VSYNC_LSB);
>+			} while (status == SYSTEM_CTRL_CRT_VSYNC_ACTIVE);
>+
>+			/* Wait for start of vsync. */
>+			do {
>+				status = 1&(PEEK32(SYSTEM_CTRL) >> SYSTEM_CTRL_CRT_VSYNC_LSB);
>+			} 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 &= ~(1 << PANEL_DISPLAY_CTRL_FPEN_LSB);
>+	reg = reg|(disp << PANEL_DISPLAY_CTRL_FPEN_LSB);
>+	POKE32(PANEL_DISPLAY_CTRL, reg);
>+	primaryWaitVerticalSync(delay);
>+
>+	reg = PEEK32(PANEL_DISPLAY_CTRL);
>+	reg &= ~(1 << PANEL_DISPLAY_CTRL_DATA_LSB);
>+	reg = reg|(disp << PANEL_DISPLAY_CTRL_DATA_LSB);
>+	POKE32(PANEL_DISPLAY_CTRL, reg);
>+	primaryWaitVerticalSync(delay);
>+
>+	reg = PEEK32(PANEL_DISPLAY_CTRL);
>+	reg &= ~(1 << PANEL_DISPLAY_CTRL_VBIASEN_LSB);
>+	reg = reg|(disp << PANEL_DISPLAY_CTRL_VBIASEN_LSB);
>+	POKE32(PANEL_DISPLAY_CTRL, reg);
>+	primaryWaitVerticalSync(delay);
>+
>+	reg = PEEK32(PANEL_DISPLAY_CTRL);
>+	reg &= ~(1 << PANEL_DISPLAY_CTRL_FPEN_LSB);
>+	reg = reg|(disp << PANEL_DISPLAY_CTRL_FPEN_LSB);
>+	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 &= ~(3 << PANEL_DISPLAY_CTRL_SELECT_LSB);
>+		reg = reg|((output & PNL_2_MASK) >> PNL_2_OFFSET) << PANEL_DISPLAY_CTRL_SELECT_LSB;
>+		POKE32(PANEL_DISPLAY_CTRL, reg);
>+	}
>+
>+	if (output & CRT_2_USAGE) {
>+		/* set crt path controller select */
>+		reg = PEEK32(CRT_DISPLAY_CTRL);
>+		reg &= ~(3 << CRT_DISPLAY_CTRL_SELECT_LSB);
>+		reg = reg|((output & CRT_2_MASK) >> CRT_2_OFFSET) << CRT_DISPLAY_CTRL_SELECT_LSB;
>+		/*se blank off */
>+		reg = reg&(~(1 << CRT_DISPLAY_CTRL_BLANK_LSB));
>+		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;
>+
>+}
>+
>diff --git a/drivers/video/lynxfb/ddk750_display.h b/drivers/video/lynxfb/ddk750_display.h
>new file mode 100644
>index 0000000..abc2a93
>--- /dev/null
>+++ b/drivers/video/lynxfb/ddk750_display.h
>@@ -0,0 +1,124 @@
>+/*******************************************************************
>+*Copyright (c) 2012 by Silicon Motion, Inc. (SMI)
>+*Permission is hereby granted, free of charge, to any person obtaining a copy
>+*of this software and associated documentation files (the "Software"), to deal
>+*in the Software without restriction, including without limitation the rights to
>+*use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
>+*of the Software, and to permit persons to whom the Software is furnished to
>+*do so, subject to the following conditions:
>+*
>+*THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
>+*EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
>+*OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
>+*NONINFRINGEMENT.  IN NO EVENT SHALL Mill.Chen and Monk.Liu OR COPYRIGHT
>+*HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
>+*WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
>+*FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
>+*OTHER DEALINGS IN THE SOFTWARE.
>+*******************************************************************/
>+#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
>+   */
>+
>+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,
>+	do_LCD2_PRI = CRT_2_PRI|PRI_TP_ON|DUAL_TFT_ON,
>+	do_LCD2_SEC = CRT_2_SEC|SEC_TP_ON|DUAL_TFT_ON,
>+	/*
>+	   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,
>+	   */
>+	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,
>+}
>+disp_output_t;
>+
>+void ddk750_setLogicalDispOut(disp_output_t);
>+int ddk750_initDVIDisp(void);
>+
>+#endif
>diff --git a/drivers/video/lynxfb/ddk750_dvi.c b/drivers/video/lynxfb/ddk750_dvi.c
>new file mode 100644
>index 0000000..0663009
>--- /dev/null
>+++ b/drivers/video/lynxfb/ddk750_dvi.c
>@@ -0,0 +1,114 @@
>+/*******************************************************************
>+*Copyright (c) 2012 by Silicon Motion, Inc. (SMI)
>+*Permission is hereby granted, free of charge, to any person obtaining a copy
>+*of this software and associated documentation files (the "Software"), to deal
>+*in the Software without restriction, including without limitation the rights to
>+*use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
>+*of the Software, and to permit persons to whom the Software is furnished to
>+*do so, subject to the following conditions:
>+*
>+*THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
>+*EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
>+*OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
>+*NONINFRINGEMENT.  IN NO EVENT SHALL Mill.Chen and Monk.Liu OR COPYRIGHT
>+*HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
>+*WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
>+*FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
>+*OTHER DEALINGS IN THE SOFTWARE.
>+*******************************************************************/
>+#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
>+
>+
>diff --git a/drivers/video/lynxfb/ddk750_dvi.h b/drivers/video/lynxfb/ddk750_dvi.h
>new file mode 100644
>index 0000000..64773fd
>--- /dev/null
>+++ b/drivers/video/lynxfb/ddk750_dvi.h
>@@ -0,0 +1,84 @@
>+/*******************************************************************
>+*Copyright (c) 2012 by Silicon Motion, Inc. (SMI)
>+*Permission is hereby granted, free of charge, to any person obtaining a copy
>+*of this software and associated documentation files (the "Software"), to deal
>+*in the Software without restriction, including without limitation the rights to
>+*use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
>+*of the Software, and to permit persons to whom the Software is furnished to
>+*do so, subject to the following conditions:
>+*
>+*THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
>+*EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
>+*OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
>+*NONINFRINGEMENT.  IN NO EVENT SHALL Mill.Chen and Monk.Liu OR COPYRIGHT
>+*HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
>+*WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
>+*FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
>+*OTHER DEALINGS IN THE SOFTWARE.
>+*******************************************************************/
>+#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
>+
>diff --git a/drivers/video/lynxfb/ddk750_help.c b/drivers/video/lynxfb/ddk750_help.c
>new file mode 100644
>index 0000000..2e95b58
>--- /dev/null
>+++ b/drivers/video/lynxfb/ddk750_help.c
>@@ -0,0 +1,37 @@
>+/*******************************************************************
>+*Copyright (c) 2012 by Silicon Motion, Inc. (SMI)
>+*Permission is hereby granted, free of charge, to any person obtaining a copy
>+*of this software and associated documentation files (the "Software"), to deal
>+*in the Software without restriction, including without limitation the rights to
>+*use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
>+*of the Software, and to permit persons to whom the Software is furnished to
>+*do so, subject to the following conditions:
>+*
>+*THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
>+*EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
>+*OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
>+*NONINFRINGEMENT.  IN NO EVENT SHALL Mill.Chen and Monk.Liu OR COPYRIGHT
>+*HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
>+*WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
>+*FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
>+*OTHER DEALINGS IN THE SOFTWARE.
>+*******************************************************************/
>+/*#include "ddk750_reg.h" */
>+/*#include "ddk750_chip.h" */
>+#include "ddk750_help.h"
>+
>+volatile unsigned char __iomem *mmio750;
>+char revId750;
>+unsigned short devId750;
>+
>+/* 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");
>+}
>+
>+
>diff --git a/drivers/video/lynxfb/ddk750_help.h b/drivers/video/lynxfb/ddk750_help.h
>new file mode 100644
>index 0000000..860c0c1
>--- /dev/null
>+++ b/drivers/video/lynxfb/ddk750_help.h
>@@ -0,0 +1,42 @@
>+/*******************************************************************
>+*Copyright (c) 2012 by Silicon Motion, Inc. (SMI)
>+*Permission is hereby granted, free of charge, to any person obtaining a copy
>+*of this software and associated documentation files (the "Software"), to deal
>+*in the Software without restriction, including without limitation the rights to
>+*use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
>+*of the Software, and to permit persons to whom the Software is furnished to
>+*do so, subject to the following conditions:
>+*
>+*THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
>+*EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
>+*OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
>+*NONINFRINGEMENT.  IN NO EVENT SHALL Mill.Chen and Monk.Liu OR COPYRIGHT
>+*HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
>+*WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
>+*FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
>+*OTHER DEALINGS IN THE SOFTWARE.
>+*******************************************************************/
>+#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 "lynx_help.h"
>+
>+
>+ /* software control endianess */
>+#define PEEK32(addr) readl((addr)+mmio750)
>+#define POKE32(addr, data) writel((data), (addr)+mmio750)
>+
>+
>+extern volatile unsigned  char __iomem *mmio750;
>+extern char revId750;
>+extern unsigned short devId750;
>+#else
>+/* implement if you want use it*/
>+#endif
>+
>+#endif
>diff --git a/drivers/video/lynxfb/ddk750_hwi2c.c b/drivers/video/lynxfb/ddk750_hwi2c.c
>new file mode 100644
>index 0000000..c37ff82
>--- /dev/null
>+++ b/drivers/video/lynxfb/ddk750_hwi2c.c
>@@ -0,0 +1,290 @@
>+/*******************************************************************
>+*Copyright (c) 2012 by Silicon Motion, Inc. (SMI)
>+*Permission is hereby granted, free of charge, to any person obtaining a copy
>+*of this software and associated documentation files (the "Software"), to deal
>+*in the Software without restriction, including without limitation the rights to
>+*use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
>+*of the Software, and to permit persons to whom the Software is furnished to
>+*do so, subject to the following conditions:
>+*
>+*THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
>+*EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
>+*OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
>+*NONINFRINGEMENT.  IN NO EVENT SHALL Mill.Chen and Monk.Liu OR COPYRIGHT
>+*HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
>+*WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
>+*FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
>+*OTHER DEALINGS IN THE SOFTWARE.
>+*******************************************************************/
>+#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 |= (1 << GPIO_MUX_30_LSB)|(1 << GPIO_MUX_31_LSB);
>+	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 &= ~(1 << I2C_CTRL_MODE_LSB);
>+	else
>+		value |= 1 << I2C_CTRL_MODE_LSB;
>+	value |= 1 << I2C_CTRL_EN_LSB;
>+
>+	POKE32(I2C_CTRL, value);
>+
>+	return 0;
>+}
>+
>+
>+void hwI2CClose(void)
>+{
>+	unsigned int value;
>+
>+	/* Disable I2C controller */
>+	value = PEEK32(I2C_CTRL);
>+
>+	value &= ~(1 << I2C_CTRL_EN_LSB);
>+	POKE32(I2C_CTRL, value);
>+
>+	/* Disable I2C Power */
>+	enableI2C(0);
>+
>+	/* Set GPIO 30 & 31 back as GPIO pins */
>+	value = PEEK32(GPIO_MUX);
>+	value &= ~(1 << GPIO_MUX_30_LSB);
>+	value &= ~(1 << GPIO_MUX_31_LSB);
>+	POKE32(GPIO_MUX, value);
>+}
>+
>+
>+long hwI2CWaitTXDone(void)
>+{
>+	unsigned int timeout;
>+
>+	/* Wait until the transfer is completed. */
>+	timeout = HWI2C_WAIT_TIMEOUT;
>+
>+	while (((1&(PEEK32(I2C_STATUS) >> I2C_STATUS_TX_LSB)) != 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, PEEK32(I2C_CTRL)|(1 << I2C_CTRL_CTRL_LSB));
>+
>+		/* 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, PEEK32(I2C_CTRL)|(1 << I2C_CTRL_CTRL_LSB));
>+
>+		/* 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
>diff --git a/drivers/video/lynxfb/ddk750_hwi2c.h b/drivers/video/lynxfb/ddk750_hwi2c.h
>new file mode 100644
>index 0000000..6cbd292
>--- /dev/null
>+++ b/drivers/video/lynxfb/ddk750_hwi2c.h
>@@ -0,0 +1,28 @@
>+/*******************************************************************
>+*Copyright (c) 2012 by Silicon Motion, Inc. (SMI)
>+*Permission is hereby granted, free of charge, to any person obtaining a copy
>+*of this software and associated documentation files (the "Software"), to deal
>+*in the Software without restriction, including without limitation the rights to
>+*use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
>+*of the Software, and to permit persons to whom the Software is furnished to
>+*do so, subject to the following conditions:
>+*
>+*THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
>+*EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
>+*OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
>+*NONINFRINGEMENT.  IN NO EVENT SHALL Mill.Chen and Monk.Liu OR COPYRIGHT
>+*HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
>+*WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
>+*FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
>+*OTHER DEALINGS IN THE SOFTWARE.
>+*******************************************************************/
>+#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
>diff --git a/drivers/video/lynxfb/ddk750_mode.c b/drivers/video/lynxfb/ddk750_mode.c
>new file mode 100644
>index 0000000..ecb55c2
>--- /dev/null
>+++ b/drivers/video/lynxfb/ddk750_mode.c
>@@ -0,0 +1,213 @@
>+/*******************************************************************
>+*Copyright (c) 2012 by Silicon Motion, Inc. (SMI)
>+*Permission is hereby granted, free of charge, to any person obtaining a copy
>+*of this software and associated documentation files (the "Software"), to deal
>+*in the Software without restriction, including without limitation the rights to
>+*use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
>+*of the Software, and to permit persons to whom the Software is furnished to
>+*do so, subject to the following conditions:
>+*
>+*THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
>+*EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
>+*OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
>+*NONINFRINGEMENT.  IN NO EVENT SHALL Mill.Chen and Monk.Liu OR COPYRIGHT
>+*HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
>+*WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
>+*FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
>+*OTHER DEALINGS IN THE SOFTWARE.
>+*******************************************************************/
>+#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,
>+			(~(0x7FF << CRT_AUTO_CENTERING_TL_TOP_LSB))&
>+			(~(0x7FF << CRT_AUTO_CENTERING_TL_LEFT_LSB)));
>+
>+	/*clear*/
>+	POKE32(CRT_AUTO_CENTERING_BR,
>+			(~(0x7FF << CRT_AUTO_CENTERING_BR_BOTTOM_LSB))|
>+			(~(0x7FF << CRT_AUTO_CENTERING_BR_RIGHT_LSB)));
>+	POKE32(CRT_AUTO_CENTERING_BR,
>+			(y-1 << CRT_AUTO_CENTERING_BR_BOTTOM_LSB)|
>+			(x-1 << CRT_AUTO_CENTERING_BR_RIGHT_LSB));
>+	/* Clear bit 29:27 of display control register */
>+	dispControl &= ~(7 << CRT_DISPLAY_CTRL_CLK_LSB);
>+	/* Assume common fields in dispControl have been properly set before
>+	   calling this function.
>+	   This function only sets the extra fields in dispControl.
>+	   */
>+
>+
>+	/* Set bit 29:27 of display control register for the right clock */
>+	/* Note that SM750LE only need to supported 7 resoluitons. */
>+	dispControl &= (~(7 << CRT_DISPLAY_CTRL_CLK_LSB));
>+	if (x == 800 && y == 600)
>+		dispControl |= 1 << CRT_DISPLAY_CTRL_CLK_LSB;
>+	else if (x == 1024 && y == 768)
>+		dispControl |= 3 << CRT_DISPLAY_CTRL_CLK_LSB;
>+	else if (x == 1152 && y == 864)
>+		dispControl |= 5 << CRT_DISPLAY_CTRL_CLK_LSB;
>+	else if (x == 1280 && y == 768)
>+		dispControl |= 5 << CRT_DISPLAY_CTRL_CLK_LSB;
>+	else if (x == 1280 && y == 720)
>+		dispControl |= 4 << CRT_DISPLAY_CTRL_CLK_LSB;
>+	else if (x == 1280 && y == 960)
>+		dispControl |= 6 << CRT_DISPLAY_CTRL_CLK_LSB;
>+	else if (x == 1280 && y == 1024)
>+		dispControl |= 6 << CRT_DISPLAY_CTRL_CLK_LSB;
>+	else /* default to VGA clock */
>+		dispControl &= ~(7 << CRT_DISPLAY_CTRL_CLK_LSB);
>+
>+	/* Set bit 25:24 of display controller */
>+	dispControl |= 1 << CRT_DISPLAY_CTRL_CRTSELECT_LSB;
>+	dispControl &= ~(1 << CRT_DISPLAY_CTRL_RGBBIT_LSB);
>+
>+	/* Set bit 14 of display controller */
>+	dispControl |= 1 << CRT_DISPLAY_CTRL_CLOCK_PHASE_LSB;
>+	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,
>+			((pModeParam->horizontal_total - 1) << CRT_HORIZONTAL_TOTAL_TOTAL_LSB)
>+			|((pModeParam->horizontal_display_end - 1) << CRT_HORIZONTAL_TOTAL_DISPLAY_END_LSB));
>+
>+		POKE32(CRT_HORIZONTAL_SYNC,
>+			(pModeParam->horizontal_sync_width << CRT_HORIZONTAL_SYNC_WIDTH_LSB)
>+			|((pModeParam->horizontal_sync_start - 1) << CRT_HORIZONTAL_SYNC_START_LSB));
>+
>+		POKE32(CRT_VERTICAL_TOTAL,
>+				((pModeParam->vertical_total - 1) << CRT_VERTICAL_TOTAL_TOTAL_LSB)
>+				|((pModeParam->vertical_display_end - 1) << CRT_VERTICAL_TOTAL_DISPLAY_END_LSB));
>+		POKE32(CRT_VERTICAL_SYNC,
>+				(pModeParam->vertical_sync_height << CRT_VERTICAL_SYNC_HEIGHT_LSB)
>+				|((pModeParam->vertical_sync_start - 1) << CRT_VERTICAL_SYNC_START_LSB));
>+
>+
>+		ulTmpValue = (pModeParam->vertical_sync_polarity << CRT_DISPLAY_CTRL_VSYNC_PHASE_LSB)|
>+				(pModeParam->horizontal_sync_polarity << CRT_DISPLAY_CTRL_HSYNC_PHASE_LSB)|
>+				(1 << CRT_DISPLAY_CTRL_TIMING_LSB)|
>+				(1 << CRT_DISPLAY_CTRL_PLANE_LSB);
>+
>+		if (getChipType() == SM750LE) {
>+			displayControlAdjust_SM750LE(pModeParam, ulTmpValue);
>+		} else{
>+			ulReg = PEEK32(CRT_DISPLAY_CTRL)
>+				& (~(1 << CRT_DISPLAY_CTRL_VSYNC_PHASE_LSB))
>+				& (~(1 << CRT_DISPLAY_CTRL_HSYNC_PHASE_LSB))
>+				& (~(1 << CRT_DISPLAY_CTRL_TIMING_LSB))
>+				& (~(1 << CRT_DISPLAY_CTRL_PLANE_LSB));
>+			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,
>+				((pModeParam->horizontal_total - 1) << PANEL_HORIZONTAL_TOTAL_TOTAL_LSB)
>+				|((pModeParam->horizontal_display_end - 1) << PANEL_HORIZONTAL_TOTAL_DISPLAY_END_LSB));
>+
>+		POKE32(PANEL_HORIZONTAL_SYNC,
>+				(pModeParam->horizontal_sync_width << PANEL_HORIZONTAL_SYNC_WIDTH_LSB)
>+				|((pModeParam->horizontal_sync_start - 1) << PANEL_HORIZONTAL_SYNC_START_LSB));
>+
>+		POKE32(PANEL_VERTICAL_TOTAL,
>+				((pModeParam->vertical_total - 1) << PANEL_VERTICAL_TOTAL_TOTAL_LSB)
>+				|((pModeParam->vertical_display_end - 1) << PANEL_VERTICAL_TOTAL_DISPLAY_END_LSB));
>+
>+		POKE32(PANEL_VERTICAL_SYNC,
>+				(pModeParam->vertical_sync_height << PANEL_VERTICAL_SYNC_HEIGHT_LSB)
>+				|((pModeParam->vertical_sync_start - 1) << PANEL_VERTICAL_SYNC_START_LSB));
>+		ulTmpValue |= (pModeParam->vertical_sync_polarity << PANEL_DISPLAY_CTRL_VSYNC_PHASE_LSB)
>+				|(pModeParam->horizontal_sync_polarity << PANEL_DISPLAY_CTRL_HSYNC_PHASE_LSB)
>+				|(pModeParam->clock_phase_polarity << PANEL_DISPLAY_CTRL_CLOCK_PHASE_LSB)
>+				|(1 << PANEL_DISPLAY_CTRL_TIMING_LSB)
>+				|(1 << PANEL_DISPLAY_CTRL_PLANE_LSB);
>+		ulReservedBits = (3 <<  PANEL_DISPLAY_CTRL_RESERVED_1_MASK_LSB)|
>+				(15 << PANEL_DISPLAY_CTRL_RESERVED_2_MASK_LSB)|
>+				(1 << PANEL_DISPLAY_CTRL_RESERVED_3_MASK_LSB)|
>+				(1 << PANEL_DISPLAY_CTRL_VSYNC_LSB);
>+		ulReg = (PEEK32(PANEL_DISPLAY_CTRL) & ~ulReservedBits)
>+			& (~(1 << PANEL_DISPLAY_CTRL_CLOCK_PHASE_LSB))
>+			& (~(1 << PANEL_DISPLAY_CTRL_VSYNC_PHASE_LSB))
>+			& (~(1 << PANEL_DISPLAY_CTRL_HSYNC_PHASE_LSB))
>+			& (~(1 << PANEL_DISPLAY_CTRL_TIMING_LSB))
>+			& (~(1 << PANEL_DISPLAY_CTRL_PLANE_LSB));
>+
>+		/* 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);
>+
>+		while ((PEEK32(PANEL_DISPLAY_CTRL) & ~ulReservedBits) != (ulTmpValue|ulReg)) {
>+			cnt++;
>+			if (cnt > 1000)
>+				break;
>+			POKE32(PANEL_DISPLAY_CTRL, ulTmpValue|ulReg);
>+		}
>+
>+	} 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;
>+}
>+
>+
>diff --git a/drivers/video/lynxfb/ddk750_mode.h b/drivers/video/lynxfb/ddk750_mode.h
>new file mode 100644
>index 0000000..7c12b46
>--- /dev/null
>+++ b/drivers/video/lynxfb/ddk750_mode.h
>@@ -0,0 +1,59 @@
>+/*******************************************************************
>+*Copyright (c) 2012 by Silicon Motion, Inc. (SMI)
>+*Permission is hereby granted, free of charge, to any person obtaining a copy
>+*of this software and associated documentation files (the "Software"), to deal
>+*in the Software without restriction, including without limitation the rights to
>+*use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
>+*of the Software, and to permit persons to whom the Software is furnished to
>+*do so, subject to the following conditions:
>+*
>+*THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
>+*EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
>+*OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
>+*NONINFRINGEMENT.  IN NO EVENT SHALL Mill.Chen and Monk.Liu OR COPYRIGHT
>+*HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
>+*WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
>+*FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
>+*OTHER DEALINGS IN THE SOFTWARE.
>+*******************************************************************/
>+#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
>diff --git a/drivers/video/lynxfb/ddk750_power.c b/drivers/video/lynxfb/ddk750_power.c
>new file mode 100644
>index 0000000..ad4fbd1
>--- /dev/null
>+++ b/drivers/video/lynxfb/ddk750_power.c
>@@ -0,0 +1,243 @@
>+/*******************************************************************
>+*Copyright (c) 2012 by Silicon Motion, Inc. (SMI)
>+*Permission is hereby granted, free of charge, to any person obtaining a copy
>+*of this software and associated documentation files (the "Software"), to deal
>+*in the Software without restriction, including without limitation the rights to
>+*use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
>+*of the Software, and to permit persons to whom the Software is furnished to
>+*do so, subject to the following conditions:
>+*
>+*THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
>+*EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
>+*OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
>+*NONINFRINGEMENT.  IN NO EVENT SHALLMill.Chen and Monk.Liu OR COPYRIGHT
>+*HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
>+*WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
>+*FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
>+*OTHER DEALINGS IN THE SOFTWARE.
>+*******************************************************************/
>+#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);
>+		value &= (~(3 << CRT_DISPLAY_CTRL_DPMS_LSB));
>+		POKE32(CRT_DISPLAY_CTRL, value|(state << CRT_DISPLAY_CTRL_DPMS_LSB));
>+	} else{
>+		value = PEEK32(SYSTEM_CTRL);
>+		value &= (~(3 << SYSTEM_CTRL_DPMS_LSB));
>+		value |= state << SYSTEM_CTRL_DPMS_LSB;
>+		POKE32(SYSTEM_CTRL,  value);
>+	}
>+}
>+
>+unsigned int getPowerMode()
>+{
>+	if (getChipType() == SM750LE)
>+		return 0;
>+	return 2&(PEEK32(POWER_MODE_CTRL) >> POWER_MODE_CTRL_MODE_LSB);
>+}
>+
>+
>+/*
>+ * 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);
>+	control_value &= (~(3 << POWER_MODE_CTRL_MODE_LSB));
>+	if (getChipType() == SM750LE)
>+		return;
>+
>+	switch (powerMode) {
>+	case POWER_MODE_CTRL_MODE_MODE0:
>+		control_value &= (~(3 << POWER_MODE_CTRL_MODE_LSB));
>+		break;
>+	case POWER_MODE_CTRL_MODE_MODE1:
>+		control_value |= 1 << POWER_MODE_CTRL_MODE_LSB;
>+		break;
>+
>+	case POWER_MODE_CTRL_MODE_SLEEP:
>+		control_value |= 2 << POWER_MODE_CTRL_MODE_LSB;
>+		break;
>+
>+	default:
>+		break;
>+	}
>+
>+	/* Set up other fields in Power Control Register */
>+	if (powerMode == POWER_MODE_CTRL_MODE_SLEEP) {
>+		control_value &=
>+#ifdef VALIDATION_CHIP
>+			(~(1 << POWER_MODE_CTRL_336CLK_LSB))|
>+#endif
>+			(~(1 << POWER_MODE_CTRL_OSC_INPUT_LSB));
>+	} else{
>+		control_value |=
>+#ifdef VALIDATION_CHIP
>+			(1 << POWER_MODE_CTRL_336CLK_LSB)|
>+#endif
>+			(1 << POWER_MODE_CTRL_OSC_INPUT_LSB);
>+	}
>+
>+	/* 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 |= 1 << CURRENT_GATE_DE_LSB;
>+		gate |= 1 << CURRENT_GATE_CSC_LSB;
>+	} else{
>+		gate &= (~(1 << CURRENT_GATE_DE_LSB));
>+		gate &= (~(1 << CURRENT_GATE_CSC_LSB));
>+	}
>+	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 |= 1 << CURRENT_GATE_ZVPORT_LSB;
>+
>+		/* Using Software I2C */
>+		gate |= 1 << CURRENT_GATE_GPIO_LSB;
>+
>+	} 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 &= (~(1 << CURRENT_GATE_ZVPORT_LSB));
>+	}
>+
>+	setCurrentGate(gate);
>+}
>+
>+
>+void enableSSP(unsigned int enable)
>+{
>+	uint32_t gate;
>+
>+	/* Enable SSP Gate */
>+	gate = PEEK32(CURRENT_GATE);
>+	if (enable)
>+		gate |= 1 << CURRENT_GATE_SSP_LSB;
>+	else
>+		gate &= (~(1 <<  CURRENT_GATE_SSP_LSB));
>+
>+	setCurrentGate(gate);
>+}
>+
>+void enableDMA(unsigned int enable)
>+{
>+	uint32_t gate;
>+
>+	/* Enable DMA Gate */
>+	gate = PEEK32(CURRENT_GATE);
>+	if (enable)
>+		gate |= 1 << CURRENT_GATE_DMA_LSB;
>+	else
>+		gate &= (~(1 << CURRENT_GATE_DMA_LSB));
>+
>+	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 |= 1 << CURRENT_GATE_GPIO_LSB;
>+	else
>+		gate &= (~(1 << CURRENT_GATE_GPIO_LSB));
>+
>+	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 |= 1 << CURRENT_GATE_PWM_LSB;
>+	else
>+		gate &= (~(1 << CURRENT_GATE_PWM_LSB));
>+
>+	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 |= 1 << CURRENT_GATE_I2C_LSB;
>+	else
>+		gate &= (~(1 << CURRENT_GATE_I2C_LSB));
>+
>+	setCurrentGate(gate);
>+}
>+
>+
>diff --git a/drivers/video/lynxfb/ddk750_power.h b/drivers/video/lynxfb/ddk750_power.h
>new file mode 100644
>index 0000000..da65b00
>--- /dev/null
>+++ b/drivers/video/lynxfb/ddk750_power.h
>@@ -0,0 +1,85 @@
>+/*******************************************************************
>+*Copyright (c) 2012 by Silicon Motion, Inc. (SMI)
>+*Permission is hereby granted, free of charge, to any person obtaining a copy
>+*of this software and associated documentation files (the "Software"), to deal
>+*in the Software without restriction, including without limitation the rights to
>+*use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
>+*of the Software, and to permit persons to whom the Software is furnished to
>+*do so, subject to the following conditions:
>+*
>+*THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
>+*EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
>+*OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
>+*NONINFRINGEMENT.  IN NO EVENT SHALL Mill.Chen and Monk.Liu OR COPYRIGHT
>+*HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
>+*WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
>+*FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
>+*OTHER DEALINGS IN THE SOFTWARE.
>+*******************************************************************/
>+#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, PEEK32(MISC_CTRL)|(off << MISC_CTRL_DAC_POWER_LSB));	\
>+}
>+
>+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
>diff --git a/drivers/video/lynxfb/ddk750_reg.h b/drivers/video/lynxfb/ddk750_reg.h
>new file mode 100644
>index 0000000..e2560bf
>--- /dev/null
>+++ b/drivers/video/lynxfb/ddk750_reg.h
>@@ -0,0 +1,362 @@
>+/*******************************************************************
>+*Copyright (c) 2012 by Silicon Motion, Inc. (SMI)
>+*Permission is hereby granted, free of charge, to any person obtaining a copy
>+*of this software and associated documentation files (the "Software"), to deal
>+*in the Software without restriction, including without limitation the rights to
>+*use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
>+*of the Software, and to permit persons to whom the Software is furnished to
>+*do so, subject to the following conditions:
>+*
>+*THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
>+*EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
>+*OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
>+*NONINFRINGEMENT.  IN NO EVENT SHALL Mill.Chen and Monk.Liu OR COPYRIGHT
>+*HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
>+*WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
>+*FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
>+*OTHER DEALINGS IN THE SOFTWARE.
>+*******************************************************************/
>+#ifndef DDK750_REG_H__
>+#define DDK750_REG_H__
>+
>+/* New register for SM750LE */
>+#ifdef OPENSOURCE
>+#define MISC_CTRL                                     0x000004
>+#define MISC_CTRL_DAC_POWER_LSB                       20
>+#define MISC_CTRL_LOCALMEM_SIZE_LSB                   12
>+#define MISC_CTRL_LOCALMEM_SIZE_8M                    3
>+#define MISC_CTRL_LOCALMEM_SIZE_16M                   0
>+#define MISC_CTRL_LOCALMEM_SIZE_32M                   1
>+#define MISC_CTRL_LOCALMEM_SIZE_64M                   2
>+#define MISC_CTRL_LOCALMEM_RESET_LSB                  6
>+#define SYSTEM_CTRL                                   0x000000
>+#define SYSTEM_CTRL_DPMS_LSB                          30
>+#define SYSTEM_CTRL_DPMS_VPHP                         0
>+#define SYSTEM_CTRL_DPMS_VPHN                         1
>+#define SYSTEM_CTRL_DPMS_VNHP                         2
>+#define SYSTEM_CTRL_DPMS_VNHN                         3
>+#define SYSTEM_CTRL_PCI_BURST_LSB                     29
>+#define SYSTEM_CTRL_DE_FIFO_LSB                       23
>+#define SYSTEM_CTRL_DE_FIFO_NOTEMPTY                  0
>+#define SYSTEM_CTRL_DE_FIFO_EMPTY                     1
>+#define SYSTEM_CTRL_DE_STATUS_LSB                     22
>+#define SYSTEM_CTRL_DE_STATUS_IDLE                    0
>+#define SYSTEM_CTRL_DE_STATUS_BUSY                    1
>+#define SYSTEM_CTRL_DE_MEM_FIFO_LSB                   21
>+#define SYSTEM_CTRL_DE_MEM_FIFO_NOTEMPTY              0
>+#define SYSTEM_CTRL_DE_MEM_FIFO_EMPTY                 1
>+#define SYSTEM_CTRL_PANEL_VSYNC_LSB                   18
>+#define SYSTEM_CTRL_PANEL_VSYNC_INACTIVE              0
>+#define SYSTEM_CTRL_PANEL_VSYNC_ACTIVE                1
>+#define SYSTEM_CTRL_CRT_VSYNC_LSB                     19
>+#define SYSTEM_CTRL_CRT_VSYNC_INACTIVE                0
>+#define SYSTEM_CTRL_CRT_VSYNC_ACTIVE                  1
>+#define SYSTEM_CTRL_DE_ABORT_LSB                          13
>+
>+#define DE_STATE1                                        0x100054
>+#define DE_STATE1_DE_ABORT_LSB                               0
>+
>+#define DE_STATE2                                        0x100058
>+#define DE_STATE2_DE_FIFO_LSB                            3
>+#define DE_STATE2_DE_FIFO_NOTEMPTY                       0
>+#define DE_STATE2_DE_FIFO_EMPTY                          1
>+#define DE_STATE2_DE_STATUS_LSB                          2
>+#define DE_STATE2_DE_STATUS_IDLE                         0
>+#define DE_STATE2_DE_STATUS_BUSY                         1
>+#define DE_STATE2_DE_MEM_FIFO_LSB                        1
>+#define DE_STATE2_DE_MEM_FIFO_NOTEMPTY                   0
>+#define DE_STATE2_DE_MEM_FIFO_EMPTY                      1
>+#endif
>+
>+#ifdef OPENSOURCE
>+#define GPIO_MUX                                      0x000008
>+#define GPIO_MUX_31_LSB                                   31
>+#define GPIO_MUX_30_LSB                                   30
>+#endif
>+#define CURRENT_GATE                                  0x000040
>+#ifdef OPENSOURCE
>+#define CURRENT_GATE_M2XCLK_LSB                         12
>+#define CURRENT_GATE_MCLK_LSB                           14
>+#define CURRENT_GATE_PWM_LSB                            9
>+#define CURRENT_GATE_I2C_LSB                            8
>+#define CURRENT_GATE_SSP_LSB                            7
>+#define CURRENT_GATE_GPIO_LSB                           6
>+#define CURRENT_GATE_ZVPORT_LSB                         5
>+#define CURRENT_GATE_CSC_LSB                            4
>+#define CURRENT_GATE_DE_LSB                             3
>+#define MODE0_GATE                                    0x000044
>+#define CURRENT_GATE_DISPLAY_LSB                           2
>+#define CURRENT_GATE_LOCALMEM_LSB                          1
>+#define CURRENT_GATE_DMA_LSB                               0
>+#endif
>+#ifdef OPENSOURCE
>+#define MODE0_GATE                                    0x000044
>+#define MODE0_GATE_I2C_LSB                            8
>+#define MODE0_GATE_GPIO_LSB                           6
>+#endif
>+
>+
>+#ifdef OPENSOURCE
>+#define MODE1_GATE                                    0x000048
>+#define POWER_MODE_CTRL                               0x00004C
>+#define POWER_MODE_CTRL_MODE_LSB                          0
>+#define POWER_MODE_CTRL_MODE_MODE0                    0
>+#define POWER_MODE_CTRL_MODE_MODE1                    1
>+#define POWER_MODE_CTRL_MODE_SLEEP                    2
>+#ifdef VALIDATION_CHIP
>+    #define POWER_MODE_CTRL_336CLK_LSB                    4
>+#endif
>+#define POWER_MODE_CTRL_OSC_INPUT_LSB                     3
>+#endif
>+
>+#define PLL_CLK_COUNT                                 0x000058
>+
>+#ifdef OPENSOURCE
>+#define PANEL_PLL_CTRL                                0x00005C
>+#ifdef VALIDATION_CHIP
>+    #define PANEL_PLL_CTRL_OD_LSB                     14
>+#else
>+    #define PANEL_PLL_CTRL_POD_LSB                    14
>+    #define PANEL_PLL_CTRL_OD_LSB                     12
>+#endif
>+#define PANEL_PLL_CTRL_N_LSB                           8
>+#define PANEL_PLL_CTRL                                0x00005C
>+#define PANEL_PLL_CTRL_BYPASS_LSB                     18
>+#define PANEL_PLL_CTRL_POWER_LSB                      17
>+#define PANEL_PLL_CTRL_POWER_OFF                      0
>+#define PANEL_PLL_CTRL_POWER_ON                       1
>+#define PANEL_PLL_CTRL_INPUT_LSB                      16
>+#ifdef VALIDATION_CHIP
>+    #define PANEL_PLL_CTRL_OD_LSB                     14
>+#else
>+    #define PANEL_PLL_CTRL_POD_LSB                    14
>+    #define PANEL_PLL_CTRL_OD_LSB                     12
>+#endif
>+#define PANEL_PLL_CTRL_N_LSB                           8
>+#define PANEL_PLL_CTRL_M_LSB                           0
>+#define CRT_PLL_CTRL_POWER_LSB                        17
>+#define CRT_PLL_CTRL_POWER_OFF                        0
>+#define CRT_PLL_CTRL_POWER_ON                         1
>+#endif
>+#define MXCLK_PLL_CTRL                                0x000070
>+#define CRT_PLL_CTRL                                  0x000060
>+#define VGA_PLL0_CTRL                                 0x000064
>+#define VGA_PLL1_CTRL                                 0x000068
>+
>+#ifdef OPENSOURCE
>+#define VGA_CONFIGURATION                             0x000088
>+#define VGA_CONFIGURATION_PLL_LSB                         2
>+#define VGA_CONFIGURATION_MODE_LSB                        1
>+#endif
>+
>+#define GPIO_DATA                                       0x010000
>+#define GPIO_DATA_DIRECTION                             0x010004
>+
>+
>+#ifdef OPENSOURCE
>+#define PANEL_DISPLAY_CTRL                            0x080000
>+#define PANEL_DISPLAY_CTRL_RESERVED_1_MASK_LSB        30
>+#define PANEL_DISPLAY_CTRL_SELECT_LSB                 28
>+#define PANEL_DISPLAY_CTRL_RESERVED_2_MASK_LSB        20
>+#define PANEL_DISPLAY_CTRL_RESERVED_3_MASK_LSB        15
>+#define PANEL_DISPLAY_CTRL_FPEN_LSB                   27
>+#define PANEL_DISPLAY_CTRL_VBIASEN_LSB                26
>+#define PANEL_DISPLAY_CTRL_DATA_LSB                   25
>+#define PANEL_DISPLAY_CTRL_DATA_DISABLE               0
>+#define PANEL_DISPLAY_CTRL_DATA_ENABLE                1
>+#define PANEL_DISPLAY_CTRL_TFT_DISP_LSB		      18
>+#define PANEL_DISPLAY_CTRL_TIMING_LSB                 8
>+#define PANEL_DISPLAY_CTRL_TIMING_DISABLE             0
>+#define PANEL_DISPLAY_CTRL_TIMING_ENABLE              1
>+#define PANEL_DISPLAY_CTRL_CLOCK_PHASE_LSB            14
>+#define PANEL_DISPLAY_CTRL_VSYNC_PHASE_LSB            13
>+#define PANEL_DISPLAY_CTRL_HSYNC_PHASE_LSB            12
>+#define PANEL_DISPLAY_CTRL_VSYNC_LSB                  11
>+#define PANEL_DISPLAY_CTRL_PLANE_LSB                  2
>+#define PANEL_DISPLAY_CTRL_FORMAT_LSB                 0
>+#endif
>+
>+
>+#ifdef OPENSOURCE
>+#define PANEL_FB_ADDRESS                             0x08000C
>+#define PANEL_FB_ADDRESS_STATUS_LSB                  31
>+#define PANEL_FB_ADDRESS_EXT_LSB                     27
>+#define PANEL_FB_ADDRESS_ADDRESS_LSB                 0
>+
>+#define PANEL_FB_WIDTH                                0x080010
>+#define PANEL_FB_WIDTH_WIDTH_LSB                      16
>+#define PANEL_FB_WIDTH_OFFSET_LSB                     0
>+
>+#define PANEL_WINDOW_WIDTH                            0x080014
>+#define PANEL_WINDOW_WIDTH_WIDTH_LSB                  16
>+#define PANEL_WINDOW_WIDTH_X_LSB                      0
>+
>+#define PANEL_WINDOW_HEIGHT                           0x080018
>+#define PANEL_WINDOW_HEIGHT_HEIGHT_LSB                16
>+#define PANEL_WINDOW_HEIGHT_Y_LSB                     0
>+
>+#define PANEL_PLANE_TL                                0x08001C
>+#define PANEL_PLANE_TL_TOP_LSB                        16
>+#define PANEL_PLANE_TL_LEFT_LSB                       0
>+
>+#define PANEL_PLANE_BR                                0x080020
>+#define PANEL_PLANE_BR_BOTTOM_LSB                     16
>+#define PANEL_PLANE_BR_RIGHT_LSB                      0
>+#endif
>+
>+
>+#ifdef OPENSOURCE
>+#define PANEL_HORIZONTAL_TOTAL                        0x080024
>+#define PANEL_HORIZONTAL_TOTAL_TOTAL_LSB                  16
>+#define PANEL_HORIZONTAL_TOTAL_DISPLAY_END_LSB            0
>+#define PANEL_HORIZONTAL_SYNC                         0x080028
>+#define PANEL_HORIZONTAL_SYNC_WIDTH_LSB                   16
>+#define PANEL_HORIZONTAL_SYNC_START_LSB                   0
>+#define PANEL_VERTICAL_TOTAL                          0x08002C
>+#define PANEL_VERTICAL_TOTAL_TOTAL_LSB                    16
>+#define PANEL_VERTICAL_TOTAL_DISPLAY_END_LSB              0
>+#define PANEL_VERTICAL_SYNC                           0x080030
>+#define PANEL_VERTICAL_SYNC_HEIGHT_LSB                    16
>+#define PANEL_VERTICAL_SYNC_START_LSB                     0
>+#endif
>+
>+
>+/* Video Control */
>+#ifdef OPENSOURCE
>+#define VIDEO_DISPLAY_CTRL                              0x080040
>+#define VIDEO_DISPLAY_CTRL_PLANE_LSB                    2
>+#endif
>+/* Alpha Control */
>+#ifdef OPENSOURCE
>+#define ALPHA_DISPLAY_CTRL                            0x080100
>+#define ALPHA_DISPLAY_CTRL_PLANE_LSB                      2
>+#endif
>+
>+/* Video Alpha Control */
>+#ifdef OPENSOURCE
>+#define VIDEO_ALPHA_DISPLAY_CTRL                        0x080080
>+#define VIDEO_ALPHA_DISPLAY_CTRL_PLANE_LSB              2
>+#endif
>+
>+/* CRT Graphics Control */
>+#ifdef OPENSOURCE
>+#define CRT_DISPLAY_CTRL                              0x080200
>+#define CRT_DISPLAY_CTRL_TIMING_LSB                   8
>+#define CRT_DISPLAY_CTRL_TIMING_DISABLE               0
>+#define CRT_DISPLAY_CTRL_TIMING_ENABLE                1
>+#define CRT_DISPLAY_CTRL_PLANE_LSB                    2
>+#define CRT_DISPLAY_CTRL_CLK_LSB                         27
>+#define CRT_DISPLAY_CTRL_RESERVED_1_MASK_LSB	      27
>+#define CRT_DISPLAY_CTRL_RESERVED_2_MASK_LSB 	      24
>+#define CRT_DISPLAY_CTRL_SELECT_LSB                   18
>+#define CRT_DISPLAY_CTRL_RESERVED_3_MASK_LSB 	      15
>+#define CRT_DISPLAY_CTRL_CLOCK_PHASE_LSB              14
>+#define CRT_DISPLAY_CTRL_BLANK_LSB                    10
>+#define CRT_DISPLAY_CTRL_BLANK_OFF                    0
>+#define CRT_DISPLAY_CTRL_BLANK_ON                     1
>+#define CRT_DISPLAY_CTRL_RESERVED_4_MASK_LSB 	       9
>+/* SM750LE definition */
>+#define CRT_DISPLAY_CTRL_DPMS_LSB                      30
>+#define CRT_DISPLAY_CTRL_DPMS_0                       0
>+#define CRT_DISPLAY_CTRL_DPMS_1                       1
>+#define CRT_DISPLAY_CTRL_DPMS_2                       2
>+#define CRT_DISPLAY_CTRL_DPMS_3                       3
>+#define CRT_DISPLAY_CTRL_CLK_LSB                       27
>+#define CRT_DISPLAY_CTRL_CRTSELECT_LSB                 25
>+#define CRT_DISPLAY_CTRL_RGBBIT_LSB                    24
>+#define CRT_DISPLAY_CTRL_VSYNC_PHASE_LSB               13
>+#define CRT_DISPLAY_CTRL_HSYNC_PHASE_LSB               12
>+#define CRT_DISPLAY_CTRL_FORMAT_LSB                    0
>+#endif
>+
>+
>+#ifdef OPENSOURCE
>+#define CRT_FB_ADDRESS                                0x080204
>+#define CRT_FB_ADDRESS_STATUS_LSB                     31
>+#define CRT_FB_ADDRESS_STATUS_CURRENT                 0
>+#define CRT_FB_ADDRESS_STATUS_PENDING                 1
>+#define CRT_FB_ADDRESS_EXT_LSB                        27
>+#define CRT_FB_ADDRESS_EXT_LOCAL                      0
>+#define CRT_FB_ADDRESS_EXT_EXTERNAL                   1
>+#define CRT_FB_ADDRESS_ADDRESS_LSB                    0
>+#endif
>+
>+
>+#ifdef OPENSOURCE
>+#define CRT_FB_WIDTH                                  0x080208
>+#define CRT_FB_WIDTH_WIDTH_LSB                        16
>+#define CRT_FB_WIDTH_OFFSET_LSB                       0
>+#endif
>+
>+#ifdef OPENSOURCE
>+#define CRT_HORIZONTAL_TOTAL                          0x08020C
>+#define CRT_HORIZONTAL_TOTAL_TOTAL_LSB                16
>+#define CRT_HORIZONTAL_TOTAL_DISPLAY_END_LSB          0
>+#define CRT_HORIZONTAL_SYNC                           0x080210
>+#define CRT_HORIZONTAL_SYNC_WIDTH_LSB                 16
>+#define CRT_HORIZONTAL_SYNC_START_LSB                 0
>+#define CRT_VERTICAL_TOTAL                            0x080214
>+#define CRT_VERTICAL_TOTAL_TOTAL_LSB                  16
>+#define CRT_VERTICAL_TOTAL_DISPLAY_END_LSB            0
>+#define CRT_VERTICAL_SYNC                             0x080218
>+#define CRT_VERTICAL_SYNC_HEIGHT_LSB                  16
>+#define CRT_VERTICAL_SYNC_START_LSB                   0
>+#endif
>+
>+
>+#ifndef VALIDATION_CHIP
>+    /* Auto Centering */
>+#ifdef OPENSOURCE
>+    #define CRT_AUTO_CENTERING_TL                     0x080280
>+    #define CRT_AUTO_CENTERING_TL_TOP_LSB             16
>+    #define CRT_AUTO_CENTERING_TL_LEFT_LSB            0
>+    #define CRT_AUTO_CENTERING_BR                     0x080284
>+    #define CRT_AUTO_CENTERING_BR_BOTTOM_LSB              16
>+    #define CRT_AUTO_CENTERING_BR_RIGHT_LSB               0
>+#endif
>+#endif
>+
>+/* sm750le new register to control panel output */
>+#define DISPLAY_CONTROL_750LE 	0x80288
>+/* Palette RAM */
>+
>+/* Panel Pallete register starts at 0x080400 ~ 0x0807FC */
>+#define PANEL_PALETTE_RAM                             0x080400
>+
>+/* Panel Pallete register starts at 0x080C00 ~ 0x080FFC */
>+#define CRT_PALETTE_RAM                               0x080C00
>+
>+/* 2D registers
>+ * move their defination into general lynx_accel.h file
>+ * because all smi graphic chip share the same drawing engine
>+ * register format */
>+
>+#ifdef OPENSOURCE
>+#define I2C_CTRL                                        0x010041
>+#define I2C_CTRL_MODE_LSB                               1
>+#define I2C_CTRL_EN_LSB                                 0
>+#define I2C_STATUS                                      0x010042
>+#define I2C_STATUS_TX_LSB                               3
>+#define I2C_CTRL_CTRL_LSB                               2
>+#define I2C_STATUS_TX_COMPLETED                         1
>+#define I2C_SLAVE_ADDRESS                               0x010043
>+#define I2C_RESET                                       0x010042
>+#define I2C_SLAVE_ADDRESS                               0x010043
>+#define I2C_DATA0                                       0x010044
>+#define I2C_BYTE_COUNT                                  0x010040
>+#endif
>+
>+#ifdef OPENSOURCE
>+#define DMA_ABORT_INTERRUPT                             0x0D0020
>+#define DMA_ABORT_INTERRUPT_ABORT_1_LSB                     5
>+#endif
>+
>+
>+
>+/* Default i2c CLK and Data GPIO. These are the default i2c pins */
>+#define DEFAULT_I2C_SCL                     30
>+#define DEFAULT_I2C_SDA                     31
>+
>+#define GPIO_DATA_SM750LE                               0x020018
>+#define GPIO_DATA_DIRECTION_SM750LE                     0x02001C
>+#endif
>diff --git a/drivers/video/lynxfb/ddk750_sii164.c b/drivers/video/lynxfb/ddk750_sii164.c
>new file mode 100644
>index 0000000..6915939
>--- /dev/null
>+++ b/drivers/video/lynxfb/ddk750_sii164.c
>@@ -0,0 +1,435 @@
>+/*******************************************************************
>+*Copyright (c) 2012 by Silicon Motion, Inc. (SMI)
>+*Permission is hereby granted, free of charge, to any person obtaining a copy
>+*of this software and associated documentation files (the "Software"), to deal
>+*in the Software without restriction, including without limitation the rights to
>+*use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
>+*of the Software, and to permit persons to whom the Software is furnished to
>+*do so, subject to the following conditions:
>+*
>+*THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
>+*EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
>+*OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
>+*NONINFRINGEMENT.  IN NO EVENT SHALL Mill.Chen and Monk.Liu OR COPYRIGHT
>+*HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
>+*WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
>+*FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
>+*OTHER DEALINGS IN THE SOFTWARE.
>+*******************************************************************/
>+#ifdef USE_DVICHIP
>+
>+#include "ddk750_sii164.h"
>+#include "ddk750_hwi2c.h"
>+
>+/* I2C Address of each SII164 chip */
>+#define SII164_I2C_ADDRESS                  0x70
>+
>+/* Define this definition to use hardware i2c. */
>+/*#define USE_HW_I2C*/
>+#ifdef USE_HW_I2C
>+#define i2cWriteReg hwI2CWriteReg
>+#define i2cReadReg  hwI2CReadReg
>+#else
>+#define i2cWriteReg swI2CWriteReg
>+#define i2cReadReg  swI2CReadReg
>+#endif
>+
>+/* SII164 Vendor and Device ID */
>+#define SII164_VENDOR_ID                    0x0001
>+#define SII164_DEVICE_ID                    0x0006
>+
>+#ifdef SII164_FULL_FUNCTIONS
>+/* Name of the DVI Controller chip */
>+static char *gDviCtrlChipName = "Silicon Image SiI 164";
>+#endif
>+
>+/*
>+ *  sii164GetVendorID
>+ *      This function gets the vendor ID of the DVI controller chip.
>+ *
>+ *  Output:
>+ *      Vendor ID
>+ */
>+unsigned short sii164GetVendorID()
>+{
>+	unsigned short vendorID;
>+
>+	vendorID = ((unsigned short) i2cReadReg(SII164_I2C_ADDRESS, SII164_VENDOR_ID_HIGH) << 8) |
>+		(unsigned short) i2cReadReg(SII164_I2C_ADDRESS, SII164_VENDOR_ID_LOW);
>+
>+	return vendorID;
>+}
>+
>+/*
>+ *  sii164GetDeviceID
>+ *      This function gets the device ID of the DVI controller chip.
>+ *
>+ *  Output:
>+ *      Device ID
>+ */
>+unsigned short sii164GetDeviceID()
>+{
>+	unsigned short deviceID;
>+
>+	deviceID = ((unsigned short) i2cReadReg(SII164_I2C_ADDRESS, SII164_DEVICE_ID_HIGH) << 8) |
>+		(unsigned short) i2cReadReg(SII164_I2C_ADDRESS, SII164_DEVICE_ID_LOW);
>+
>+	return deviceID;
>+}
>+
>+
>+
>+/* DVI.C will handle all SiI164 chip stuffs and try it best to make code minimal and useful */
>+
>+/*
>+ *  sii164InitChip
>+ *      This function initialize and detect the DVI controller chip.
>+ *
>+ *  Input:
>+ *      edgeSelect          - Edge Select:
>+ *                              0 = Input data is falling edge latched (falling edge
>+ *                                  latched first in dual edge mode)
>+ *                              1 = Input data is rising edge latched (rising edge
>+ *                                  latched first in dual edge mode)
>+ *      busSelect           - Input Bus Select:
>+ *                              0 = Input data bus is 12-bits wide
>+ *                              1 = Input data bus is 24-bits wide
>+ *      dualEdgeClkSelect   - Dual Edge Clock Select
>+ *                              0 = Input data is single edge latched
>+ *                              1 = Input data is dual edge latched
>+ *      hsyncEnable         - Horizontal Sync Enable:
>+ *                              0 = HSYNC input is transmitted as fixed LOW
>+ *                              1 = HSYNC input is transmitted as is
>+ *      vsyncEnable         - Vertical Sync Enable:
>+ *                              0 = VSYNC input is transmitted as fixed LOW
>+ *                              1 = VSYNC input is transmitted as is
>+ *      deskewEnable        - De-skewing Enable:
>+ *                              0 = De-skew disabled
>+ *                              1 = De-skew enabled
>+ *      deskewSetting       - De-skewing Setting (increment of 260psec)
>+ *                              0 = 1 step --> minimum setup / maximum hold
>+ *                              1 = 2 step
>+ *                              2 = 3 step
>+ *                              3 = 4 step
>+ *                              4 = 5 step
>+ *                              5 = 6 step
>+ *                              6 = 7 step
>+ *                              7 = 8 step --> maximum setup / minimum hold
>+ *      continuousSyncEnable- SYNC Continuous:
>+ *                              0 = Disable
>+ *                              1 = Enable
>+ *      pllFilterEnable     - PLL Filter Enable
>+ *                              0 = Disable PLL Filter
>+ *                              1 = Enable PLL Filter
>+ *      pllFilterValue      - PLL Filter characteristics:
>+ *                              0~7 (recommended value is 4)
>+ *
>+ *  Output:
>+ *      0   - Success
>+ *     -1   - Fail.
>+ */
>+long sii164InitChip(
>+		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 char ucRegIndex, ucRegValue;
>+	unsigned char ucDeviceAddress, */
>+	unsigned char config;
>+	/* unsigned long delayCount; */
>+
>+	/* Initialize the i2c bus */
>+#ifdef USE_HW_I2C
>+	/* Use fast mode. */
>+	hwI2CInit(1);
>+#else
>+	swI2CInit(DEFAULT_I2C_SCL, DEFAULT_I2C_SDA);
>+#endif
>+
>+	/* Check if SII164 Chip exists */
>+	if ((sii164GetVendorID() == SII164_VENDOR_ID) && (sii164GetDeviceID() == SII164_DEVICE_ID)) {
>+
>+#ifdef DDKDEBUG
>+		/* sii164PrintRegisterValues(); */
>+#endif
>+		/*
>+		 *  Initialize SII164 controller chip.
>+		 */
>+
>+		/* Select the edge */
>+		if (edgeSelect == 0)
>+			config = SII164_CONFIGURATION_LATCH_FALLING;
>+		else
>+			config = SII164_CONFIGURATION_LATCH_RISING;
>+
>+		/* Select bus wide */
>+		if (busSelect == 0)
>+			config |= SII164_CONFIGURATION_BUS_12BITS;
>+		else
>+			config |= SII164_CONFIGURATION_BUS_24BITS;
>+
>+		/* Select Dual/Single Edge Clock */
>+		if (dualEdgeClkSelect == 0)
>+			config |= SII164_CONFIGURATION_CLOCK_SINGLE;
>+		else
>+			config |= SII164_CONFIGURATION_CLOCK_DUAL;
>+
>+		/* Select HSync Enable */
>+		if (hsyncEnable == 0)
>+			config |= SII164_CONFIGURATION_HSYNC_FORCE_LOW;
>+		else
>+			config |= SII164_CONFIGURATION_HSYNC_AS_IS;
>+
>+		/* Select VSync Enable */
>+		if (vsyncEnable == 0)
>+			config |= SII164_CONFIGURATION_VSYNC_FORCE_LOW;
>+		else
>+			config |= SII164_CONFIGURATION_VSYNC_AS_IS;
>+
>+		i2cWriteReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION, config);
>+
>+		/* 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 (deskewEnable == 0)
>+			config = SII164_DESKEW_DISABLE;
>+		else
>+			config = SII164_DESKEW_ENABLE;
>+
>+		switch (deskewSetting) {
>+		case 0:
>+			config |= SII164_DESKEW_1_STEP;
>+			break;
>+		case 1:
>+			config |= SII164_DESKEW_2_STEP;
>+			break;
>+		case 2:
>+			config |= SII164_DESKEW_3_STEP;
>+			break;
>+		case 3:
>+			config |= SII164_DESKEW_4_STEP;
>+			break;
>+		case 4:
>+			config |= SII164_DESKEW_5_STEP;
>+			break;
>+		case 5:
>+			config |= SII164_DESKEW_6_STEP;
>+			break;
>+		case 6:
>+			config |= SII164_DESKEW_7_STEP;
>+			break;
>+		case 7:
>+			config |= SII164_DESKEW_8_STEP;
>+			break;
>+		}
>+		i2cWriteReg(SII164_I2C_ADDRESS, SII164_DESKEW, config);
>+
>+		/* Enable/Disable Continuous Sync. */
>+		if (continuousSyncEnable == 0)
>+			config = SII164_PLL_FILTER_SYNC_CONTINUOUS_DISABLE;
>+		else
>+			config = SII164_PLL_FILTER_SYNC_CONTINUOUS_ENABLE;
>+
>+		/* Enable/Disable PLL Filter */
>+		if (pllFilterEnable == 0)
>+			config |= SII164_PLL_FILTER_DISABLE;
>+		else
>+			config |= SII164_PLL_FILTER_ENABLE;
>+
>+		/* Set the PLL Filter value */
>+		config |= ((pllFilterValue & 0x07) << 1);
>+
>+		i2cWriteReg(SII164_I2C_ADDRESS, SII164_PLL, config);
>+
>+		/* Recover from Power Down and enable output. */
>+		config = i2cReadReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION);
>+		config |= SII164_CONFIGURATION_POWER_NORMAL;
>+		i2cWriteReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION, config);
>+
>+#ifdef DDKDEBUG
>+		/* sii164PrintRegisterValues(); */
>+#endif
>+
>+		return 0;
>+	}
>+
>+	/* Return -1 if initialization fails. */
>+	return -1;
>+}
>+
>+
>+
>+
>+
>+/* below sii164 function is not neccessary */
>+
>+#ifdef SII164_FULL_FUNCTIONS
>+
>+/*
>+ *  sii164ResetChip
>+ *      This function resets the DVI Controller Chip.
>+ */
>+void sii164ResetChip()
>+{
>+	/* Power down */
>+	sii164SetPower(0);
>+	sii164SetPower(1);
>+}
>+
>+
>+/*
>+ * sii164GetChipString
>+ *      This function returns a char string name of the current DVI Controller chip.
>+ *      It's convenient for application need to display the chip name.
>+ */
>+char *sii164GetChipString()
>+{
>+	return gDviCtrlChipName;
>+}
>+
>+
>+/*
>+ *  sii164SetPower
>+ *      This function sets the power configuration of the DVI Controller Chip.
>+ *
>+ *  Input:
>+ *      powerUp - Flag to set the power down or up
>+ */
>+void sii164SetPower(
>+		unsigned char powerUp
>+		)
>+{
>+	unsigned char config;
>+
>+	config = i2cReadReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION);
>+	if (powerUp == 1) {
>+		/* Power up the chip */
>+		config &= ~SII164_CONFIGURATION_POWER_MASK;
>+		config |= SII164_CONFIGURATION_POWER_NORMAL;
>+		i2cWriteReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION, config);
>+	} else{
>+		/* Power down the chip */
>+		config &= ~SII164_CONFIGURATION_POWER_MASK;
>+		config |= SII164_CONFIGURATION_POWER_DOWN;
>+		i2cWriteReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION, config);
>+	}
>+}
>+
>+
>+/*
>+ *  sii164SelectHotPlugDetectionMode
>+ *      This function selects the mode of the hot plug detection.
>+ */
>+static void sii164SelectHotPlugDetectionMode(
>+		sii164_hot_plug_mode_t hotPlugMode
>+		)
>+{
>+	unsigned char detectReg;
>+
>+	detectReg = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT) & ~SII164_DETECT_MONITOR_SENSE_OUTPUT_FLAG;
>+	switch (hotPlugMode) {
>+	case SII164_HOTPLUG_DISABLE:
>+		detectReg |= SII164_DETECT_MONITOR_SENSE_OUTPUT_HIGH;
>+		break;
>+	case SII164_HOTPLUG_USE_MDI:
>+		detectReg &= ~SII164_DETECT_INTERRUPT_MASK;
>+		detectReg |= SII164_DETECT_INTERRUPT_BY_HTPLG_PIN;
>+		detectReg |= SII164_DETECT_MONITOR_SENSE_OUTPUT_MDI;
>+		break;
>+	case SII164_HOTPLUG_USE_RSEN:
>+		detectReg |= SII164_DETECT_MONITOR_SENSE_OUTPUT_RSEN;
>+		break;
>+	case SII164_HOTPLUG_USE_HTPLG:
>+		detectReg |= SII164_DETECT_MONITOR_SENSE_OUTPUT_HTPLG;
>+		break;
>+	}
>+
>+	i2cWriteReg(SII164_I2C_ADDRESS, SII164_DETECT, detectReg);
>+}
>+
>+/*
>+ *  sii164EnableHotPlugDetection
>+ *      This function enables the Hot Plug detection.
>+ *
>+ *  enableHotPlug   - Enable (=1) / disable (=0) Hot Plug detection
>+ */
>+void sii164EnableHotPlugDetection(
>+		unsigned char enableHotPlug
>+		)
>+{
>+	unsigned char detectReg;
>+	detectReg = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT);
>+
>+	/* Depending on each DVI controller, need to enable the hot plug based on each
>+	   individual chip design. */
>+	if (enableHotPlug != 0)
>+		sii164SelectHotPlugDetectionMode(SII164_HOTPLUG_USE_MDI);
>+	else
>+		sii164SelectHotPlugDetectionMode(SII164_HOTPLUG_DISABLE);
>+}
>+
>+/*
>+ *  sii164IsConnected
>+ *      Check if the DVI Monitor is connected.
>+ *
>+ *  Output:
>+ *      0   - Not Connected
>+ *      1   - Connected
>+ */
>+unsigned char sii164IsConnected()
>+{
>+	unsigned char hotPlugValue;
>+
>+	hotPlugValue = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT) & SII164_DETECT_HOT_PLUG_STATUS_MASK;
>+	if (hotPlugValue == SII164_DETECT_HOT_PLUG_STATUS_ON)
>+		return 1;
>+	else
>+		return 0;
>+}
>+
>+/*
>+ *  sii164CheckInterrupt
>+ *      Checks if interrupt has occured.
>+ *
>+ *  Output:
>+ *      0   - No interrupt
>+ *      1   - Interrupt occurs
>+ */
>+unsigned char sii164CheckInterrupt()
>+{
>+	unsigned char detectReg;
>+
>+	detectReg = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT) & SII164_DETECT_MONITOR_STATE_MASK;
>+	if (detectReg == SII164_DETECT_MONITOR_STATE_CHANGE)
>+		return 1;
>+	else
>+		return 0;
>+}
>+
>+/*
>+ *  sii164ClearInterrupt
>+ *      Clear the hot plug interrupt.
>+ */
>+void sii164ClearInterrupt()
>+{
>+	unsigned char detectReg;
>+
>+	/* Clear the MDI interrupt */
>+	detectReg = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT);
>+	i2cWriteReg(SII164_I2C_ADDRESS, SII164_DETECT, detectReg | SII164_DETECT_MONITOR_STATE_CLEAR);
>+}
>+
>+#endif
>+
>+#endif
>+
>+
>diff --git a/drivers/video/lynxfb/ddk750_sii164.h b/drivers/video/lynxfb/ddk750_sii164.h
>new file mode 100644
>index 0000000..a279286
>--- /dev/null
>+++ b/drivers/video/lynxfb/ddk750_sii164.h
>@@ -0,0 +1,187 @@
>+/*******************************************************************
>+*Copyright (c) 2012 by Silicon Motion, Inc. (SMI)
>+*Permission is hereby granted, free of charge, to any person obtaining a copy
>+*of this software and associated documentation files (the "Software"), to deal
>+*in the Software without restriction, including without limitation the rights to
>+*use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
>+*of the Software, and to permit persons to whom the Software is furnished to
>+*do so, subject to the following conditions:
>+*
>+*THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
>+*EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
>+*OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
>+*NONINFRINGEMENT.  IN NO EVENT SHALL Mill.Chen and Monk.Liu OR COPYRIGHT
>+*HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
>+*WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
>+*FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
>+*OTHER DEALINGS IN THE SOFTWARE.
>+*******************************************************************/
>+#ifndef DDK750_SII164_H__
>+#define DDK750_SII164_H__
>+
>+/* Hot Plug detection mode structure */
>+typedef enum _sii164_hot_plug_mode_t{
>+    SII164_HOTPLUG_DISABLE = 0,         /* Disable Hot Plug output bit (always high). */
>+    SII164_HOTPLUG_USE_MDI,             /* Use Monitor Detect Interrupt bit. */
>+    SII164_HOTPLUG_USE_RSEN,            /* Use Receiver Sense detect bit. */
>+    SII164_HOTPLUG_USE_HTPLG            /* Use Hot Plug detect bit. */
>+} sii164_hot_plug_mode_t;
>+
>+
>+/* Silicon Image SiI164 chip prototype */
>+long sii164InitChip(
>+    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 sii164GetVendorID(void);
>+unsigned short sii164GetDeviceID(void);
>+
>+
>+#ifdef SII164_FULL_FUNCTIONS
>+void sii164ResetChip(void);
>+char *sii164GetChipString(void);
>+void sii164SetPower(unsigned char powerUp);
>+void sii164EnableHotPlugDetection(unsigned char enableHotPlug);
>+unsigned char sii164IsConnected(void);
>+unsigned char sii164CheckInterrupt(void);
>+void sii164ClearInterrupt(void);
>+#endif
>+/* below register definination is used for Silicon Image SiI164 DVI controller chip */
>+/*
>+ * Vendor ID registers
>+ */
>+#define SII164_VENDOR_ID_LOW                        0x00
>+#define SII164_VENDOR_ID_HIGH                       0x01
>+
>+/*
>+ * Device ID registers
>+ */
>+#define SII164_DEVICE_ID_LOW                        0x02
>+#define SII164_DEVICE_ID_HIGH                       0x03
>+
>+/*
>+ * Device Revision
>+ */
>+#define SII164_DEVICE_REVISION                      0x04
>+
>+/*
>+ * Frequency Limitation registers
>+ */
>+#define SII164_FREQUENCY_LIMIT_LOW                  0x06
>+#define SII164_FREQUENCY_LIMIT_HIGH                 0x07
>+
>+/*
>+ * Power Down and Input Signal Configuration registers
>+ */
>+#define SII164_CONFIGURATION                        0x08
>+
>+/* Power down (PD) */
>+#define SII164_CONFIGURATION_POWER_DOWN             0x00
>+#define SII164_CONFIGURATION_POWER_NORMAL           0x01
>+#define SII164_CONFIGURATION_POWER_MASK             0x01
>+
>+/* Input Edge Latch Select (EDGE) */
>+#define SII164_CONFIGURATION_LATCH_FALLING          0x00
>+#define SII164_CONFIGURATION_LATCH_RISING           0x02
>+
>+/* Bus Select (BSEL) */
>+#define SII164_CONFIGURATION_BUS_12BITS             0x00
>+#define SII164_CONFIGURATION_BUS_24BITS             0x04
>+
>+/* Dual Edge Clock Select (DSEL) */
>+#define SII164_CONFIGURATION_CLOCK_SINGLE           0x00
>+#define SII164_CONFIGURATION_CLOCK_DUAL             0x08
>+
>+/* Horizontal Sync Enable (HEN) */
>+#define SII164_CONFIGURATION_HSYNC_FORCE_LOW        0x00
>+#define SII164_CONFIGURATION_HSYNC_AS_IS            0x10
>+
>+/* Vertical Sync Enable (VEN) */
>+#define SII164_CONFIGURATION_VSYNC_FORCE_LOW        0x00
>+#define SII164_CONFIGURATION_VSYNC_AS_IS            0x20
>+
>+/*
>+ * Detection registers
>+ */
>+#define SII164_DETECT                               0x09
>+
>+/* Monitor Detect Interrupt (MDI) */
>+#define SII164_DETECT_MONITOR_STATE_CHANGE          0x00
>+#define SII164_DETECT_MONITOR_STATE_NO_CHANGE       0x01
>+#define SII164_DETECT_MONITOR_STATE_CLEAR           0x01
>+#define SII164_DETECT_MONITOR_STATE_MASK            0x01
>+
>+/* Hot Plug detect Input (HTPLG) */
>+#define SII164_DETECT_HOT_PLUG_STATUS_OFF           0x00
>+#define SII164_DETECT_HOT_PLUG_STATUS_ON            0x02
>+#define SII164_DETECT_HOT_PLUG_STATUS_MASK          0x02
>+
>+/* Receiver Sense (RSEN) */
>+#define SII164_DETECT_RECEIVER_SENSE_NOT_DETECTED   0x00
>+#define SII164_DETECT_RECEIVER_SENSE_DETECTED       0x04
>+
>+/* Interrupt Generation Method (TSEL) */
>+#define SII164_DETECT_INTERRUPT_BY_RSEN_PIN         0x00
>+#define SII164_DETECT_INTERRUPT_BY_HTPLG_PIN        0x08
>+#define SII164_DETECT_INTERRUPT_MASK                0x08
>+
>+/* Monitor Sense Output (MSEN) */
>+#define SII164_DETECT_MONITOR_SENSE_OUTPUT_HIGH     0x00
>+#define SII164_DETECT_MONITOR_SENSE_OUTPUT_MDI      0x10
>+#define SII164_DETECT_MONITOR_SENSE_OUTPUT_RSEN     0x20
>+#define SII164_DETECT_MONITOR_SENSE_OUTPUT_HTPLG    0x30
>+#define SII164_DETECT_MONITOR_SENSE_OUTPUT_FLAG     0x30
>+
>+/*
>+ * Skewing registers
>+ */
>+#define SII164_DESKEW                               0x0A
>+
>+/* General Purpose Input (CTL[3:1]) */
>+#define SII164_DESKEW_GENERAL_PURPOSE_INPUT_MASK    0x0E
>+
>+/* De-skewing Enable bit (DKEN) */
>+#define SII164_DESKEW_DISABLE                       0x00
>+#define SII164_DESKEW_ENABLE                        0x10
>+
>+/* De-skewing Setting (DK[3:1])*/
>+#define SII164_DESKEW_1_STEP                        0x00
>+#define SII164_DESKEW_2_STEP                        0x20
>+#define SII164_DESKEW_3_STEP                        0x40
>+#define SII164_DESKEW_4_STEP                        0x60
>+#define SII164_DESKEW_5_STEP                        0x80
>+#define SII164_DESKEW_6_STEP                        0xA0
>+#define SII164_DESKEW_7_STEP                        0xC0
>+#define SII164_DESKEW_8_STEP                        0xE0
>+
>+/*
>+ * User Configuration Data registers (CFG 7:0)
>+ */
>+#define SII164_USER_CONFIGURATION                   0x0B
>+
>+/*
>+ * PLL registers
>+ */
>+#define SII164_PLL                                  0x0C
>+
>+/* PLL Filter Value (PLLF) */
>+#define SII164_PLL_FILTER_VALUE_MASK                0x0E
>+
>+/* PLL Filter Enable (PFEN) */
>+#define SII164_PLL_FILTER_DISABLE                   0x00
>+#define SII164_PLL_FILTER_ENABLE                    0x01
>+
>+/* Sync Continuous (SCNT) */
>+#define SII164_PLL_FILTER_SYNC_CONTINUOUS_DISABLE   0x00
>+#define SII164_PLL_FILTER_SYNC_CONTINUOUS_ENABLE    0x80
>+
>+#endif
>diff --git a/drivers/video/lynxfb/ddk750_swi2c.c b/drivers/video/lynxfb/ddk750_swi2c.c
>new file mode 100644
>index 0000000..ff532c7
>--- /dev/null
>+++ b/drivers/video/lynxfb/ddk750_swi2c.c
>@@ -0,0 +1,522 @@
>+/*******************************************************************
>+*Copyright (c) 2012 by Silicon Motion, Inc. (SMI)
>+*Permission is hereby granted, free of charge, to any person obtaining a copy
>+*of this software and associated documentation files (the "Software"), to deal
>+*in the Software without restriction, including without limitation the rights to
>+*use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
>+*of the Software, and to permit persons to whom the Software is furnished to
>+*do so, subject to the following conditions:
>+*
>+*THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
>+*EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
>+*OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
>+*NONINFRINGEMENT.  IN NO EVENT SHALL Mill.Chen and Monk.Liu OR COPYRIGHT
>+*HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
>+*WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
>+*FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
>+*OTHER DEALINGS IN THE SOFTWARE.
>+*******************************************************************/
>+#include "ddk750_help.h"
>+#include "ddk750_reg.h"
>+#include "ddk750_swi2c.h"
>+#include "ddk750_power.h"
>+
>+
>+/*******************************************************************
>+ * I2C Software Master Driver:
>+ * ===========================
>+ * Each i2c cycle is split into 4 sections. Each of these section marks
>+ * a point in time where the SCL or SDA may be changed.
>+ *
>+ * 1 Cycle == |  Section I. |  Section 2. |  Section 3. |  Section 4. |
>+ *            +-------------+-------------+-------------+-------------+
>+ *            | SCL set LOW |SCL no change| SCL set HIGH|SCL no change|
>+ *
>+ *                                          ____________ _____________
>+ * SCL == XXXX _____________ ____________ /
>+ *
>+ * I.e. the SCL may only be changed in section 1. and section 3. while
>+ * the SDA may only be changed in section 2. and section 4. The table
>+ * below gives the changes for these 2 lines in the varios sections.
>+ *
>+ * Section changes Table:
>+ * ======================
>+ * blank = no change, L = set bit LOW, H = set bit HIGH
>+ *
>+ *                                | 1.| 2.| 3.| 4.|
>+ *                 ---------------+---+---+---+---+
>+ *                 Tx Start   SDA |   | H |   | L |
>+ *                            SCL | L |   | H |   |
>+ *                 ---------------+---+---+---+---+
>+ *                 Tx Stop    SDA |   | L |   | H |
>+ *                            SCL | L |   | H |   |
>+ *                 ---------------+---+---+---+---+
>+ *                 Tx bit H   SDA |   | H |   |   |
>+ *                            SCL | L |   | H |   |
>+ *                 ---------------+---+---+---+---+
>+ *                 Tx bit L   SDA |   | L |   |   |
>+ *                            SCL | L |   | H |   |
>+ *                 ---------------+---+---+---+---+
>+ *
>+ ******************************************************************/
>+
>+/* GPIO pins used for this I2C. It ranges from 0 to 63. */
>+static unsigned char g_i2cClockGPIO = DEFAULT_I2C_SCL;
>+static unsigned char g_i2cDataGPIO = DEFAULT_I2C_SDA;
>+
>+/*
>+ *  Below is the variable declaration for the GPIO pin register usage
>+ *  for the i2c Clock and i2c Data.
>+ *
>+ *  Note:
>+ *      Notice that the GPIO usage for the i2c clock and i2c Data are
>+ *      separated. This is to make this code flexible enough when
>+ *      two separate GPIO pins for the clock and data are located
>+ *      in two different GPIO register set (worst case).
>+ */
>+
>+/* i2c Clock GPIO Register usage */
>+static unsigned long g_i2cClkGPIOMuxReg = GPIO_MUX;
>+static unsigned long g_i2cClkGPIODataReg = GPIO_DATA;
>+static unsigned long g_i2cClkGPIODataDirReg = GPIO_DATA_DIRECTION;
>+
>+/* i2c Data GPIO Register usage */
>+static unsigned long g_i2cDataGPIOMuxReg = GPIO_MUX;
>+static unsigned long g_i2cDataGPIODataReg = GPIO_DATA;
>+static unsigned long g_i2cDataGPIODataDirReg = GPIO_DATA_DIRECTION;
>+
>+static unsigned char peekIO(unsigned short port, unsigned short index)
>+{
>+#if defined(__i386__) || defined(__x86_64__)
>+	outb_p(index, port);
>+	return inb_p(port+1);
>+#endif
>+}
>+
>+/*
>+ *  This function puts a delay between command
>+ */
>+static void swI2CWait(void)
>+{
>+	/* find a bug:
>+	 * peekIO method works well before suspend/resume
>+	 * but after suspend, peekIO(0x3ce,0x61) & 0x10
>+	 * always be non-zero,which makes the while loop
>+	 * never finish.
>+	 * use non-ultimate for loop below is safe
>+	 * */
>+	int i, Temp;
>+
>+	for (i = 0; i < 600; i++) {
>+		Temp = i;
>+		Temp += i;
>+	}
>+}
>+
>+/*
>+ *  This function set/reset the SCL GPIO pin
>+ *
>+ *  Parameters:
>+ *      value    - Bit value to set to the SCL or SDA (0 = low, 1 = high)
>+ *
>+ *  Notes:
>+ *      When setting SCL to high, just set the GPIO as input where the pull up
>+ *      resistor will pull the signal up. Do not use software to pull up the
>+ *      signal because the i2c will fail when other device try to drive the
>+ *      signal due to SM50x will drive the signal to always high.
>+ */
>+void swI2CSCL(unsigned char value)
>+{
>+	unsigned long ulGPIOData;
>+	unsigned long ulGPIODirection;
>+
>+	ulGPIODirection = PEEK32(g_i2cClkGPIODataDirReg);
>+	if (value) {     /* High */
>+		/* Set direction as input. This will automatically pull the signal up. */
>+		ulGPIODirection &= ~(1 << g_i2cClockGPIO);
>+		POKE32(g_i2cClkGPIODataDirReg, ulGPIODirection);
>+	} else{            /* Low */
>+		/* Set the signal down */
>+		ulGPIOData = PEEK32(g_i2cClkGPIODataReg);
>+		ulGPIOData &= ~(1 << g_i2cClockGPIO);
>+		POKE32(g_i2cClkGPIODataReg, ulGPIOData);
>+
>+		/* Set direction as output */
>+		ulGPIODirection |= (1 << g_i2cClockGPIO);
>+		POKE32(g_i2cClkGPIODataDirReg, ulGPIODirection);
>+	}
>+}
>+
>+/*
>+ *  This function set/reset the SDA GPIO pin
>+ *
>+ *  Parameters:
>+ *      value    - Bit value to set to the SCL or SDA (0 = low, 1 = high)
>+ *
>+ *  Notes:
>+ *      When setting SCL to high, just set the GPIO as input where the pull up
>+ *      resistor will pull the signal up. Do not use software to pull up the
>+ *      signal because the i2c will fail when other device try to drive the
>+ *      signal due to SM50x will drive the signal to always high.
>+ */
>+void swI2CSDA(unsigned char value)
>+{
>+	unsigned long ulGPIOData;
>+	unsigned long ulGPIODirection;
>+
>+	ulGPIODirection = PEEK32(g_i2cDataGPIODataDirReg);
>+	if (value) {      /* High */
>+		/* Set direction as input. This will automatically pull the signal up. */
>+		ulGPIODirection &= ~(1 << g_i2cDataGPIO);
>+		POKE32(g_i2cDataGPIODataDirReg, ulGPIODirection);
>+	} else{            /* Low */
>+		/* Set the signal down */
>+		ulGPIOData = PEEK32(g_i2cDataGPIODataReg);
>+		ulGPIOData &= ~(1 << g_i2cDataGPIO);
>+		POKE32(g_i2cDataGPIODataReg, ulGPIOData);
>+
>+		/* Set direction as output */
>+		ulGPIODirection |= (1 << g_i2cDataGPIO);
>+		POKE32(g_i2cDataGPIODataDirReg, ulGPIODirection);
>+	}
>+}
>+
>+/*
>+ *  This function read the data from the SDA GPIO pin
>+ *
>+ *  Return Value:
>+ *      The SDA data bit sent by the Slave
>+ */
>+static unsigned char swI2CReadSDA()
>+{
>+	unsigned long ulGPIODirection;
>+	unsigned long ulGPIOData;
>+
>+	/* Make sure that the direction is input (High) */
>+	ulGPIODirection = PEEK32(g_i2cDataGPIODataDirReg);
>+	if ((ulGPIODirection & (1 << g_i2cDataGPIO))
>+	!= (~(1 << g_i2cDataGPIO))) {
>+		ulGPIODirection &= ~(1 << g_i2cDataGPIO);
>+		POKE32(g_i2cDataGPIODataDirReg, ulGPIODirection);
>+	}
>+
>+	/* Now read the SDA line */
>+	ulGPIOData = PEEK32(g_i2cDataGPIODataReg);
>+	if (ulGPIOData & (1 << g_i2cDataGPIO))
>+		return 1;
>+	else
>+		return 0;
>+}
>+
>+#pragma optimize("", off)
>+
>+/*
>+ *  This function sends ACK signal
>+ */
>+static void swI2CAck(void)
>+{
>+	return;  /* Single byte read is ok without it. */
>+}
>+
>+/*
>+ *  This function sends the start command to the slave device
>+ */
>+void swI2CStart(void)
>+{
>+	/* Start I2C */
>+	swI2CSDA(1);
>+	swI2CSCL(1);
>+	swI2CSDA(0);
>+}
>+
>+/*
>+ *  This function sends the stop command to the slave device
>+ */
>+void swI2CStop()
>+{
>+	/* Stop the I2C */
>+	swI2CSCL(1);
>+	swI2CSDA(0);
>+	swI2CSDA(1);
>+}
>+
>+/*
>+ *  This function writes one byte to the slave device
>+ *
>+ *  Parameters:
>+ *      data    - Data to be write to the slave device
>+ *
>+ *  Return Value:
>+ *       0   - Success
>+ *      -1   - Fail to write byte
>+ */
>+long swI2CWriteByte(unsigned char data)
>+{
>+	unsigned char value = data;
>+	int i;
>+
>+	/* Sending the data bit by bit */
>+	for (i = 0; i < 8; i++) {
>+		/* Set SCL to low */
>+		swI2CSCL(0);
>+
>+		/* Send data bit */
>+		if ((value & 0x80) != 0)
>+			swI2CSDA(1);
>+		else
>+			swI2CSDA(0);
>+
>+		swI2CWait();
>+
>+		/* Toggle clk line to one */
>+		swI2CSCL(1);
>+		swI2CWait();
>+
>+		/* Shift byte to be sent */
>+		value = value << 1;
>+	}
>+
>+	/* Set the SCL Low and SDA High (prepare to get input) */
>+	swI2CSCL(0);
>+	swI2CSDA(1);
>+
>+	/* Set the SCL High for ack */
>+	swI2CWait();
>+	swI2CSCL(1);
>+	swI2CWait();
>+
>+	/* Read SDA, until SDA==0 */
>+	for (i = 0; i < 0xff; i++) {
>+		if (!swI2CReadSDA())
>+			break;
>+
>+		swI2CSCL(0);
>+		swI2CWait();
>+		swI2CSCL(1);
>+		swI2CWait();
>+	}
>+
>+	/* Set the SCL Low and SDA High */
>+	swI2CSCL(0);
>+	swI2CSDA(1);
>+
>+	if (i < 0xff)
>+		return 0;
>+	else
>+		return -1;
>+}
>+
>+/*
>+ *  This function reads one byte from the slave device
>+ *
>+ *  Parameters:
>+ *      ack    - Flag to indicate either to send the acknowledge
>+ *            message to the slave device or not
>+ *
>+ *  Return Value:
>+ *      One byte data read from the Slave device
>+ */
>+unsigned char swI2CReadByte(unsigned char ack)
>+{
>+	int i;
>+	unsigned char data = 0;
>+
>+	for (i = 7; i >= 0; i--) {
>+		/* Set the SCL to Low and SDA to High (Input) */
>+		swI2CSCL(0);
>+		swI2CSDA(1);
>+		swI2CWait();
>+
>+		/* Set the SCL High */
>+		swI2CSCL(1);
>+		swI2CWait();
>+
>+		/* Read data bits from SDA */
>+		data |= (swI2CReadSDA() << i);
>+	}
>+
>+	if (ack)
>+		swI2CAck();
>+
>+	/* Set the SCL Low and SDA High */
>+	swI2CSCL(0);
>+	swI2CSDA(1);
>+
>+	return data;
>+}
>+#pragma optimize("", on)
>+
>+/*
>+ * This function initializes GPIO port for SW I2C communication.
>+ *
>+ * Parameters:
>+ *      i2cClkGPIO      - The GPIO pin to be used as i2c SCL
>+ *      i2cDataGPIO     - The GPIO pin to be used as i2c SDA
>+ *
>+ * Return Value:
>+ *      -1   - Fail to initialize the i2c
>+ *       0   - Success
>+ */
>+long swI2CInit_SM750LE(
>+		unsigned char i2cClkGPIO,
>+		unsigned char i2cDataGPIO
>+		)
>+{
>+	int i;
>+
>+	/* Initialize the GPIO pin for the i2c Clock Register */
>+	g_i2cClkGPIODataReg = GPIO_DATA_SM750LE;
>+	g_i2cClkGPIODataDirReg = GPIO_DATA_DIRECTION_SM750LE;
>+
>+	/* Initialize the Clock GPIO Offset */
>+	g_i2cClockGPIO = i2cClkGPIO;
>+
>+	/* Initialize the GPIO pin for the i2c Data Register */
>+	g_i2cDataGPIODataReg = GPIO_DATA_SM750LE;
>+	g_i2cDataGPIODataDirReg = GPIO_DATA_DIRECTION_SM750LE;
>+
>+	/* Initialize the Data GPIO Offset */
>+	g_i2cDataGPIO = i2cDataGPIO;
>+
>+	/* Note that SM750LE don't have GPIO MUX and power is always on */
>+
>+	/* Clear the i2c lines. */
>+	for (i = 0; i < 9; i++)
>+		swI2CStop();
>+
>+	return 0;
>+}
>+
>+/*
>+ * This function initializes the i2c attributes and bus
>+ *
>+ * Parameters:
>+ *      i2cClkGPIO      - The GPIO pin to be used as i2c SCL
>+ *      i2cDataGPIO     - The GPIO pin to be used as i2c SDA
>+ *
>+ * Return Value:
>+ *      -1   - Fail to initialize the i2c
>+ *       0   - Success
>+ */
>+long swI2CInit(
>+		unsigned char i2cClkGPIO,
>+		unsigned char i2cDataGPIO
>+	      )
>+{
>+	int i;
>+
>+	/* Return 0 if the GPIO pins to be used is out of range. The range is only from [0..63] */
>+	if ((i2cClkGPIO > 31) || (i2cDataGPIO > 31))
>+		return -1;
>+
>+	if (getChipType() == SM750LE)
>+		return swI2CInit_SM750LE(i2cClkGPIO, i2cDataGPIO);
>+
>+	/* Initialize the GPIO pin for the i2c Clock Register */
>+	g_i2cClkGPIOMuxReg = GPIO_MUX;
>+	g_i2cClkGPIODataReg = GPIO_DATA;
>+	g_i2cClkGPIODataDirReg = GPIO_DATA_DIRECTION;
>+
>+	/* Initialize the Clock GPIO Offset */
>+	g_i2cClockGPIO = i2cClkGPIO;
>+
>+	/* Initialize the GPIO pin for the i2c Data Register */
>+	g_i2cDataGPIOMuxReg = GPIO_MUX;
>+	g_i2cDataGPIODataReg = GPIO_DATA;
>+	g_i2cDataGPIODataDirReg = GPIO_DATA_DIRECTION;
>+
>+	/* Initialize the Data GPIO Offset */
>+	g_i2cDataGPIO = i2cDataGPIO;
>+
>+	/* Enable the GPIO pins for the i2c Clock and Data (GPIO MUX) */
>+	POKE32(g_i2cClkGPIOMuxReg,
>+			PEEK32(g_i2cClkGPIOMuxReg) & ~(1 << g_i2cClockGPIO));
>+	POKE32(g_i2cDataGPIOMuxReg,
>+			PEEK32(g_i2cDataGPIOMuxReg) & ~(1 << g_i2cDataGPIO));
>+
>+	/* Enable GPIO power */
>+	enableGPIO(1);
>+
>+	/* Clear the i2c lines. */
>+	for (i = 0; i < 9; i++)
>+		swI2CStop();
>+
>+	return 0;
>+}
>+
>+/*
>+ *  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 swI2CReadReg(
>+		unsigned char deviceAddress,
>+		unsigned char registerIndex
>+		)
>+{
>+	unsigned char data;
>+
>+	/* Send the Start signal */
>+	swI2CStart();
>+
>+	/* Send the device address */
>+	swI2CWriteByte(deviceAddress);
>+
>+	/* Send the register index */
>+	swI2CWriteByte(registerIndex);
>+
>+	/* Get the bus again and get the data from the device read address */
>+	swI2CStart();
>+	swI2CWriteByte(deviceAddress + 1);
>+	data = swI2CReadByte(1);
>+
>+	/* Stop swI2C and release the bus */
>+	swI2CStop();
>+
>+	return data;
>+}
>+
>+/*
>+ *  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
>+ */
>+long swI2CWriteReg(
>+		unsigned char deviceAddress,
>+		unsigned char registerIndex,
>+		unsigned char data
>+		)
>+{
>+	long returnValue = 0;
>+
>+	/* Send the Start signal */
>+	swI2CStart();
>+
>+	/* Send the device address and read the data. All should return success
>+	   in order for the writing processed to be successful
>+	   */
>+	if ((swI2CWriteByte(deviceAddress) != 0) ||
>+			(swI2CWriteByte(registerIndex) != 0) ||
>+			(swI2CWriteByte(data) != 0)) {
>+		returnValue = -1;
>+	}
>+
>+	/* Stop i2c and release the bus */
>+	swI2CStop();
>+
>+	return returnValue;
>+}
>diff --git a/drivers/video/lynxfb/ddk750_swi2c.h b/drivers/video/lynxfb/ddk750_swi2c.h
>new file mode 100644
>index 0000000..cf42753
>--- /dev/null
>+++ b/drivers/video/lynxfb/ddk750_swi2c.h
>@@ -0,0 +1,98 @@
>+/*******************************************************************
>+*Copyright (c) 2012 by Silicon Motion, Inc. (SMI)
>+*Permission is hereby granted, free of charge, to any person obtaining a copy
>+*of this software and associated documentation files (the "Software"), to deal
>+*in the Software without restriction, including without limitation the rights to
>+*use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
>+*of the Software, and to permit persons to whom the Software is furnished to
>+*do so, subject to the following conditions:
>+*
>+*THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
>+*EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
>+*OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
>+*NONINFRINGEMENT.  IN NO EVENT SHALL Mill.Chen and Monk.Liu OR COPYRIGHT
>+*HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
>+*WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
>+*FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
>+*OTHER DEALINGS IN THE SOFTWARE.
>+*******************************************************************/
>+#ifndef _SWI2C_H_
>+#define _SWI2C_H_
>+
>+/* Default i2c CLK and Data GPIO. These are the default i2c pins */
>+#define DEFAULT_I2C_SCL                     30
>+#define DEFAULT_I2C_SDA                     31
>+
>+/*
>+ * This function initializes the i2c attributes and bus
>+ *
>+ * Parameters:
>+ *      i2cClkGPIO  - The GPIO pin to be used as i2c SCL
>+ *      i2cDataGPIO - The GPIO pin to be used as i2c SDA
>+ *
>+ * Return Value:
>+ *      -1   - Fail to initialize the i2c
>+ *       0   - Success
>+ */
>+long swI2CInit(
>+    unsigned char i2cClkGPIO,
>+    unsigned char i2cDataGPIO
>+);
>+
>+/*
>+ *  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 swI2CReadReg(
>+    unsigned char deviceAddress,
>+    unsigned char registerIndex
>+);
>+
>+/*
>+ *  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
>+ */
>+long swI2CWriteReg(
>+    unsigned char deviceAddress,
>+    unsigned char registerIndex,
>+    unsigned char data
>+);
>+
>+/*
>+ *  These two functions are used to toggle the data on the SCL and SDA I2C lines.
>+ *  The used of these two functions are not recommended unless it is necessary.
>+ */
>+
>+/*
>+ *  This function set/reset the SCL GPIO pin
>+ *
>+ *  Parameters:
>+ *      value	- Bit value to set to the SCL or SDA (0 = low, 1 = high)
>+ */
>+void swI2CSCL(unsigned char value);
>+
>+/*
>+ *  This function set/reset the SDA GPIO pin
>+ *
>+ *  Parameters:
>+ *      value	- Bit value to set to the SCL or SDA (0 = low, 1 = high)
>+ */
>+void swI2CSDA(unsigned char value);
>+
>+#endif  /* _SWI2C_H_ */
>diff --git a/drivers/video/lynxfb/lynx_accel.c b/drivers/video/lynxfb/lynx_accel.c
>new file mode 100644
>index 0000000..844f90e
>--- /dev/null
>+++ b/drivers/video/lynxfb/lynx_accel.c
>@@ -0,0 +1,417 @@
>+/*******************************************************************
>+*Copyright (c) 2012 by Silicon Motion, Inc. (SMI)
>+*Permission is hereby granted, free of charge, to any person obtaining a copy
>+*of this software and associated documentation files (the "Software"), to deal
>+*in the Software without restriction, including without limitation the rights to
>+*use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
>+*of the Software, and to permit persons to whom the Software is furnished to
>+*do so, subject to the following conditions:
>+*
>+*THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
>+*EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
>+*OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
>+*NONINFRINGEMENT.  IN NO EVENT SHALL Mill.Chen and Monk.Liu OR COPYRIGHT
>+*HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
>+*WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
>+*FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
>+*OTHER DEALINGS IN THE SOFTWARE.
>+*******************************************************************/
>+#include <linux/version.h>
>+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 10)
>+#include <linux/config.h>
>+#endif
>+#include <linux/module.h>
>+#include <linux/kernel.h>
>+#include <linux/errno.h>
>+#include <linux/string.h>
>+#include <linux/mm.h>
>+#include <linux/slab.h>
>+#include <linux/delay.h>
>+#include <linux/fb.h>
>+#include <linux/ioport.h>
>+#include <linux/init.h>
>+#include <linux/pci.h>
>+#include <linux/vmalloc.h>
>+#include <linux/pagemap.h>
>+#include <linux/console.h>
>+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
>+/* no below two header files in 2.6.9 */
>+#include <linux/platform_device.h>
>+#include <linux/screen_info.h>
>+#else
>+/* nothing by far */
>+#endif
>+
>+#include "lynx_drv.h"
>+#include "lynx_accel.h"
>+#include "lynx_help.h"
>+static inline void write_dpr(struct lynx_accel *accel, int offset, u32 regValue)
>+{
>+	writel(regValue, accel->dprBase + offset);
>+}
>+
>+static inline u32 read_dpr(struct lynx_accel *accel, int offset)
>+{
>+	return readl(accel->dprBase + offset);
>+}
>+
>+static inline void write_dpPort(struct lynx_accel *accel, u32 data)
>+{
>+	writel(data, accel->dpPortBase);
>+}
>+
>+void hw_de_init(struct lynx_accel *accel)
>+{
>+	/* setup 2d engine registers */
>+	u32 reg, clr;
>+	ENTER();
>+	write_dpr(accel, DE_MASKS, 0xFFFFFFFF);
>+
>+	/* dpr1c */
>+	reg = (~(1 << DE_STRETCH_FORMAT_PATTERN_XY_LSB))&
>+		(~(1 << DE_STRETCH_FORMAT_PATTERN_Y_LSB))&
>+		(~(1 << DE_STRETCH_FORMAT_PATTERN_X_LSB))&
>+		(~(15 << DE_STRETCH_FORMAT_ADDRESSING_LSB))|
>+		(3 << DE_STRETCH_FORMAT_SOURCE_HEIGHT_LSB);
>+
>+	clr &= (~(1 << DE_STRETCH_FORMAT_PATTERN_XY_LSB))&
>+		(~(7 << DE_STRETCH_FORMAT_PATTERN_Y_LSB))&
>+		(~(7 << DE_STRETCH_FORMAT_PATTERN_X_LSB))&
>+		(~(15 << DE_STRETCH_FORMAT_ADDRESSING_LSB))&
>+		(~(0xFFF << DE_STRETCH_FORMAT_SOURCE_HEIGHT_LSB));
>+
>+	/* DE_STRETCH bpp format need be initilized in setMode routine */
>+	write_dpr(accel, DE_STRETCH_FORMAT, (read_dpr(accel, DE_STRETCH_FORMAT) & clr) | reg);
>+
>+	/* disable clipping and transparent */
>+	write_dpr(accel, DE_CLIP_TL, 0);
>+	write_dpr(accel, DE_CLIP_BR, 0);
>+
>+	write_dpr(accel, DE_COLOR_COMPARE_MASK, 0);
>+	write_dpr(accel, DE_COLOR_COMPARE, 0);
>+
>+	reg = (~(1 << DE_CONTROL_TRANSPARENCY_LSB))&
>+		(~(1 << DE_CONTROL_TRANSPARENCY_MATCH_LSB))&
>+		(~(1 << DE_CONTROL_TRANSPARENCY_SELECT_LSB));
>+
>+	clr = (~(1 << DE_CONTROL_TRANSPARENCY_LSB))&
>+		(~(1 << DE_CONTROL_TRANSPARENCY_MATCH_LSB))&
>+		(~(1 << DE_CONTROL_TRANSPARENCY_SELECT_LSB));
>+
>+	/* dpr0c */
>+	write_dpr(accel, DE_CONTROL, (read_dpr(accel, DE_CONTROL)&clr)|reg);
>+	LEAVE();
>+}
>+
>+/* set2dformat only be called from setmode functions
>+ * but if you need dual framebuffer driver, need call set2dformat
>+ * every time you use 2d function */
>+
>+void hw_set2dformat(struct lynx_accel *accel, int fmt)
>+{
>+	u32 reg;
>+	ENTER();
>+	/* fmt=0, 1, 2 for 8, 16, 32, bpp on sm718/750/502 */
>+	reg = read_dpr(accel, DE_STRETCH_FORMAT);
>+	reg &= (~(3 << DE_STRETCH_FORMAT_PIXEL_FORMAT_LSB));
>+	reg |= fmt << DE_STRETCH_FORMAT_PIXEL_FORMAT_LSB;
>+	write_dpr(accel, DE_STRETCH_FORMAT, reg);
>+	LEAVE();
>+}
>+
>+int hw_fillrect(struct lynx_accel *accel,
>+		u32 base, u32 pitch, u32 Bpp,
>+		u32 x, u32 y, u32 width, u32 height,
>+		u32 color, u32 rop)
>+{
>+	u32 deCtrl;
>+
>+	if (accel->de_wait() != 0) {
>+		/* int time wait and always busy, seems hardware
>+		 * got something error */
>+		dbg_msg("%s:De engine always bussy\n", __func__);
>+		return -1;
>+	}
>+
>+	write_dpr(accel, DE_WINDOW_DESTINATION_BASE, base);
>+	write_dpr(accel, DE_PITCH,
>+			(pitch/Bpp << DE_PITCH_DESTINATION_LSB)|
>+			(pitch/Bpp << DE_PITCH_SOURCE_LSB));
>+
>+	write_dpr(accel, DE_WINDOW_WIDTH,
>+			(pitch/Bpp << DE_WINDOW_WIDTH_DESTINATION_LSB)|
>+			(pitch/Bpp << DE_WINDOW_WIDTH_SOURCE_LSB));
>+	write_dpr(accel, DE_FOREGROUND, color);
>+
>+	write_dpr(accel, DE_DESTINATION, (x << DE_DESTINATION_X_LSB)|
>+			(y << DE_DESTINATION_Y_LSB));
>+
>+	write_dpr(accel, DE_DIMENSION,
>+			(width << DE_DIMENSION_X_LSB)|
>+			(height << DE_DIMENSION_Y_ET_LSB));
>+
>+	deCtrl |=
>+		(1 << DE_CONTROL_STATUS_LSB)&
>+		(~(1 << DE_CONTROL_DIRECTION_LSB))|
>+		(1 << DE_CONTROL_LAST_PIXEL_LSB)|
>+		(1 << DE_CONTROL_COMMAND_LSB)|
>+		(1 << DE_CONTROL_ROP_SELECT_LSB)|
>+		(rop << DE_CONTROL_ROP_LSB);
>+	write_dpr(accel, DE_CONTROL, deCtrl);
>+	return 0;
>+}
>+
>+int hw_copyarea(
>+		struct lynx_accel *accel,
>+		unsigned int sBase, /* Address of source: offset in frame buffer */
>+		unsigned int sPitch, /* Pitch value of source surface in BYTE */
>+		unsigned int sx,
>+		unsigned int sy, /* Starting coordinate of source surface */
>+		unsigned int dBase, /* Address of destination: offset in frame buffer */
>+		unsigned int dPitch, /* Pitch value of destination surface in BYTE */
>+		unsigned int Bpp, /* Color depth of destination surface */
>+		unsigned int dx,
>+		unsigned int dy, /* Starting coordinate of destination surface */
>+		unsigned int width,
>+		unsigned int height, /* width and height of rectangle in pixel value */
>+		unsigned int rop2)   /* ROP value */
>+{
>+	unsigned int nDirection, de_ctrl;
>+	int opSign;
>+	nDirection = LEFT_TO_RIGHT;
>+	/* Direction of ROP2 operation: 1 = Left to Right, (-1) = Right to Left */
>+	opSign = 1;
>+	de_ctrl = 0;
>+
>+	/* If source and destination are the same surface, need to check for overlay cases */
>+	if (sBase == dBase && sPitch == dPitch) {
>+
>+		/* Determine direction of operation */
>+		if (sy < dy) {
>+
>+			/* +----------+
>+			   |S         |
>+			   |   +----------+
>+			   |   |      |   |
>+			   |   |      |   |
>+			   +---|------+   |
>+			   |         D|
>+			   +----------+ */
>+
>+			nDirection = BOTTOM_TO_TOP;
>+		} else if (sy > dy)	{
>+
>+			/* +----------+
>+			   |D         |
>+			   |   +----------+
>+			   |   |      |   |
>+			   |   |      |   |
>+			   +---|------+   |
>+			   |         S|
>+			   +----------+ */
>+
>+			nDirection = TOP_TO_BOTTOM;
>+		} else{
>+
>+			/* sy == dy */
>+
>+			if (sx <= dx) {
>+
>+				/* +------+---+------+
>+				   |S     |   |     D|
>+				   |      |   |      |
>+				   |      |   |      |
>+				   |      |   |      |
>+				   +------+---+------+ */
>+
>+				nDirection = RIGHT_TO_LEFT;
>+			} else{
>+
>+				/* sx > dx */
>+
>+				/* +------+---+------+
>+				   |D     |   |     S|
>+				   |      |   |      |
>+				   |      |   |      |
>+				   |      |   |      |
>+				   +------+---+------+ */
>+
>+				nDirection = LEFT_TO_RIGHT;
>+			}
>+		}
>+	}
>+
>+	if ((nDirection == BOTTOM_TO_TOP) || (nDirection == RIGHT_TO_LEFT)) {
>+
>+		sx += width - 1;
>+		sy += height - 1;
>+		dx += width - 1;
>+		dy += height - 1;
>+		opSign = (-1);
>+	}
>+
>+	/* Note:
>+	   DE_FOREGROUND are DE_BACKGROUND are don't care.
>+	   DE_COLOR_COMPARE and DE_COLOR_COMPARE_MAKS are set by set deSetTransparency().
>+	   */
>+
>+	/* 2D Source Base.
>+	   It is an address offset (128 bit aligned) from the beginning of frame buffer.
>+	   */
>+	write_dpr(accel, DE_WINDOW_SOURCE_BASE, sBase);
>+
>+	/* 2D Destination Base.
>+	   It is an address offset (128 bit aligned) from the beginning of frame buffer.
>+	   */
>+	write_dpr(accel, DE_WINDOW_DESTINATION_BASE, dBase);
>+
>+
>+	{
>+		write_dpr(accel, DE_PITCH,
>+				((dPitch/Bpp) << DE_PITCH_DESTINATION_LSB) |
>+				((sPitch/Bpp) << DE_PITCH_SOURCE_LSB));
>+	}
>+
>+	/* Screen Window width in Pixels.
>+	   2D engine uses this value to calculate the linear address in frame buffer for a given point.
>+	   */
>+	write_dpr(accel, DE_WINDOW_WIDTH,
>+			((dPitch/Bpp) << DE_WINDOW_WIDTH_DESTINATION_LSB) |
>+			((sPitch/Bpp) << DE_WINDOW_WIDTH_SOURCE_LSB));
>+
>+	if (accel->de_wait() != 0) {
>+		return -1;
>+	}
>+
>+	{
>+		write_dpr(accel, DE_SOURCE, (~(1 << DE_SOURCE_WRAP_LSB))&
>+				(sx << DE_SOURCE_X_K1_LSB)|
>+				(sy << DE_SOURCE_Y_K2_LSB));
>+
>+		write_dpr(accel, DE_DESTINATION, (dx << DE_DESTINATION_X_LSB)|
>+				(dy << DE_DESTINATION_Y_LSB));
>+
>+		write_dpr(accel, DE_DIMENSION,
>+				(width << DE_DIMENSION_X_LSB)|
>+				(height << DE_DIMENSION_Y_ET_LSB));
>+
>+		de_ctrl = (rop2 << DE_CONTROL_ROP_LSB)|
>+			(1 << DE_CONTROL_ROP_SELECT_LSB)&
>+			(~(0x1f << DE_CONTROL_COMMAND_LSB))|
>+			(1 << DE_CONTROL_STATUS_LSB);
>+
>+		if (nDirection == RIGHT_TO_LEFT)
>+			de_ctrl |= 1 << DE_CONTROL_DIRECTION_LSB;
>+		else
>+			de_ctrl &= ~(1 << DE_CONTROL_DIRECTION_LSB);
>+
>+		write_dpr(accel, DE_CONTROL, de_ctrl);
>+	}
>+
>+	return 0;
>+}
>+
>+static unsigned int deGetTransparency(struct lynx_accel *accel)
>+{
>+	unsigned int de_ctrl;
>+
>+	de_ctrl = read_dpr(accel, DE_CONTROL);
>+	de_ctrl &=
>+		(1 << DE_CONTROL_TRANSPARENCY_MATCH_LSB) |
>+		(1 << DE_CONTROL_TRANSPARENCY_SELECT_LSB)|
>+		(1 << DE_CONTROL_TRANSPARENCY_LSB);
>+	return de_ctrl;
>+}
>+
>+int hw_imageblit(
>+		struct lynx_accel *accel,
>+		unsigned char *pSrcbuf, /* pointer to start of source buffer in system memory */
>+		int srcDelta, /* Pitch value (in bytes) of the source buffer, +ive means top down and -ive mean button up */
>+		unsigned int startBit, /* Mono data can start at any bit in a byte, this value should be 0 to 7 */
>+		unsigned int dBase, /* Address of destination: offset in frame buffer */
>+		unsigned int dPitch, /* Pitch value of destination surface in BYTE */
>+		unsigned int bytePerPixel, /* Color depth of destination surface */
>+		unsigned int dx,
>+		unsigned int dy, /* Starting coordinate of destination surface */
>+		unsigned int width,
>+		unsigned int height, /* width and height of rectange in pixel value */
>+		unsigned int fColor, /* Foreground color (corresponding to a 1 in the monochrome data */
>+		unsigned int bColor, /* Background color (corresponding to a 0 in the monochrome data */
>+		unsigned int rop2)     /* ROP value */
>+{
>+	unsigned int ulBytesPerScan;
>+	unsigned int ul4BytesPerScan;
>+	unsigned int ulBytesRemain;
>+	unsigned int de_ctrl = 0;
>+	unsigned char ajRemain[4];
>+	int i, j;
>+
>+	startBit &= 7; /* Just make sure the start bit is within legal range */
>+	ulBytesPerScan = (width + startBit + 7) / 8;
>+	ul4BytesPerScan = ulBytesPerScan & ~3;
>+	ulBytesRemain = ulBytesPerScan & 3;
>+
>+	if (accel->de_wait() != 0) {
>+		/* inf_msg("*** ImageBlit return -1 ***\n"); */
>+		return -1;
>+	}
>+
>+	/* 2D Source Base.
>+	   Use 0 for HOST Blt.
>+	   */
>+	write_dpr(accel, DE_WINDOW_SOURCE_BASE, 0);
>+
>+	/* 2D Destination Base.
>+	   It is an address offset (128 bit aligned) from the beginning of frame buffer.
>+	   */
>+	write_dpr(accel, DE_WINDOW_DESTINATION_BASE, dBase);
>+	{
>+		write_dpr(accel, DE_PITCH,
>+				(dPitch/bytePerPixel << DE_PITCH_DESTINATION_LSB) |
>+				(dPitch/bytePerPixel << DE_PITCH_SOURCE_LSB));
>+	}
>+
>+	/* Screen Window width in Pixels.
>+	   2D engine uses this value to calculate the linear address in frame buffer for a given point.
>+	   */
>+	write_dpr(accel, DE_WINDOW_WIDTH,
>+			((dPitch/bytePerPixel) << DE_WINDOW_WIDTH_DESTINATION_LSB) |
>+			((dPitch/bytePerPixel) << DE_WINDOW_WIDTH_SOURCE_LSB));
>+
>+	/* Note: For 2D Source in Host Write, only X_K1_MONO field is needed, and Y_K2 field is not used.
>+	   For mono bitmap, use startBit for X_K1. */
>+	write_dpr(accel, DE_SOURCE, startBit << DE_SOURCE_X_K1_MONO);
>+	write_dpr(accel, DE_DESTINATION, (dx << DE_DESTINATION_X_LSB)|
>+			(dy << DE_DESTINATION_Y_LSB));
>+
>+	write_dpr(accel, DE_DIMENSION,
>+			(width << DE_DIMENSION_X_LSB)|
>+			(height << DE_DIMENSION_Y_ET_LSB));
>+	write_dpr(accel, DE_FOREGROUND, fColor);
>+	write_dpr(accel, DE_BACKGROUND, bColor);
>+
>+	de_ctrl = (rop2 << DE_CONTROL_ROP_LSB)|
>+		(1 << DE_CONTROL_ROP_SELECT_LSB)|
>+		(8 << DE_CONTROL_COMMAND_LSB)|
>+		(1 << DE_CONTROL_HOST_LSB)|
>+		(1 << DE_CONTROL_STATUS_LSB);
>+	write_dpr(accel, DE_CONTROL, de_ctrl | deGetTransparency(accel));
>+
>+	/* Write MONO data (line by line) to 2D Engine data port */
>+	for (i = 0; i < height; i++) {
>+		/* For each line, send the data in chunks of 4 bytes */
>+		for (j = 0; j < (ul4BytesPerScan/4); j++)	{
>+			write_dpPort(accel, *(unsigned int *)(pSrcbuf + (j * 4)));
>+		}
>+
>+		if (ulBytesRemain) {
>+			memcpy(ajRemain, pSrcbuf+ul4BytesPerScan, ulBytesRemain);
>+			write_dpPort(accel, *(unsigned int *)ajRemain);
>+		}
>+
>+		pSrcbuf += srcDelta;
>+	}
>+
>+	return 0;
>+}
>+
>diff --git a/drivers/video/lynxfb/lynx_accel.h b/drivers/video/lynxfb/lynx_accel.h
>new file mode 100644
>index 0000000..328157c
>--- /dev/null
>+++ b/drivers/video/lynxfb/lynx_accel.h
>@@ -0,0 +1,161 @@
>+/*******************************************************************
>+*Copyright (c) 2012 by Silicon Motion, Inc. (SMI)
>+*Permission is hereby granted, free of charge, to any person obtaining a copy
>+*of this software and associated documentation files (the "Software"), to deal
>+*in the Software without restriction, including without limitation the rights to
>+*use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
>+*of the Software, and to permit persons to whom the Software is furnished to
>+*do so, subject to the following conditions:
>+*
>+*THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
>+*EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
>+*OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
>+*NONINFRINGEMENT.  IN NO EVENT SHALL Mill.Chen and Monk.Liu OR COPYRIGHT
>+*HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
>+*WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
>+*FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
>+*OTHER DEALINGS IN THE SOFTWARE.
>+*******************************************************************/
>+#ifndef ACCEL_H__
>+#define ACCEL_H__
>+
>+#define HW_ROP2_COPY 0xc
>+#define HW_ROP2_XOR 0x6
>+
>+/* notes: below address are the offset value from de_base_address (0x100000)*/
>+
>+/* for sm718/750/502 de_base is at mmreg_1mb*/
>+#define DE_BASE_ADDR_TYPE1	0x100000
>+/* for sm712, de_base is at mmreg_32kb */
>+#define DE_BASE_ADDR_TYPE2	0x8000
>+/* for sm722, de_base is at mmreg_0 */
>+#define DE_BASE_ADDR_TYPE3 0
>+
>+/* type1 data port address is at mmreg_0x110000*/
>+#define DE_PORT_ADDR_TYPE1 0x110000
>+/* for sm712, data port address is at mmreg_0 */
>+#define DE_PORT_ADDR_TYPE2 0x100000
>+/* for sm722, data port address is at mmreg_1mb */
>+#define DE_PORT_ADDR_TYPE3 0x100000
>+
>+#define DE_SOURCE 0
>+#define DE_SOURCE_WRAP_LSB	31
>+#define DE_SOURCE_X_K1_LSB	16
>+#define DE_SOURCE_Y_K2_LSB	0
>+#define DE_SOURCE_X_K1_MONO 0
>+
>+#define DE_DESTINATION		0x4
>+#define DE_DESTINATION_WRAP_LSB 31
>+#define DE_DESTINATION_X_LSB 16
>+#define DE_DESTINATION_Y_LSB 0
>+
>+#define DE_DIMENSION                                    0x8
>+#define DE_DIMENSION_X_LSB                              16
>+#define DE_DIMENSION_Y_ET_LSB                           0
>+
>+#define DE_CONTROL                                      0xC
>+#define DE_CONTROL_STATUS_LSB                           31
>+#define DE_CONTROL_DIRECTION_LSB                            27
>+#define DE_CONTROL_HOST_LSB                                 22
>+#define DE_CONTROL_LAST_PIXEL_LSB                           21
>+#define DE_CONTROL_COMMAND_LSB                          16
>+#define DE_CONTROL_ROP_SELECT_LSB                       15
>+#define DE_CONTROL_ROP2_SOURCE_LSB                      14
>+#define DE_CONTROL_TRANSPARENCY_MATCH_LSB               10
>+#define DE_CONTROL_TRANSPARENCY_SELECT_LSB              9
>+#define DE_CONTROL_TRANSPARENCY_LSB 					8
>+#define DE_CONTROL_ROP_LSB                              0
>+#define DE_MASKS                                        0x000028
>+#define DE_CLIP_TL                                      0x00002C
>+#define DE_CLIP_BR                                      0x000030
>+#define DE_COLOR_COMPARE                                0x000020
>+#define DE_COLOR_COMPARE_MASK                           0x000024
>+#define DE_MONO_PATTERN_LOW                             0x000034
>+#define DE_MONO_PATTERN_HIGH                            0x000038
>+#define DE_WINDOW_SOURCE_BASE                           0x000040
>+#define DE_WINDOW_DESTINATION_BASE                      0x000044
>+
>+#define DE_PITCH                                        0x000010
>+#define DE_PITCH_DESTINATION_LSB                        16
>+#define DE_PITCH_SOURCE_LSB                             0
>+
>+
>+#define DE_FOREGROUND                                   0x000014
>+#define DE_BACKGROUND                                   0x000018
>+
>+#define DE_STRETCH_FORMAT                               0x00001C
>+#define DE_STRETCH_FORMAT_PATTERN_XY_LSB                30
>+#define DE_STRETCH_FORMAT_PATTERN_Y_LSB                 27
>+#define DE_STRETCH_FORMAT_PATTERN_X_LSB                 23
>+#define DE_STRETCH_FORMAT_PIXEL_FORMAT_LSB              20
>+#define DE_STRETCH_FORMAT_ADDRESSING_LSB                16
>+#define DE_STRETCH_FORMAT_SOURCE_HEIGHT_LSB             0
>+#define DE_MASKS                                        0x000028
>+#define DE_CLIP_TL                                      0x00002C
>+#define DE_CLIP_BR                                      0x000030
>+#define DE_COLOR_COMPARE                                0x000020
>+#define DE_COLOR_COMPARE_MASK                           0x000024
>+#define DE_MONO_PATTERN_LOW                             0x000034
>+#define DE_MONO_PATTERN_HIGH                            0x000038
>+#define DE_WINDOW_SOURCE_BASE                           0x000040
>+#define DE_WINDOW_DESTINATION_BASE                      0x000044
>+
>+
>+
>+#define DE_WINDOW_WIDTH                                 0x00003C
>+#define DE_WINDOW_WIDTH_DESTINATION_LSB                     16
>+#define DE_WINDOW_WIDTH_SOURCE_LSB                          0
>+
>+
>+
>+/* blt direction */
>+#define TOP_TO_BOTTOM 0
>+#define LEFT_TO_RIGHT 0
>+#define BOTTOM_TO_TOP 1
>+#define RIGHT_TO_LEFT 1
>+
>+void hw_set2dformat(struct lynx_accel *accel, int fmt);
>+
>+void hw_de_init(struct lynx_accel *accel);
>+
>+int hw_fillrect(struct lynx_accel *accel,
>+				u32 base, u32 pitch, u32 Bpp,
>+				u32 x, u32 y, u32 width, u32 height,
>+				u32 color, u32 rop);
>+
>+int hw712_fillrect(struct lynx_accel *accel,
>+				u32 base, u32 pitch, u32 Bpp,
>+				u32 x, u32 y, u32 width, u32 height,
>+				u32 color, u32 rop);
>+
>+int hw_copyarea(
>+struct lynx_accel *accel,
>+unsigned int sBase,  /* Address of source: offset in frame buffer */
>+unsigned int sPitch, /* Pitch value of source surface in BYTE */
>+unsigned int sx,
>+unsigned int sy,     /* Starting coordinate of source surface */
>+unsigned int dBase,  /* Address of destination: offset in frame buffer */
>+unsigned int dPitch, /* Pitch value of destination surface in BYTE */
>+unsigned int bpp,    /* Color depth of destination surface */
>+unsigned int dx,
>+unsigned int dy,     /* Starting coordinate of destination surface */
>+unsigned int width,
>+unsigned int height, /* width and height of rectangle in pixel value */
>+unsigned int rop2);
>+
>+int hw_imageblit(
>+struct lynx_accel *accel,
>+unsigned char *pSrcbuf, /* pointer to start of source buffer in system memory */
>+int srcDelta,          /* Pitch value (in bytes) of the source buffer, +ive means top down and -ive mean button up */
>+unsigned int startBit, /* Mono data can start at any bit in a byte, this value should be 0 to 7 */
>+unsigned int dBase,    /* Address of destination: offset in frame buffer */
>+unsigned int dPitch,   /* Pitch value of destination surface in BYTE */
>+unsigned int bytePerPixel,      /* Color depth of destination surface */
>+unsigned int dx,
>+unsigned int dy,       /* Starting coordinate of destination surface */
>+unsigned int width,
>+unsigned int height,   /* width and height of rectange in pixel value */
>+unsigned int fColor,   /* Foreground color (corresponding to a 1 in the monochrome data */
>+unsigned int bColor,   /* Background color (corresponding to a 0 in the monochrome data */
>+unsigned int rop2);
>+#endif
>diff --git a/drivers/video/lynxfb/lynx_cursor.c b/drivers/video/lynxfb/lynx_cursor.c
>new file mode 100644
>index 0000000..8aa471f
>--- /dev/null
>+++ b/drivers/video/lynxfb/lynx_cursor.c
>@@ -0,0 +1,223 @@
>+/*******************************************************************
>+*Copyright (c) 2012 by Silicon Motion, Inc. (SMI)
>+*Permission is hereby granted, free of charge, to any person obtaining a copy
>+*of this software and associated documentation files (the "Software"), to deal
>+*in the Software without restriction, including without limitation the rights to
>+*use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
>+*of the Software, and to permit persons to whom the Software is furnished to
>+*do so, subject to the following conditions:
>+*
>+*THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
>+*EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
>+*OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
>+*NONINFRINGEMENT.  IN NO EVENT SHALL Mill.Chen and Monk.Liu OR COPYRIGHT
>+*HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
>+*WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
>+*FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
>+*OTHER DEALINGS IN THE SOFTWARE.
>+*******************************************************************/
>+#include <linux/version.h>
>+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 10)
>+#include <linux/config.h>
>+#endif
>+#include <linux/module.h>
>+#include <linux/kernel.h>
>+#include <linux/errno.h>
>+#include <linux/string.h>
>+#include <linux/mm.h>
>+#include <linux/slab.h>
>+#include <linux/delay.h>
>+#include <linux/fb.h>
>+#include <linux/ioport.h>
>+#include <linux/init.h>
>+#include <linux/pci.h>
>+#include <linux/vmalloc.h>
>+#include <linux/pagemap.h>
>+#include <linux/console.h>
>+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
>+/* no below two header files in 2.6.9 */
>+#include <linux/platform_device.h>
>+#include <linux/screen_info.h>
>+#else
>+/* nothing by far */
>+#endif
>+
>+#include "lynx_drv.h"
>+#include "lynx_help.h"
>+#include "lynx_cursor.h"
>+
>+#define PEEK32(addr) \
>+readl(cursor->mmio + (addr))
>+
>+#define POKE32(addr, data) \
>+writel((data), cursor->mmio + (addr))
>+
>+/* cursor control for voyager and 718/750*/
>+
>+#define HWC_ADDRESS                         0x0
>+#define HWC_ADDRESS_ENABLE_LSB              31
>+#define HWC_ADDRESS_EXT_LSB                 27
>+#define HWC_ADDRESS_CS                      26
>+#define HWC_ADDRESS_ADDRESS_LSB             0
>+#define HWC_LOCATION                        0x4
>+#define HWC_LOCATION_TOP_LSB                27
>+#define HWC_LOCATION_Y_LSB                  16
>+#define HWC_LOCATION_LEFT                   11
>+#define HWC_LOCATION_X_LSB                  0
>+#define HWC_COLOR_12                        0x8
>+#define HWC_COLOR_3                         0xC
>+
>+/* hw_cursor_xxx works for voyager, 718 and 750 */
>+void hw_cursor_enable(struct lynx_cursor *cursor)
>+{
>+	u32 reg;
>+	reg =  (cursor->offset << HWC_ADDRESS_ADDRESS_LSB)&
>+			(~(1 << HWC_ADDRESS_EXT_LSB))|
>+			(1 << HWC_ADDRESS_ENABLE_LSB);
>+	POKE32(HWC_ADDRESS, reg);
>+}
>+void hw_cursor_disable(struct lynx_cursor *cursor)
>+{
>+	POKE32(HWC_ADDRESS, 0);
>+}
>+
>+void hw_cursor_setSize(struct lynx_cursor *cursor,
>+						int w, int h)
>+{
>+	cursor->w = w;
>+	cursor->h = h;
>+}
>+void hw_cursor_setPos(struct lynx_cursor *cursor,
>+						int x, int y)
>+{
>+	u32 reg;
>+	reg = (y << HWC_LOCATION_Y_LSB)|
>+			(x << HWC_LOCATION_X_LSB);
>+	POKE32(HWC_LOCATION, reg);
>+}
>+void hw_cursor_setColor(struct lynx_cursor *cursor,
>+						u32 fg, u32 bg)
>+{
>+	POKE32(HWC_COLOR_12, (fg<<16)|(bg&0xffff));
>+	POKE32(HWC_COLOR_3, 0xffe0);
>+}
>+
>+void hw_cursor_setData(struct lynx_cursor *cursor,
>+			u16 rop, const u8 *pcol, const u8 *pmsk)
>+{
>+	int i, j, count, pitch, offset;
>+	u8 color, mask, opr;
>+	u16 data;
>+	u16 *pbuffer, *pstart;
>+	static ulong odd;
>+
>+	/*  in byte*/
>+	pitch = cursor->w >> 3;
>+
>+	/* in byte	*/
>+	count = pitch * cursor->h;
>+
>+	/* in ushort */
>+	offset = cursor->maxW * 2 / 8 / 2;
>+
>+	data = 0;
>+	pstart = (u16 *)cursor->vstart;
>+	pbuffer = pstart;
>+
>+/*
>+	if (odd &1) {
>+		hw_cursor_setData2(cursor, rop, pcol, pmsk);
>+	}
>+	odd++;
>+	if (odd > 0xfffffff0)
>+		odd=0;
>+*/
>+
>+	for (i = 0; i < count; i++) {
>+
>+		color = *pcol++;
>+		mask = *pmsk++;
>+		data = 0;
>+
>+		/* either method below works well,
>+		 * but method 2 shows no lag
>+		 * and method 1 seems a bit wrong*/
>+
>+		for (j = 0; j < 8; j++) {
>+			if (mask & (0x80>>j)) {
>+				if (rop == ROP_XOR)
>+					opr = mask ^ color;
>+				else
>+					opr = mask & color;
>+
>+				/* 2 stands for forecolor and 1 for backcolor */
>+				data |= ((opr & (0x80>>j)) ? 2 : 1)<<(j*2);
>+			}
>+		}
>+
>+		*pbuffer = data;
>+
>+		/* assume pitch is 1, 2, 4, 8, ...*/
>+		if ((i+1) % pitch == 0) {
>+			/* need a return */
>+			pstart += offset;
>+			pbuffer = pstart;
>+		} else{
>+			pbuffer++;
>+		}
>+
>+	}
>+
>+
>+}
>+
>+void hw_cursor_setData2(struct lynx_cursor *cursor,
>+			u16 rop, const u8 *pcol, const u8 *pmsk)
>+{
>+	int i, j, count, pitch, offset;
>+	u8 color, mask, opr;
>+	u16 data;
>+	u16 *pbuffer, *pstart;
>+
>+	/*  in byte*/
>+	pitch = cursor->w >> 3;
>+
>+	/* in byte	*/
>+	count = pitch * cursor->h;
>+
>+	/* in ushort */
>+	offset = cursor->maxW * 2 / 8 / 2;
>+
>+	data = 0;
>+	pstart = (u16 *)cursor->vstart;
>+	pbuffer = pstart;
>+
>+	for (i = 0; i < count; i++) {
>+
>+		color = *pcol++;
>+		mask = *pmsk++;
>+		data = 0;
>+
>+		/* either method below works well,  but method 2 shows no lag */
>+
>+		for (j = 0; j < 8; j++) {
>+			if (mask & (1 << j))
>+				data |= ((color & (1<<j)) ? 1 : 2)<<(j*2);
>+		}
>+
>+		*pbuffer = data;
>+
>+		/* assume pitch is 1, 2, 4, 8, ...*/
>+		if (!(i&(pitch-1))) {
>+
>+
>+			/* need a return */
>+			pstart += offset;
>+			pbuffer = pstart;
>+		} else{
>+			pbuffer++;
>+		}
>+
>+	}
>+	return 0;
>+}
>diff --git a/drivers/video/lynxfb/lynx_cursor.h b/drivers/video/lynxfb/lynx_cursor.h
>new file mode 100644
>index 0000000..c9aa096
>--- /dev/null
>+++ b/drivers/video/lynxfb/lynx_cursor.h
>@@ -0,0 +1,36 @@
>+/*******************************************************************
>+*Copyright (c) 2012 by Silicon Motion, Inc. (SMI)
>+*Permission is hereby granted, free of charge, to any person obtaining a copy
>+*of this software and associated documentation files (the "Software"), to deal
>+*in the Software without restriction, including without limitation the rights to
>+*use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
>+*of the Software, and to permit persons to whom the Software is furnished to
>+*do so, subject to the following conditions:
>+*
>+*THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
>+*EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
>+*OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
>+*NONINFRINGEMENT.  IN NO EVENT SHALL Mill.Chen and Monk.Liu OR COPYRIGHT
>+*HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
>+*WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
>+*FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
>+*OTHER DEALINGS IN THE SOFTWARE.
>+*******************************************************************/
>+#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
>diff --git a/drivers/video/lynxfb/lynx_drv.c b/drivers/video/lynxfb/lynx_drv.c
>new file mode 100644
>index 0000000..556902d
>--- /dev/null
>+++ b/drivers/video/lynxfb/lynx_drv.c
>@@ -0,0 +1,1688 @@
>+/*******************************************************************
>+*Copyright (c) 2012 by Silicon Motion, Inc. (SMI)
>+*Permission is hereby granted, free of charge, to any person obtaining a copy
>+*of this software and associated documentation files (the "Software"), to deal
>+*in the Software without restriction, including without limitation the rights to
>+*use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
>+*of the Software, and to permit persons to whom the Software is furnished to
>+*do so, subject to the following conditions:
>+*
>+*THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
>+*EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
>+*OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
>+*NONINFRINGEMENT.  IN NO EVENT SHALL Mill.Chen and Monk.Liu OR COPYRIGHT
>+*HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
>+*WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
>+*FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
>+*OTHER DEALINGS IN THE SOFTWARE.
>+*******************************************************************/
>+#include <linux/version.h>
>+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 10)
>+#include <linux/config.h>
>+#endif
>+#include <linux/kernel.h>
>+#include <linux/module.h>
>+#include <linux/errno.h>
>+#include <linux/string.h>
>+#include <linux/mm.h>
>+#include <linux/slab.h>
>+#include <linux/delay.h>
>+#include <linux/fb.h>
>+#include <linux/ioport.h>
>+#include <linux/init.h>
>+#include <linux/pci.h>
>+
>+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
>+/* no below two header files in 2.6.9 */
>+#include <linux/platform_device.h>
>+#include <linux/vmalloc.h>
>+#include <linux/pagemap.h>
>+#include <linux/screen_info.h>
>+#else
>+/* nothing by far */
>+#endif
>+#include <linux/vmalloc.h> #include<linux/pagemap.h>
>+#include <linux/console.h>
>+#ifdef CONFIG_MTRR
>+#include <asm/mtrr.h>
>+#endif
>+
>+#include "lynx_drv.h"
>+#include "ver.h"
>+#include "lynx_hw750.h"
>+#include "lynx_accel.h"
>+#include "lynx_cursor.h"
>+
>+#include "modedb.c"
>+
>+int smi_indent;
>+#ifdef MODULE
>+static void __exit lynxfb_exit(void);
>+#endif
>+
>+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
>+static int  lynxfb_setup(char *);
>+static int __init lynxfb_init(void);
>+#else
>+int __init lynxfb_setup(char *);
>+int __init lynxfb_init(void);
>+#endif
>+
>+/* chip specific setup routine */
>+static void sm750fb_setup(struct lynx_share *, char *);
>+static int __devinit lynxfb_pci_probe(struct pci_dev *, const struct pci_device_id *);
>+static void __devexit lynxfb_pci_remove(struct pci_dev *);
>+
>+#ifdef CONFIG_PM
>+static int lynxfb_suspend(struct pci_dev *, pm_message_t);
>+static int lynxfb_resume(struct pci_dev *);
>+#endif
>+
>+static int __devinit lynxfb_set_fbinfo(struct fb_info *, int);
>+static int lynxfb_ops_check_var(struct fb_var_screeninfo *, struct fb_info *);
>+static int lynxfb_ops_set_par(struct fb_info *);
>+static int lynxfb_ops_setcolreg(unsigned, unsigned, unsigned, unsigned, unsigned, struct fb_info *);
>+static int lynxfb_ops_blank(int, struct fb_info *);
>+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
>+static int lynxfb_ops_cursor(struct fb_info *, struct fb_cursor *);
>+#endif
>+/*
>+#ifdef __BIG_ENDIAN
>+ssize_t lynxfb_ops_write(struct fb_info *info, const char __user *buf,
>+size_t count, loff_t *ppos);
>+ssize_t lynxfb_ops_read(struct fb_info *info, char __user *buf,
>+size_t count, loff_t *ppos);
>+#endif
>+*/
>+
>+typedef void (*PROC_SPEC_SETUP)(struct lynx_share *, char *);
>+typedef int (*PROC_SPEC_MAP)(struct lynx_share *, struct pci_dev *);
>+typedef int (*PROC_SPEC_INITHW)(struct lynx_share *, struct pci_dev *);
>+
>+/* common var for all device */
>+int g_hwcursor = 1;
>+int g_noaccel;
>+#ifdef CONFIG_MTRR
>+int g_nomtrr;
>+#endif
>+const char *g_fbmode[] = {NULL, NULL};
>+const char *g_def_fbmode = "800x600-16 at 60";
>+char *g_settings;
>+int g_dualview;
>+#ifdef MODULE
>+char *g_option;
>+#endif
>+
>+/* if not use spin_lock, system will die if user load driver
>+ *and immediatly unload driver frequently (dual)*/
>+static inline void myspin_lock(spinlock_t *sl)
>+{
>+	struct lynx_share *share;
>+	share = container_of(sl, struct lynx_share, slock);
>+	if (share->dual) {
>+		spin_lock(sl);
>+	}
>+}
>+
>+static inline void myspin_unlock(spinlock_t *sl)
>+{
>+	struct lynx_share *share;
>+	share = container_of(sl, struct lynx_share, slock);
>+	if (share->dual) {
>+		spin_unlock(sl);
>+	}
>+}
>+
>+static const struct fb_videomode lynx750_ext[] = {
>+	/*  	1024x600-60 VESA 	[1.71:1]	*/
>+	{NULL, 60, 1024, 600, 20423, 144, 40, 18, 1, 104, 3,
>+		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED},
>+
>+	/* 	1024x600-70 VESA */
>+	{NULL, 70, 1024, 600, 17211, 152, 48, 21, 1, 104, 3,
>+		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED},
>+
>+	/*  	1024x600-75 VESA */
>+	{NULL, 75, 1024, 600, 15822, 160, 56, 23, 1, 104, 3,
>+		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED},
>+
>+	/*  	1024x600-85 VESA */
>+	{NULL, 85, 1024, 600, 13730, 168, 56, 26, 1, 112, 3,
>+		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED},
>+
>+	/*	720x480	*/
>+	{NULL, 60, 720, 480, 37427, 88, 16, 13, 1, 72, 3,
>+		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED},
>+
>+	/*	1280x720		[1.78:1]	*/
>+	{NULL, 60, 1280, 720, 13426, 162, 86, 22, 1, 136, 3,
>+		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED},
>+
>+	/* 1280x768 at 60 */
>+	{NULL, 60, 1280, 768, 12579, 192, 64, 20, 3, 128, 7,
>+		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED},
>+
>+	{NULL, 60, 1360, 768, 11804, 208, 64, 23, 1, 144, 3,
>+		FB_SYNC_HOR_HIGH_ACT|FB_VMODE_NONINTERLACED},
>+
>+	/*	1360 x 768	[1.77083:1]	*/
>+	{NULL, 60, 1360, 768, 11804, 208, 64, 23, 1, 144, 3,
>+		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED},
>+
>+	/*	1368 x 768      [1.78:1]	*/
>+	{NULL, 60, 1368, 768, 11647, 216, 72, 23, 1, 144, 3,
>+		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED},
>+
>+	/* 	1440 x 900		[16:10]	*/
>+	{NULL, 60, 1440, 900, 9392, 232, 80, 28, 1, 152, 3,
>+		FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED},
>+
>+	/*	1440x960		[15:10]	*/
>+	{NULL, 60, 1440, 960, 8733, 240, 88, 30, 1, 152, 3,
>+		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED},
>+
>+	/*	1920x1080	[16:9]	*/
>+	{NULL, 60, 1920, 1080, 6734, 148, 88, 41, 1, 44, 3,
>+		FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED},
>+};
>+
>+
>+static struct pci_device_id smi_pci_table[] = {
>+	{PCI_VENDOR_ID_SMI, PCI_DEVID_LYNX_EXP, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
>+	{PCI_VENDOR_ID_SMI, PCI_DEVID_LYNX_SE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
>+	{PCI_VENDOR_ID_SMI, PCI_DEVID_LYNX_EM, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
>+	{PCI_VENDOR_ID_SMI, PCI_DEVID_LYNX_3DM, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
>+	{PCI_VENDOR_ID_SMI, PCI_DEVID_VOYAGER, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
>+	{0, }
>+};
>+
>+static struct pci_driver lynxfb_driver = {
>+	.name =	_moduleName_,
>+	.id_table =	smi_pci_table,
>+	.probe =	lynxfb_pci_probe,
>+	.remove =	__devexit_p(lynxfb_pci_remove),
>+#ifdef CONFIG_PM
>+	.suspend = lynxfb_suspend,
>+	.resume = lynxfb_resume,
>+#endif
>+};
>+
>+
>+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
>+/* no hardware cursor supported under version 2.6.10, kernel bug */
>+static int lynxfb_ops_cursor(struct fb_info *info, struct fb_cursor *fbcursor)
>+{
>+	struct lynxfb_par *par;
>+	struct lynxfb_crtc *crtc;
>+	struct lynx_cursor *cursor;
>+
>+	par = info->par;
>+	crtc = &par->crtc;
>+	cursor = &crtc->cursor;
>+
>+	if (fbcursor->image.width > cursor->maxW ||
>+			fbcursor->image.height > cursor->maxH ||
>+			fbcursor->image.depth > 1) {
>+		return -ENXIO;
>+	}
>+
>+	cursor->disable(cursor);
>+	if (fbcursor->set & FB_CUR_SETSIZE) {
>+		cursor->setSize(cursor, fbcursor->image.width, fbcursor->image.height);
>+	}
>+
>+	if (fbcursor->set & FB_CUR_SETPOS) {
>+		cursor->setPos(cursor, fbcursor->image.dx - info->var.xoffset,
>+				fbcursor->image.dy - info->var.yoffset);
>+	}
>+
>+	if (fbcursor->set & FB_CUR_SETCMAP) {
>+		/* get the 16bit color of kernel means */
>+		u16 fg, bg;
>+		fg = ((info->cmap.red[fbcursor->image.fg_color] & 0xf800))|
>+			((info->cmap.green[fbcursor->image.fg_color] & 0xfc00) >> 5)|
>+			((info->cmap.blue[fbcursor->image.fg_color] & 0xf800) >> 11);
>+
>+		bg = ((info->cmap.red[fbcursor->image.bg_color] & 0xf800))|
>+			((info->cmap.green[fbcursor->image.bg_color] & 0xfc00) >> 5)|
>+			((info->cmap.blue[fbcursor->image.bg_color] & 0xf800) >> 11);
>+
>+		cursor->setColor(cursor, fg, bg);
>+	}
>+
>+
>+	if (fbcursor->set & (FB_CUR_SETSHAPE | FB_CUR_SETIMAGE)) {
>+
>+		cursor->setData(cursor,
>+				fbcursor->rop,
>+				fbcursor->image.data,
>+				fbcursor->mask);
>+	}
>+
>+	if (fbcursor->enable) {
>+		cursor->enable(cursor);
>+	}
>+
>+	return 0;
>+}
>+
>+#endif
>+
>+static void lynxfb_ops_fillrect(struct fb_info *info, const struct fb_fillrect *region)
>+{
>+	struct lynxfb_par *par;
>+	struct lynx_share *share;
>+	unsigned int base, pitch, Bpp, rop;
>+	u32 color;
>+
>+	if (info->state != FBINFO_STATE_RUNNING) {
>+		return;
>+	}
>+
>+	par = info->par;
>+	share = par->share;
>+
>+	/* each time 2d function begin to work, below three variable always need
>+	 *be set, seems we can put them together in some place  */
>+	base = par->crtc.oScreen;
>+	pitch = info->fix.line_length;
>+	Bpp = info->var.bits_per_pixel >> 3;
>+
>+	color = (Bpp == 1) ? region->color : ((u32 *)info->pseudo_palette)[region->color];
>+	rop = (region->rop != ROP_COPY) ? HW_ROP2_XOR : HW_ROP2_COPY;
>+
>+	myspin_lock(&share->slock);
>+	share->accel.de_fillrect(&share->accel,
>+			base, pitch, Bpp,
>+			region->dx, region->dy,
>+			region->width, region->height,
>+			color, rop);
>+	myspin_unlock(&share->slock);
>+}
>+
>+static void lynxfb_ops_copyarea(struct fb_info *info, const struct fb_copyarea *region)
>+{
>+	struct lynxfb_par *par;
>+	struct lynx_share *share;
>+	unsigned int base, pitch, Bpp;
>+
>+	par = info->par;
>+	share = par->share;
>+
>+	/* each time 2d function begin to work, below three variable always need
>+	 *be set, seems we can put them together in some place  */
>+	base = par->crtc.oScreen;
>+	pitch = info->fix.line_length;
>+	Bpp = info->var.bits_per_pixel >> 3;
>+
>+	myspin_lock(&share->slock);
>+	share->accel.de_copyarea(&share->accel,
>+			base, pitch, region->sx, region->sy,
>+			base, pitch, Bpp, region->dx, region->dy,
>+			region->width, region->height, HW_ROP2_COPY);
>+	myspin_unlock(&share->slock);
>+}
>+
>+static void lynxfb_ops_imageblit(struct fb_info *info, const struct fb_image *image)
>+{
>+	unsigned int base, pitch, Bpp;
>+	unsigned int fgcol, bgcol;
>+	struct lynxfb_par *par;
>+	struct lynx_share *share;
>+
>+	par = info->par;
>+	share = par->share;
>+	/* each time 2d function begin to work, below three variable always need
>+	 *be set, seems we can put them together in some place  */
>+	base = par->crtc.oScreen;
>+	pitch = info->fix.line_length;
>+	Bpp = info->var.bits_per_pixel >> 3;
>+
>+	if (image->depth == 1) {
>+		if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
>+				info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
>+			fgcol = ((u32 *)info->pseudo_palette)[image->fg_color];
>+			bgcol = ((u32 *)info->pseudo_palette)[image->bg_color];
>+		} else{
>+			fgcol = image->fg_color;
>+			bgcol = image->bg_color;
>+		}
>+		goto _do_work;
>+	}
>+	return;
>+_do_work:
>+	myspin_lock(&share->slock);
>+	share->accel.de_imageblit(&share->accel,
>+			image->data, image->width>>3, 0,
>+			base, pitch, Bpp,
>+			image->dx, image->dy,
>+			image->width, image->height,
>+			fgcol, bgcol, HW_ROP2_COPY);
>+	myspin_unlock(&share->slock);
>+}
>+
>+static int lynxfb_ops_pan_display(struct fb_var_screeninfo *var,
>+		struct fb_info *info)
>+{
>+	struct lynxfb_par *par;
>+	struct lynxfb_crtc *crtc;
>+	int ret;
>+	ENTER();
>+
>+	if (!info)
>+		LEAVE(-EINVAL);
>+
>+	ret = 0;
>+	par = info->par;
>+	crtc = &par->crtc;
>+	ret = crtc->proc_panDisplay(crtc, var, info);
>+
>+	LEAVE(ret);
>+}
>+
>+static struct fb_ops lynxfb_ops = {
>+	.owner = THIS_MODULE,
>+	.fb_check_var =  lynxfb_ops_check_var,
>+	.fb_set_par = lynxfb_ops_set_par,
>+	.fb_setcolreg = lynxfb_ops_setcolreg,
>+	.fb_blank = lynxfb_ops_blank,
>+	/* will be hooked by hardware */
>+	.fb_fillrect = cfb_fillrect,
>+	.fb_imageblit = cfb_imageblit,
>+	.fb_copyarea = cfb_copyarea,
>+	/* cursor */
>+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
>+	.fb_cursor = lynxfb_ops_cursor,
>+#else
>+	.fb_cursor = soft_cursor,
>+#endif
>+};
>+
>+static size_t spec_size[] = {
>+	[SPC_SM750] = sizeof(struct sm750_share),
>+};
>+
>+static PROC_SPEC_SETUP setup_rout[] = {
>+	[SPC_SM750] = sm750fb_setup,
>+};
>+
>+static PROC_SPEC_MAP map_rout[] = {
>+	[SPC_SM750] = hw_sm750_map,
>+};
>+
>+static PROC_SPEC_INITHW inithw_rout[] = {
>+	[SPC_SM750] = hw_sm750_inithw,
>+};
>+static int g_specId;
>+
>+#ifdef CONFIG_PM
>+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 10)
>+static u32 pci_state[16];
>+
>+static int lynxfb_suspend(struct pci_dev *pdev, pm_message_t mesg)
>+{
>+	int ret;
>+	struct fb_info *info;
>+	struct lynx_share *share;
>+
>+	ENTER();
>+	ret = 0;
>+	share = pci_get_drvdata(pdev);
>+
>+	if (mesg != 2 || mesg == pdev->dev.power_state)
>+		return ret;
>+
>+	/* suspend */
>+	acquire_console_sem();
>+
>+	info = share->fbinfo[0];
>+	if (info) {
>+		fb_set_suspend(info, 1);
>+	}
>+
>+	info = share->fbinfo[1];
>+
>+	if (info) {
>+		fb_set_suspend(info, 1);
>+	}
>+
>+	/* hardware suspend stuffs */
>+	if (mesg == 2 && share->suspend)
>+		share->suspend(share);
>+
>+	pci_save_state(pdev, &pci_state);
>+	pci_disable_device(pdev);
>+	ret = pci_set_power_state(pdev, mesg);
>+
>+	release_console_sem();
>+	pdev->dev.power_state = mesg;
>+	LEAVE(ret);
>+}
>+
>+static int lynxfb_resume(struct pci_dev *pdev)
>+{
>+	int ret;
>+	struct fb_info *info;
>+	struct lynx_share *share;
>+	struct lynxfb_par *par;
>+	struct lynxfb_crtc *crtc;
>+	struct lynx_cursor *cursor;
>+
>+	ENTER();
>+	share = pci_get_drvdata(pdev);
>+	ret = 0;
>+
>+	acquire_console_sem();
>+
>+	pci_set_power_state(pdev, 0);
>+	pci_restore_state(pdev, &pci_state);
>+	pci_enable_device(pdev);
>+
>+	if (pdev->dev.power_state == 2 && share->resume)
>+		share->resume(share);
>+
>+	(*inithw_rout[g_specId])(share, pdev);
>+
>+	info = share->fbinfo[0];
>+	if (info) {
>+		par = info->par;
>+		crtc = &par->crtc;
>+		cursor = &crtc->cursor;
>+		memset(cursor->vstart, 0x0, cursor->size);
>+		memset(crtc->vScreen, 0x0, crtc->vidmem_size);
>+		lynxfb_ops_set_par(info);
>+		fb_set_suspend(info, 0);
>+	}
>+
>+	info = share->fbinfo[1];
>+
>+	if (info) {
>+		par = info->par;
>+		crtc = &par->crtc;
>+		cursor = &crtc->cursor;
>+		memset(cursor->vstart, 0x0, cursor->size);
>+		memset(crtc->vScreen, 0x0, crtc->vidmem_size);
>+		lynxfb_ops_set_par(info);
>+		fb_set_suspend(info, 0);
>+	}
>+
>+	release_console_sem();
>+	pdev->dev.power_state = 0;
>+	LEAVE(ret);
>+}
>+
>+
>+#else
>+static int lynxfb_suspend(struct pci_dev *pdev, pm_message_t mesg)
>+{
>+	struct fb_info *info;
>+	struct lynx_share *share;
>+	int ret;
>+	ENTER();
>+
>+	if (mesg.event == pdev->dev.power.power_state.event)
>+		LEAVE(0);
>+
>+	ret = 0;
>+	share = pci_get_drvdata(pdev);
>+	switch (mesg.event) {
>+	case PM_EVENT_FREEZE:
>+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
>+	case PM_EVENT_PRETHAW:
>+#endif
>+			pdev->dev.power.power_state = mesg;
>+			LEAVE(0);
>+	}
>+
>+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35)
>+	acquire_console_sem();
>+#else
>+	console_lock();
>+#endif
>+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 24)
>+	if (mesg.event & PM_EVENT_SUSPEND) {
>+#else
>+		if (mesg.event & PM_EVENT_SLEEP) {
>+#endif
>+			info = share->fbinfo[0];
>+			if (info)
>+				fb_set_suspend(info, 1);/* 1 means do suspend*/
>+
>+			info = share->fbinfo[1];
>+			if (info)
>+				fb_set_suspend(info, 1);/* 1 means do suspend*/
>+
>+			ret = pci_save_state(pdev);
>+			if (ret) {
>+				err_msg("error:%d occured in pci_save_state\n", ret);
>+				LEAVE(ret);
>+			}
>+
>+			/* set chip to sleep mode	*/
>+			if (share->suspend)
>+				(*share->suspend)(share);
>+
>+			pci_disable_device(pdev);
>+			ret = pci_set_power_state(pdev, pci_choose_state(pdev, mesg));
>+			if (ret) {
>+				err_msg("error:%d occured in pci_set_power_state\n", ret);
>+				LEAVE(ret);
>+			}
>+		}
>+
>+		pdev->dev.power.power_state = mesg;
>+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35)
>+		release_console_sem();
>+#else
>+		console_unlock();
>+#endif
>+		LEAVE(ret);
>+	}
>+
>+	static int lynxfb_resume(struct pci_dev *pdev)
>+	{
>+		struct fb_info *info;
>+		struct lynx_share *share;
>+
>+		struct lynxfb_par *par;
>+		struct lynxfb_crtc *crtc;
>+		struct lynx_cursor *cursor;
>+
>+		int ret;
>+		ENTER();
>+
>+		ret = 0;
>+		share = pci_get_drvdata(pdev);
>+
>+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35)
>+		acquire_console_sem();
>+#else
>+		console_lock();
>+#endif
>+
>+		ret = pci_set_power_state(pdev, PCI_D0);
>+		if (ret != 0) {
>+			err_msg("error:%d occured in pci_set_power_state\n", ret);
>+			LEAVE(ret);
>+		}
>+
>+
>+		if (pdev->dev.power.power_state.event != PM_EVENT_FREEZE) {
>+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35)
>+			/* for linux 2.6.35 and lower */
>+			ret = pci_restore_state(pdev);
>+			if (ret != 0) {
>+				err_msg("error:%d occured in pci_restore_state\n", ret);
>+				LEAVE(ret);
>+			}
>+#else
>+			pci_restore_state(pdev);
>+#endif
>+			ret = pci_enable_device(pdev);
>+			if (ret != 0) {
>+				err_msg("error:%d occured in pci_enable_device\n", ret);
>+				LEAVE(ret);
>+			}
>+			pci_set_master(pdev);
>+		}
>+		if (share->resume)
>+			(*share->resume)(share);
>+
>+		(*inithw_rout[g_specId])(share, pdev);
>+
>+
>+		info = share->fbinfo[0];
>+
>+		if (info) {
>+			par = info->par;
>+			crtc = &par->crtc;
>+			cursor = &crtc->cursor;
>+			memset(cursor->vstart, 0x0, cursor->size);
>+			memset(crtc->vScreen, 0x0, crtc->vidmem_size);
>+			lynxfb_ops_set_par(info);
>+			fb_set_suspend(info, 0);
>+		}
>+
>+		info = share->fbinfo[1];
>+
>+		if (info) {
>+			par = info->par;
>+			crtc = &par->crtc;
>+			cursor = &crtc->cursor;
>+			memset(cursor->vstart, 0x0, cursor->size);
>+			memset(crtc->vScreen, 0x0, crtc->vidmem_size);
>+			lynxfb_ops_set_par(info);
>+			fb_set_suspend(info, 0);
>+		}
>+
>+
>+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35)
>+		release_console_sem();
>+#else
>+		console_unlock();
>+#endif
>+		LEAVE(ret);
>+	}
>+#endif
>+#endif
>+
>+static int lynxfb_ops_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
>+{
>+	struct lynxfb_par *par;
>+	struct lynxfb_crtc *crtc;
>+	struct lynxfb_output *output;
>+	struct lynx_share *share;
>+	int ret;
>+	resource_size_t request;
>+
>+	ENTER();
>+	par = info->par;
>+	crtc = &par->crtc;
>+	output = &par->output;
>+	share = par->share;
>+	ret = 0;
>+
>+	dbg_msg("check var:%dx%d-%d\n",
>+			var->xres,
>+			var->yres,
>+			var->bits_per_pixel);
>+
>+
>+	switch (var->bits_per_pixel) {
>+	case 8:
>+	case 16:
>+	case 24: /* support 24 bpp for only lynx712/722/720 */
>+	case 32:
>+		break;
>+	default:
>+		err_msg("bpp %d not supported\n", var->bits_per_pixel);
>+		ret = -EINVAL;
>+		goto exit;
>+	}
>+
>+	switch (var->bits_per_pixel) {
>+	case 8:
>+		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
>+		var->red.offset = 0;
>+		var->red.length = 8;
>+		var->green.offset = 0;
>+		var->green.length = 8;
>+		var->blue.offset = 0;
>+		var->blue.length = 8;
>+		var->transp.length = 0;
>+		var->transp.offset = 0;
>+		break;
>+	case 16:
>+		var->red.offset = 11;
>+		var->red.length = 5;
>+		var->green.offset = 5;
>+		var->green.length = 6;
>+		var->blue.offset = 0;
>+		var->blue.length = 5;
>+		var->transp.length = 0;
>+		var->transp.offset = 0;
>+		info->fix.visual = FB_VISUAL_TRUECOLOR;
>+		break;
>+	case 24:
>+	case 32:
>+		var->red.offset = 16;
>+		var->red.length = 8;
>+		var->green.offset = 8;
>+		var->green.length = 8;
>+		var->blue.offset = 0 ;
>+		var->blue.length = 8;
>+		info->fix.visual = FB_VISUAL_TRUECOLOR;
>+		break;
>+	default:
>+		ret = -EINVAL;
>+		break;
>+	}
>+	var->height = var->width = -1;
>+	var->accel_flags = FB_ACCELF_TEXT;
>+
>+	/* check if current fb's video memory big enought to hold the onscreen */
>+	request = var->xres_virtual * (var->bits_per_pixel >> 3);
>+	/* defaulty crtc->channel go with par->index */
>+
>+	request = PADDING(crtc->line_pad, request);
>+	request = request * var->yres_virtual;
>+	if (crtc->vidmem_size < request) {
>+		err_msg("not enough video memory for mode\n");
>+		LEAVE(-ENOMEM);
>+	}
>+
>+	ret = output->proc_checkMode(output, var);
>+	if (!ret)
>+		ret = crtc->proc_checkMode(crtc, var);
>+exit:
>+	LEAVE(ret);
>+}
>+
>+static int lynxfb_ops_set_par(struct fb_info *info)
>+{
>+	struct lynxfb_par *par;
>+	struct lynx_share *share;
>+	struct lynxfb_crtc *crtc;
>+	struct lynxfb_output *output;
>+	struct fb_var_screeninfo *var;
>+	struct fb_fix_screeninfo *fix;
>+	int ret;
>+	unsigned int line_length;
>+	ENTER();
>+
>+	if (!info)
>+		LEAVE(-EINVAL);
>+
>+	ret = 0;
>+	par = info->par;
>+	share = par->share;
>+	crtc = &par->crtc;
>+	output = &par->output;
>+	var = &info->var;
>+	fix = &info->fix;
>+
>+	/* fix structur is not so FIX ... */
>+	line_length = var->xres_virtual * var->bits_per_pixel / 8;
>+	line_length = PADDING(crtc->line_pad, line_length);
>+	fix->line_length = line_length;
>+	err_msg("fix->line_length = %d\n", fix->line_length);
>+
>+	/* var->red, green, blue, transp are need to be set by driver
>+	 *and these data should be set before setcolreg routine
>+	 **/
>+
>+	switch (var->bits_per_pixel) {
>+	case 8:
>+		fix->visual = FB_VISUAL_PSEUDOCOLOR;
>+		var->red.offset = 0;
>+		var->red.length = 8;
>+		var->green.offset = 0;
>+		var->green.length = 8;
>+		var->blue.offset = 0;
>+		var->blue.length = 8;
>+		var->transp.length = 0;
>+		var->transp.offset = 0;
>+		break;
>+	case 16:
>+		var->red.offset = 11;
>+		var->red.length = 5;
>+		var->green.offset = 5;
>+		var->green.length = 6;
>+		var->blue.offset = 0;
>+		var->blue.length = 5;
>+		var->transp.length = 0;
>+		var->transp.offset = 0;
>+		fix->visual = FB_VISUAL_TRUECOLOR;
>+		break;
>+	case 24:
>+	case 32:
>+		var->red.offset = 16;
>+		var->red.length = 8;
>+		var->green.offset = 8;
>+		var->green.length = 8;
>+		var->blue.offset = 0 ;
>+		var->blue.length = 8;
>+		fix->visual = FB_VISUAL_TRUECOLOR;
>+		break;
>+	default:
>+		ret = -EINVAL;
>+		break;
>+	}
>+	var->height = var->width = -1;
>+	var->accel_flags = FB_ACCELF_TEXT;
>+
>+	if (ret) {
>+		err_msg("pixel bpp format not satisfied\n.");
>+		LEAVE(ret);
>+	}
>+	ret = crtc->proc_setMode(crtc, var, fix);
>+	if (!ret)
>+		ret = output->proc_setMode(output, var, fix);
>+	LEAVE(ret);
>+}
>+static inline unsigned int chan_to_field(unsigned int chan, struct fb_bitfield *bf)
>+{
>+	chan &= 0xffff;
>+	chan >>= 16 - bf->length;
>+	return chan << bf->offset;
>+}
>+
>+static int lynxfb_ops_setcolreg(unsigned regno, unsigned red,
>+		unsigned green, unsigned blue,
>+		unsigned transp, struct fb_info *info)
>+{
>+	struct lynxfb_par *par;
>+	struct lynxfb_crtc *crtc;
>+	struct fb_var_screeninfo *var;
>+	int ret;
>+
>+	par = info->par;
>+	crtc = &par->crtc;
>+	var = &info->var;
>+	ret = 0;
>+
>+	/*dbg_msg("regno=%d, red=%d, green=%d, blue=%d\n", regno, red, green, blue);*/
>+	if (regno > 256) {
>+		err_msg("regno = %d\n", regno);
>+		LEAVE(-EINVAL);
>+	}
>+
>+	if (info->var.grayscale)
>+		red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
>+
>+	if (var->bits_per_pixel == 8 && info->fix.visual == FB_VISUAL_PSEUDOCOLOR) {
>+		red >>= 8;
>+		green >>= 8;
>+		blue >>= 8;
>+		ret = crtc->proc_setColReg(crtc, regno, red, green, blue);
>+		goto exit;
>+	}
>+
>+
>+	if (info->fix.visual == FB_VISUAL_TRUECOLOR && regno < 256) {
>+		u32 val;
>+		if (var->bits_per_pixel == 16 ||
>+				var->bits_per_pixel == 32 ||
>+				var->bits_per_pixel == 24) {
>+			val = chan_to_field(red, &var->red);
>+			val |= chan_to_field(green, &var->green);
>+			val |= chan_to_field(blue, &var->blue);
>+			par->pseudo_palette[regno] = val;
>+			goto exit;
>+		}
>+	}
>+
>+	ret = -EINVAL;
>+
>+exit:
>+	return ret;
>+	LEAVE(ret);
>+
>+}
>+
>+static int lynxfb_ops_blank(int blank, struct fb_info *info)
>+{
>+	struct lynxfb_par *par;
>+	struct lynxfb_output *output;
>+	ENTER();
>+	dbg_msg("blank = %d.\n", blank);
>+	par = info->par;
>+	output = &par->output;
>+	LEAVE(output->proc_setBLANK(output, blank));
>+}
>+static int sm750fb_set_drv(struct lynxfb_par *par)
>+{
>+	int ret;
>+	struct lynx_share *share;
>+	struct sm750_share *spec_share;
>+	struct lynxfb_output *output;
>+	struct lynxfb_crtc *crtc;
>+	ENTER();
>+	ret = 0;
>+
>+	share = par->share;
>+	spec_share = container_of(share, struct sm750_share, share);
>+	output = &par->output;
>+	crtc = &par->crtc;
>+
>+	crtc->vidmem_size = (share->dual) ? share->vidmem_size>>1 : share->vidmem_size;
>+	/* setup crtc and output member */
>+	spec_share->hwCursor = g_hwcursor;
>+
>+	crtc->proc_setMode = hw_sm750_crtc_setMode;
>+	crtc->proc_checkMode = hw_sm750_crtc_checkMode;
>+	crtc->proc_setColReg = hw_sm750_setColReg;
>+	crtc->proc_panDisplay = hw_sm750_pan_display;
>+	crtc->clear = hw_sm750_crtc_clear;
>+	crtc->line_pad = 16;
>+	/*crtc->xpanstep = crtc->ypanstep = crtc->ywrapstep = 0;*/
>+	crtc->xpanstep = 8;
>+	crtc->ypanstep = 1;
>+	crtc->ywrapstep = 0;
>+
>+	output->proc_setMode = hw_sm750_output_setMode;
>+	output->proc_checkMode = hw_sm750_output_checkMode;
>+
>+	output->proc_setBLANK = (share->revid == SM750LE_REVISION_ID) ? hw_sm750le_setBLANK : hw_sm750_setBLANK;
>+	output->clear = hw_sm750_output_clear;
>+	/* chip specific phase */
>+	share->accel.de_wait = (share->revid == SM750LE_REVISION_ID) ? hw_sm750le_deWait : hw_sm750_deWait;
>+	switch (spec_share->state.dataflow) {
>+	case sm750_simul_pri:
>+			output->paths = sm750_pnc;
>+			crtc->channel = sm750_primary;
>+			crtc->oScreen = 0;
>+			crtc->vScreen = share->pvMem;
>+			inf_msg("use simul primary mode\n");
>+			break;
>+	case sm750_simul_sec:
>+			output->paths = sm750_pnc;
>+			crtc->channel = sm750_secondary;
>+			crtc->oScreen = 0;
>+			crtc->vScreen = share->pvMem;
>+			break;
>+	case sm750_dual_normal:
>+			if (par->index == 0) {
>+				output->paths = sm750_panel;
>+				crtc->channel = sm750_primary;
>+				crtc->oScreen = 0;
>+				crtc->vScreen = share->pvMem;
>+			} else{
>+				output->paths = sm750_crt;
>+				crtc->channel = sm750_secondary;
>+				/* not consider of padding stuffs for oScreen, need fix*/
>+				crtc->oScreen = (share->vidmem_size >> 1);
>+				crtc->vScreen = share->pvMem + crtc->oScreen;
>+			}
>+			break;
>+	case sm750_dual_swap:
>+			if (par->index == 0) {
>+				output->paths = sm750_panel;
>+				crtc->channel = sm750_secondary;
>+				crtc->oScreen = 0;
>+				crtc->vScreen = share->pvMem;
>+			} else{
>+				output->paths = sm750_crt;
>+				crtc->channel = sm750_primary;
>+				/* not consider of padding stuffs for oScreen, need fix*/
>+				crtc->oScreen = (share->vidmem_size >> 1);
>+				crtc->vScreen = share->pvMem + crtc->oScreen;
>+			}
>+			break;
>+	default:
>+			ret = -EINVAL;
>+	}
>+
>+	LEAVE(ret);
>+}
>+
>+static int __devinit lynxfb_set_fbinfo(struct fb_info *info, int index)
>+{
>+	int i;
>+	struct lynxfb_par *par;
>+	struct lynx_share *share;
>+	struct lynxfb_crtc *crtc;
>+	struct lynxfb_output *output;
>+	struct fb_var_screeninfo *var;
>+	struct fb_fix_screeninfo *fix;
>+
>+	const struct fb_videomode *pdb[] = {
>+		NULL, NULL, vesa_modes,
>+	};
>+	int cdb[] = {0, 0, VESA_MODEDB_SIZE};
>+	static const char *mdb_desc[] = {
>+		"driver prepared modes",
>+		"kernel prepared default modedb",
>+		"kernel HELPERS prepared vesa_modes",
>+	};
>+
>+#define sm502_ext lynx750_ext
>+	static const struct fb_videomode *ext_table[] = {lynx750_ext, NULL, sm502_ext};
>+	static size_t ext_size[] = {ARRAY_SIZE(lynx750_ext), 0, ARRAY_SIZE(sm502_ext)};
>+
>+	static const char *fixId[][2] = {
>+		{"sm750_fb1", "sm750_fb2"},
>+	};
>+
>+	int ret, line_length;
>+	ENTER();
>+	ret = 0;
>+	par = (struct lynxfb_par *)info->par;
>+	share = par->share;
>+	crtc = &par->crtc;
>+	output = &par->output;
>+	var = &info->var;
>+	fix = &info->fix;
>+
>+	/* set index */
>+	par->index = index;
>+	output->channel = &crtc->channel;
>+
>+	sm750fb_set_drv(par);
>+	lynxfb_ops.fb_pan_display = lynxfb_ops_pan_display;
>+
>+	/* set current cursor variable and proc pointer,
>+	 *must be set after crtc member initialized */
>+
>+	crtc->cursor.offset = crtc->oScreen + crtc->vidmem_size - 1024;
>+	crtc->cursor.mmio = share->pvReg + 0x800f0 + (int)crtc->channel * 0x140;
>+
>+	inf_msg("crtc->cursor.mmio = %p\n", crtc->cursor.mmio);
>+	crtc->cursor.maxH = crtc->cursor.maxW = 64;
>+	crtc->cursor.size = crtc->cursor.maxH*crtc->cursor.maxW*2/8;
>+	crtc->cursor.disable = hw_cursor_disable;
>+	crtc->cursor.enable = hw_cursor_enable;
>+	crtc->cursor.setColor = hw_cursor_setColor;
>+	crtc->cursor.setPos = hw_cursor_setPos;
>+	crtc->cursor.setSize = hw_cursor_setSize;
>+	crtc->cursor.setData = hw_cursor_setData;
>+	crtc->cursor.vstart = share->pvMem + crtc->cursor.offset;
>+
>+	crtc->cursor.share = share;
>+	memset(crtc->cursor.vstart, 0, crtc->cursor.size);
>+	if (!g_hwcursor) {
>+		lynxfb_ops.fb_cursor = NULL;
>+		crtc->cursor.disable(&crtc->cursor);
>+	}
>+
>+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 10)
>+		/* hardware cursor broken under low version kernel*/
>+		lynxfb_ops.fb_cursor = soft_cursor;
>+#endif
>+
>+		/* set info->fbops, must be set before fb_find_mode */
>+		if (!share->accel_off) {
>+			/* use 2d acceleration */
>+			lynxfb_ops.fb_fillrect = lynxfb_ops_fillrect;
>+			lynxfb_ops.fb_copyarea = lynxfb_ops_copyarea;
>+			lynxfb_ops.fb_imageblit = lynxfb_ops_imageblit;
>+		}
>+		info->fbops = &lynxfb_ops;
>+
>+		if (!g_fbmode[index]) {
>+			g_fbmode[index] = g_def_fbmode;
>+			if (index)
>+				g_fbmode[index] = g_fbmode[0];
>+		}
>+
>+		pdb[0] = ext_table[g_specId];
>+		cdb[0] = ext_size[g_specId];
>+
>+		for (i = 0; i < 3; i++) {
>+			/* no NULL pointer passed to fb_find_mode @4 */
>+			if (pdb[i] == NULL) {
>+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 10)
>+				pdb[i] = &modedb2[0];
>+				cdb[i] = nmodedb2;
>+#endif
>+			}
>+
>+			ret = fb_find_mode(var, info, g_fbmode[index],
>+					pdb[i], cdb[i], NULL, 8);
>+
>+			if (ret == 1) {
>+				inf_msg("success! use specified mode:%s in %s\n",
>+						g_fbmode[index],
>+						mdb_desc[i]);
>+				break;
>+			} else if (ret == 2) {
>+				war_msg("use specified mode:%s in %s, with an ignored refresh rate\n",
>+						g_fbmode[index],
>+						mdb_desc[i]);
>+				break;
>+			} else if (ret == 3) {
>+				war_msg("wanna use default mode\n");
>+				/*			break;*/
>+			} else if (ret == 4) {
>+				war_msg("fall back to any valid mode\n");
>+			} else{
>+				war_msg("ret = %d, fb_find_mode failed, with %s\n", ret, mdb_desc[i]);
>+			}
>+		}
>+
>+		/* some member of info->var had been set by fb_find_mode */
>+
>+		inf_msg("Member of info->var is :\n\
>+				xres=%d\n\
>+				yres=%d\n\
>+				xres_virtual=%d\n\
>+				yres_virtual=%d\n\
>+				xoffset=%d\n\
>+				yoffset=%d\n\
>+				bits_per_pixel=%d\n \
>+				...\n", var->xres, var->yres, var->xres_virtual, var->yres_virtual,
>+				var->xoffset, var->yoffset, var->bits_per_pixel);
>+
>+		/* set par */
>+		par->info = info;
>+
>+		/* set info */
>+		line_length = PADDING(crtc->line_pad,
>+				(var->xres_virtual * var->bits_per_pixel/8));
>+
>+		info->pseudo_palette = &par->pseudo_palette[0];
>+		info->screen_base = crtc->vScreen;
>+		dbg_msg("screen_base vaddr = %p\n", info->screen_base);
>+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 10)
>+		info->screen_size = line_length * var->yres_virtual;
>+#endif
>+		info->flags = FBINFO_FLAG_DEFAULT|0;
>+
>+		/* set info->fix */
>+		fix->type = FB_TYPE_PACKED_PIXELS;
>+		fix->type_aux = 0;
>+		fix->xpanstep = crtc->xpanstep;
>+		fix->ypanstep = crtc->ypanstep;
>+		fix->ywrapstep = crtc->ywrapstep;
>+		fix->accel = FB_ACCEL_NONE;
>+
>+		strlcpy(fix->id, fixId[g_specId][index], sizeof(fix->id));
>+
>+
>+		fix->smem_start = crtc->oScreen + share->vidmem_start;
>+		inf_msg("fix->smem_start = %lx\n", fix->smem_start);
>+
>+		/* according to mmap experiment from user space application,
>+		 *fix->mmio_len should not larger than virtual size
>+		 *(xres_virtual x yres_virtual x ByPP)
>+		 *Below line maybe buggy when user mmap fb dev node and write
>+		 *data into the bound over virtual size
>+		 **/
>+		fix->smem_len = crtc->vidmem_size;
>+		inf_msg("fix->smem_len = %x\n", fix->smem_len);
>+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 10)
>+		info->screen_size = fix->smem_len;
>+#endif
>+
>+		fix->line_length = line_length;
>+		fix->mmio_start = share->vidreg_start;
>+		inf_msg("fix->mmio_start = %lx\n", fix->mmio_start);
>+		fix->mmio_len = share->vidreg_size;
>+		inf_msg("fix->mmio_len = %x\n", fix->mmio_len);
>+		switch (var->bits_per_pixel) {
>+		case 8:
>+				fix->visual = FB_VISUAL_PSEUDOCOLOR;
>+				break;
>+		case 16:
>+		case 32:
>+				fix->visual = FB_VISUAL_TRUECOLOR;
>+				break;
>+		}
>+
>+		/* set var */
>+		var->activate = FB_ACTIVATE_NOW;
>+		var->accel_flags = 0;
>+		var->vmode = FB_VMODE_NONINTERLACED;
>+
>+		dbg_msg("#1 show info->cmap : \nstart=%d, len=%d, red=%p, green=%p, blue=%p, transp=%p\n",
>+				info->cmap.start, info->cmap.len,
>+				info->cmap.red, info->cmap.green, info->cmap.blue,
>+				info->cmap.transp);
>+
>+		ret = fb_alloc_cmap(&info->cmap, 256, 0);
>+		if (ret < 0) {
>+			err_msg("Could not allcate memory for cmap.\n");
>+			goto exit;
>+		}
>+
>+		dbg_msg("#2 show info->cmap : \nstart=%d, len=%d, red=%p, green=%p, blue=%p, transp=%p\n",
>+				info->cmap.start, info->cmap.len,
>+				info->cmap.red, info->cmap.green, info->cmap.blue,
>+				info->cmap.transp);
>+
>+exit:
>+		lynxfb_ops_check_var(var, info);
>+		/*    lynxfb_ops_set_par(info);*/
>+		LEAVE(ret);
>+	}
>+
>+	static int __devinit lynxfb_pci_probe(struct pci_dev *pdev,
>+			const struct pci_device_id *ent)
>+	{
>+		struct fb_info *info[] = {NULL, NULL};
>+		struct lynx_share *share = NULL;
>+
>+		void *spec_share = NULL;
>+		size_t spec_offset = 0;
>+		int fbidx;
>+		ENTER();
>+
>+		/* enable device */
>+		if (pci_enable_device(pdev)) {
>+			err_msg("can not enable device.\n");
>+			goto err_enable;
>+		}
>+
>+		switch (ent->device) {
>+		case PCI_DEVID_LYNX_EXP:
>+		case PCI_DEVID_LYNX_SE:
>+			g_specId = SPC_SM750;
>+				/* though offset of share in sm750_share is 0,
>+				 *we use this marcro as the same */
>+			spec_offset = offsetof(struct sm750_share, share);
>+			break;
>+		default:
>+			break;
>+		}
>+
>+		dbg_msg("spec_offset = %d\n", spec_offset);
>+		spec_share = kzalloc(spec_size[g_specId], GFP_KERNEL);
>+		if (!spec_share) {
>+			err_msg("Could not allocate memory for share.\n");
>+			goto err_share;
>+		}
>+
>+		/* setting share structure */
>+		share = (struct lynx_share *)(spec_share + spec_offset);
>+		share->fbinfo[0] = share->fbinfo[1] = NULL;
>+		share->devid = pdev->device;
>+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 22)
>+		u32 temp;
>+		pci_read_config_dword(pdev, PCI_CLASS_REVISION, &temp);
>+		share->revid = temp&0xFF;
>+#else
>+		share->revid = pdev->revision;
>+#endif
>+
>+		inf_msg("share->revid = %02x\n", share->revid);
>+		share->pdev = pdev;
>+#ifdef CONFIG_MTRR
>+		share->mtrr_off = g_nomtrr;
>+		share->mtrr.vram = 0;
>+		share->mtrr.vram_added = 0;
>+#endif
>+		share->accel_off = g_noaccel;
>+		share->dual = g_dualview;
>+		spin_lock_init(&share->slock);
>+
>+		if (!share->accel_off) {
>+			/* hook deInit and 2d routines, notes that below hw_xxx
>+			 *routine can work on most of lynx chips
>+			 *if some chip need specific function, please hook it in smXXX_set_drv
>+			 *routine */
>+			share->accel.de_init = hw_de_init;
>+			share->accel.de_fillrect = hw_fillrect;
>+			share->accel.de_copyarea = hw_copyarea;
>+			share->accel.de_imageblit = hw_imageblit;
>+			inf_msg("enable 2d acceleration\n");
>+		} else{
>+			inf_msg("disable 2d acceleration\n");
>+		}
>+
>+		/* call chip specific setup routine  */
>+		(*setup_rout[g_specId])(share, g_settings);
>+
>+		/* call chip specific mmap routine */
>+		if ((*map_rout[g_specId])(share, pdev)) {
>+			err_msg("Memory map failed\n");
>+			goto err_map;
>+		}
>+
>+#ifdef CONFIG_MTRR
>+		if (!share->mtrr_off) {
>+			inf_msg("enable mtrr\n");
>+			share->mtrr.vram = mtrr_add(share->vidmem_start,
>+					share->vidmem_size,
>+					MTRR_TYPE_WRCOMB, 1);
>+
>+			if (share->mtrr.vram < 0) {
>+				/* don't block driver with the failure of MTRR */
>+				err_msg("Unable to setup MTRR.\n");
>+			} else{
>+				share->mtrr.vram_added = 1;
>+				inf_msg("MTRR added succesfully\n");
>+			}
>+		}
>+#endif
>+
>+		memset(share->pvMem, 0, share->vidmem_size);
>+
>+		inf_msg("sm%3x mmio address = %p\n", share->devid, share->pvReg);
>+
>+		pci_set_drvdata(pdev, share);
>+
>+		/* call chipInit routine */
>+		(*inithw_rout[g_specId])(share, pdev);
>+
>+		/* detect 502 need no disp driver
>+		 *beware that other chips except 502 should not touch g_502nodisp
>+		 *(remain g_502nodisp always 0)
>+		 *so regularily, below if line will not affect other chips' behaviour
>+		 **/
>+	/*	if (!g_no502disp) {*/
>+			/* allocate frame buffer info structor according to g_dualview */
>+			fbidx = 0;
>+ALLOC_FB:
>+			info[fbidx] = framebuffer_alloc(sizeof(struct lynxfb_par), &pdev->dev);
>+			if (!info[fbidx]) {
>+				err_msg("Could not allocate framebuffer #%d.\n", fbidx);
>+				if (fbidx == 0)
>+					goto err_info0_alloc;
>+				else
>+					goto err_info1_alloc;
>+			} else{
>+				struct lynxfb_par *par;
>+				inf_msg("framebuffer #%d alloc okay\n", fbidx);
>+				share->fbinfo[fbidx] = info[fbidx];
>+				par = info[fbidx]->par;
>+				par->share = share;
>+
>+				/* set fb_info structure */
>+				if (lynxfb_set_fbinfo(info[fbidx], fbidx)) {
>+					err_msg("Failed to initial fb_info #%d.\n", fbidx);
>+					if (fbidx == 0)
>+						goto err_info0_set;
>+					else
>+						goto err_info1_set;
>+				}
>+
>+				/* register frame buffer*/
>+				inf_msg("Ready to register framebuffer #%d.\n", fbidx);
>+				int errno = register_framebuffer(info[fbidx]);
>+				if (errno < 0) {
>+					err_msg("Failed to register fb_info #%d. err %d\n", fbidx, errno);
>+					if (fbidx == 0)
>+						goto err_register0;
>+					else
>+						goto err_register1;
>+				}
>+				inf_msg("Accomplished register framebuffer #%d.\n", fbidx);
>+			}
>+
>+			/* no dual view by far */
>+			fbidx++;
>+			if (share->dual && fbidx < 2)
>+				goto ALLOC_FB;
>+/*		}*/
>+
>+		LEAVE(0);
>+
>+err_register1:
>+err_info1_set:
>+		framebuffer_release(info[1]);
>+err_info1_alloc:
>+		unregister_framebuffer(info[0]);
>+err_register0:
>+err_info0_set:
>+		framebuffer_release(info[0]);
>+err_info0_alloc:
>+err_map:
>+		kfree(spec_share);
>+err_share:
>+err_enable:
>+		LEAVE(-ENODEV);
>+	}
>+
>+static void __devexit lynxfb_pci_remove(struct pci_dev *pdev)
>+{
>+	struct fb_info *info;
>+	struct lynx_share *share;
>+	void *spec_share;
>+	struct lynxfb_par *par;
>+	int cnt;
>+	ENTER();
>+
>+	cnt = 2;
>+	share = pci_get_drvdata(pdev);
>+
>+	while (cnt-- > 0) {
>+		info = share->fbinfo[cnt];
>+		if (!info)
>+			continue;
>+		par = info->par;
>+
>+		unregister_framebuffer(info);
>+		/* clean crtc & output allocations*/
>+		par->crtc.clear(&par->crtc);
>+		par->output.clear(&par->output);
>+		/* release frame buffer*/
>+		framebuffer_release(info);
>+	}
>+#ifdef CONFIG_MTRR
>+	if (share->mtrr.vram_added)
>+		mtrr_del(share->mtrr.vram, share->vidmem_start, share->vidmem_size);
>+#endif
>+	/*	pci_release_regions(pdev);*/
>+
>+	iounmap(share->pvReg);
>+	iounmap(share->pvMem);
>+
>+	switch (share->devid) {
>+	case PCI_DEVID_LYNX_EXP:
>+	case PCI_DEVID_LYNX_SE:
>+			spec_share = container_of(share, struct sm750_share, share);
>+			break;
>+	default:
>+			spec_share = share;
>+	}
>+	kfree(g_settings);
>+	kfree(spec_share);
>+	pci_set_drvdata(pdev, NULL);
>+	LEAVE();
>+}
>+
>+
>+/* 	chip specific g_option configuration routine */
>+static void sm750fb_setup(struct lynx_share *share, char *src)
>+{
>+	struct sm750_share *spec_share;
>+	char *opt;
>+#ifdef CAP_EXPENSION
>+	char *exp_res;
>+#endif
>+	int swap;
>+	ENTER();
>+
>+	spec_share = container_of(share, struct sm750_share, share);
>+#ifdef CAP_EXPENSIION
>+	exp_res = NULL;
>+#endif
>+	swap = 0;
>+
>+	spec_share->state.initParm.chip_clk = 0;
>+	spec_share->state.initParm.mem_clk = 0;
>+	spec_share->state.initParm.master_clk = 0;
>+	spec_share->state.initParm.powerMode = 0;
>+	spec_share->state.initParm.setAllEngOff = 0;
>+	spec_share->state.initParm.resetMemory = 1;
>+
>+	/*defaultly turn g_hwcursor on for both view */
>+	g_hwcursor = 3;
>+
>+	if (!src || !*src) {
>+		war_msg("no specific g_option.\n");
>+		goto NO_PARAM;
>+	}
>+
>+	while ((opt = strsep(&src, ":")) != NULL && *opt != NULL) {
>+		err_msg("opt=%s\n", opt);
>+		err_msg("src=%s\n", src);
>+
>+		if (!strncmp(opt, "swap", strlen("swap")))
>+			swap = 1;
>+		else if (!strncmp(opt, "nocrt", strlen("nocrt")))
>+			spec_share->state.nocrt = 1;
>+		else if (!strncmp(opt, "36bit", strlen("36bit")))
>+			spec_share->state.pnltype = sm750_doubleTFT;
>+		else if (!strncmp(opt, "18bit", strlen("18bit")))
>+			spec_share->state.pnltype = sm750_dualTFT;
>+		else if (!strncmp(opt, "24bit", strlen("24bit")))
>+			spec_share->state.pnltype = sm750_24TFT;
>+#ifdef CAP_EXPANSION
>+		else if (!strncmp(opt, "exp:", strlen("exp:")))
>+			exp_res = opt + strlen("exp:");
>+#endif
>+		else if (!strncmp(opt, "nohwc0", strlen("nohwc0")))
>+			g_hwcursor &= ~0x1;
>+		else if (!strncmp(opt, "nohwc1", strlen("nohwc1")))
>+			g_hwcursor &= ~0x2;
>+		else if (!strncmp(opt, "nohwc", strlen("nohwc")))
>+			g_hwcursor = 0;
>+		else{
>+			if (!g_fbmode[0]) {
>+				g_fbmode[0] = opt;
>+				inf_msg("find fbmode0 : %s\n", g_fbmode[0]);
>+			} else if (!g_fbmode[1]) {
>+				g_fbmode[1] = opt;
>+				inf_msg("find fbmode1 : %s\n", g_fbmode[1]);
>+			} else{
>+				war_msg("How many view you wann set?\n");
>+			}
>+		}
>+	}
>+#ifdef CAP_EXPANSION
>+	if (getExpRes(exp_res, &spec_share->state.xLCD, &spec_share->state.yLCD)) {
>+		/* seems exp_res is not valid*/
>+		spec_share->state.xLCD = spec_share->state.yLCD = 0;
>+	}
>+#endif
>+
>+NO_PARAM:
>+	if (share->revid != SM750LE_REVISION_ID) {
>+		if (share->dual) {
>+			if (swap)
>+				spec_share->state.dataflow = sm750_dual_swap;
>+			else
>+				spec_share->state.dataflow = sm750_dual_normal;
>+		} else{
>+			if (swap)
>+				spec_share->state.dataflow = sm750_simul_sec;
>+			else
>+				spec_share->state.dataflow = sm750_simul_pri;
>+		}
>+	} else{
>+		/* SM750LE only have one crt channel */
>+		spec_share->state.dataflow = sm750_simul_sec;
>+		/* sm750le do not have complex attributes*/
>+		spec_share->state.nocrt = 0;
>+	}
>+
>+	LEAVE();
>+}
>+
>+
>+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
>+static int __init lynxfb_setup(char *options)
>+#else
>+int __init lynxfb_setup(char *options)
>+#endif
>+{
>+	int len;
>+	char *opt, *tmp;
>+	ENTER();
>+
>+	if (!options || !*options) {
>+		war_msg("no options.\n");
>+		LEAVE(0);
>+	}
>+
>+	inf_msg("options:%s\n", options);
>+
>+	len = strlen(options) + 1;
>+	g_settings = kmalloc(len, GFP_KERNEL);
>+	if (!g_settings)
>+		LEAVE(-ENOMEM);
>+
>+	memset(g_settings, 0, len);
>+	tmp = g_settings;
>+
>+	/* 	Notes:
>+		char *strsep(char **s, const char *ct);
>+		@s: the string to be searched
>+		@ct :the characters to search for
>+
>+		strsep() updates @options to pointer after the first found token
>+		it also returns the pointer ahead the token.
>+		*/
>+	while ((opt = strsep(&options, ":")) != NULL) {
>+		/* options that mean for any lynx chips are configured here */
>+		if (!strncmp(opt, "noaccel", strlen("noaccel")))
>+			g_noaccel = 1;
>+#ifdef CONFIG_MTRR
>+		else if (!strncmp(opt, "nomtrr", strlen("nomtrr")))
>+			g_nomtrr = 1;
>+#endif
>+		else if (!strncmp(opt, "dual", strlen("dual")))
>+			g_dualview = 1;
>+		else{
>+			strcat(tmp, opt);
>+			tmp += strlen(opt);
>+			if (options != NULL)
>+				*tmp++ = ':';
>+			else
>+				*tmp++ = 0;
>+		}
>+	}
>+
>+	/* misc g_settings are transport to chip specific routines */
>+	inf_msg("parameter left for chip specific analysis:%s\n", g_settings);
>+	LEAVE(0);
>+}
>+
>+
>+static void claim(void)
>+{
>+	inf_msg("+-------------SMI Driver Information------------+");
>+	inf_msg("Release type : " RELEASE_TYPE "\n");
>+	inf_msg("Driver version: v" _version_ "\n");
>+	inf_msg("Support products:\n"
>+			SUPPORT_CHIP);
>+	inf_msg("Support OS:\n"
>+			SUPPORT_OS);
>+	inf_msg("Support ARCH: " SUPPORT_ARCH "\n");
>+	inf_msg("+-----------------------------------------------+");
>+}
>+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
>+static int __init lynxfb_init()
>+{
>+	char *option ;
>+	int ret;
>+	smi_indent = 0;
>+	ENTER();
>+	claim();
>+#ifdef MODULE
>+	option = g_option;
>+#else
>+	if (fb_get_options("lynxfb", &option))
>+		LEAVE(-ENODEV);
>+#endif
>+
>+	lynxfb_setup(option);
>+	ret = pci_register_driver(&lynxfb_driver);
>+	LEAVE(ret);
>+}
>+#else /* kernel version >= 2.6.10*/
>+int __init lynxfb_init(void)
>+{
>+	char *option;
>+	int ret;
>+	smi_indent = 0;
>+	ENTER();
>+	claim();
>+#ifdef MODULE
>+	option = g_option;
>+	lynxfb_setup(option);
>+#else
>+	/* do nothing */
>+#endif
>+	ret = pci_register_driver(&lynxfb_driver);
>+	LEAVE(ret);
>+}
>+#endif
>+	module_init(lynxfb_init);
>+
>+#ifdef MODULE
>+static void __exit lynxfb_exit()
>+{
>+	ENTER();
>+	inf_msg(_moduleName_ " exit\n");
>+	pci_unregister_driver(&lynxfb_driver);
>+	LEAVE();
>+}
>+	module_exit(lynxfb_exit);
>+#endif
>+
>+#ifdef MODULE
>+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 10)
>+	module_param(g_option, charp, S_IRUGO);
>+#else
>+	/* be ware that PARM and param */
>+	MODULE_PARM(g_option, "s");
>+#endif
>+
>+	MODULE_PARM_DESC(g_option,
>+			"\n\t\tCommon options:\n"
>+			"\t\tnoaccel:disable 2d capabilities\n"
>+			"\t\tnomtrr:disable MTRR attribute for video memory\n"
>+			"\t\tdualview:dual frame buffer feature enabled\n"
>+			"\t\tnohwc:disable hardware cursor\n"
>+			"\t\tUsual example:\n"
>+			"\t\tinsmod ./lynxfb.ko g_option=\"noaccel, nohwc, 1280x1024-8 at 60\"\n"
>+			"\t\tFor more detail chip specific options, please refer to \"Lynxfb User Mnual\" or readme\n"
>+			);
>+#endif
>+
>+	MODULE_AUTHOR("monk liu<monk.liu at siliconmotion.com>");
>+	MODULE_DESCRIPTION("Frame buffer driver for SMI(R) " SUPPORT_CHIP " chipsets");
>+	MODULE_LICENSE("Dual BSD/GPL");
>+	MODULE_DEVICE_TABLE(pci, smi_pci_table);
>diff --git a/drivers/video/lynxfb/lynx_drv.h b/drivers/video/lynxfb/lynx_drv.h
>new file mode 100644
>index 0000000..7cf5f1b
>--- /dev/null
>+++ b/drivers/video/lynxfb/lynx_drv.h
>@@ -0,0 +1,271 @@
>+/*******************************************************************
>+*Copyright (c) 2012 by Silicon Motion, Inc. (SMI)
>+*Permission is hereby granted, free of charge, to any person obtaining a copy
>+*of this software and associated documentation files (the "Software"), to deal
>+*in the Software without restriction, including without limitation the rights to
>+*use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
>+*of the Software, and to permit persons to whom the Software is furnished to
>+*do so, subject to the following conditions:
>+*
>+*THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
>+*EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
>+*OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
>+*NONINFRINGEMENT.  IN NO EVENT SHALL Mill.Chen and Monk.Liu OR COPYRIGHT
>+*HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
>+*WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
>+*FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
>+*OTHER DEALINGS IN THE SOFTWARE.
>+*******************************************************************/
>+#ifndef LYNXDRV_H_
>+#define LYNXDRV_H_
>+
>+
>+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 17)
>+#else
>+typedef unsigned long resource_size_t;
>+#endif
>+
>+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
>+#else
>+#define SEPARATOR 1
>+typedef int pm_message_t;
>+#endif
>+
>+/* please use revision id to distinguish sm750le and sm750*/
>+#define SPC_SM750 	0
>+#define SPC_SM712 	1
>+#define SPC_SM502   2
>+/*#define SPC_SM750LE 8*/
>+
>+#define PCI_VENDOR_ID_SMI 	0x126f
>+#define PCI_DEVID_LYNX_EXP	0x0750
>+#define PCI_DEVID_LYNX_SE	0x0718
>+#define PCI_DEVID_LYNX_EM	0x0712
>+#define PCI_DEVID_LYNX_3DM	0x0720
>+#define PCI_DEVID_VOYAGER 	0x0501
>+
>+/*#define SUPPORT_ARCH "x86, x86_64"*/
>+/*#define SUPPORT_CHIP "lynx Express(750)/lynx 750LE/Lynx SE(718)/Lynx EM(712)/lynx 3DM(720/722) voyager(502/107)"*/
>+
>+/*#define _version_	"4.0.1"*/
>+#define _moduleName_ "lynxfb"
>+#define PFX _moduleName_ ": "
>+#define err_msg(fmt, args...) printk(KERN_ERR PFX fmt, ## args)
>+#define war_msg(fmt, args...) printk(KERN_WARNING PFX fmt, ## args)
>+#define inf_msg(fmt, args...) printk(KERN_INFO PFX fmt, ## args)
>+/* below code also works ok, but there must be no KERN_INFO prefix */
>+/*#define inf_msg(...) printk(__VA_ARGS__)*/
>+
>+#if (DEBUG == 1)
>+/* debug level == 1 */
>+#define dbg_msg(fmt, args...) printk(KERN_DEBUG PFX fmt, ## args)
>+#define ENTER()	printk(KERN_DEBUG PFX "%*c %s\n", smi_indent++, '>', __func__)
>+#define LEAVE(...)	\
>+	do {				\
>+	printk(KERN_DEBUG PFX "%*c %s\n", --smi_indent, '<', __func__); \
>+	return __VA_ARGS__; \
>+	} while (0)
>+
>+#elif (DEBUG == 2)
>+/* debug level == 2*/
>+#define dbg_msg(fmt, args...) printk(KERN_ERR PFX fmt, ## args)
>+#define ENTER()	printk(KERN_ERR PFX "%*c %s\n", smi_indent++, '>', __func__)
>+
>+#define LEAVE(...)	\
>+	do {				\
>+	printk(KERN_ERR PFX "%*c %s\n", --smi_indent, '<', __func__); \
>+	return __VA_ARGS__; \
>+	} while (0)
>+
>+#ifdef inf_msg
>+#undef inf_msg
>+#endif
>+
>+#define inf_msg(fmt, args...) printk(KERN_ERR PFX fmt, ## args)
>+#else
>+/* no debug */
>+#define dbg_msg(...)
>+#define ENTER()
>+#define LEAVE(...)	\
>+	do {	\
>+	return __VA_ARGS__; \
>+	} while (0)	\
>+
>+#endif
>+
>+#define MB(x) ((x)<<20)
>+#define MHZ(x) ((x) * 1000000)
>+/* align should be 2, 4, 8, 16 */
>+#define PADDING(align, data) (((data)+(align)-1)&(~((align)-1)))
>+extern int smi_indent;
>+
>+
>+struct lynx_accel{
>+	/* base virtual address of DPR registers */
>+	volatile unsigned char __iomem *dprBase;
>+	/* base virtual address of de data port */
>+	volatile unsigned char __iomem *dpPortBase;
>+
>+	/* function fointers */
>+	int (*de_init)(struct lynx_accel *);
>+
>+	int (*de_wait)(void);/* see if hardware ready to work */
>+
>+	int (*de_fillrect)(struct lynx_accel *, u32, u32, u32,
>+							u32, u32, u32, u32, u32, u32);
>+
>+	int (*de_copyarea)(struct lynx_accel *, u32, u32, u32, u32,
>+						u32, u32, u32, u32,
>+						u32, u32, u32, u32);
>+
>+	int (*de_imageblit)(struct lynx_accel *, const char *, u32, u32, u32,
>+						u32, u32, u32, u32, u32, u32, u32, u32, u32);
>+
>+};
>+
>+/* 	lynx_share stands for a presentation of two frame buffer
>+	that use one smi adaptor , it is similar to a basic class of C++
>+*/
>+struct lynx_share{
>+	/* common members */
>+	u16 devid;
>+	u8 revid;
>+	struct pci_dev *pdev;
>+	struct fb_info *fbinfo[2];
>+	struct lynx_accel accel;
>+	int accel_off;
>+	int dual;
>+#ifdef CONFIG_MTRR
>+		int mtrr_off;
>+		struct{
>+			int vram;
>+			int vram_added;
>+		} mtrr;
>+#endif
>+	/* all smi graphic adaptor got below attributes */
>+	resource_size_t vidmem_start;
>+	resource_size_t vidreg_start;
>+	resource_size_t vidmem_size;
>+	resource_size_t vidreg_size;
>+	volatile unsigned char __iomem *pvReg;
>+	unsigned char __iomem *pvMem;
>+	/* locks*/
>+	spinlock_t slock;
>+	/* function pointers */
>+	void (*suspend)(struct lynx_share *);
>+	void (*resume)(struct lynx_share *);
>+};
>+
>+struct lynx_cursor{
>+	/* cursor width , height and size */
>+	int w;
>+	int h;
>+	int size;
>+	/* hardware limitation */
>+	int maxW;
>+	int maxH;
>+	/* base virtual address and offset  of cursor image */
>+	char __iomem *vstart;
>+	int offset;
>+	/* mmio addr of hw cursor */
>+	volatile char __iomem *mmio;
>+	/* the lynx_share of this adaptor */
>+	struct lynx_share *share;
>+	/* proc_routines */
>+	void (*enable)(struct lynx_cursor *);
>+	void (*disable)(struct lynx_cursor *);
>+	void (*setSize)(struct lynx_cursor *, int, int);
>+	void (*setPos)(struct lynx_cursor *, int, int);
>+	void (*setColor)(struct lynx_cursor *, u32, u32);
>+	void (*setData)(struct lynx_cursor *, u16, const u8 *, const u8 *);
>+};
>+
>+struct lynxfb_crtc{
>+	unsigned char __iomem *vCursor;/*virtual address of cursor*/
>+	unsigned char __iomem *vScreen;/*virtual address of on_screen*/
>+	int oCursor;/*cursor address offset in vidmem*/
>+	int oScreen;/*onscreen address offset in vidmem*/
>+	int channel;/* which channel this crtc stands for*/
>+	resource_size_t vidmem_size;/* this view's video memory max size */
>+
>+	/* below attributes belong to info->fix, their value depends on specific adaptor*/
>+	u16 line_pad;/* padding information:0, 1, 2, 4, 8, 16, ... */
>+	u16 xpanstep;
>+	u16 ypanstep;
>+	u16 ywrapstep;
>+
>+	void *priv;
>+
>+	int(*proc_setMode)(struct lynxfb_crtc*,
>+						struct fb_var_screeninfo*,
>+						struct fb_fix_screeninfo*);
>+
>+	int(*proc_checkMode)(struct lynxfb_crtc *, struct fb_var_screeninfo *);
>+	int(*proc_setColReg)(struct lynxfb_crtc *, ushort, ushort, ushort, ushort);
>+	void (*clear)(struct lynxfb_crtc *);
>+	/* pan display */
>+	int(*proc_panDisplay)(struct lynxfb_crtc *, struct fb_var_screeninfo *,
>+		struct fb_info *);
>+	/* cursor information */
>+	struct lynx_cursor cursor;
>+};
>+
>+struct lynxfb_output{
>+	int dpms;
>+	int paths;
>+	/* 	which paths(s) this output stands for, for sm750:
>+		paths=1:means output for panel paths
>+		paths=2:means output for crt paths
>+		paths=3:means output for both panel and crt paths
>+	*/
>+
>+	int *channel;
>+	/* 	which channel these outputs linked with, for sm750:
>+		*channel=0 means primary channel
>+		*channel=1 means secondary channel
>+		output->channel ==> &crtc->channel
>+	*/
>+	void *priv;
>+
>+	int(*proc_setMode)(struct lynxfb_output *,
>+						struct fb_var_screeninfo *,
>+						struct fb_fix_screeninfo *);
>+
>+	int(*proc_checkMode)(struct lynxfb_output *, struct fb_var_screeninfo *);
>+	int(*proc_setBLANK)(struct lynxfb_output *, int);
>+	void  (*clear)(struct lynxfb_output *);
>+};
>+
>+struct lynxfb_par{
>+	/* either 0 or 1 for dual head adaptor, 0 is the older one registered */
>+	int index;
>+	unsigned int pseudo_palette[256];
>+	struct lynxfb_crtc crtc;
>+	struct lynxfb_output output;
>+	struct fb_info *info;
>+	struct lynx_share *share;
>+};
>+
>+#ifndef offsetof
>+#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
>+#endif
>+
>+
>+#define PS_TO_HZ(ps)	\
>+			({ 	\
>+			unsigned long long hz = 1000*1000*1000*1000ULL;	\
>+			do_div(hz, ps);	\
>+			(unsigned long)hz; `})
>+
>+
>+static inline unsigned long ps_to_hz(unsigned int psvalue)
>+{
>+	unsigned long long numerator = 1000*1000*1000*1000ULL;
>+	/* 10^12 / picosecond period gives frequency in Hz */
>+	do_div(numerator, psvalue);
>+	return (unsigned long)numerator;
>+}
>+
>+
>+
>+#endif
>diff --git a/drivers/video/lynxfb/lynx_help.h b/drivers/video/lynxfb/lynx_help.h
>new file mode 100644
>index 0000000..2d80365
>--- /dev/null
>+++ b/drivers/video/lynxfb/lynx_help.h
>@@ -0,0 +1,115 @@
>+/*******************************************************************
>+*Copyright (c) 2012 by Silicon Motion, Inc. (SMI)
>+*Permission is hereby granted, free of charge, to any person obtaining a copy
>+*of this software and associated documentation files (the "Software"), to deal
>+*in the Software without restriction, including without limitation the rights to
>+*use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
>+*of the Software, and to permit persons to whom the Software is furnished to
>+*do so, subject to the following conditions:
>+*
>+*THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
>+*EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
>+*OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
>+*NONINFRINGEMENT.  IN NO EVENT SHALL Mill.Chen and Monk.Liu OR COPYRIGHT
>+*HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
>+*WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
>+*FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
>+*OTHER DEALINGS IN THE SOFTWARE.
>+*******************************************************************/
>+#ifndef LYNX_HELP_H__
>+#define LYNX_HELP_H__
>+ /*                                FIELD MACROS                               */
>+
>+#define _LSB(f)             (0 ? f)
>+#define _MSB(f)             (1 ? f)
>+#define _COUNT(f)           (_MSB(f) - _LSB(f) + 1)
>+
>+#define RAW_MASK(f)         (0xFFFFFFFF >> (32 - _COUNT(f)))
>+#define GET_MASK(f)         (RAW_MASK(f) << _LSB(f))
>+#define GET_FIELD(d, f)      (((d) >> _LSB(f)) & RAW_MASK(f))
>+#define TEST_FIELD(d, f, v)   (GET_FIELD(d, f) == f ## _ ## v)
>+#define SET_FIELD(d, f, v)    (((d) & ~GET_MASK(f)) | \
>+		(((f ## _ ## v) & RAW_MASK(f)) << _LSB(f)))
>+#define SET_FIELDV(d, f, v)   (((d) & ~GET_MASK(f)) | \
>+		(((v) & RAW_MASK(f)) << _LSB(f)))
>+
>+
>+/* Internal macros                                                            */
>+
>+#define _F_START(f)             (0 ? f)
>+#define _F_END(f)               (1 ? f)
>+#define _F_SIZE(f)              (1 + _F_END(f) - _F_START(f))
>+#define _F_MASK(f)              (((1 << _F_SIZE(f)) - 1) << _F_START(f))
>+#define _F_NORMALIZE(v, f)      (((v) & _F_MASK(f)) >> _F_START(f))
>+#define _F_DENORMALIZE(v, f)    (((v) << _F_START(f)) & _F_MASK(f))
>+
>+
>+/* Global macros                                                              */
>+
>+#define FIELD_GET(x, reg, field) \
>+	( \
>+	  _F_NORMALIZE((x), reg ## _ ## field) \
>+	)
>+
>+#define FIELD_SET(x, reg, field, value) \
>+	( \
>+	  (x & ~_F_MASK(reg ## _ ## field)) \
>+	  | _F_DENORMALIZE(reg ## _ ## field ## _ ## value, reg ## _ ## field) \
>+	)
>+
>+#define FIELD_VALUE(x, reg, field, value) \
>+	( \
>+	  (x & ~_F_MASK(reg ## _ ## field)) \
>+	  | _F_DENORMALIZE(value, reg ## _ ## field) \
>+	)
>+
>+#define FIELD_CLEAR(reg, field) \
>+	( \
>+	  ~_F_MASK(reg ## _ ## field) \
>+	)
>+
>+
>+/* Field Macros                                                              */
>+
>+#define FIELD_START(field)              (0 ? field)
>+#define FIELD_END(field)                (1 ? field)
>+#define FIELD_SIZE(field)               (1 + FIELD_END(field) - FIELD_START(field))
>+#define FIELD_MASK(field)               (((1 << (FIELD_SIZE(field)-1)) | ((1 << (FIELD_SIZE(field)-1)) - 1)) << FIELD_START(field))
>+#define FIELD_NORMALIZE(reg, field)     (((reg) & FIELD_MASK(field)) >> FIELD_START(field))
>+#define FIELD_DENORMALIZE(field, value) (((value) << FIELD_START(field)) & FIELD_MASK(field))
>+
>+#define FIELD_INIT(reg, field, value)   FIELD_DENORMALIZE(reg ## _ ## field, \
>+		reg ## _ ## field ## _ ## value)
>+#define FIELD_INIT_VAL(reg, field, value) \
>+	(FIELD_DENORMALIZE(reg ## _ ## field, value))
>+#define FIELD_VAL_SET(x, r, f, v)       (x = x & ~FIELD_MASK(r ## _ ## f) \
>+					    | FIELD_DENORMALIZE(r ## _ ## f, r ## _ ## f ## _ ## v))
>+
>+#define RGB(r, g, b) \
>+	( \
>+	  (unsigned long) (((r) << 16) | ((g) << 8) | (b)) \
>+	)
>+
>+#define RGB16(r, g, b) \
>+	( \
>+	  (unsigned short) ((((r) & 0xF8) << 8) | (((g) & 0xFC) << 3) | (((b) & 0xF8) >> 3)) \
>+	)
>+
>+static inline unsigned int absDiff(unsigned int a, unsigned int b)
>+{
>+	if (a < b)
>+		return b-a;
>+	else
>+		return a-b;
>+}
>+
>+/* n / d + 1 / 2 = (2n + d) / 2d */
>+#define roundedDiv(num, denom)	((2 * (num) + (denom)) / (2 * (denom)))
>+#define MB(x) ((x)<<20)
>+#define KB(x) ((x)<<10)
>+#define MHz(x) ((x) * 1000000)
>+
>+
>+
>+
>+#endif
>diff --git a/drivers/video/lynxfb/lynx_hw750.c b/drivers/video/lynxfb/lynx_hw750.c
>new file mode 100644
>index 0000000..019eb68
>--- /dev/null
>+++ b/drivers/video/lynxfb/lynx_hw750.c
>@@ -0,0 +1,633 @@
>+/*******************************************************************
>+*Copyright (c) 2012 by Silicon Motion, Inc. (SMI)
>+*Permission is hereby granted, free of charge, to any person obtaining a copy
>+*of this software and associated documentation files (the "Software"), to deal
>+*in the Software without restriction, including without limitation the rights to
>+*use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
>+*of the Software, and to permit persons to whom the Software is furnished to
>+*do so, subject to the following conditions:
>+*
>+*THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
>+*EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
>+*OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
>+*NONINFRINGEMENT.  IN NO EVENT SHALL Mill.Chen and Monk.Liu OR COPYRIGHT
>+*HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
>+*WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
>+*FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
>+*OTHER DEALINGS IN THE SOFTWARE.
>+*******************************************************************/
>+#include<linux/version.h>
>+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 10)
>+#include<linux/config.h>
>+#endif
>+#include <linux/version.h>
>+#include<linux/module.h>
>+#include<linux/kernel.h>
>+#include<linux/errno.h>
>+#include<linux/string.h>
>+#include<linux/mm.h>
>+#include<linux/slab.h>
>+#include<linux/delay.h>
>+#include<linux/fb.h>
>+#include<linux/ioport.h>
>+#include<linux/init.h>
>+#include<linux/pci.h>
>+#include<linux/vmalloc.h>
>+#include<linux/pagemap.h>
>+#include <linux/console.h>
>+#ifdef CONFIG_MTRR
>+#include <asm/mtrr.h>
>+#endif
>+
>+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
>+/* no below two header files in 2.6.9 */
>+#include<linux/platform_device.h>
>+#include<linux/screen_info.h>
>+#else
>+/* nothing by far */
>+#endif
>+
>+#include "lynx_drv.h"
>+#include "lynx_hw750.h"
>+#include "ddk750.h"
>+#include "lynx_accel.h"
>+
>+int hw_sm750_map(struct lynx_share *share, struct pci_dev *pdev)
>+{
>+	int ret;
>+	struct sm750_share *spec_share;
>+	ENTER();
>+
>+	spec_share = container_of(share, struct sm750_share, share);
>+	ret = 0;
>+
>+	share->vidreg_start  = pci_resource_start(pdev, 1);
>+	share->vidreg_size = MB(2);
>+
>+	/* reserve the vidreg space of smi adaptor
>+	 * if you do this, u need to add release region code
>+	 * in lynxfb_remove, or memory will not be mapped again
>+	 * successfully
>+	 * */
>+
>+
>+	/* now map mmio and vidmem*/
>+	share->pvReg = ioremap_nocache(share->vidreg_start, share->vidreg_size);
>+	if (!share->pvReg) {
>+		err_msg("mmio failed\n");
>+		ret = -EFAULT;
>+		goto exit;
>+	}
>+
>+	share->accel.dprBase = share->pvReg + DE_BASE_ADDR_TYPE1;
>+	share->accel.dpPortBase = share->pvReg + DE_PORT_ADDR_TYPE1;
>+
>+	ddk750_set_mmio(share->pvReg, share->devid, share->revid);
>+
>+	share->vidmem_start = pci_resource_start(pdev, 0);
>+	/* don't use pdev_resource[x].end - resource[x].start to
>+	 * calculate the resource size, its only the maximum available
>+	 * size but not the actual size, use
>+	 * @hw_sm750_getVMSize function can be safe.
>+	 * */
>+	share->vidmem_size = hw_sm750_getVMSize(share);
>+	inf_msg("video memory size = %d mb\n", share->vidmem_size >> 20);
>+
>+	/* reserve the vidmem space of smi adaptor */
>+
>+	share->pvMem = ioremap(share->vidmem_start,
>+			share->vidmem_size);
>+
>+	if (!share->pvMem) {
>+		err_msg("Map video memory failed\n");
>+		ret = -EFAULT;
>+		goto exit;
>+	}
>+
>+	inf_msg("video memory vaddr = %p\n", share->pvMem);
>+exit:
>+	LEAVE(ret);
>+}
>+
>+
>+
>+int hw_sm750_inithw(struct lynx_share *share, struct pci_dev *pdev)
>+{
>+	struct sm750_share *spec_share;
>+	struct init_status *parm;
>+	ENTER();
>+	spec_share = container_of(share, struct sm750_share, share);
>+	parm = &spec_share->state.initParm;
>+	if (parm->chip_clk == 0)
>+		parm->chip_clk = (getChipType() == SM750LE) ?
>+			DEFAULT_SM750LE_CHIP_CLOCK :
>+			DEFAULT_SM750_CHIP_CLOCK;
>+
>+	if (parm->mem_clk == 0)
>+		parm->mem_clk = parm->chip_clk;
>+	if (parm->master_clk == 0)
>+		parm->master_clk = parm->chip_clk/3;
>+
>+	ddk750_initHw((initchip_param_t *)&spec_share->state.initParm);
>+	/* for sm718, open pci burst */
>+	if (share->devid == 0x718) {
>+		POKE32(SYSTEM_CTRL,
>+			PEEK32(SYSTEM_CTRL)|(1 << SYSTEM_CTRL_PCI_BURST_LSB));
>+	}
>+
>+	/* sm750 use sii164, it can be setup with default value
>+	 * by on power, so initDVIDisp can be skipped */
>+
>+	if (getChipType() != SM750LE) {
>+		/* does user need CRT ?*/
>+		if (spec_share->state.nocrt) {
>+			POKE32(MISC_CTRL,
>+					PEEK32(MISC_CTRL)|
>+					(1 << MISC_CTRL_DAC_POWER_LSB));
>+			/* shut off dpms */
>+			POKE32(SYSTEM_CTRL,
>+					PEEK32(SYSTEM_CTRL)|
>+					(3 << SYSTEM_CTRL_DPMS_LSB));
>+		} else{
>+			POKE32(MISC_CTRL,
>+					PEEK32(MISC_CTRL)&
>+					(~(1 << MISC_CTRL_DAC_POWER_LSB)));
>+			/* turn on dpms */
>+			POKE32(SYSTEM_CTRL,
>+					PEEK32(SYSTEM_CTRL)&
>+					(~(3 << SYSTEM_CTRL_DPMS_LSB)));
>+		}
>+
>+		switch (spec_share->state.pnltype) {
>+		case sm750_doubleTFT:
>+		case sm750_24TFT:
>+		case sm750_dualTFT:
>+				POKE32(PANEL_DISPLAY_CTRL,
>+						PEEK32(PANEL_DISPLAY_CTRL)&
>+						(~(3 << PANEL_DISPLAY_CTRL_TFT_DISP_LSB)));
>+				POKE32(PANEL_DISPLAY_CTRL,
>+						PEEK32(PANEL_DISPLAY_CTRL)|
>+						(spec_share->state.pnltype << PANEL_DISPLAY_CTRL_TFT_DISP_LSB));					break;
>+		}
>+	} else{
>+		/* for 750LE , no DVI chip initilization makes Monitor no signal */
>+		/* Set up GPIO for software I2C to program DVI chip in the
>+		   Xilinx SP605 board, in order to have video signal.
>+		   */
>+		swI2CInit(0, 1);
>+
>+
>+		/* Customer may NOT use CH7301 DVI chip, which has to be
>+		   initialized differently.
>+		   */
>+		if (swI2CReadReg(0xec, 0x4a) == 0x95) {
>+			/* The following register values for CH7301 are from
>+			   Chrontel app note and our experiment.
>+			   */
>+			inf_msg("yes, CH7301 DVI chip found\n");
>+			swI2CWriteReg(0xec, 0x1d, 0x16);
>+			swI2CWriteReg(0xec, 0x21, 0x9);
>+			swI2CWriteReg(0xec, 0x49, 0xC0);
>+			inf_msg("okay, CH7301 DVI chip setup done\n");
>+		}
>+	}
>+
>+	/* init 2d engine */
>+	if (!share->accel_off) {
>+		hw_sm750_initAccel(share);
>+	}
>+
>+	LEAVE(0);
>+}
>+
>+
>+resource_size_t hw_sm750_getVMSize(struct lynx_share *share)
>+{
>+	resource_size_t ret;
>+	ENTER();
>+	ret = ddk750_getVMSize();
>+	LEAVE(ret);
>+}
>+
>+
>+
>+int hw_sm750_output_checkMode(struct lynxfb_output *output, struct fb_var_screeninfo *var)
>+{
>+	ENTER();
>+	LEAVE(0);
>+}
>+
>+
>+int hw_sm750_output_setMode(struct lynxfb_output *output,
>+		struct fb_var_screeninfo *var, struct fb_fix_screeninfo *fix)
>+{
>+	int ret;
>+	disp_output_t dispSet;
>+	int channel;
>+	ENTER();
>+	ret = 0;
>+	dispSet = 0;
>+	channel = *output->channel;
>+
>+
>+	if (getChipType() != SM750LE) {
>+		if (channel == sm750_primary) {
>+			inf_msg("primary channel\n");
>+			if (output->paths & sm750_panel)
>+				dispSet |= do_LCD1_PRI;
>+			if (output->paths & sm750_crt)
>+				dispSet |= do_CRT_PRI;
>+
>+		} else{
>+			inf_msg("secondary channel\n");
>+			if (output->paths & sm750_panel)
>+				dispSet |= do_LCD1_SEC;
>+			if (output->paths & sm750_crt)
>+				dispSet |= do_CRT_SEC;
>+
>+		}
>+		ddk750_setLogicalDispOut(dispSet);
>+	} else{
>+		/* just open DISPLAY_CONTROL_750LE register bit 3:0*/
>+		u32 reg;
>+		reg = PEEK32(DISPLAY_CONTROL_750LE);
>+		reg |= 0xf;
>+		POKE32(DISPLAY_CONTROL_750LE, reg);
>+	}
>+
>+	inf_msg("ddk setlogicdispout done \n");
>+	LEAVE(ret);
>+}
>+
>+void hw_sm750_output_clear(struct lynxfb_output *output)
>+{
>+	ENTER();
>+	LEAVE();
>+}
>+
>+int hw_sm750_crtc_checkMode(struct lynxfb_crtc *crtc, struct fb_var_screeninfo *var)
>+{
>+	struct lynx_share *share;
>+	ENTER();
>+
>+	share = container_of(crtc, struct lynxfb_par, crtc)->share;
>+
>+	switch (var->bits_per_pixel) {
>+	case 8:
>+	case 16:
>+		break;
>+	case 32:
>+		if (share->revid == (unsigned char)SM750LE_REVISION_ID) {
>+			dbg_msg("750le do not support 32bpp\n");
>+			LEAVE (-EINVAL);
>+		}
>+		break;
>+	default:
>+			LEAVE(-EINVAL);
>+
>+	}
>+
>+	LEAVE(0);
>+}
>+
>+
>+/*
>+   set the controller's mode for @crtc charged with @var and @fix parameters
>+   */
>+int hw_sm750_crtc_setMode(struct lynxfb_crtc *crtc,
>+		struct fb_var_screeninfo *var,
>+		struct fb_fix_screeninfo *fix)
>+{
>+	int ret, fmt;
>+	u32 reg;
>+	mode_parameter_t modparm;
>+	clock_type_t clock;
>+	struct lynx_share *share;
>+	struct lynxfb_par *par;
>+
>+	ENTER();
>+	ret = 0;
>+	par = container_of(crtc, struct lynxfb_par, crtc);
>+	share = par->share;
>+
>+	if (!share->accel_off) {
>+		/* set 2d engine pixel format according to mode bpp */
>+		switch (var->bits_per_pixel) {
>+		case 8:
>+			fmt = 0;
>+			break;
>+		case 16:
>+			fmt = 1;
>+			break;
>+		case 32:
>+		default:
>+			fmt = 2;
>+			break;
>+		}
>+		hw_set2dformat(&share->accel, fmt);
>+	}
>+
>+
>+	/* set timing */
>+	modparm.pixel_clock = ps_to_hz(var->pixclock);
>+	modparm.vertical_sync_polarity = (var->sync & FB_SYNC_HOR_HIGH_ACT) ? POS : NEG;
>+	modparm.horizontal_sync_polarity = (var->sync & FB_SYNC_VERT_HIGH_ACT) ? POS : NEG;
>+	modparm.clock_phase_polarity = (var->sync & FB_SYNC_COMP_HIGH_ACT) ? POS : NEG;
>+	modparm.horizontal_display_end = var->xres;
>+	modparm.horizontal_sync_width = var->hsync_len;
>+	modparm.horizontal_sync_start = var->xres + var->right_margin;
>+	modparm.horizontal_total = var->xres + var->left_margin + var->right_margin + var->hsync_len;
>+	modparm.vertical_display_end = var->yres;
>+	modparm.vertical_sync_height = var->vsync_len;
>+	modparm.vertical_sync_start = var->yres + var->lower_margin;
>+	modparm.vertical_total = var->yres + var->upper_margin + var->lower_margin + var->vsync_len;
>+
>+	/* choose pll */
>+	if (crtc->channel != sm750_secondary)
>+		clock = PRIMARY_PLL;
>+	else
>+		clock = SECONDARY_PLL;
>+
>+	dbg_msg("Request pixel clock = %lu\n", modparm.pixel_clock);
>+	ret = ddk750_setModeTiming(&modparm, clock);
>+	if (ret) {
>+		err_msg("Set mode timing failed\n");
>+		goto exit;
>+	}
>+
>+	if (crtc->channel != sm750_secondary) {
>+		/* set pitch, offset , width, start address , etc... */
>+		POKE32(PANEL_FB_ADDRESS,
>+				(~(1 << PANEL_FB_ADDRESS_STATUS_LSB))&
>+				(~(1 << PANEL_FB_ADDRESS_EXT_LSB))&
>+				(~(0X3FFFFFF << PANEL_FB_ADDRESS_ADDRESS_LSB))|
>+				(crtc->oScreen << PANEL_FB_ADDRESS_ADDRESS_LSB));
>+		reg = var->xres * (var->bits_per_pixel >> 3);
>+		/* crtc->channel is not equal to par->index on numeric, be aware of that */
>+		reg = PADDING(crtc->line_pad, reg);
>+		POKE32(PANEL_FB_WIDTH,
>+				(reg << PANEL_FB_WIDTH_WIDTH_LSB)|
>+				(fix->line_length << PANEL_FB_WIDTH_OFFSET_LSB));
>+
>+		POKE32(PANEL_WINDOW_WIDTH,
>+				(var->xres - 1 << PANEL_WINDOW_WIDTH_WIDTH_LSB)|
>+				(var->xoffset << PANEL_WINDOW_WIDTH_X_LSB));
>+
>+		POKE32(PANEL_WINDOW_HEIGHT,
>+				(var->yres_virtual - 1 << PANEL_WINDOW_HEIGHT_HEIGHT_LSB)|
>+				(var->yoffset << PANEL_WINDOW_HEIGHT_Y_LSB));
>+		POKE32(PANEL_PLANE_TL, 0);
>+
>+		POKE32(PANEL_PLANE_BR,
>+				(var->yres - 1 << PANEL_PLANE_BR_BOTTOM_LSB)|
>+				(var->xres - 1 << PANEL_PLANE_BR_RIGHT_LSB));
>+
>+		/* set pixel format */
>+		reg = PEEK32(PANEL_DISPLAY_CTRL);
>+		POKE32(PANEL_DISPLAY_CTRL,
>+				reg&(~(3 << PANEL_DISPLAY_CTRL_FORMAT_LSB))|
>+				((var->bits_per_pixel >> 4) << PANEL_DISPLAY_CTRL_FORMAT_LSB));
>+	} else{
>+		/* not implemented now */
>+		POKE32(CRT_FB_ADDRESS, crtc->oScreen);
>+		reg = var->xres * (var->bits_per_pixel >> 3);
>+		/* crtc->channel is not equal to par->index on numeric, be aware of that */
>+		reg = PADDING(crtc->line_pad, reg);
>+		POKE32(CRT_FB_WIDTH,
>+				(reg << CRT_FB_WIDTH_WIDTH_LSB)|
>+				(fix->line_length << CRT_FB_WIDTH_OFFSET_LSB));
>+
>+		/* SET PIXEL FORMAT */
>+		reg = PEEK32(CRT_DISPLAY_CTRL);
>+		reg |= (var->bits_per_pixel >> 4) << CRT_DISPLAY_CTRL_FORMAT_LSB;
>+		POKE32(CRT_DISPLAY_CTRL, reg);
>+	}
>+
>+
>+exit:
>+	LEAVE(ret);
>+}
>+
>+void hw_sm750_crtc_clear(struct lynxfb_crtc *crtc)
>+{
>+	ENTER();
>+	LEAVE();
>+}
>+
>+int hw_sm750_setColReg(struct lynxfb_crtc *crtc, ushort index,
>+		ushort red, ushort green, ushort blue)
>+{
>+	static unsigned int add[] = {PANEL_PALETTE_RAM, CRT_PALETTE_RAM};
>+	POKE32(add[crtc->channel] + index*4, (red<<16)|(green<<8)|blue);
>+	return 0;
>+}
>+
>+int hw_sm750le_setBLANK(struct lynxfb_output *output, int blank)
>+{
>+	int dpms, crtdb;
>+	ENTER();
>+	switch (blank) {
>+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
>+	case FB_BLANK_UNBLANK:
>+#else
>+	case VESA_NO_BLANKING:
>+#endif
>+		dpms = CRT_DISPLAY_CTRL_DPMS_0;
>+		crtdb = CRT_DISPLAY_CTRL_BLANK_OFF;
>+		break;
>+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
>+	case FB_BLANK_NORMAL:
>+		dpms = CRT_DISPLAY_CTRL_DPMS_0;
>+		crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
>+		break;
>+#endif
>+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
>+	case FB_BLANK_VSYNC_SUSPEND:
>+#else
>+	case VESA_VSYNC_SUSPEND:
>+#endif
>+		dpms = CRT_DISPLAY_CTRL_DPMS_2;
>+		crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
>+		break;
>+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
>+	case FB_BLANK_HSYNC_SUSPEND:
>+#else
>+	case VESA_HSYNC_SUSPEND:
>+#endif
>+		dpms = CRT_DISPLAY_CTRL_DPMS_1;
>+		crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
>+		break;
>+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
>+	case FB_BLANK_POWERDOWN:
>+#else
>+	case VESA_POWERDOWN:
>+#endif
>+		dpms = CRT_DISPLAY_CTRL_DPMS_3;
>+		crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
>+		break;
>+	}
>+
>+	if (output->paths & sm750_crt) {
>+		POKE32(CRT_DISPLAY_CTRL, PEEK32(CRT_DISPLAY_CTRL)&(~(3 << CRT_DISPLAY_CTRL_DPMS_LSB))|(dpms << CRT_DISPLAY_CTRL_DPMS_LSB));
>+		POKE32(CRT_DISPLAY_CTRL, PEEK32(CRT_DISPLAY_CTRL)&(~(1 << CRT_DISPLAY_CTRL_BLANK_LSB))|(crtdb << CRT_DISPLAY_CTRL_BLANK_LSB));
>+	}
>+	LEAVE(0);
>+}
>+
>+int hw_sm750_setBLANK(struct lynxfb_output *output, int blank)
>+{
>+	unsigned int dpms, pps, crtdb;
>+	ENTER();
>+	dpms = pps = crtdb = 0;
>+
>+	switch (blank) {
>+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
>+	case FB_BLANK_UNBLANK:
>+#else
>+	case VESA_NO_BLANKING:
>+#endif
>+		inf_msg("flag = FB_BLANK_UNBLANK \n");
>+		dpms = SYSTEM_CTRL_DPMS_VPHP;
>+		pps = PANEL_DISPLAY_CTRL_DATA_ENABLE;
>+		crtdb = CRT_DISPLAY_CTRL_BLANK_OFF;
>+		break;
>+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
>+	case FB_BLANK_NORMAL:
>+		inf_msg("flag = FB_BLANK_NORMAL \n");
>+		dpms = SYSTEM_CTRL_DPMS_VPHP;
>+		pps = PANEL_DISPLAY_CTRL_DATA_DISABLE;
>+		crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
>+		break;
>+#endif
>+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
>+	case FB_BLANK_VSYNC_SUSPEND:
>+#else
>+	case VESA_VSYNC_SUSPEND:
>+#endif
>+		dpms = SYSTEM_CTRL_DPMS_VNHP;
>+		pps = PANEL_DISPLAY_CTRL_DATA_DISABLE;
>+		crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
>+		break;
>+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
>+	case FB_BLANK_HSYNC_SUSPEND:
>+#else
>+	case VESA_HSYNC_SUSPEND:
>+#endif
>+		dpms = SYSTEM_CTRL_DPMS_VPHN;
>+		pps = PANEL_DISPLAY_CTRL_DATA_DISABLE;
>+		crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
>+		break;
>+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
>+	case FB_BLANK_POWERDOWN:
>+#else
>+	case VESA_POWERDOWN:
>+#endif
>+		dpms = SYSTEM_CTRL_DPMS_VNHN;
>+		pps = PANEL_DISPLAY_CTRL_DATA_DISABLE;
>+		crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
>+		break;
>+	}
>+
>+	if (output->paths & sm750_crt) {
>+		POKE32(SYSTEM_CTRL, PEEK32(SYSTEM_CTRL)&(~(3 << SYSTEM_CTRL_DPMS_LSB))
>+				|(dpms << SYSTEM_CTRL_DPMS_LSB));
>+		POKE32(CRT_DISPLAY_CTRL, PEEK32(CRT_DISPLAY_CTRL)&(~(1 << CRT_DISPLAY_CTRL_BLANK_LSB))
>+				|(crtdb << CRT_DISPLAY_CTRL_BLANK_LSB));
>+	}
>+
>+	if (output->paths & sm750_panel) {
>+		POKE32(PANEL_DISPLAY_CTRL, PEEK32(PANEL_DISPLAY_CTRL)&(~(1 << PANEL_DISPLAY_CTRL_DATA_LSB))
>+				|(pps << PANEL_DISPLAY_CTRL_DATA_LSB));
>+	}
>+
>+	LEAVE(0);
>+}
>+
>+
>+void hw_sm750_initAccel(struct lynx_share *share)
>+{
>+	u32 reg;
>+	enable2DEngine(1);
>+
>+	if (getChipType() == SM750LE) {
>+		reg = PEEK32(DE_STATE1);
>+		reg |= 1 << DE_STATE1_DE_ABORT_LSB;
>+		POKE32(DE_STATE1, reg);
>+
>+		reg = PEEK32(DE_STATE1);
>+		reg &= ~(1 << DE_STATE1_DE_ABORT_LSB);
>+		POKE32(DE_STATE1, reg);
>+
>+	} else{
>+		/* engine reset */
>+		reg = PEEK32(SYSTEM_CTRL);
>+		reg |= 1 << SYSTEM_CTRL_DE_ABORT_LSB;
>+		POKE32(SYSTEM_CTRL, reg);
>+
>+		reg = PEEK32(SYSTEM_CTRL);
>+		reg &= ~(1 << SYSTEM_CTRL_DE_ABORT_LSB);
>+		POKE32(SYSTEM_CTRL, reg);
>+	}
>+
>+	/* call 2d init */
>+	share->accel.de_init(&share->accel);
>+}
>+
>+int hw_sm750le_deWait()
>+{
>+	int i = 0x10000000;
>+	while (i--) {
>+		unsigned int dwVal = PEEK32(DE_STATE2);
>+		if (((1&(dwVal >> DE_STATE2_DE_STATUS_LSB)) == DE_STATE2_DE_STATUS_IDLE) &&
>+				((1&(dwVal >> DE_STATE2_DE_FIFO_LSB))  == DE_STATE2_DE_FIFO_EMPTY) &&
>+				((1&(dwVal >> DE_STATE2_DE_MEM_FIFO_LSB)) == DE_STATE2_DE_MEM_FIFO_EMPTY)) {
>+				return 0;
>+			}
>+	}
>+	/* timeout error */
>+	return -1;
>+}
>+
>+
>+int hw_sm750_deWait()
>+{
>+	int i = 0x10000000;
>+	while (i--) {
>+		unsigned int dwVal = PEEK32(SYSTEM_CTRL);
>+		if (((1&(dwVal >> SYSTEM_CTRL_DE_STATUS_LSB)) == SYSTEM_CTRL_DE_STATUS_IDLE) &&
>+				((1&(dwVal >> SYSTEM_CTRL_DE_FIFO_LSB))  == SYSTEM_CTRL_DE_FIFO_EMPTY) &&
>+				((1&(dwVal >> SYSTEM_CTRL_DE_MEM_FIFO_LSB)) == SYSTEM_CTRL_DE_MEM_FIFO_EMPTY)) {
>+				return 0;
>+			}
>+	}
>+	/* timeout error */
>+	return -1;
>+}
>+
>+int hw_sm750_pan_display(struct lynxfb_crtc *crtc,
>+		const struct fb_var_screeninfo *var,
>+		const struct fb_info *info)
>+{
>+	uint32_t total;
>+	if ((var->xoffset + var->xres > var->xres_virtual) ||
>+			(var->yoffset + var->yres > var->yres_virtual)) {
>+		return -EINVAL;
>+	}
>+
>+	total = var->yoffset * info->fix.line_length +
>+		((var->xoffset * var->bits_per_pixel) >> 3);
>+	total += crtc->oScreen;
>+	if (crtc->channel == sm750_primary) {
>+		POKE32(PANEL_FB_ADDRESS,
>+				PEEK32(PANEL_FB_ADDRESS)&
>+				(~(0x3ffffff << PANEL_FB_ADDRESS_ADDRESS_LSB))|
>+				(total << PANEL_FB_ADDRESS_ADDRESS_LSB));
>+	} else{
>+		POKE32(CRT_FB_ADDRESS,
>+				PEEK32(CRT_FB_ADDRESS)&
>+				(~(0x3ffffff << CRT_FB_ADDRESS_ADDRESS_LSB))|
>+				(total << CRT_FB_ADDRESS_ADDRESS_LSB));
>+	}
>+	return 0;
>+}
>+
>diff --git a/drivers/video/lynxfb/lynx_hw750.h b/drivers/video/lynxfb/lynx_hw750.h
>new file mode 100644
>index 0000000..9f91ad1
>--- /dev/null
>+++ b/drivers/video/lynxfb/lynx_hw750.h
>@@ -0,0 +1,120 @@
>+/*******************************************************************
>+*Copyright (c) 2012 by Silicon Motion, Inc. (SMI)
>+*Permission is hereby granted, free of charge, to any person obtaining a copy
>+*of this software and associated documentation files (the "Software"), to deal
>+*in the Software without restriction, including without limitation the rights to
>+*use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
>+*of the Software, and to permit persons to whom the Software is furnished to
>+*do so, subject to the following conditions:
>+*
>+*THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
>+*EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
>+*OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
>+*NONINFRINGEMENT.  IN NO EVENT SHALL Mill.Chen and Monk.Liu OR COPYRIGHT
>+*HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
>+*WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
>+*FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
>+*OTHER DEALINGS IN THE SOFTWARE.
>+*******************************************************************/
>+#ifndef LYNX_HW750_H__
>+#define LYNX_HW750_H__
>+
>+
>+#define DEFAULT_SM750_CHIP_CLOCK 		290
>+#define DEFAULT_SM750LE_CHIP_CLOCK  	333
>+#ifndef SM750LE_REVISION_ID
>+#define SM750LE_REVISION_ID ((unsigned char)0xfe)
>+#endif
>+
>+
>+
>+enum sm750_pnltype{
>+
>+	sm750_24TFT = 0, /* 24bit tft */
>+
>+	sm750_dualTFT = 2, /* dual 18 bit tft */
>+
>+	sm750_doubleTFT = 1, /* 36 bit double pixel tft */
>+};
>+
>+/* vga channel is not concerned  */
>+enum sm750_dataflow{
>+	sm750_simul_pri, /* primary => all head */
>+
>+	sm750_simul_sec, /* secondary => all head */
>+
>+	sm750_dual_normal, /* 	primary => panel head and secondary => crt */
>+
>+	sm750_dual_swap, /* 	primary => crt head and secondary => panel */
>+};
>+
>+
>+enum sm750_channel{
>+	sm750_primary = 0,
>+	/* enum value equal to the register filed data */
>+	sm750_secondary = 1,
>+};
>+
>+enum sm750_path{
>+	sm750_panel = 1,
>+	sm750_crt = 2,
>+	sm750_pnc = 3, /* panel and crt */
>+};
>+
>+struct init_status{
>+	ushort powerMode;
>+	/* below three clocks are in unit of MHZ*/
>+	ushort chip_clk;
>+	ushort mem_clk;
>+	ushort master_clk;
>+	ushort setAllEngOff;
>+	ushort resetMemory;
>+};
>+
>+struct sm750_state{
>+	struct init_status initParm;
>+	enum sm750_pnltype pnltype;
>+	enum sm750_dataflow dataflow;
>+	int nocrt;
>+	int xLCD;
>+	int yLCD;
>+};
>+
>+/* 	sm750_share stands for a presentation of two frame buffer
>+	that use one sm750 adaptor, it is similiar to the super class of lynx_share
>+	in C++
>+*/
>+
>+struct sm750_share{
>+	/* it's better to put lynx_share struct to the first place of sm750_share */
>+	struct lynx_share share;
>+	struct sm750_state state;
>+	int hwCursor;
>+	/* 	0: no hardware cursor
>+		1: primary crtc hw cursor enabled,
>+		2: secondary crtc hw cursor enabled
>+		3: both ctrc hw cursor enabled
>+	*/
>+};
>+
>+int hw_sm750_map(struct lynx_share *share, struct pci_dev *pdev);
>+int hw_sm750_inithw(struct lynx_share *, struct pci_dev *);
>+void hw_sm750_initAccel(struct lynx_share *);
>+int hw_sm750_deWait(void);
>+int hw_sm750le_deWait(void);
>+
>+resource_size_t hw_sm750_getVMSize(struct lynx_share *);
>+int hw_sm750_output_checkMode(struct lynxfb_output *, struct fb_var_screeninfo *);
>+int hw_sm750_output_setMode(struct lynxfb_output *, struct fb_var_screeninfo *, struct fb_fix_screeninfo *);
>+int hw_sm750_crtc_checkMode(struct lynxfb_crtc *, struct fb_var_screeninfo *);
>+int hw_sm750_crtc_setMode(struct lynxfb_crtc *, struct fb_var_screeninfo *, struct fb_fix_screeninfo *);
>+int hw_sm750_setColReg(struct lynxfb_crtc *, ushort, ushort, ushort, ushort);
>+int hw_sm750_setBLANK(struct lynxfb_output *, int);
>+int hw_sm750le_setBLANK(struct lynxfb_output *, int);
>+void hw_sm750_crtc_clear(struct lynxfb_crtc *);
>+void hw_sm750_output_clear(struct lynxfb_output *);
>+int hw_sm750_pan_display(struct lynxfb_crtc *crtc,
>+	const struct fb_var_screeninfo *var,
>+	const struct fb_info *info);
>+
>+#endif
>diff --git a/drivers/video/lynxfb/modedb.c b/drivers/video/lynxfb/modedb.c
>new file mode 100644
>index 0000000..50fc8b9
>--- /dev/null
>+++ b/drivers/video/lynxfb/modedb.c
>@@ -0,0 +1,238 @@
>+/*******************************************************************
>+*Copyright (c) 2012 by Silicon Motion, Inc. (SMI)
>+*Permission is hereby granted, free of charge, to any person obtaining a copy
>+*of this software and associated documentation files (the "Software"), to deal
>+*in the Software without restriction, including without limitation the rights to
>+*use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
>+*of the Software, and to permit persons to whom the Software is furnished to
>+*do so, subject to the following conditions:
>+*
>+*THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
>+*EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
>+*OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
>+*NONINFRINGEMENT.  IN NO EVENT SHALL Mill.Chen and Monk.Liu OR COPYRIGHT
>+*HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
>+*WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
>+*FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
>+*OTHER DEALINGS IN THE SOFTWARE.
>+*******************************************************************/
>+static const struct fb_videomode modedb2[] = {
>+    {
>+	/* 640x400 @ 70 Hz, 31.5 kHz hsync */
>+	NULL, 70, 640, 400, 39721, 40, 24, 39, 9, 96, 2,
>+	0, FB_VMODE_NONINTERLACED
>+    }, {
>+	/* 640x480 @ 60 Hz, 31.5 kHz hsync */
>+	NULL, 60, 640, 480, 39721, 40, 24, 32, 11, 96, 2,
>+	0, FB_VMODE_NONINTERLACED
>+    }, {
>+	/* 800x600 @ 56 Hz, 35.15 kHz hsync */
>+	NULL, 56, 800, 600, 27777, 128, 24, 22, 1, 72, 2,
>+	0, FB_VMODE_NONINTERLACED
>+    }, {
>+	/* 1024x768 @ 87 Hz interlaced, 35.5 kHz hsync */
>+	NULL, 87, 1024, 768, 22271, 56, 24, 33, 8, 160, 8,
>+	0, FB_VMODE_INTERLACED
>+    }, {
>+	/* 640x400 @ 85 Hz, 37.86 kHz hsync */
>+	NULL, 85, 640, 400, 31746, 96, 32, 41, 1, 64, 3,
>+	FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
>+    }, {
>+	/* 640x480 @ 72 Hz, 36.5 kHz hsync */
>+	NULL, 72, 640, 480, 31746, 144, 40, 30, 8, 40, 3,
>+	0, FB_VMODE_NONINTERLACED
>+    }, {
>+	/* 640x480 @ 75 Hz, 37.50 kHz hsync */
>+	NULL, 75, 640, 480, 31746, 120, 16, 16, 1, 64, 3,
>+	0, FB_VMODE_NONINTERLACED
>+    }, {
>+	/* 800x600 @ 60 Hz, 37.8 kHz hsync */
>+	NULL, 60, 800, 600, 25000, 88, 40, 23, 1, 128, 4,
>+	FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
>+    }, {
>+	/* 640x480 @ 85 Hz, 43.27 kHz hsync */
>+	NULL, 85, 640, 480, 27777, 80, 56, 25, 1, 56, 3,
>+	0, FB_VMODE_NONINTERLACED
>+    }, {
>+	/* 1152x864 @ 89 Hz interlaced, 44 kHz hsync */
>+	NULL, 69, 1152, 864, 15384, 96, 16, 110, 1, 216, 10,
>+	0, FB_VMODE_INTERLACED
>+    }, {
>+	/* 800x600 @ 72 Hz, 48.0 kHz hsync */
>+	NULL, 72, 800, 600, 20000, 64, 56, 23, 37, 120, 6,
>+	FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
>+    }, {
>+	/* 1024x768 @ 60 Hz, 48.4 kHz hsync */
>+	NULL, 60, 1024, 768, 15384, 168, 8, 29, 3, 144, 6,
>+	0, FB_VMODE_NONINTERLACED
>+    }, {
>+	/* 640x480 @ 100 Hz, 53.01 kHz hsync */
>+	NULL, 100, 640, 480, 21834, 96, 32, 36, 8, 96, 6,
>+	0, FB_VMODE_NONINTERLACED
>+    }, {
>+	/* 1152x864 @ 60 Hz, 53.5 kHz hsync */
>+	NULL, 60, 1152, 864, 11123, 208, 64, 16, 4, 256, 8,
>+	0, FB_VMODE_NONINTERLACED
>+    }, {
>+	/* 800x600 @ 85 Hz, 55.84 kHz hsync */
>+	NULL, 85, 800, 600, 16460, 160, 64, 36, 16, 64, 5,
>+	0, FB_VMODE_NONINTERLACED
>+    }, {
>+	/* 1024x768 @ 70 Hz, 56.5 kHz hsync */
>+	NULL, 70, 1024, 768, 13333, 144, 24, 29, 3, 136, 6,
>+	0, FB_VMODE_NONINTERLACED
>+    }, {
>+	/*  1280x960-60 VESA */
>+	NULL, 60, 1280, 960, 9259, 312, 96, 36, 1, 112, 3,
>+	FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA
>+    }, {
>+	/*  1280x1024-60 VESA */
>+	NULL, 60, 1280, 1024, 9259, 248, 48, 38, 1, 112, 3,
>+	FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA
>+    }, {
>+	/* 1280x1024 @ 87 Hz interlaced, 51 kHz hsync */
>+	NULL, 87, 1280, 1024, 12500, 56, 16, 128, 1, 216, 12,
>+	0, FB_VMODE_INTERLACED
>+    }, {
>+	/* 800x600 @ 100 Hz, 64.02 kHz hsync */
>+	NULL, 100, 800, 600, 14357, 160, 64, 30, 4, 64, 6,
>+	0, FB_VMODE_NONINTERLACED
>+    }, {
>+	/* 1024x768 @ 76 Hz, 62.5 kHz hsync */
>+	NULL, 76, 1024, 768, 11764, 208, 8, 36, 16, 120, 3,
>+	0, FB_VMODE_NONINTERLACED
>+    }, {
>+	/* 1152x864 @ 70 Hz, 62.4 kHz hsync */
>+	NULL, 70, 1152, 864, 10869, 106, 56, 20, 1, 160, 10,
>+	0, FB_VMODE_NONINTERLACED
>+    }, {
>+	/* 1280x1024 @ 61 Hz, 64.2 kHz hsync */
>+	NULL, 61, 1280, 1024, 9090, 200, 48, 26, 1, 184, 3,
>+	0, FB_VMODE_NONINTERLACED
>+    }, {
>+	/* 1400x1050 @ 60Hz, 63.9 kHz hsync */
>+	NULL, 68, 1400, 1050, 9259, 136, 40, 13, 1, 112, 3,
>+	0, FB_VMODE_NONINTERLACED
>+    }, {
>+	/* 1400x1050 @ 75,107 Hz, 82,392 kHz +hsync +vsync*/
>+	NULL, 75, 1400, 1050, 9271, 120, 56, 13, 0, 112, 3,
>+	FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
>+    }, {
>+	/* 1400x1050 @ 60 Hz, ? kHz +hsync +vsync*/
>+	NULL, 60, 1400, 1050, 9259, 128, 40, 12, 0, 112, 3,
>+	FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
>+    }, {
>+	/* 1024x768 @ 85 Hz, 70.24 kHz hsync */
>+	NULL, 85, 1024, 768, 10111, 192, 32, 34, 14, 160, 6,
>+	0, FB_VMODE_NONINTERLACED
>+    }, {
>+	/* 1152x864 @ 78 Hz, 70.8 kHz hsync */
>+	NULL, 78, 1152, 864, 9090, 228, 88, 32, 0, 84, 12,
>+	0, FB_VMODE_NONINTERLACED
>+    }, {
>+	/* 1280x1024 @ 70 Hz, 74.59 kHz hsync */
>+	NULL, 70, 1280, 1024, 7905, 224, 32, 28, 8, 160, 8,
>+	0, FB_VMODE_NONINTERLACED
>+    }, {
>+	/* 1600x1200 @ 60Hz, 75.00 kHz hsync */
>+	NULL, 60, 1600, 1200, 6172, 304, 64, 46, 1, 192, 3,
>+	FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
>+    }, {
>+	/* 1152x864 @ 84 Hz, 76.0 kHz hsync */
>+	NULL, 84, 1152, 864, 7407, 184, 312, 32, 0, 128, 12,
>+	0, FB_VMODE_NONINTERLACED
>+    }, {
>+	/* 1280x1024 @ 74 Hz, 78.85 kHz hsync */
>+	NULL, 74, 1280, 1024, 7407, 256, 32, 34, 3, 144, 3,
>+	0, FB_VMODE_NONINTERLACED
>+    }, {
>+	/* 1024x768 @ 100Hz, 80.21 kHz hsync */
>+	NULL, 100, 1024, 768, 8658, 192, 32, 21, 3, 192, 10,
>+	0, FB_VMODE_NONINTERLACED
>+    }, {
>+	/* 1280x1024 @ 76 Hz, 81.13 kHz hsync */
>+	NULL, 76, 1280, 1024, 7407, 248, 32, 34, 3, 104, 3,
>+	0, FB_VMODE_NONINTERLACED
>+    }, {
>+	/* 1600x1200 @ 70 Hz, 87.50 kHz hsync */
>+	NULL, 70, 1600, 1200, 5291, 304, 64, 46, 1, 192, 3,
>+	0, FB_VMODE_NONINTERLACED
>+    }, {
>+	/* 1152x864 @ 100 Hz, 89.62 kHz hsync */
>+	NULL, 100, 1152, 864, 7264, 224, 32, 17, 2, 128, 19,
>+	0, FB_VMODE_NONINTERLACED
>+    }, {
>+	/* 1280x1024 @ 85 Hz, 91.15 kHz hsync */
>+	NULL, 85, 1280, 1024, 6349, 224, 64, 44, 1, 160, 3,
>+	FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
>+    }, {
>+	/* 1600x1200 @ 75 Hz, 93.75 kHz hsync */
>+	NULL, 75, 1600, 1200, 4938, 304, 64, 46, 1, 192, 3,
>+	FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
>+    }, {
>+	/* 1600x1200 @ 85 Hz, 105.77 kHz hsync */
>+	NULL, 85, 1600, 1200, 4545, 272, 16, 37, 4, 192, 3,
>+	FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
>+    }, {
>+	/* 1280x1024 @ 100 Hz, 107.16 kHz hsync */
>+	NULL, 100, 1280, 1024, 5502, 256, 32, 26, 7, 128, 15,
>+	0, FB_VMODE_NONINTERLACED
>+    }, {
>+	/* 1800x1440 @ 64Hz, 96.15 kHz hsync  */
>+	NULL, 64, 1800, 1440, 4347, 304, 96, 46, 1, 192, 3,
>+	FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
>+    }, {
>+	/* 1800x1440 @ 70Hz, 104.52 kHz hsync  */
>+	NULL, 70, 1800, 1440, 4000, 304, 96, 46, 1, 192, 3,
>+	FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
>+    }, {
>+	/* 512x384 @ 78 Hz, 31.50 kHz hsync */
>+	NULL, 78, 512, 384, 49603, 48, 16, 16, 1, 64, 3,
>+	0, FB_VMODE_NONINTERLACED
>+    }, {
>+	/* 512x384 @ 85 Hz, 34.38 kHz hsync */
>+	NULL, 85, 512, 384, 45454, 48, 16, 16, 1, 64, 3,
>+	0, FB_VMODE_NONINTERLACED
>+    }, {
>+	/* 320x200 @ 70 Hz, 31.5 kHz hsync, 8:5 aspect ratio */
>+	NULL, 70, 320, 200, 79440, 16, 16, 20, 4, 48, 1,
>+	0, FB_VMODE_DOUBLE
>+    }, {
>+	/* 320x240 @ 60 Hz, 31.5 kHz hsync, 4:3 aspect ratio */
>+	NULL, 60, 320, 240, 79440, 16, 16, 16, 5, 48, 1,
>+	0, FB_VMODE_DOUBLE
>+    }, {
>+	/* 320x240 @ 72 Hz, 36.5 kHz hsync */
>+	NULL, 72, 320, 240, 63492, 16, 16, 16, 4, 48, 2,
>+	0, FB_VMODE_DOUBLE
>+    }, {
>+	/* 400x300 @ 56 Hz, 35.2 kHz hsync, 4:3 aspect ratio */
>+	NULL, 56, 400, 300, 55555, 64, 16, 10, 1, 32, 1,
>+	0, FB_VMODE_DOUBLE
>+    }, {
>+	/* 400x300 @ 60 Hz, 37.8 kHz hsync */
>+	NULL, 60, 400, 300, 50000, 48, 16, 11, 1, 64, 2,
>+	0, FB_VMODE_DOUBLE
>+    }, {
>+	/* 400x300 @ 72 Hz, 48.0 kHz hsync */
>+	NULL, 72, 400, 300, 40000, 32, 24, 11, 19, 64, 3,
>+	0, FB_VMODE_DOUBLE
>+    }, {
>+	/* 480x300 @ 56 Hz, 35.2 kHz hsync, 8:5 aspect ratio */
>+	NULL, 56, 480, 300, 46176, 80, 16, 10, 1, 40, 1,
>+	0, FB_VMODE_DOUBLE
>+    }, {
>+	/* 480x300 @ 60 Hz, 37.8 kHz hsync */
>+	NULL, 60, 480, 300, 41858, 56, 16, 11, 1, 80, 2,
>+	0, FB_VMODE_DOUBLE
>+    }, {
>+	/* 480x300 @ 63 Hz, 39.6 kHz hsync */
>+	NULL, 63, 480, 300, 40000, 56, 16, 11, 1, 80, 2,
>+	0, FB_VMODE_DOUBLE
>+    }, {
>+	/* 480x300 @ 72 Hz, 48.0 kHz hsync */
>+	NULL, 72, 480, 300, 33386, 40, 24, 11, 19, 80, 3,
>+	0, FB_VMODE_DOUBLE
>+    },
>+};
>+static const int nmodedb2 = sizeof(modedb2);
>diff --git a/drivers/video/lynxfb/ver.h b/drivers/video/lynxfb/ver.h
>new file mode 100644
>index 0000000..d11362a
>--- /dev/null
>+++ b/drivers/video/lynxfb/ver.h
>@@ -0,0 +1,38 @@
>+/*******************************************************************
>+*Copyright (c) 2012 by Silicon Motion, Inc. (SMI)
>+*Permission is hereby granted, free of charge, to any person obtaining a copy
>+*of this software and associated documentation files (the "Software"), to deal
>+*in the Software without restriction, including without limitation the rights to
>+*use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
>+*of the Software, and to permit persons to whom the Software is furnished to
>+*do so, subject to the following conditions:
>+*
>+*THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
>+*EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
>+*OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
>+*NONINFRINGEMENT.  IN NO EVENT SHALL Mill.Chen and Monk.Liu OR COPYRIGHT
>+*HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
>+*WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
>+*FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
>+*OTHER DEALINGS IN THE SOFTWARE.
>+*******************************************************************/
>+#ifndef __VER_H_
>+#define __VER_H_
>+
>+#define RELEASE_TYPE "Electra(formal release)"
>+#define SUPPORT_ARCH "x86,x86_64"
>+#define SUPPORT_CHIP "lynx Express(750)/lynx 750LE/Lynx SE(718)"
>+/*#define SUPPORT_CHIP " \
>+\tlynx 750LE\n"*/
>+
>+#define SUPPORT_OS " \
>+\tRHEL 4.3 i386 and x86_64\n \
>+\tRHEL 5.3 i386 and x86_64\n \
>+\tRHEL 6.0 i386 and x86_64\n \
>+\tSLES 9   i386 and x86_64\n \
>+\tSLES 10  i386 and x86_64\n \
>+\tSLES 11  i386 and x86_64\n"
>+#define _version_	"4.1.3"
>+
>+#endif
>+
>-- 
>1.7.9.5
>


More information about the dri-devel mailing list