From 021fae4975e5dae8010ce9d1deac1fca17670fb3 Mon Sep 17 00:00:00 2001
From: Aaron Chen <aaron.chen@siliconmotion.com>
Date: Tue, 5 Feb 2013 10:09:00 +0800
Subject: [PATCH] Siliconmotion initial patch

Add SM750 support. Add 2d accelerate and hw curser feature.

Signed-off-by: Aaron Chen <aaron.chen@siliconmotion.com.cn>
---
 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 e7068c5..d8b2ba5 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -2419,6 +2419,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 768a137..5283ac3 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -146,6 +146,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
+
+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
+
+
+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
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{
+	unsigned char power;/* d : 0~ 6*/
+	unsigned char pod;
+	unsigned char od;
+	unsigned char value;/* value of  2 power d (2^d) */
+}
+pllcalparam;
+
+
+logical_chip_type_t getChipType()
+{
+	unsigned short physicalID;
+	char physicalRev;
+	logical_chip_type_t chip;
+
+	physicalID = devId750;/* either 0x718 or 0x750 */
+	physicalRev = revId750;
+
+	if (physicalID == 0x718) {
+		chip = SM718;
+	} else if (physicalID == 0x750) {
+		chip = SM750;
+		/* SM750 and SM750LE are different in their revision ID only. */
+		if (physicalRev == SM750LE_REVISION_ID) {
+			chip = SM750LE;
+		}
+	} else{
+		chip = SM_UNKNOWN;
+	}
+
+	return chip;
+}
+
+
+inline unsigned int twoToPowerOfx(unsigned long x)
+{
+	unsigned long i;
+	unsigned long result = 1;
+
+	for (i = 1; i <= x; i++)
+		result *= 2;
+	return result;
+}
+
+inline unsigned int calcPLL(pll_value_t *pPLL)
+{
+	return pPLL->inputFreq * pPLL->M / pPLL->N / twoToPowerOfx(pPLL->OD) / twoToPowerOfx(pPLL->POD);
+}
+
+unsigned int getPllValue(clock_type_t clockType, pll_value_t *pPLL)
+{
+	unsigned int ulPllReg = 0;
+
+	pPLL->inputFreq = DEFAULT_INPUT_CLOCK;
+	pPLL->clockType = clockType;
+
+	switch (clockType) {
+	case MXCLK_PLL:
+		ulPllReg = PEEK32(MXCLK_PLL_CTRL);
+		break;
+	case PRIMARY_PLL:
+		ulPllReg = PEEK32(PANEL_PLL_CTRL);
+		break;
+	case SECONDARY_PLL:
+		ulPllReg = PEEK32(CRT_PLL_CTRL);
+		break;
+	case VGA0_PLL:
+		ulPllReg = PEEK32(VGA_PLL0_CTRL);
+		break;
+	case VGA1_PLL:
+		ulPllReg = PEEK32(VGA_PLL1_CTRL);
+		break;
+	}
+	pPLL->M = 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 */
+		pll.clockType = MXCLK_PLL;
+
+		/*
+		 * Call calcPllValue() to fill up the other fields for PLL structure.
+		 * Sometime, the chip cannot set up the exact clock required by User.
+		 * Return value from calcPllValue() gives the actual possible clock.
+		 */
+		ulActualMxClk = calcPllValue(frequency, &pll);
+
+		/* Master Clock Control: MXCLK_PLL */
+		POKE32(MXCLK_PLL_CTRL, formatPllReg(&pll));
+	}
+}
+
+
+
+void setMemoryClock(unsigned int frequency)
+{
+	unsigned int ulReg, divisor;
+
+	/* 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
+	/* 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@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@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@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@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

