All of lore.kernel.org
 help / color / mirror / Atom feed
* 转发: Siliconmotion new kernel driver initial patch
@ 2012-08-13  8:56 Aaron.Chen  陈俊杰
  2012-08-13 18:03   ` Konrad Rzeszutek Wilk
  0 siblings, 1 reply; 5+ messages in thread
From: Aaron.Chen  陈俊杰 @ 2012-08-13  8:56 UTC (permalink / raw)
  To: linux-fbdev
  Cc: mill.chen 陈军, Mandy.Wang 王少媚,
	Paul.Chen 陈波, dri-devel,
	caesar.qiu 裘赛海, Sunny.Yang 杨光

[-- Attachment #1: Type: text/plain, Size: 174 bytes --]


Since there is no response for the last mail. Maybe it didn't sent successfully. So I send it again. Here is the initial patch for siliconmotion kernel driver.

Aaron


[-- Attachment #2: 0001-Siliconmotion-new-kernel-driver-initial-patch.patch --]
[-- Type: application/octet-stream, Size: 369305 bytes --]

From f3b98301a2a9d9af36ff9e10b3ce40804b1078d8 Mon Sep 17 00:00:00 2001
From: Aaron Chen <aaron.chen@siliconmotion.com>
Date: Thu, 9 Aug 2012 09:52:29 +0800
Subject: [PATCH] Siliconmotion new kernel driver initial patch

This is a framebuffer driver for all the siliconmotion graphics chips such as SM750/718/712/722/750le/502. It can support both 32 and 64bit OS.

Signed-off-by: Aaron Chen <aaron.chen@siliconmotion.com>
---
 drivers/video/Kconfig                        |   13 +
 drivers/video/Makefile                       |    1 +
 drivers/video/lynxfb/Makefile                |   63 +
 drivers/video/lynxfb/ddk712/ddk712.h         |   27 +
 drivers/video/lynxfb/ddk712/ddk712_chip.c    |  163 ++
 drivers/video/lynxfb/ddk712/ddk712_chip.h    |   71 +
 drivers/video/lynxfb/ddk712/ddk712_help.c    |   47 +
 drivers/video/lynxfb/ddk712/ddk712_help.h    |  117 ++
 drivers/video/lynxfb/ddk712/ddk712_mode.c    |  278 ++++
 drivers/video/lynxfb/ddk712/ddk712_mode.h    |   40 +
 drivers/video/lynxfb/ddk712/ddk712_reg.h     |   32 +
 drivers/video/lynxfb/ddk750/ddk750.h         |   31 +
 drivers/video/lynxfb/ddk750/ddk750_chip.c    |  610 +++++++
 drivers/video/lynxfb/ddk750/ddk750_chip.h    |   97 ++
 drivers/video/lynxfb/ddk750/ddk750_display.c |  295 ++++
 drivers/video/lynxfb/ddk750/ddk750_display.h |  177 +++
 drivers/video/lynxfb/ddk750/ddk750_dvi.c     |  114 ++
 drivers/video/lynxfb/ddk750/ddk750_dvi.h     |   84 +
 drivers/video/lynxfb/ddk750/ddk750_help.c    |   37 +
 drivers/video/lynxfb/ddk750/ddk750_help.h    |   47 +
 drivers/video/lynxfb/ddk750/ddk750_hwi2c.c   |  290 ++++
 drivers/video/lynxfb/ddk750/ddk750_hwi2c.h   |   28 +
 drivers/video/lynxfb/ddk750/ddk750_mode.c    |  213 +++
 drivers/video/lynxfb/ddk750/ddk750_mode.h    |   59 +
 drivers/video/lynxfb/ddk750/ddk750_power.c   |  246 +++
 drivers/video/lynxfb/ddk750/ddk750_power.h   |   85 +
 drivers/video/lynxfb/ddk750/ddk750_reg.h     |  362 +++++
 drivers/video/lynxfb/ddk750/ddk750_sii164.c  |  435 +++++
 drivers/video/lynxfb/ddk750/ddk750_sii164.h  |  187 +++
 drivers/video/lynxfb/ddk750/ddk750_swi2c.c   |  531 +++++++
 drivers/video/lynxfb/ddk750/ddk750_swi2c.h   |   98 ++
 drivers/video/lynxfb/lynx_accel.c            |  521 ++++++
 drivers/video/lynxfb/lynx_accel.h            |  176 +++
 drivers/video/lynxfb/lynx_cursor.c           |  385 +++++
 drivers/video/lynxfb/lynx_cursor.h           |   46 +
 drivers/video/lynxfb/lynx_drv.c              | 2183 ++++++++++++++++++++++++++
 drivers/video/lynxfb/lynx_drv.h              |  271 ++++
 drivers/video/lynxfb/lynx_help.h             |  115 ++
 drivers/video/lynxfb/lynx_hw502.c            |  987 ++++++++++++
 drivers/video/lynxfb/lynx_hw502.h            |  145 ++
 drivers/video/lynxfb/lynx_hw712.c            |  526 +++++++
 drivers/video/lynxfb/lynx_hw712.h            |   53 +
 drivers/video/lynxfb/lynx_hw750.c            |  636 ++++++++
 drivers/video/lynxfb/lynx_hw750.h            |  120 ++
 drivers/video/lynxfb/modedb.c                |  238 +++
 drivers/video/lynxfb/ver.h                   |   38 +
 drivers/video/lynxfb/voyager.h               |  167 ++
 47 files changed, 11485 insertions(+), 0 deletions(-)
 create mode 100644 drivers/video/lynxfb/Makefile
 create mode 100644 drivers/video/lynxfb/ddk712/ddk712.h
 create mode 100644 drivers/video/lynxfb/ddk712/ddk712_chip.c
 create mode 100644 drivers/video/lynxfb/ddk712/ddk712_chip.h
 create mode 100644 drivers/video/lynxfb/ddk712/ddk712_help.c
 create mode 100644 drivers/video/lynxfb/ddk712/ddk712_help.h
 create mode 100644 drivers/video/lynxfb/ddk712/ddk712_mode.c
 create mode 100644 drivers/video/lynxfb/ddk712/ddk712_mode.h
 create mode 100644 drivers/video/lynxfb/ddk712/ddk712_reg.h
 create mode 100644 drivers/video/lynxfb/ddk750/ddk750.h
 create mode 100644 drivers/video/lynxfb/ddk750/ddk750_chip.c
 create mode 100644 drivers/video/lynxfb/ddk750/ddk750_chip.h
 create mode 100644 drivers/video/lynxfb/ddk750/ddk750_display.c
 create mode 100644 drivers/video/lynxfb/ddk750/ddk750_display.h
 create mode 100644 drivers/video/lynxfb/ddk750/ddk750_dvi.c
 create mode 100644 drivers/video/lynxfb/ddk750/ddk750_dvi.h
 create mode 100644 drivers/video/lynxfb/ddk750/ddk750_help.c
 create mode 100644 drivers/video/lynxfb/ddk750/ddk750_help.h
 create mode 100644 drivers/video/lynxfb/ddk750/ddk750_hwi2c.c
 create mode 100644 drivers/video/lynxfb/ddk750/ddk750_hwi2c.h
 create mode 100644 drivers/video/lynxfb/ddk750/ddk750_mode.c
 create mode 100644 drivers/video/lynxfb/ddk750/ddk750_mode.h
 create mode 100644 drivers/video/lynxfb/ddk750/ddk750_power.c
 create mode 100644 drivers/video/lynxfb/ddk750/ddk750_power.h
 create mode 100644 drivers/video/lynxfb/ddk750/ddk750_reg.h
 create mode 100644 drivers/video/lynxfb/ddk750/ddk750_sii164.c
 create mode 100644 drivers/video/lynxfb/ddk750/ddk750_sii164.h
 create mode 100644 drivers/video/lynxfb/ddk750/ddk750_swi2c.c
 create mode 100644 drivers/video/lynxfb/ddk750/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_hw502.c
 create mode 100644 drivers/video/lynxfb/lynx_hw502.h
 create mode 100644 drivers/video/lynxfb/lynx_hw712.c
 create mode 100644 drivers/video/lynxfb/lynx_hw712.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
 create mode 100644 drivers/video/lynxfb/voyager.h

diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 0217f74..8c52b1a 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -2444,6 +2444,19 @@ config FB_PUV3_UNIGFX
 	  Choose this option if you want to use the Unigfx device as a
 	  framebuffer device. Without the support of PCI & AGP.
 
+config FB_LYNXFB
+	tristate "SMI lynx sm750/718/712/722/502 display support"
+	depends on FB && PCI
+	select FB_CFB_IMAGEBLIT
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	---help---
+	  This driver supports graphic board with the siliconmotion
+	  sm750/sm718/sm712/sm722/sm502. Say Y if you have such a
+	  graphic board.
+	  To compile this driver as a module, choose M here: the
+	  module will be called lynxfb.
+
 source "drivers/video/omap/Kconfig"
 source "drivers/video/omap2/Kconfig"
 source "drivers/video/exynos/Kconfig"
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index ee8dafb..e2a5c65 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -149,6 +149,7 @@ obj-$(CONFIG_FB_MSM)              += msm/
 obj-$(CONFIG_FB_NUC900)           += nuc900fb.o
 obj-$(CONFIG_FB_JZ4740)		  += jz4740_fb.o
 obj-$(CONFIG_FB_PUV3_UNIGFX)      += fb-puv3.o
+Obj-$(CONFIG_FB_LYNXFB)		  += lynxfb/
 
 # Platform or fallback drivers go here
 obj-$(CONFIG_FB_UVESA)            += uvesafb.o
diff --git a/drivers/video/lynxfb/Makefile b/drivers/video/lynxfb/Makefile
new file mode 100644
index 0000000..fdaa403
--- /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_hw712.o lynx_hw502.o lynx_accel.o lynx_cursor.o
+lynxfb-y += ddk750/ddk750_chip.o ddk750/ddk750_power.o ddk750/ddk750_mode.o ddk750/ddk750_display.o ddk750/ddk750_help.o
+lynxfb-y += ddk712/ddk712_chip.o ddk712/ddk712_mode.o ddk712/ddk712_help.o ddk750/ddk750_swi2c.o
+
+
+EXTRA_CFLAGS += -DOPENSOURCE
+
+ifneq ($(nodvi),1)
+lynxfb-y += ddk750/ddk750_sii164.o
+lynxfb-y += ddk750/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/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/ddk712/ddk712.h b/drivers/video/lynxfb/ddk712/ddk712.h
new file mode 100644
index 0000000..faf4102
--- /dev/null
+++ b/drivers/video/lynxfb/ddk712/ddk712.h
@@ -0,0 +1,27 @@
+/*******************************************************************
+*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 DDK712_H__
+#define DDK712_H__
+#include "ddk712_reg.h"
+#include "ddk712_mode.h"
+#include "ddk712_chip.h"
+/*#include "ddk712_display.h"*/
+#include "ddk712_help.h"
+
+#endif
diff --git a/drivers/video/lynxfb/ddk712/ddk712_chip.c b/drivers/video/lynxfb/ddk712/ddk712_chip.c
new file mode 100644
index 0000000..fe58187
--- /dev/null
+++ b/drivers/video/lynxfb/ddk712/ddk712_chip.c
@@ -0,0 +1,163 @@
+/*******************************************************************
+*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 "ddk712_chip.h"
+#include "ddk712_help.h"
+
+/* MCLK X mdr = INPUT X mnr */
+unsigned int ddk712_calcPllValue(unsigned int clock, int *o_mnr, int *o_mdr)
+{
+	int mdr, mnr;
+	unsigned int mxm;
+	unsigned int request, input;
+	unsigned int quo, rem;
+	unsigned int miniDiff, diff0;
+
+	miniDiff = ~0;
+	/* clocl diveded b 1000 to prevent from overflow exception */
+	request = clock / 1000;
+	input = DEFAULT_INPUT_CLOCK / 1000;
+
+	for (mdr = 1; mdr < 64; mdr++) {
+		mxm = request * mdr;
+		quo = mxm / input;
+		rem = mxm % input;
+		if ((rem * 100 / input) > 500)
+			quo++;
+		mnr = quo;
+
+		if (mnr < 256) {
+			diff0 = absDiff(calcMCLK(mnr, mdr), clock);
+			if (diff0 < miniDiff) {
+				*o_mnr = mnr;
+				*o_mdr = mdr;
+			}
+		}
+	}
+
+	return calcMCLK(*o_mnr, *o_mdr);
+}
+
+void ddk712_hw_init(init_parm_712 *param)
+{
+	int mnr, mdr;
+	mnr = mdr = 1;
+
+	/* for sm712 pci burst enabling
+	 * either:
+	 * open both burst write and read
+	 * or
+	 * open burst write and disable burst read
+	 * nothing else
+	 * */
+	if (param->pci_burst == 2) {
+		/* burst write on and read off*/
+		poke_scr(0x17, peek_scr(0x17)|0x20);
+		poke_scr(0x15, peek_scr(0x15)&~0x80);
+	} else if (param->pci_burst == 3) {
+		/* both burst  read and write on*/
+		poke_scr(0x17, peek_scr(0x17)|0x20);
+		poke_scr(0x15, peek_scr(0x15)|0x80);
+	} else{
+		/* no pci burst */
+		poke_scr(0x17, peek_scr(0x17) & ~0x20);
+	}
+
+	/* use 3dx for crtc IO */
+	poke8_io(0x3c2, peek8_io(0x3cc)|1);
+
+	/* if memClock is 0, than use BIOS setting */
+	if (param->memClock > 0) {
+		/* get approprite mnr, mdr for memory clock */
+		ddk712_calcPllValue(param->memClock, &mnr, &mdr);
+		poke_ccr(0x6a, mnr&0xff);
+		poke_ccr(0x6b, mdr&0xff);
+	}
+
+	if (param->devid == 0x720) {
+		/* for sm722, always set pdr21 bit 5 to 0*/
+		poke_pdr(0x21, peek_pdr(0x21)&~0x20);
+	}
+
+	/* Disable LCD framebuffer r/w operation */
+	/* enable VPR power gate, VPR is used in frame buffer driver
+	 * enable CPR power gate, and DPR power gate
+	 * */
+	poke_pdr(0x21, (peek_pdr(0x21)|0x30)&0xf8);
+
+	/* Enable DAC defaultly */
+	poke_pdr(0x21, peek_pdr(0x21)&0x7f);
+
+	/* power down mode is standby mode, VCLK and MCLK divided by 4*/
+	poke_pdr(0x20, (peek_pdr(0x20) & ~0xb0)|0x10);
+
+	/* Disable horizontal expansion and auto centering */
+	poke_fpr(0x32, peek_fpr(0x32)&~3);
+
+	/* Disable verticle expansion/vertical centering/horizontal centering */
+	poke_crt(0x9e, peek_crt(0x9e) & ~7);
+	poke_crt(0x17, peek_crt(0x17) | 0x80);
+
+	/* use vclk1 */
+	poke_ccr(0x68, 0x54);
+
+	/* Disable panel video */
+	poke_fpr(0xa0, 0);
+	poke_ccr(0x33, 0);
+	poke_ccr(0x3a, 0);
+
+	/* memory control regsiter */
+	poke_mcr(0x60, 1);
+
+	/* below mcr register should be set by BIOS/GPIO pin */
+#if 1
+	/* memory bank set */
+	poke_mcr(0x61, 0);
+
+	/* mcr6 should be set by onboard GPIO pin, but for internal memory 720
+	 * only ff is workable, while 0x3e for sm712
+	 * */
+	if (param->devid == 0x720)
+		poke_mcr(0x62, 0xff);
+	else
+		poke_mcr(0x62, 0x3e);
+
+	/* MCR 63 is not claimed on datasheet, but experiment shows that sm712 need it be 0x1a
+	 * for stable timing */
+	poke_mcr(0x63, 0x1a);
+
+#endif
+
+	if (param->lcd != LCD712_USE_JUMP) {
+		poke_fpr(0x30, (peek_fpr(0x30)&0xfe)|param->lcd);
+		/* set other related registers*/
+	}
+
+	if (param->lcd_color.tftColor != TFT_USE_JUMP) {
+/*		printk("monk:param->lcd_color.tftColor = %d\n", param->lcd_color.tftColor);*/
+		poke_fpr(0x30, (peek_fpr(0x30)&0x8f)|(param->lcd_color.tftColor << 4));
+/*		printk("monk peek scr 0x30 = %02x\n", peek_fpr(0x30));*/
+		/* set other related registers*/
+	}
+
+	if (param->lcd_color.dstnColor != DSTN_USE_JUMP) {
+		poke_fpr(0x30, (peek_fpr(0x30)&0x7f)|(param->lcd_color.dstnColor << 7));
+		/* set other related registers*/
+	}
+}
+
diff --git a/drivers/video/lynxfb/ddk712/ddk712_chip.h b/drivers/video/lynxfb/ddk712/ddk712_chip.h
new file mode 100644
index 0000000..99d8a34
--- /dev/null
+++ b/drivers/video/lynxfb/ddk712/ddk712_chip.h
@@ -0,0 +1,71 @@
+/*******************************************************************
+*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 DDK712_CHIP_H__
+#define DDK712_CHIP_H__
+#define DEFAULT_INPUT_CLOCK 14318181 /* Default reference clock */
+
+enum LCD_TYPE{
+	LCD712_USE_JUMP = -1,
+	LCD712_DSTN = 1,
+	LCD712_TFT = 0,
+};
+
+enum TFT_COLOR{
+	TFT_USE_JUMP = -1,
+	TFT_9BIT = 0,
+	TFT_12BIT = 1,
+	TFT_18BIT = 2,
+	TFT_24BIT = 3,
+	TFT_12P12 = 4,
+	TFT_ANALOG = 5,
+	TFT_18P18 = 6,
+};
+
+enum DSTN_COLOR{
+	DSTN_USE_JUMP = -1,
+	DSTN_16BIT = 0,
+	DSTN_24BIT = 1,
+};
+
+typedef struct _init_parm_712{
+	int devid;/* sm712 sm722*/
+	unsigned int memClock;
+	/* pci burst read,write enable bit*/
+	int pci_burst;/* bit 0 stand for read and 1 for write*/
+	/* lcd settings*/
+	enum LCD_TYPE lcd;
+	struct {
+	enum TFT_COLOR tftColor;
+	enum DSTN_COLOR dstnColor;
+	} lcd_color;
+} init_parm_712;
+
+static inline unsigned int calcMCLK(int mnr, int mdr)
+{
+	/* don't worry about overlflow
+	 * 14.318181 mhz * 255 == 3.4 G */
+	return DEFAULT_INPUT_CLOCK * mnr / mdr;
+}
+
+
+unsigned int ddk712_calcPllValue(unsigned int, int*, int*);
+void ddk712_hw_init(init_parm_712 *);
+void ddk712_set_mmio(int, volatile unsigned char *);
+
+#endif
diff --git a/drivers/video/lynxfb/ddk712/ddk712_help.c b/drivers/video/lynxfb/ddk712/ddk712_help.c
new file mode 100644
index 0000000..69606eb
--- /dev/null
+++ b/drivers/video/lynxfb/ddk712/ddk712_help.c
@@ -0,0 +1,47 @@
+/*******************************************************************
+*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 "ddk712_help.h"
+
+volatile unsigned char __iomem *mmio712;
+/* below offset used for sm712/sm722 */
+int io_offset712;
+/* DPR and VPR memory mapped registers,treated as 32bit access */
+int dpr_offset712;
+int vpr_offset712;
+int dataPort_offset712;
+
+/* after driver mapped io registers, use this function first */
+void ddk712_set_mmio(int devid, volatile unsigned char __iomem *addr)
+{
+	mmio712 = addr;
+	if (devid == 0x712) {
+		/* sm712 register offset stuffs */
+		io_offset712 = MB(3);
+		dpr_offset712 = KB(32);
+		vpr_offset712 = KB(48);
+		dataPort_offset712 = MB(1);
+	} else if (devid == 0x720) {
+		/* sm722 register offset stuffs */
+		io_offset712 = KB(768);
+		dpr_offset712 = KB(0);
+		vpr_offset712 = KB(2);
+		dataPort_offset712 = MB(1);
+	}
+}
+
diff --git a/drivers/video/lynxfb/ddk712/ddk712_help.h b/drivers/video/lynxfb/ddk712/ddk712_help.h
new file mode 100644
index 0000000..86fb65f
--- /dev/null
+++ b/drivers/video/lynxfb/ddk712/ddk712_help.h
@@ -0,0 +1,117 @@
+/*******************************************************************
+*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 DDK712_HELP_H__
+#define DDK712_HELP_H__
+#include "ddk712_chip.h"
+#ifndef USE_INTERNAL_REGISTER_ACCESS
+
+#include <linux/ioport.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include "../lynx_help.h"
+
+/* mmio712 start from framebuffer + 4mega bytes */
+extern volatile unsigned  char __iomem *mmio712;
+extern int io_offset712;
+/* DPR and VPR memory mapped registers, treated as 32bit access */
+extern int dpr_offset712;
+extern int vpr_offset712;
+extern int dataPort_offset712;
+
+#define peek32(addr) readl((addr)+mmio712)
+#define poke32(addr, data) writel((data), (addr)+mmio712)
+
+#define peek8(addr) readb((addr)+mmio712)
+#define poke8(addr, data) writeb((data), (addr)+mmio712)
+
+#define peek8_io(addr) peek8(addr+io_offset712)
+#define poke8_io(addr, data) poke8(addr+io_offset712, data)
+
+static inline char peek_scr(int idx)
+{
+	poke8_io(0x3c4, idx);
+	return peek8_io(0x3c5);
+}
+
+static inline void poke_scr(int idx, char val)
+{
+	poke8_io(0x3c4, idx);
+	poke8_io(0x3c5, val);
+}
+
+static inline char peek_crt(int idx)
+{
+	poke8_io(0x3d4, idx);
+	return peek8_io(0x3d5);
+}
+
+static inline void poke_crt(int idx, char val)
+{
+	poke8_io(0x3d4, idx);
+	poke8_io(0x3d5, val);
+}
+
+/* below registers equal to sequence registers */
+#define peek_pdr(a) peek_scr(a)
+#define peek_fpr(a) peek_scr(a)
+#define peek_mcr(a) peek_scr(a)
+#define peek_ccr(a) peek_scr(a)
+#define peek_gpr(a) peek_scr(a)
+#define peek_phr(a) peek_scr(a)
+#define peek_pop(a) peek_scr(a)
+#define peek_hcr(a) peek_scr(a)
+
+#define poke_pdr(a, b) poke_scr(a, b)
+#define poke_fpr(a, b) poke_scr(a, b)
+#define poke_mcr(a, b) poke_scr(a, b)
+#define poke_ccr(a, b) poke_scr(a, b)
+#define poke_gpr(a, b) poke_scr(a, b)
+#define poke_phr(a, b) poke_scr(a, b)
+#define poke_pop(a, b) poke_scr(a, b)
+#define poke_hcr(a, b) poke_scr(a, b)
+
+/* below registers equal to crtc registers*/
+#define peek_svr(a) peek_crt(a)
+#define poke_svr(a, b) poke_crt(a, b)
+
+
+static inline unsigned int peek32_dpr(int index)
+{
+	return peek32(index + dpr_offset712);
+}
+
+static inline void poke32_dpr(int index, unsigned int val)
+{
+	poke32(index + dpr_offset712, val);
+}
+
+static inline unsigned int peek32_vpr(int index)
+{
+	return peek32(index + vpr_offset712);
+}
+
+static inline void poke32_vpr(int index, unsigned int val)
+{
+	poke32(index + vpr_offset712, val);
+}
+#else
+/* implement if you want use it*/
+#endif
+
+#endif
diff --git a/drivers/video/lynxfb/ddk712/ddk712_mode.c b/drivers/video/lynxfb/ddk712/ddk712_mode.c
new file mode 100644
index 0000000..ef48d08
--- /dev/null
+++ b/drivers/video/lynxfb/ddk712/ddk712_mode.c
@@ -0,0 +1,278 @@
+/*******************************************************************
+*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 "ddk712_mode.h"
+#include "ddk712_help.h"
+#include "ddk712_reg.h"
+
+const SM712CrtTiming sm712_crt_modedb[] = {
+/* 640x480 */
+{
+    640, 480, 60,
+    0x5F, 0x4F, 0x00, 0x54, 0x00, 0x0B, 0xDF, 0x00,
+    0xEA, 0x0C, 0x2E, 0x00, 0x4F, 0xDF, 0x07, 0x82,
+},
+{
+    640, 480, 75,
+    0x64, 0x4F, 0x00, 0x52, 0x1A, 0xF2, 0xDF, 0x00,
+    0xE0, 0x03, 0x0F, 0xC0, 0x4F, 0xDF, 0x16, 0x85,
+},
+{
+    640, 480, 85,
+    0x63, 0x4F, 0x00, 0x57, 0x1E, 0xFB, 0xDF, 0x00,
+    0xE0, 0x03, 0x0F, 0xC0, 0x4F, 0xDF, 0x88, 0x9B,
+},
+/* 800x480 */
+{
+    800, 480, 60,
+    0x6B, 0x63, 0x00, 0x69, 0x1B, 0xF2, 0xDF, 0x00,
+    0xE2, 0xE4, 0x1F, 0xC0, 0x63, 0xDF, 0x2C, 0x17,
+},
+{
+    800, 480, 75,
+    0x6B, 0x63, 0x00, 0x69, 0x1B, 0xF2, 0xDF, 0x00,
+    0xE2, 0xE4, 0x1F, 0xC0, 0x63, 0xDF, 0x2C, 0x17,
+},
+{
+    800, 480, 85,
+    0x6B, 0x63, 0x00, 0x69, 0x1B, 0xF2, 0xDF, 0x00,
+    0xE2, 0xE4, 0x1F, 0xC0, 0x63, 0xDF, 0x2C, 0x17,
+},
+/* 800x600 */
+{
+    800, 600, 60,
+    0x7F, 0x63, 0x00, 0x69, 0x18, 0x72, 0x57, 0x00,
+    0x58, 0x0C, 0xE0, 0x20, 0x63, 0x57, 0x1C, 0x85,
+},
+{
+    800, 600, 75,
+    0x7F, 0x63, 0x00, 0x66, 0x10, 0x6F, 0x57, 0x00,
+    0x58, 0x0B, 0xE0, 0x20, 0x63, 0x57, 0x4C, 0x8B,
+},
+{
+    800, 600, 85,
+    0x7E, 0x63, 0x00, 0x68, 0x10, 0x75, 0x57, 0x00,
+    0x58, 0x0B, 0xE0, 0x20, 0x63, 0x57, 0x37, 0x87,
+},
+#if 0
+/* 1024x600 */
+{
+    1024, 600, 60,
+    0xA3, 0x7F, 0x00, 0x82, 0x0B, 0x6F, 0x57, 0x00,
+    0x5C, 0x0F, 0xE0, 0xE0, 0x7F, 0x57, 0x16, 0x07,
+},
+#endif
+/* 1024x768 */
+
+{
+    1024, 768, 60,
+    0xA3, 0x7F, 0x00, 0x86, 0x15, 0x24, 0xFF, 0x00,
+    0x01, 0x07, 0xE5, 0x20, 0x7F, 0xFF, 0x52, 0x89,
+},
+{
+    1024, 768, 75,
+    0x9F, 0x7F, 0x00, 0x82, 0x0E, 0x1E, 0xFF, 0x00,
+    0x00, 0x03, 0xE5, 0x20, 0x7F, 0xFF, 0x0B, 0x02,
+},
+{
+    1024, 768, 85,
+    0xA7, 0x7F, 0x00, 0x86, 0x12, 0x26, 0xFF, 0x00,
+    0x00, 0x03, 0xE5, 0x20, 0x7F, 0xFF, 0x70, 0x11,
+},
+
+/* 1280x1024 */
+{
+    1280, 1024, 60,
+    0xCE, 0x9F, 0x00, 0xA7, 0x15, 0x28, 0xFF, 0x00,
+    0x00, 0x03, 0x4A, 0x20, 0x9F, 0xFF, 0x53, 0x0B,
+},
+{
+    1280, 1024, 75,
+    0xCE, 0x9F, 0x00, 0xA2, 0x14, 0x28, 0xFF, 0x00,
+/*           0x00, 0x03, 0x4A, 0x20, 0x9F, 0xFF, 0x13, 0x02,  */
+    0x00, 0x03, 0x4A, 0x20, 0x9F, 0xFF, 0x42, 0x07,
+},
+{
+    1280, 1024, 85,
+    0xD3, 0x9F, 0x00, 0xA8, 0x1C, 0x2E, 0xFF, 0x00,
+/*           0x00, 0x03, 0x4A, 0x20, 0x9F, 0xFF, 0x16, 0x42,  */
+    0x00, 0x03, 0x4A, 0x20, 0x9F, 0xFF, 0x0b, 0x01,
+},
+
+};
+
+const SM712PnlTiming sm712_pnl_modedb[] = {
+#if 0
+{
+
+    640, 480, 60,
+    0x04, 0x24, 0x63, 0x4F, 0x52, 0x0C, 0xDF, 0xE9,
+    0x00, 0x03, 0x59, 0x00, 0x4F, 0xDF, 0x03, 0x02,
+},
+
+{
+    640, 480, 75,
+    0x04, 0x24, 0x63, 0x4F, 0x52, 0x0C, 0xDF, 0xE9,
+    0x00, 0x03, 0x59, 0xC0, 0x4F, 0xDF, 0x16, 0x85,
+},
+{
+    640, 480, 85,
+    0x04, 0x24, 0x63, 0x4F, 0x52, 0x0C, 0xDF, 0xE9,
+    0x00, 0x03, 0x59, 0xC0, 0x4F, 0xDF, 0x88, 0x9B,
+},
+#endif
+{
+    800, 480, 60,
+    0x02, 0x24, 0x7B, 0x63, 0x67, 0xF3, 0xDF, 0xE2,
+    0x00, 0x03, 0x41, 0xC0, 0x63, 0xDF, 0x2C, 0x17,
+},
+#if 0
+{
+    800, 480, 75,
+    0x6B, 0x63, 0x00, 0x69, 0x1B, 0xF2, 0xDF, 0x00,
+    0xE2, 0xE4, 0x1F, 0xC0, 0x63, 0xDF, 0x2C, 0x17,
+},
+{
+    800, 480, 85,
+    0x6B, 0x63, 0x00, 0x69, 0x1B, 0xF2, 0xDF, 0x00,
+    0xE2, 0xE4, 0x1F, 0xC0, 0x63, 0xDF, 0x2C, 0x17,
+},
+#endif
+{
+    800, 600, 60,
+    0x04, 0x48, 0x83, 0x63, 0x69, 0x73, 0x57, 0x58,
+    0x00, 0x03, 0x7B, 0x20, 0x63, 0x57, 0x0E, 0x05,
+},
+#if 0
+{
+    800, 600, 75,
+    0x7F, 0x63, 0x00, 0x66, 0x10, 0x6F, 0x57, 0x00,
+    0x58, 0x0B, 0xE0, 0x20, 0x63, 0x57, 0x4C, 0x8B,
+},
+{
+    800, 600, 85,
+    0x7E, 0x63, 0x00, 0x68, 0x10, 0x75, 0x57, 0x00,
+    0x58, 0x0B, 0xE0, 0x20, 0x63, 0x57, 0x37, 0x87,
+},
+#endif
+#if 0
+{
+    1024, 600, 60,
+    0x04, 0x48, 0x95, 0x7F, 0x86, 0x70, 0x57, 0x5B,
+    0x00, 0x60, 0x1c, 0x22, 0x7F, 0x57, 0x16, 0x07,
+},
+#endif
+{
+    1024, 768, 60,
+    0x06, 0x68, 0xA7, 0x7F, 0x83, 0x25, 0xFF, 0x02,
+    0x00, 0x62, 0x85, 0x20, 0x7F, 0xFF, 0x29, 0x09,
+},
+#if 0
+{
+    1024, 768, 75,
+    0x9F, 0x7F, 0x00, 0x82, 0x0E, 0x1E, 0xFF, 0x00,
+    0x00, 0x03, 0xE5, 0x20, 0x7F, 0xFF, 0x0B, 0x02,
+},
+{
+    1024, 768, 85,
+    0xA7, 0x7F, 0x00, 0x86, 0x12, 0x26, 0xFF, 0x00,
+    0x00, 0x03, 0xE5, 0x20, 0x7F, 0xFF, 0x70, 0x11,
+},
+#endif
+{
+    1280, 1024, 60,
+    0x08, 0x8C, 0xD5, 0x9F, 0xAB, 0x26, 0xFF, 0x00,
+    0x00, 0x03, 0x7E, 0x20, 0x9F, 0xFF, 0x53, 0x0B,
+},
+#if 0
+{
+    1280, 1024, 75,
+    0xCE, 0x9F, 0x00, 0xA2, 0x14, 0x28, 0xFF, 0x00,
+    0x00, 0x03, 0x4A, 0x20, 0x9F, 0xFF, 0x42, 0x07,
+},
+{
+    1280, 1024, 85,
+    0xD3, 0x9F, 0x00, 0xA8, 0x1C, 0x2E, 0xFF, 0x00,
+    0x00, 0x03, 0x4A, 0x20, 0x9F, 0xFF, 0x0b, 0x01,
+},
+#endif
+};
+
+#define CNT_CRT (sizeof(sm712_crt_modedb)/sizeof(sm712_crt_modedb[0]))
+#define CNT_PNL (sizeof(sm712_pnl_modedb)/sizeof(sm712_pnl_modedb[0]))
+
+void ddk712_setModeTiming(int channel, int x, int y, int hz)
+{
+	int i;
+	int index;
+	index = 0;
+	if (channel == 0) {
+		while (index < CNT_CRT) {
+			if (sm712_crt_modedb[index].h_res == x &&
+				sm712_crt_modedb[index].v_res == y &&
+				sm712_crt_modedb[index].vsync == hz)
+				break;
+			index++;
+		}
+		if (index == CNT_CRT) {
+			/* no mode found in table */
+			return;
+		}
+
+		/* program svr */
+		for (i = 0; i < 14; i++) {
+			poke_svr(0x40+i, sm712_crt_modedb[index].svr[i]);
+		}
+
+		/* work around crt */
+		if (y >= 1024) {
+			poke_crt(0x30, peek_crt(0x30)|9);
+		} else{
+			poke_crt(0x30, peek_crt(0x30)&~9);
+		}
+
+		/* programe ccr for pixel clock */
+		poke_ccr(0x6c, sm712_crt_modedb[index].ccr[0]);
+		poke_ccr(0x6d, sm712_crt_modedb[index].ccr[1]);
+
+	} else{
+		while (index < CNT_PNL) {
+			if (sm712_pnl_modedb[index].h_res == x &&
+				sm712_pnl_modedb[index].v_res == y &&
+				sm712_pnl_modedb[index].vsync == hz)
+				break;
+			index++;
+		}
+		if (index == CNT_PNL) {
+			return;
+		}
+
+		/* program FPR */
+		for (i = 0; i < 8; i++) {
+			poke_fpr(0x50+i, sm712_pnl_modedb[index].fpr[i]);
+		}
+
+		/* program fpr5a*/
+		poke_fpr(0x5a, sm712_pnl_modedb[index].fpr[0xa]);
+
+		/* program ccr for pixel clock*/
+		poke_ccr(0x6e, sm712_pnl_modedb[index].ccr[0]);
+		poke_ccr(0x6f, sm712_pnl_modedb[index].ccr[1]);
+
+	}
+}
diff --git a/drivers/video/lynxfb/ddk712/ddk712_mode.h b/drivers/video/lynxfb/ddk712/ddk712_mode.h
new file mode 100644
index 0000000..7e153a4
--- /dev/null
+++ b/drivers/video/lynxfb/ddk712/ddk712_mode.h
@@ -0,0 +1,40 @@
+/*******************************************************************
+*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 DDK712_MODE_H__
+#define DDK712_MODE_H__
+
+typedef struct{
+	unsigned short h_res;
+	unsigned short v_res;
+	char vsync;
+	char svr[14];/* shadow vga register :svr 40 => svr 4d*/
+	char ccr[2];/* pixel pll:ccr6c,6d */
+} SM712CrtTiming;
+
+typedef struct{
+	unsigned short h_res;
+	unsigned short v_res;
+	char vsync;
+	char fpr[14];/* fpr50 ==> fpr57,fpr5a*/
+	char ccr[2];/* ccr6e.ccr6f*/
+} SM712PnlTiming;
+
+
+void ddk712_setModeTiming(int channel, int x, int y, int hz);
+#endif
diff --git a/drivers/video/lynxfb/ddk712/ddk712_reg.h b/drivers/video/lynxfb/ddk712/ddk712_reg.h
new file mode 100644
index 0000000..f2d0096
--- /dev/null
+++ b/drivers/video/lynxfb/ddk712/ddk712_reg.h
@@ -0,0 +1,32 @@
+/*******************************************************************
+*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 DDK712_REG_H__
+#define DDK712_REG_H__
+
+#define MISC_GRAPH_VIDEO_CTRL 0
+#define MISC_GRAPH_VIDEO_CTRL_DATA_FORMAT_LSB 16
+#define MISC_GRAPH_VIDEO_CTRL_DATA_FORMAT_8 0
+#define MISC_GRAPH_VIDEO_CTRL_DATA_FORMAT_15 1
+#define MISC_GRAPH_VIDEO_CTRL_DATA_FORMAT_16 2
+#define MISC_GRAPH_VIDEO_CTRL_DATA_FORMAT_32 3
+#define MISC_GRAPH_VIDEO_CTRL_DATA_FORMAT_24 4
+#define MISC_GRAPH_VIDEO_CTRL_DATA_FORMAT_8P 5
+
+
+#endif
diff --git a/drivers/video/lynxfb/ddk750/ddk750.h b/drivers/video/lynxfb/ddk750/ddk750.h
new file mode 100644
index 0000000..fd3e279
--- /dev/null
+++ b/drivers/video/lynxfb/ddk750/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/ddk750_chip.c b/drivers/video/lynxfb/ddk750/ddk750_chip.c
new file mode 100644
index 0000000..5ab9ec3
--- /dev/null
+++ b/drivers/video/lynxfb/ddk750/ddk750_chip.c
@@ -0,0 +1,610 @@
+/*******************************************************************
+*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 1
+	if (getChipType() == SM750LE)
+		return MHz(130);
+#endif
+
+	return getPllValue(MXCLK_PLL, &pll);
+}
+
+
+/*
+ * This function set up the main chip clock.
+ *
+ * Input: Frequency to be set.
+ */
+void setChipClock(unsigned int frequency)
+{
+	pll_value_t pll;
+	unsigned int ulActualMxClk;
+#if 1
+	/* Cheok_0509: For SM750LE, the chip clock is fixed. Nothing to set. */
+	if (getChipType() == SM750LE)
+		return;
+#endif
+
+	if (frequency != 0) {
+		/*
+		 * Set up PLL, a structure to hold the value to be set in clocks.
+		 */
+		pll.inputFreq = DEFAULT_INPUT_CLOCK; /* Defined in CLOCK.H */
+		pll.clockType = MXCLK_PLL;
+
+		/*
+		 * Call calcPllValue() to fill up the other fields for PLL structure.
+		 * Sometime, the chip cannot set up the exact clock required by User.
+		 * Return value from calcPllValue() gives the actual possible clock.
+		 */
+		ulActualMxClk = calcPllValue(frequency, &pll);
+
+		/* Master Clock Control: MXCLK_PLL */
+		POKE32(MXCLK_PLL_CTRL, formatPllReg(&pll));
+	}
+}
+
+
+
+void setMemoryClock(unsigned int frequency)
+{
+	unsigned int ulReg, divisor;
+#if 1
+	/* Cheok_0509: For SM750LE, the memory clock is fixed. Nothing to set. */
+	if (getChipType() == SM750LE)
+		return;
+#endif
+	if (frequency != 0) {
+		/* Set the frequency to the maximum frequency that the DDR Memory can take
+		   which is 336MHz. */
+		if (frequency > MHz(336))
+			frequency = MHz(336);
+		/* Calculate the divisor */
+		divisor = (unsigned int) roundedDiv(getChipClock(), frequency);
+		/* Set the corresponding divisor in the register. */
+		ulReg = PEEK32(CURRENT_GATE);
+		switch (divisor) {
+		default:
+		case 1:
+			ulReg = 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;
+#if 1
+	/* Cheok_0509: For SM750LE, the memory clock is fixed. Nothing to set. */
+	if (getChipType() == SM750LE)
+		return;
+#endif
+	if (frequency != 0) {
+		/* Set the frequency to the maximum frequency that the SM750 engine can
+		   run, which is about 190 MHz. */
+		if (frequency > MHz(190))
+			frequency = MHz(190);
+		/* Calculate the divisor */
+		divisor = (unsigned int) roundedDiv(getChipClock(), frequency);
+		/* Set the corresponding divisor in the register. */
+		ulReg = PEEK32(CURRENT_GATE);
+		switch (divisor) {
+		default:
+		case 3:
+			ulReg = 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 0
+	/* move the code to map regiter function. */
+	if (getChipType() == SM718) {
+		/* turn on big endian bit*/
+		ulReg = PEEK32(0x74);
+		/* now consider register definition in a big endian pattern*/
+		POKE32(0x74, ulReg|0x80000000);
+	}
+
+#endif
+
+
+	if (pInitParam->powerMode != 0)
+		pInitParam->powerMode = 0;
+	setPowerMode(pInitParam->powerMode);
+
+	/* Enable display power gate & LOCALMEM power gate*/
+	ulReg = PEEK32(CURRENT_GATE);
+	ulReg = 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;
+}
+
+#if 0
+
+unsigned int absDiff(unsigned int a, unsigned int b)
+{
+	if (a > b)
+		return a - b;
+	else
+		return b - a;
+}
+
+#endif
+/*
+   monk liu @ 4/6/2011:
+   re-write the calculatePLL function of ddk750.
+   the original version function does not use some mathematics tricks and shortcut
+   when it doing the calculation of the best N,M,D combination
+   I think this version gives a little upgrade in speed
+
+   750 pll clock formular:
+   Request Clock = (Input Clock * M )/(N * X)
+
+   Input Clock = 14318181 hz
+   X = 2 power D
+   D ={0,1,2,3,4,5,6}
+   M = {1,...,255}
+   N = {2,...,15}
+   */
+unsigned int calcPllValue(unsigned int request_orig, pll_value_t *pll)
+{
+	/* used for primary and secondary channel pixel clock pll */
+	static pllcalparam xparm_PIXEL[] = {
+		/* 2^0 = 1*/			{0, 0, 0, 1},
+		/* 2^ 1 =2*/			{1, 0, 1, 2},
+		/* 2^ 2  = 4*/		{2, 0, 2, 4},
+		{3, 0, 3, 8},
+		{4, 1, 3, 16},
+		{5, 2, 3, 32},
+		/* 2^6 = 64  */		{6, 3, 3, 64},
+	};
+
+	/* used for MXCLK (chip clock) */
+	static pllcalparam xparm_MXCLK[] = {
+		/* 2^0 = 1*/			{0, 0, 0, 1},
+		/* 2^ 1 =2*/			{1, 0, 1, 2},
+		/* 2^ 2  = 4*/		{2, 0, 2, 4},
+		{3, 0, 3, 8},
+	};
+
+	/* 	as sm750 register definition,  N located in 2, 15 and M located in 1, 255	*/
+	int N, M, X, d;
+	int xcnt;
+	int miniDiff;
+	unsigned int RN, quo, rem, fl_quo;
+	unsigned int input, request;
+	unsigned int tmpClock, ret;
+	pllcalparam *xparm;
+
+#if 1
+	if (getChipType() == SM750LE) {
+		/* SM750LE don't have prgrammable PLL and M/N values to work on.
+		   Just return the requested clock. */
+		return request_orig;
+	}
+#endif
+
+	ret = 0;
+	miniDiff = ~0;
+	request = request_orig / 1000;
+	input = pll->inputFreq / 1000;
+
+	/* for MXCLK register , no POD provided, so need be treated differently	*/
+
+	if (pll->clockType != MXCLK_PLL) {
+		xparm = &xparm_PIXEL[0];
+		xcnt = sizeof(xparm_PIXEL)/sizeof(xparm_PIXEL[0]);
+	} else{
+		xparm = &xparm_MXCLK[0];
+		xcnt = sizeof(xparm_MXCLK)/sizeof(xparm_MXCLK[0]);
+	}
+
+
+	for (N = 15; N > 1; N--) {
+		/* RN will not exceed maximum long if @request <= 285 MHZ (for 32bit cpu) */
+		RN = N * request;
+		quo = RN / input;
+		rem = RN % input;/* rem always small than 14318181 */
+		fl_quo = (rem * 10000 / input);
+
+		for (d = xcnt - 1; d >= 0; d--) {
+			X = xparm[d].value;
+			M = quo*X;
+			M += fl_quo * X / 10000;
+			/* round step */
+			M += (fl_quo*X % 10000) > 5000 ? 1 : 0;
+			if (M < 256 && M > 0) {
+				unsigned int diff;
+				tmpClock = pll->inputFreq * M / N / X;
+				diff = absDiff(tmpClock, request_orig);
+				if (diff < miniDiff) {
+					pll->M = M;
+					pll->N = N;
+					pll->OD = xparm[d].od;
+					pll->POD = xparm[d].pod;
+					miniDiff = diff;
+					ret = tmpClock;
+				}
+			}
+		}
+	}
+
+	/* printk("Finally:  pll->n[%lu],m[%lu],od[%lu],pod[%lu]\n",pll->N,pll->M,pll->OD,pll->POD); */
+	return ret;
+}
+
+unsigned int calcPllValue2(
+		unsigned int ulRequestClk, /* Required pixel clock in Hz unit */
+		pll_value_t *pPLL           /* Structure to hold the value to be set in PLL */
+		)
+{
+
+	unsigned int M, N, OD, POD = 0, diff, pllClk, odPower, podPower;
+	unsigned int bestDiff = 0xffffffff; /* biggest 32 bit unsigned number */
+	unsigned int ret;
+	/* Init PLL structure to know states */
+	pPLL->M = 0;
+	pPLL->N = 0;
+	pPLL->OD = 0;
+	pPLL->POD = 0;
+
+	/* Sanity check: None at the moment */
+
+	/* Convert everything in Khz range in order to avoid calculation overflow */
+	pPLL->inputFreq /= 1000;
+	ulRequestClk /= 1000;
+
+#ifndef VALIDATION_CHIP
+	/* The maximum of post divider is 8. */
+	for (POD = 0; POD <= 3; POD++)
+#endif
+	{
+
+#ifndef VALIDATION_CHIP
+		/* MXCLK_PLL does not have post divider. */
+		if ((POD > 0) && (pPLL->clockType == MXCLK_PLL))
+			break;
+#endif
+
+		/* Work out 2 to the power of POD */
+		podPower = twoToPowerOfx(POD);
+		/* OD has only 2 bits [15:14] and its value must between 0 to 3 */
+		for (OD = 0; OD <= 3; OD++) {
+			/* Work out 2 to the power of OD */
+			odPower = twoToPowerOfx(OD);
+
+#ifdef VALIDATION_CHIP
+			if (odPower > 4)
+				podPower = 4;
+			else
+				podPower = odPower;
+#endif
+
+			/* N has 4 bits [11:8] and its value must between 2 and 15.
+			   The N == 1 will behave differently --> Result is not correct. */
+			for (N = 2; N <= 15; N++) {
+				/* The formula for PLL is ulRequestClk = inputFreq * M / N / (2^OD)
+				   In the following steps, we try to work out a best M value given the others are known.
+				   To avoid decimal calculation, we use 1000 as multiplier for up to 3 decimal places of accuracy.
+				   */
+				M = ulRequestClk * N * odPower * 1000 / pPLL->inputFreq;
+				M = roundedDiv(M, 1000);
+
+				/* M field has only 8 bits, reject value bigger than 8 bits */
+				if (M < 256) {
+					/* Calculate the actual clock for a given M & N */
+					pllClk = pPLL->inputFreq * M / N / odPower / podPower;
+
+					/* How much are we different from the requirement */
+					diff = absDiff(pllClk, ulRequestClk);
+
+					if (diff < bestDiff) {
+						bestDiff = diff;
+
+						/* Store M and N values */
+						pPLL->M  = M;
+						pPLL->N  = N;
+						pPLL->OD = OD;
+
+#ifdef VALIDATION_CHIP
+						if (OD > 2)
+							POD = 2;
+						else
+							POD = OD;
+#endif
+
+						pPLL->POD = POD;
+					}
+				}
+			}
+		}
+	}
+
+	/* Restore input frequency from Khz to hz unit */
+	/*    pPLL->inputFreq *= 1000;*/
+	ulRequestClk *= 1000;
+	pPLL->inputFreq = DEFAULT_INPUT_CLOCK; /* Default reference clock */
+
+	/* Output debug information */
+	/* DDKDEBUGPRINT((DISPLAY_LEVEL, "calcPllValue: Requested Frequency = %d\n", ulRequestClk));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/ddk750_chip.h b/drivers/video/lynxfb/ddk750/ddk750_chip.h
new file mode 100644
index 0000000..f24af16
--- /dev/null
+++ b/drivers/video/lynxfb/ddk750/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/ddk750_display.c b/drivers/video/lynxfb/ddk750/ddk750_display.c
new file mode 100644
index 0000000..6e973cc
--- /dev/null
+++ b/drivers/video/lynxfb/ddk750/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/ddk750_display.h b/drivers/video/lynxfb/ddk750/ddk750_display.h
new file mode 100644
index 0000000..028e5e8
--- /dev/null
+++ b/drivers/video/lynxfb/ddk750/ddk750_display.h
@@ -0,0 +1,177 @@
+/*******************************************************************
+*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
+   */
+#if 0
+typedef enum _disp_output_t{
+	NO_DISPLAY = DPMS_OFF,
+
+	LCD1_PRI = PNL_2_PRI|PRI_TP_ON|PNL_SEQ_ON|DPMS_OFF|DAC_ON,
+	LCD1_SEC = PNL_2_SEC|SEC_TP_ON|PNL_SEQ_ON|DPMS_OFF|DAC_ON,
+
+	LCD2_PRI = CRT_2_PRI|PRI_TP_ON|DUAL_TFT_ON|DPMS_OFF,
+	LCD2_SEC = CRT_2_SEC|SEC_TP_ON|DUAL_TFT_ON|DPMS_OFF,
+
+	DSUB_PRI = CRT_2_PRI|PRI_TP_ON|DAC_ON,
+	DSUB_SEC = CRT_2_SEC|SEC_TP_ON|DAC_ON,
+
+	LCD1_DSUB_PRI = PNL_2_PRI|PRI_TP_ON|PNL_SEQ_ON|
+		CRT_2_PRI|SEC_TP_OFF|DAC_ON,
+
+	LCD1_DSUB_SEC = PNL_2_SEC|SEC_TP_ON|PNL_SEQ_ON|
+		CRT_2_SEC|PRI_TP_OFF|DAC_ON,
+
+	/* LCD1 show primary and DSUB show secondary */
+	LCD1_DSUB_DUAL = PNL_2_PRI|PRI_TP_ON|PNL_SEQ_ON|
+		CRT_2_SEC|SEC_TP_ON|DAC_ON,
+
+	/* LCD1 show secondary and DSUB show primary */
+	LCD1_DSUB_DUAL_SWAP = PNL_2_SEC|SEC_TP_ON|PNL_SEQ_ON|
+		CRT_2_PRI|PRI_TP_ON|DAC_ON,
+
+	LCD1_LCD2_PRI = PNL_2_PRI|PRI_TP_ON|PNL_SEQ_ON|
+		CRT_2_PRI|SEC_TP_OFF|DPMS_OFF|DUAL_TFT_ON,
+
+	LCD1_LCD2_SEC = PNL_2_SEC|SEC_TP_ON|PNL_SEQ_ON|
+		CRT_2_SEC|PRI_TP_OFF|DPMS_OFF|DUAL_TFT_ON,
+
+	LCD1_LCD2_DSUB_PRI = PNL_2_PRI|PRI_TP_ON|PNL_SEQ_ON|DAC_ON|
+		CRT_2_PRI|SEC_TP_OFF|DPMS_ON|DUAL_TFT_ON,
+
+	LCD1_LCD2_DSUB_SEC = PNL_2_SEC|SEC_TP_ON|PNL_SEQ_ON|DAC_ON|
+		CRT_2_SEC|PRI_TP_OFF|DPMS_ON|DUAL_TFT_ON,
+
+
+}
+disp_output_t;
+#else
+typedef enum _disp_output_t{
+	do_LCD1_PRI = PNL_2_PRI|PRI_TP_ON|PNL_SEQ_ON|DAC_ON,
+	do_LCD1_SEC = PNL_2_SEC|SEC_TP_ON|PNL_SEQ_ON|DAC_ON,
+#if 0
+	do_LCD2_PRI = CRT_2_PRI|PRI_TP_ON,
+	do_LCD2_SEC = CRT_2_SEC|SEC_TP_ON,
+#else
+	do_LCD2_PRI = CRT_2_PRI|PRI_TP_ON|DUAL_TFT_ON,
+	do_LCD2_SEC = CRT_2_SEC|SEC_TP_ON|DUAL_TFT_ON,
+#endif
+	/*
+	   do_DSUB_PRI = CRT_2_PRI|PRI_TP_ON|DPMS_ON|DAC_ON,
+	   do_DSUB_SEC = CRT_2_SEC|SEC_TP_ON|DPMS_ON|DAC_ON,
+	   */
+#if 0
+	do_CRT_PRI = CRT_2_PRI|PRI_TP_ON,
+	do_CRT_SEC = CRT_2_SEC|SEC_TP_ON,
+#else
+	do_CRT_PRI = CRT_2_PRI|PRI_TP_ON|DPMS_ON|DAC_ON,
+	do_CRT_SEC = CRT_2_SEC|SEC_TP_ON|DPMS_ON|DAC_ON,
+#endif
+}
+disp_output_t;
+#endif
+
+void ddk750_setLogicalDispOut(disp_output_t);
+int ddk750_initDVIDisp(void);
+
+#endif
diff --git a/drivers/video/lynxfb/ddk750/ddk750_dvi.c b/drivers/video/lynxfb/ddk750/ddk750_dvi.c
new file mode 100644
index 0000000..0663009
--- /dev/null
+++ b/drivers/video/lynxfb/ddk750/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/ddk750_dvi.h b/drivers/video/lynxfb/ddk750/ddk750_dvi.h
new file mode 100644
index 0000000..64773fd
--- /dev/null
+++ b/drivers/video/lynxfb/ddk750/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/ddk750_help.c b/drivers/video/lynxfb/ddk750/ddk750_help.c
new file mode 100644
index 0000000..2e95b58
--- /dev/null
+++ b/drivers/video/lynxfb/ddk750/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/ddk750_help.h b/drivers/video/lynxfb/ddk750/ddk750_help.h
new file mode 100644
index 0000000..0a254ad
--- /dev/null
+++ b/drivers/video/lynxfb/ddk750/ddk750_help.h
@@ -0,0 +1,47 @@
+/*******************************************************************
+*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"
+
+
+#if 0
+/* if 718 big endian turned on, be aware that don't use this driver for general use, only for ppc big-endian */
+#warning "big endian on target cpu and enable nature big endian support of 718 capability !"
+#define PEEK32(addr)  			__raw_readl((void __iomem *)(mmio750)+(addr))
+#define POKE32(addr, data) 		__raw_writel((data), (void __iomem *)(mmio750)+(addr))
+#else /* software control endianess */
+#define PEEK32(addr) readl((addr)+mmio750)
+#define POKE32(addr, data) writel((data), (addr)+mmio750)
+#endif
+
+extern volatile unsigned  char __iomem *mmio750;
+extern char revId750;
+extern unsigned short devId750;
+#else
+/* implement if you want use it*/
+#endif
+
+#endif
diff --git a/drivers/video/lynxfb/ddk750/ddk750_hwi2c.c b/drivers/video/lynxfb/ddk750/ddk750_hwi2c.c
new file mode 100644
index 0000000..c37ff82
--- /dev/null
+++ b/drivers/video/lynxfb/ddk750/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/ddk750_hwi2c.h b/drivers/video/lynxfb/ddk750/ddk750_hwi2c.h
new file mode 100644
index 0000000..6cbd292
--- /dev/null
+++ b/drivers/video/lynxfb/ddk750/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/ddk750_mode.c b/drivers/video/lynxfb/ddk750/ddk750_mode.c
new file mode 100644
index 0000000..3b1ed71
--- /dev/null
+++ b/drivers/video/lynxfb/ddk750/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);
+#if 1
+		while ((PEEK32(PANEL_DISPLAY_CTRL) & ~ulReservedBits) != (ulTmpValue|ulReg)) {
+			cnt++;
+			if (cnt > 1000)
+				break;
+			POKE32(PANEL_DISPLAY_CTRL, ulTmpValue|ulReg);
+		}
+#endif
+	} else{
+		ret = -1;
+	}
+	return ret;
+}
+
+int ddk750_setModeTiming(mode_parameter_t *parm, clock_type_t clock)
+{
+	pll_value_t pll;
+	unsigned int uiActualPixelClk;
+	pll.inputFreq = DEFAULT_INPUT_CLOCK;
+	pll.clockType = clock;
+
+	uiActualPixelClk = calcPllValue(parm->pixel_clock, &pll);
+	if (getChipType() == SM750LE) {
+		/* set graphic mode via IO method */
+		outb_p(0x88, 0x3d4);
+		outb_p(0x06, 0x3d5);
+	}
+	programModeRegisters(parm, &pll);
+	return 0;
+}
+
+
diff --git a/drivers/video/lynxfb/ddk750/ddk750_mode.h b/drivers/video/lynxfb/ddk750/ddk750_mode.h
new file mode 100644
index 0000000..7c12b46
--- /dev/null
+++ b/drivers/video/lynxfb/ddk750/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/ddk750_power.c b/drivers/video/lynxfb/ddk750/ddk750_power.c
new file mode 100644
index 0000000..56c6d55
--- /dev/null
+++ b/drivers/video/lynxfb/ddk750/ddk750_power.c
@@ -0,0 +1,246 @@
+/*******************************************************************
+*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;
+#if 1
+		/* Using Software I2C */
+		gate |= 1 << CURRENT_GATE_GPIO_LSB;
+#else
+		/* Using Hardware I2C */
+		gate |= 1 << CURRENT_GATE_I2C_LSB;
+#endif
+	} else{
+		/* Disable ZV Port Gate. There is no way to know whether the GPIO pins are being used
+		   or not. Therefore, do not disable the GPIO gate. */
+		gate &= (~(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/ddk750_power.h b/drivers/video/lynxfb/ddk750/ddk750_power.h
new file mode 100644
index 0000000..da65b00
--- /dev/null
+++ b/drivers/video/lynxfb/ddk750/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/ddk750_reg.h b/drivers/video/lynxfb/ddk750/ddk750_reg.h
new file mode 100644
index 0000000..e2560bf
--- /dev/null
+++ b/drivers/video/lynxfb/ddk750/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/ddk750_sii164.c b/drivers/video/lynxfb/ddk750/ddk750_sii164.c
new file mode 100644
index 0000000..6915939
--- /dev/null
+++ b/drivers/video/lynxfb/ddk750/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/ddk750_sii164.h b/drivers/video/lynxfb/ddk750/ddk750_sii164.h
new file mode 100644
index 0000000..a279286
--- /dev/null
+++ b/drivers/video/lynxfb/ddk750/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/ddk750_swi2c.c b/drivers/video/lynxfb/ddk750/ddk750_swi2c.c
new file mode 100644
index 0000000..f0a36d6
--- /dev/null
+++ b/drivers/video/lynxfb/ddk750/ddk750_swi2c.c
@@ -0,0 +1,531 @@
+/*******************************************************************
+*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
+	 * */
+#if 0
+	/* Change wait algorithm to use PCI bus clock,
+	   it's more reliable than counter loop ..
+	   write 0x61 to 0x3ce and read from 0x3cf
+	   */
+	while (peekIO(0x3ce, 0x61) & 0x10)
+	;
+#else
+	int i, Temp;
+
+	for (i = 0; i < 600; i++) {
+		Temp = i;
+		Temp += i;
+	}
+#endif
+}
+
+/*
+ *  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/ddk750_swi2c.h b/drivers/video/lynxfb/ddk750/ddk750_swi2c.h
new file mode 100644
index 0000000..cf42753
--- /dev/null
+++ b/drivers/video/lynxfb/ddk750/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..73cf480
--- /dev/null
+++ b/drivers/video/lynxfb/lynx_accel.c
@@ -0,0 +1,521 @@
+/*******************************************************************
+*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();
+}
+
+/* seems sm712 RectFill command is broken, so need use BitBlt to
+ * replace it. */
+
+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)
+{
+	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;
+	}
+	/* 24bpp 2d acceleration still not work, we already support 2d on
+	 * both 8/16/32 bpp now, so there is no harm if we disable 2d on
+	 * 24bpp for current stage. */
+#if 0
+	if (Bpp == 3) {
+		width *= 3;
+		x *= 3;
+		write_dpr(accel, DE_PITCH,
+				FIELD_VALUE(0, DE_PITCH, DESTINATION, pitch)|
+				FIELD_VALUE(0, DE_PITCH, SOURCE, pitch));
+	} else
+#endif
+	{
+		write_dpr(accel, DE_PITCH,
+				(pitch/Bpp << DE_PITCH_DESTINATION_LSB)|
+				(pitch/Bpp << DE_PITCH_SOURCE_LSB));
+
+	}
+
+	write_dpr(accel, DE_FOREGROUND, color);
+	write_dpr(accel, DE_MONO_PATTERN_HIGH, ~0);
+	write_dpr(accel, DE_MONO_PATTERN_LOW, ~0);
+
+	write_dpr(accel, DE_WINDOW_SOURCE_BASE, base);
+	write_dpr(accel, DE_WINDOW_DESTINATION_BASE, base);
+
+
+	write_dpr(accel, DE_WINDOW_WIDTH,
+			(pitch/Bpp << DE_WINDOW_WIDTH_DESTINATION_LSB)|
+			(pitch/Bpp << DE_WINDOW_WIDTH_SOURCE_LSB));
+
+	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)&
+		(~(0x1f << DE_CONTROL_COMMAND_LSB))|
+		(1 << DE_CONTROL_ROP2_SOURCE_LSB)|
+		(1 << DE_CONTROL_ROP_SELECT_LSB)|
+		(rop << DE_CONTROL_ROP_LSB);
+
+#if 0
+	/* dump registers */
+	int i;
+	inf_msg("x, y, w, h = %d, %d, %d, %d\n", x, y, width, height);
+	for (i = 0x04; i <= 0x44; i += 4) {
+		inf_msg("dpr%02x = %08x\n", i, read_dpr(accel, i));
+	}
+	inf_msg("deCtrl = %08x\n", deCtrl);
+#endif
+
+	write_dpr(accel, DE_CONTROL, deCtrl);
+	return 0;
+}
+
+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);
+
+#if 0
+	/* Program pitch (distance between the 1st points of two adjacent lines).
+	   Note that input pitch is BYTE value, but the 2D Pitch register uses
+	   pixel values. Need Byte to pixel convertion.
+	   */
+	if (Bpp == 3) {
+		sx *= 3;
+		dx *= 3;
+		width *= 3;
+		write_dpr(accel, DE_PITCH,
+				FIELD_VALUE(0, DE_PITCH, DESTINATION, dPitch) |
+				FIELD_VALUE(0, DE_PITCH, SOURCE, sPitch));
+	} else
+#endif
+
+	{
+		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);
+#if 0
+	/* Program pitch (distance between the 1st points of two adjacent lines).
+	   Note that input pitch is BYTE value, but the 2D Pitch register uses
+	   pixel values. Need Byte to pixel convertion.
+	   */
+	if (bytePerPixel == 3) {
+		dx *= 3;
+		width *= 3;
+		startBit *= 3;
+		write_dpr(accel, DE_PITCH,
+				FIELD_VALUE(0, DE_PITCH, DESTINATION, dPitch) |
+				FIELD_VALUE(0, DE_PITCH, SOURCE, dPitch));
+
+	} else
+#endif
+	{
+		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..c7d8f3f
--- /dev/null
+++ b/drivers/video/lynxfb/lynx_accel.h
@@ -0,0 +1,176 @@
+/*******************************************************************
+*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
+
+#ifdef OPENSOURCE
+
+#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
+#endif
+
+
+#ifdef OPENSOURCE
+#define DE_DESTINATION		0x4
+#define DE_DESTINATION_WRAP_LSB 31
+#define DE_DESTINATION_X_LSB 16
+#define DE_DESTINATION_Y_LSB 0
+#endif
+
+#define DE_DIMENSION                                    0x8
+#ifdef OPENSOURCE
+#define DE_DIMENSION_X_LSB                              16
+#define DE_DIMENSION_Y_ET_LSB                           0
+#endif
+
+#ifdef OPENSOURCE
+#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
+#endif
+#ifdef OPENSOURCE
+#define DE_PITCH                                        0x000010
+#define DE_PITCH_DESTINATION_LSB                        16
+#define DE_PITCH_SOURCE_LSB                             0
+#endif
+
+#define DE_FOREGROUND                                   0x000014
+
+#define DE_BACKGROUND                                   0x000018
+
+
+#define DE_STRETCH_FORMAT                               0x00001C
+#define DE_STRETCH
+#ifdef OPENSOURCE
+#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
+#endif
+
+#ifdef OPENSOURCE
+#define DE_WINDOW_WIDTH                                 0x00003C
+#define DE_WINDOW_WIDTH_DESTINATION_LSB                     16
+#define DE_WINDOW_WIDTH_SOURCE_LSB                          0
+#endif
+
+
+/* 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..ea52361
--- /dev/null
+++ b/drivers/video/lynxfb/lynx_cursor.c
@@ -0,0 +1,385 @@
+/*******************************************************************
+*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"
+#include "ddk712/ddk712_help.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
+
+void hw712_cursor_enable(struct lynx_cursor *cursor)
+{
+	/* 712/722 offset is not in unit of byte, but in unit of 2kByte */
+	poke_phr(0x80, cursor->offset & 0xff);
+	poke_phr(0x81, ~0x80 & (cursor->offset >> 8));
+	poke_pop(0x82, 0x80);
+}
+
+void hw712_cursor_disable(struct lynx_cursor *cursor)
+{
+	poke_hcr(0x82,  0);
+}
+
+void hw712_cursor_setSize(struct lynx_cursor *cursor,
+					int w, int h)
+{
+	ENTER();
+	cursor->w = w;
+	cursor->h = h;
+}
+
+void hw712_cursor_setPos(struct lynx_cursor *cursor,
+						int x, int y)
+{
+	poke_pop(0x90, (x & 0xff));
+	poke_pop(0x91, (x >> 8)&0x7);
+	poke_hcr(0x92,  (y & 0xff));
+	poke_hcr(0x93,  (y >> 8)&0x7);
+}
+
+void hw712_cursor_setColor(struct lynx_cursor *cursor,
+						u32 fg, u32 bg)
+{
+	char fg8 = 0;
+	char bg8 = 0;
+	ENTER();
+#if 0
+	fg8 = ((fg&0xc000)>>8)|((fg & 0x600)>>6) | ((fg & 0x18)>>3);
+	bg8 = ((bg&0xc000)>>8)|((bg & 0x600)>>6) | ((bg & 0x18)>>3);
+#else
+	int r, g, b;
+	r = (fg >> 11)&0x1f;
+	g = (fg >> 5)&0x3f;
+	b = fg & 0x1f;
+	r = (r-2)*8/32;
+	g = (g-4)*8/64;
+	b = (b)*4/32;
+	fg8 = (r<<5)|(g<<2)|b;
+
+	r = (bg >> 11)&0x1f;
+	g = (bg >> 5)&0x3f;
+	b = bg & 0x1f;
+	r = (r-2)*8/32;
+	g = (g-4)*8/64;
+	b = (b)*4/32;
+	bg8 = (r<<5)|(g<<2)|b;
+#endif
+
+	poke_pop(0x84, fg8);
+	poke_pop(0x86, bg8);
+	LEAVE();
+}
+
+
+void hw712_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;
+
+	/*  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
+		 * and method 1 seems a bit wrong*/
+		for (j = 0; j < 8; j++) {
+
+			if (rop == ROP_XOR)
+				opr = mask ^ color;
+			else
+				opr = mask & color;
+
+			/* 2 stands for forecolor and 1 for backcolor */
+			data |= ((opr & (0x80>>j)) ? 0x4000 : 0xc000)>>(j*2);
+		}
+
+		data = ((data&0x00ff)<<8)|((data&0xff00)>>8);
+		*pbuffer = data;
+
+		/* assume pitch is 1, 2, 4, 8, ...*/
+		if ((i+1) % pitch == 0) {/* below line equal to is line */
+
+			/* need a return */
+			pstart += offset;
+			pbuffer = pstart;
+		} else{
+			pbuffer++;
+		}
+	}
+	return 0;
+}
+
+/* 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*/
+#if 0
+		if (rop == ROP_XOR)
+			opr = mask ^ color;
+		else
+			opr = mask & color;
+
+		for (j = 0; j < 8; j++) {
+
+			if (opr & (0x80 >> j)) {
+				/* use fg color, id = 2 */
+				data |= 2 << (j*2);
+			} else{
+				/* use bg color, id = 1 */
+				data |= 1 << (j*2);
+			}
+		}
+#else
+
+		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);
+			}
+		}
+#endif
+		*pbuffer = data;
+
+		/* assume pitch is 1, 2, 4, 8, ...*/
+#if 0
+		if (!((i+1)&(pitch-1)))   /* below line equal to is line */
+#else
+		if ((i+1) % pitch == 0)
+#endif
+		{
+			/* 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 */
+#if 0
+		if (rop == ROP_XOR)
+			opr = mask ^ color;
+		else
+			opr = mask & color;
+
+		for (j = 0; j < 8; j++) {
+
+
+			if (opr & (0x80 >> j)) {
+				/* use fg color, id = 2 */
+				data |= 2 << (j*2);
+			} else{
+				/* use bg color, id = 1 */
+				data |= 1 << (j*2);
+			}
+		}
+#else
+		for (j = 0; j < 8; j++) {
+			if (mask & (1 << j))
+				data |= ((color & (1<<j)) ? 1 : 2)<<(j*2);
+		}
+#endif
+		*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..74a73b0
--- /dev/null
+++ b/drivers/video/lynxfb/lynx_cursor.h
@@ -0,0 +1,46 @@
+/*******************************************************************
+*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);
+void hw712_cursor_enable(struct lynx_cursor *cursor);
+
+void hw712_cursor_disable(struct lynx_cursor *cursor);
+
+void hw712_cursor_setSize(struct lynx_cursor *cursor, int w, int h);
+void hw712_cursor_setPos(struct lynx_cursor *cursor, int x, int y);
+void hw712_cursor_setColor(struct lynx_cursor *cursor, u32 fg, u32 bg);
+
+
+void hw712_cursor_setData(struct lynx_cursor *cursor, u16 rop,
+						const u8 *pcol, const u8 *pmsk);
+#endif
diff --git a/drivers/video/lynxfb/lynx_drv.c b/drivers/video/lynxfb/lynx_drv.c
new file mode 100644
index 0000000..3838113
--- /dev/null
+++ b/drivers/video/lynxfb/lynx_drv.c
@@ -0,0 +1,2183 @@
+/*******************************************************************
+*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_hw712.h"
+#include "lynx_hw502.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 void sm712fb_setup(struct lynx_share *, char *);
+static void sm502fb_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 *);
+static struct platform_device *sm502_create_subdev(struct lynx_share *, const char *, int);
+static void sm502_create_irq(struct lynx_share *, struct resource *);
+static void sm502_create_mem(struct lynx_share *, struct resource *,
+		resource_size_t, resource_size_t, int);
+static void sm502_device_release(struct device *);
+#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 *);
+
+/* some dedicated var for sm502 */
+static struct platform_device *g_plf_502aud;
+
+
+static int g_no502disp;
+static int g_no502aud;
+static int g_no502usb;
+
+/* 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)*/
+#if 1
+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);
+	}
+}
+#else
+#define myspin_lock(a) spin_lock(a)
+#define myspin_unlock(a) spin_unlock(a)
+#endif
+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;
+
+#if 0
+	share->accel.de_wait();
+	cfb_copyarea(info, region);
+	return;
+#endif
+	/* 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
+};
+#if 0
+static size_t spec_size[] = { sizeof(struct sm750_share), /* for sm718/750*/
+	sizeof(struct sm712_share), /* for sm712/722/710/720 */
+	sizeof(struct sm502_share), /* for sm502/sm107 */
+};
+
+static PROC_SPEC_SETUP setup_rout[] = {
+	sm750fb_setup,
+	sm712fb_setup,
+	sm502fb_setup,
+};
+
+static PROC_SPEC_MAP map_rout[] = {
+	hw_sm750_map,
+	hw_sm712_map,
+	hw_sm502_map,
+};
+
+static PROC_SPEC_INITHW inithw_rout[] = {
+	hw_sm750_inithw,
+	hw_sm712_inithw,
+	hw_sm502_inithw,
+};
+#else
+static size_t spec_size[] = {
+	[SPC_SM750] = sizeof(struct sm750_share),
+	[SPC_SM712] = sizeof(struct sm712_share),
+	[SPC_SM502] = sizeof(struct sm502_share)
+};
+
+static PROC_SPEC_SETUP setup_rout[] = {
+	[SPC_SM750] = sm750fb_setup,
+	[SPC_SM712] = sm712fb_setup,
+	[SPC_SM502] = sm502fb_setup
+};
+
+static PROC_SPEC_MAP map_rout[] = {
+	[SPC_SM750] = hw_sm750_map,
+	[SPC_SM712] = hw_sm712_map,
+	[SPC_SM502] = hw_sm502_map
+};
+
+static PROC_SPEC_INITHW inithw_rout[] = {
+	[SPC_SM750] = hw_sm750_inithw,
+	[SPC_SM712] = hw_sm712_inithw,
+	[SPC_SM502] = hw_sm502_inithw,
+};
+#endif
+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 sm502fb_set_drv(struct lynxfb_par *par)
+	{
+		int ret;
+		struct lynx_share *share;
+		struct sm502_share *spec_share;
+		struct lynxfb_output *output;
+		struct lynxfb_crtc *crtc;
+
+		ENTER();
+		ret = 0;
+		share = par->share;
+		spec_share = container_of(share, struct sm502_share, share);
+		output = &par->output;
+		crtc = &par->crtc;
+
+		spec_share->hwCursor = g_hwcursor;
+		spec_share->usb_off = g_no502usb;
+		spec_share->aud_off = g_no502aud;
+
+		crtc->proc_setMode = hw_sm502_crtc_setMode;
+		crtc->proc_checkMode = hw_sm502_crtc_checkMode;
+		crtc->proc_setColReg = hw_sm502_setColReg;
+		crtc->clear = hw_sm502_crtc_clear;
+		crtc->line_pad = 16;
+		crtc->xpanstep = crtc->ypanstep = crtc->ywrapstep = 0;
+
+		output->proc_setMode = hw_sm502_output_setMode;
+		output->proc_checkMode = hw_sm502_output_checkMode;
+		output->proc_setBLANK = hw_sm502_setBLANK;
+		output->clear = hw_sm502_output_clear;
+
+		/* chip specific phase */
+		share->accel.de_wait = hw_sm502_deWait;
+
+		crtc->vidmem_size = (share->dual) ? share->vidmem_size>>1 : share->vidmem_size;
+		if (!spec_share->usb_off && par->index == 1) {
+			/* usb function on, and this is the second view */
+			crtc->vidmem_size -= 0x80000;
+		}
+
+
+		output->channel = &crtc->channel;
+		switch (spec_share->state.dataflow) {
+		case sm502_simul_pri:
+				output->paths = sm502_pnc;
+				crtc->channel = sm502_primary;
+				crtc->oScreen = 0;
+				crtc->vScreen = share->pvMem;
+				inf_msg("use simul primary mode\n");
+				break;
+		case sm502_dual_normal:
+				if (par->index == 0) {
+					output->paths = sm502_panel;
+					crtc->channel = sm502_primary;
+					crtc->oScreen = 0;
+					crtc->vScreen = share->pvMem;
+				} else{
+					output->paths = sm502_crt;
+					crtc->channel = sm502_secondary;
+					crtc->oScreen = (share->vidmem_size >> 1);
+					crtc->vScreen = share->pvMem + crtc->oScreen;
+				}
+				inf_msg("use dual mode\n");
+				break;
+		case sm502_single_sec:
+				output->paths = sm502_crt;
+				crtc->channel = sm502_secondary;
+				crtc->oScreen = 0;
+				crtc->vScreen = share->pvMem;
+				inf_msg("use secondary channel single mode\n");
+				break;
+		default:
+				ret = -EINVAL;
+		}
+
+		LEAVE(ret);
+	}
+
+	static int sm712fb_set_drv(struct lynxfb_par *par)
+	{
+		int ret;
+		struct lynx_share *share;
+		struct sm712_share *spec_share;
+		struct lynxfb_output *output;
+		struct lynxfb_crtc *crtc;
+
+		ENTER();
+		ret = 0;
+		share = par->share;
+		spec_share = container_of(share, struct sm712_share, share);
+		output = &par->output;
+		crtc = &par->crtc;
+
+		/* moved from lynxfb_set_fbinfo to here */
+		crtc->proc_setMode = hw_sm712_crtc_setMode;
+		crtc->proc_checkMode = hw_sm712_crtc_checkMode;
+		crtc->proc_setColReg = hw_sm712_setColReg;
+		crtc->clear = hw_sm712_crtc_clear;
+
+		/* for sm712/722, crt channel and lcd channel both
+		 *share the same padding value of their offset register,
+		 *which is 8 bytes. so no need of the check of crtc
+		 **/
+		crtc->line_pad = 8;
+		crtc->xpanstep = crtc->ypanstep = crtc->ywrapstep = 0;
+
+		output->proc_setMode = hw_sm712_output_setMode;
+		output->proc_checkMode = hw_sm712_output_checkMode;
+		output->proc_setBLANK = hw_sm712_setBLANK;
+		output->clear = hw_sm712_output_clear;
+		/* chip specific phase */
+		share->accel.de_wait = hw_sm712_deWait;
+
+		/* sm712/722 can't use RectFill feature
+		 *so use bitblt to replace it
+		 **/
+		share->accel.de_fillrect = hw712_fillrect;
+		crtc->vidmem_size = share->vidmem_size;
+		crtc->vScreen = share->pvMem;
+		crtc->oScreen = 0;
+		/*defaultly use SIMUL mode */
+		output->paths = 3;
+
+		if (share->dual) {
+			crtc->vidmem_size >>= 1;
+			if (par->index) {
+				crtc->oScreen += share->vidmem_size - crtc->vidmem_size;
+				crtc->vScreen += crtc->oScreen;
+				output->paths = 2;
+			} else{
+				output->paths = 1;
+			}
+		}
+
+		LEAVE(0);
+	}
+
+	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"},
+			{"sm712_fb1", "sm712_fb2"},
+			{"sm502_fb1", "sm502_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;
+		switch (g_specId) {
+		case SPC_SM750:
+				sm750fb_set_drv(par);
+				lynxfb_ops.fb_pan_display = lynxfb_ops_pan_display;
+				break;
+		case SPC_SM712:
+				sm712fb_set_drv(par);
+				break;
+		case SPC_SM502:
+				sm502fb_set_drv(par);
+				break;
+		}
+
+		/* set current cursor variable and proc pointer,
+		 *must be set after crtc member initialized */
+		if (g_specId != SPC_SM712) {
+			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;
+		} else{
+			/* sm712/722 hardware cursor */
+			/* sm712/722 requir 2kb the chunk size
+			 *high 1kb for cursor and low 1kb for pop up icon
+			 **/
+			crtc->cursor.offset = (crtc->oScreen + crtc->vidmem_size)/2048 - 1;
+			crtc->cursor.mmio = NULL;
+			crtc->cursor.maxH = crtc->cursor.maxW = 64;/*popup icon*/
+			crtc->cursor.size = crtc->cursor.maxH * crtc->cursor.maxW*2/8;
+			crtc->cursor.disable = hw712_cursor_disable;
+			crtc->cursor.enable = hw712_cursor_enable;
+			crtc->cursor.setColor = hw712_cursor_setColor;
+			crtc->cursor.setPos = hw712_cursor_setPos;
+			crtc->cursor.setSize = hw712_cursor_setSize;
+			crtc->cursor.setData = hw712_cursor_setData;
+			crtc->cursor.vstart = crtc->vScreen +
+				(crtc->cursor.offset * 2048);
+		}
+
+
+		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);
+#if 0
+		/*	how many frame buffer this fb_info get, currently we set onscreen size to it
+			we may set it to video memory size
+			*/
+		fix->smem_len = info->screen_size;
+#else
+		/* 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
+#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;
+		case PCI_DEVID_LYNX_EM:
+		case PCI_DEVID_LYNX_3DM:
+			g_specId = SPC_SM712;
+			spec_offset = offsetof(struct sm712_share, share);
+			break;
+		case PCI_DEVID_VOYAGER:
+			g_specId = SPC_SM502;
+			spec_offset = offsetof(struct sm502_share, share);
+		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;
+		}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
+		/* no platform.h in 2.6.9 */
+		if (g_specId == SPC_SM502) {
+			struct platform_device *plf_dev = NULL;
+			/* do not use sm502_share->aud_off flag
+			 *if nodisp is passed to driver, fb_set_info will not evoked
+			 *which means aud_off never get a chance to be set value
+			 **/
+
+			if (!g_no502aud) {
+				inf_msg("audio feature enabled\n");
+				/* register 502 audio device */
+				/* use name sm501-audio because original audio driver
+				 *also use it, maybe later we'll shift all name to
+				 *sm502-xxx */
+				plf_dev = sm502_create_subdev(share, "sm501-audio", 1);
+
+				if (!plf_dev) {
+					/* no need to roll back all, basically we successed */
+					err_msg("Create \"sm501-audio\" failed\n");
+				} else{
+					sm502_create_irq(share, &plf_dev->resource[0]);
+					if (platform_device_register(plf_dev) < 0)
+						err_msg("Register \"%s\" failed\n", plf_dev->name);
+					g_plf_502aud = plf_dev;
+				}
+			}
+		}
+#endif
+		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);
+	}
+
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
+	static void sm502_device_release(struct device *dev)
+	{
+		/* totally we used below memory size when created the sub dev
+		 *sizeof(struct platform_device) + sizeof(struct resource) *resource_count
+		 *they are allocated toghether, so we need only kfree the start address */
+		ENTER();
+		kfree(to_platform_device(dev));
+		LEAVE();
+	}
+
+	static struct platform_device *sm502_create_subdev(struct lynx_share *share, const char *name, int rescnt)
+	{
+		struct platform_device *plf_dev;
+		ENTER();
+		plf_dev = kzalloc(sizeof(struct platform_device) + sizeof(struct resource) * rescnt, GFP_KERNEL);
+		if (plf_dev) {
+			plf_dev->dev.release = sm502_device_release;
+			plf_dev->name = name;
+			/* a unique id for sub device of voyager */
+			plf_dev->id = share->pdev->devfn + 32;
+/*need consideration later, what if 502 itself is a platform device? that makes share->pdev non-sense*/
+			plf_dev->resource = (struct resource *)(plf_dev+1);
+			plf_dev->num_resources = rescnt;
+			plf_dev->dev.parent = &share->pdev->dev;/*need consideration later*/
+		}
+		LEAVE(plf_dev);
+	}
+
+	static void sm502_create_irq(struct lynx_share *share, struct resource *res)
+	{
+		ENTER();
+		if (res) {
+			res->flags = IORESOURCE_IRQ;
+			res->parent = NULL;
+			res->start = res->end = share->pdev->irq;
+		}
+		LEAVE();
+	}
+
+
+	static void sm502_create_mem(struct lynx_share *share, struct resource *res,
+			resource_size_t offset, resource_size_t size,
+			int type)
+	{
+		ENTER();
+		res->flags = IORESOURCE_MEM;
+		switch (type) {
+		case VGX_MMIO:
+				res->parent = &share->pdev->resource[1];
+				/* actually the physic address of vgx mmio*/
+				break;
+		case VGX_MEM:
+				res->parent = &share->pdev->resource[0];
+				break;
+		default:
+				err_msg("infalid resource type\n");
+				LEAVE (-EINVAL);
+		}
+		res->start = res->parent->start + offset;
+		res->end = res->start + size - 1;
+		LEAVE();
+	}
+#endif
+
+	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);
+#if 1
+			/* clean crtc & output allocations*/
+			par->crtc.clear(&par->crtc);
+			par->output.clear(&par->output);
+#endif
+			/* 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);*/
+
+		/* release sm502 sub device*/
+		if (g_plf_502aud) {
+			platform_device_unregister(g_plf_502aud);
+		}
+		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;
+		case PCI_DEVID_LYNX_EM:
+		case PCI_DEVID_LYNX_3DM:
+				spec_share = container_of(share, struct sm712_share, share);
+				break;
+		case PCI_DEVID_VOYAGER:
+				spec_share = container_of(share, struct sm502_share, share);
+				break;
+		default:
+				spec_share = share;
+		}
+		kfree(g_settings);
+		kfree(spec_share);
+		pci_set_drvdata(pdev, NULL);
+		LEAVE();
+	}
+
+
+	static void sm712fb_setup(struct lynx_share *share, char *src)
+	{
+		struct sm712_share *spec_share;
+		char *opt;
+		ENTER();
+
+		spec_share = container_of(share, struct sm712_share, share);
+		spec_share->mclk = 130*1000000;/*130 mhz is the maximum for sm712 BA version*/
+
+		/* defaultly use onboard jump setting */
+		spec_share->lcd = LCD712_USE_JUMP;
+
+		/* defaultlly use 24-bit color for TFT, it
+		 *will both affect 2nd CRT and Panel TFT */
+		spec_share->lcd_color.tftColor = TFT_24BIT;
+
+		spec_share->lcd_color.dstnColor = DSTN_USE_JUMP;
+
+		if (!src || !*src) {
+			war_msg("no specific g_option.\n");
+			goto FLAG1;
+		}
+
+		/* walk through the options */
+		while ((opt = strsep(&src, ":")) != NULL && *opt != NULL) {
+			if (!strncmp(opt, "tft", strlen("tft")))
+				spec_share->lcd = LCD712_TFT;
+			else if (!strncmp(opt, "dstn", strlen("dstn")))
+				spec_share->lcd = LCD712_DSTN;
+
+			else if (!strncmp(opt, "9bit", strlen("9bit")))
+				spec_share->lcd_color.tftColor = TFT_9BIT;
+			else if (!strncmp(opt, "18bit", strlen("18bit")))
+				spec_share->lcd_color.tftColor = TFT_18BIT;
+			else if (!strncmp(opt, "24bit", strlen("24bit")))
+				spec_share->lcd_color.tftColor = TFT_24BIT;
+			else if (!strncmp(opt, "12p12", strlen("12p12")))
+				spec_share->lcd_color.tftColor = TFT_12P12;
+			else if (!strncmp(opt, "analog", strlen("analog")))
+				spec_share->lcd_color.tftColor = TFT_ANALOG;
+			else if (!strncmp(opt, "18p18", strlen("18p18")))
+				spec_share->lcd_color.tftColor = TFT_18P18;
+			else if (!strncmp(opt, "dstn16b", strlen("dstn16")))
+				spec_share->lcd_color.dstnColor = DSTN_16BIT;
+			else if (!strncmp(opt, "dstn24", strlen("dstn24")))
+				spec_share->lcd_color.dstnColor = DSTN_24BIT;
+
+			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");
+				}
+			}
+		}
+FLAG1:
+
+		LEAVE();
+	}
+
+	static void sm502fb_setup(struct lynx_share *share, char *src)
+	{
+		struct sm502_share *spec_share;
+		char *opt, *exp_res;
+		int use_sec_ctrl;
+		ENTER();
+
+		spec_share = container_of(share, struct sm502_share, share);
+		exp_res = NULL;
+		use_sec_ctrl = 0;
+
+		spec_share->state.initParm.mem_clk = 144;
+		spec_share->state.initParm.master_clk = 72;
+		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 FLAG1;
+		}
+
+		while ((opt = strsep(&src, ":")) != NULL && *opt != NULL) {
+			if (!strncmp(opt, "sec_ctrl", strlen("sec_ctrl")))
+				use_sec_ctrl = 1;
+			else if (!strncmp(opt, "nocrt", strlen("nocrt")))
+				spec_share->state.nocrt = 1;
+			else if (!strncmp(opt, "9bit", strlen("9bit")))
+				spec_share->state.pnltype = sm502_9TFT;
+			else if (!strncmp(opt, "12bit", strlen("12bit")))
+				spec_share->state.pnltype = sm502_12TFT;
+			else if (!strncmp(opt, "24bit", strlen("24bit")))
+				spec_share->state.pnltype = sm502_24TFT;
+			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 (!strncmp(opt, "nodisp", strlen("nodisp")))
+				g_no502disp = 1;/*disable sm502 frame buffer*/
+			else if (!strncmp(opt, "noaud", strlen("noaud")))
+				g_no502aud = 1;/*disable sm502 audio dev register*/
+			else if (!strncmp(opt, "nousb", strlen("nousb")))
+				g_no502usb = 1;/*disable sm502 usb dev register*/
+			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");
+				}
+			}
+		}
+
+FLAG1:
+		if (share->dual) {
+			spec_share->state.dataflow = sm502_dual_normal;
+		} else{
+			if (use_sec_ctrl)
+				spec_share->state.dataflow = sm502_single_sec;
+			else
+				spec_share->state.dataflow = sm502_simul_pri;
+		}
+		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();
+		g_plf_502aud = NULL;
+		g_no502disp = 0;
+		g_no502aud = 0;
+		g_no502usb = 0;
+		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();
+		g_plf_502aud = NULL;
+		g_no502disp = 0;
+		g_no502aud = 0;
+		g_no502usb = 0;
+		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..2f3f636
--- /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; `})
+
+#if 1
+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
+
+
+#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_hw502.c b/drivers/video/lynxfb/lynx_hw502.c
new file mode 100644
index 0000000..e060789
--- /dev/null
+++ b/drivers/video/lynxfb/lynx_hw502.c
@@ -0,0 +1,987 @@
+/*******************************************************************
+*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>
+#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_hw502.h"
+#include "lynx_accel.h"
+
+static volatile unsigned char __iomem *mmio502;
+#define PEEK32(addr) readl((addr)+mmio502)
+#define POKE32(addr, data) writel((data), (addr)+mmio502)
+
+/* IMPORTANT:
+ * you must use below two line macro to access 2d registers
+ * do not use POKE32 and PEEK32 to access 2d registers
+ * because all 2d register address is just an offset from its
+ * chip's 2d base address
+ * */
+#if 0
+#define dePOKE32(a, b) POKE32(a+DE_BASE_ADDR_TYPE1, b)
+#define dePEEK32(a) PEEK32(a+DE_BASE_ADDR_TYPE1)
+#endif
+
+static inline int h_total(struct fb_var_screeninfo *var)
+{
+	return var->xres + var->left_margin + var->right_margin + var->hsync_len;
+}
+
+static inline int v_total(struct fb_var_screeninfo *var)
+{
+	return var->yres + var->upper_margin + var->lower_margin + var->vsync_len;
+}
+
+static void set_mmio(volatile unsigned char __iomem *addr)
+{
+	mmio502 = addr;
+}
+
+unsigned long SmRead8(unsigned long nOffset)
+{
+	return readb(mmio502 + nOffset);
+}
+
+unsigned long SmRead16(unsigned long nOffset)
+{
+	return readw(mmio502 + nOffset);
+}
+
+unsigned long SmRead32(unsigned long nOffset)
+{
+	return readl(mmio502 + nOffset);
+}
+
+void SmWrite8(unsigned long nOffset, unsigned long nData)
+{
+	writeb(nData, mmio502+nOffset);
+}
+
+void SmWrite16(unsigned long nOffset, unsigned long nData)
+{
+	writew(nData, mmio502 + nOffset);
+}
+
+void SmWrite32(unsigned long nOffset, unsigned long nData)
+{
+	writel(nData, mmio502 + nOffset);
+}
+
+volatile unsigned char __iomem *SmIoAddress(void)
+{
+	return mmio502;
+}
+
+void SmMemset(unsigned long nOffset, unsigned char val, int cnt)
+{
+	memset((void __force *)(mmio502 + nOffset), val, cnt);
+}
+
+void sm501_set_gate(unsigned long gate)
+{
+	unsigned long mode = SmRead32(POWER_MODE_CTRL);
+	switch (mode) {
+	case 0:
+			SmWrite32(POWER_MODE0_GATE, gate);
+			break;
+	case 1:
+			SmWrite32(POWER_MODE1_GATE, gate);
+			break;
+	default:
+			return;
+	}
+	msleep(16);
+}
+extern int sm501_unit_power(struct device *dev, unsigned int bit, unsigned int on)
+{
+	/*
+	   struct lynx_share *share;
+	   share = dev_get_drvdata(dev);
+	   */
+	ENTER();
+
+	u32 reg;
+	reg = PEEK32(CURRENT_POWER_GATE);
+	reg &= ~(1 << bit);
+	reg |= (1 << on);
+	POKE32(POWER_MODE0_GATE, reg);
+	LEAVE(0);
+}
+
+extern int sm501_modify_reg(struct device *dev, unsigned long regoff, unsigned long set,
+		unsigned long clear)
+{
+	u32 reg;
+	reg = PEEK32(regoff);
+	reg |= set;
+	reg &= ~clear;
+
+	POKE32(regoff, reg);
+	return reg;
+}
+
+EXPORT_SYMBOL_GPL(SmRead8);
+EXPORT_SYMBOL_GPL(SmRead16);
+EXPORT_SYMBOL_GPL(SmRead32);
+EXPORT_SYMBOL_GPL(SmWrite8);
+EXPORT_SYMBOL_GPL(SmWrite16);
+EXPORT_SYMBOL_GPL(SmWrite32);
+EXPORT_SYMBOL_GPL(SmIoAddress);
+EXPORT_SYMBOL_GPL(SmMemset);
+EXPORT_SYMBOL_GPL(sm501_set_gate);
+
+int hw_sm502_map(struct lynx_share *share, struct pci_dev *pdev)
+{
+	ENTER();
+	share->vidreg_start = pci_resource_start(pdev, 1);
+	dbg_msg("share->vidreg_start = %08x\n", share->vidreg_start);
+	share->vidreg_size = MB(2);
+
+	share->pvReg = ioremap(share->vidreg_start, share->vidreg_size);
+	if (!share->pvReg) {
+		err_msg("mmio failed\n");
+		LEAVE(-EFAULT);
+	}
+	share->accel.dprBase = share->pvReg + DE_BASE_ADDR_TYPE1;
+	share->accel.dpPortBase = share->pvReg + DE_PORT_ADDR_TYPE1;
+
+	set_mmio(share->pvReg);
+
+	dbg_msg("share->pvReg = %p, mmio 60 = %08x \n", share->pvReg, PEEK32(0x60));
+
+	share->vidmem_start = pci_resource_start(pdev, 0);
+	dbg_msg("share->vidmem_start = %08x\n", share->vidmem_start);
+
+	share->vidmem_size = hw_sm502_getVMSize(share);
+
+	inf_msg("memory size = %d\n", (int)share->vidmem_size);
+
+	share->pvMem = ioremap(share->vidmem_start, share->vidmem_size);
+	if (!share->pvMem) {
+		err_msg("Map video memory failed\n");
+		LEAVE(-EFAULT);
+	}
+
+	LEAVE(0);
+}
+
+static unsigned int voyager_calcProgPllCtrl(unsigned int ulRequestClk,
+		struct sm502_pll_value *pPLL)
+{
+	unsigned int M, N, diff, pllClk, i;
+	unsigned int bestDiff = ~0; /* biggest 32 bit unsigned number */
+
+	/* Sanity check */
+	if (pPLL->inputFreq < MHz(5) || pPLL->inputFreq > MHz(100)) {
+		return 0;
+	}
+
+	/* Convert everything in Khz range in order to avoid calculation overflow */
+	pPLL->inputFreq /= 1000;
+	ulRequestClk /= 1000;
+
+	/* Try both ulRequestClk and (ulRequestClk x 2) to work out the best M & N values. */
+	for (i = 0; i < 2; i++) {
+		/* N must between 2 and 24, according to design */
+		for (N = 2; N < 25; N++) {
+			M = ulRequestClk * N * 1000 / pPLL->inputFreq;
+			M = roundedDiv(M, 1000);
+
+			pllClk = pPLL->inputFreq * M / N;
+			diff = absDiff(pllClk, ulRequestClk);
+			/*printk("Need=%u, M=%u, N=%u, div2=%u, clk=%d, diff=%u\n", ulRequestClk, M, N, i, pllClk, diff);*/
+			if (diff < bestDiff) {
+				bestDiff = diff;
+				pPLL->M = M;
+				pPLL->N = N;
+				pPLL->divBy2 = i;
+			}
+		}
+		ulRequestClk *= 2;
+	}
+
+	pPLL->inputFreq *= 1000;
+
+	/*	printk("pPLL->inputFreq = %u, M = %u, N = %u, div2 = %u\n", pPLL->inputFreq, pPLL->M, pPLL->N, pPLL->divBy2);*/
+
+
+	return (pPLL->divBy2 == 0) ?
+		(pPLL->inputFreq * pPLL->M / pPLL->N) :
+		(pPLL->inputFreq * pPLL->M / pPLL->N / 2);
+
+}
+
+static unsigned int voyager_calcDividerClock(unsigned int ulRequestClk,
+		struct sm502_pll_value *pPLL)
+{
+	unsigned int pll1, pll2, pllDiff, dividerClk, diff;
+	unsigned short divider, divider_limit, shift;
+	unsigned int best_diff = ~0; /* biggest 32 bit unsigned number */
+
+	/* Sanity check */
+	if (pPLL->inputFreq < MHz(5) || pPLL->inputFreq > MHz(100)) {
+		return 0;
+	}
+
+	/* Convert everything in Khz range in order to avoid overflow */
+	pPLL->inputFreq /= 1000;
+	ulRequestClk /= 1000;
+
+	pll1 = pPLL->inputFreq * 12;
+	pll2 = pPLL->inputFreq * 14;
+	pllDiff = pll2 - pll1;
+
+	/* For panel clock, try divider 1, 3 and 5, while all others only have 1 and 3 */
+	if (pPLL->clockType == SM502_P1XCLK || pPLL->clockType == SM502_P2XCLK)
+		divider_limit = 5;
+	else
+		divider_limit = 3;
+
+	for (dividerClk = pll1; dividerClk <= pll2; dividerClk += pllDiff) {
+		for (divider = 1; divider <= divider_limit; divider += 2) {
+			/* Try all 8 shift values. */
+			for (shift = 0; shift < 8; shift++) {
+				/* Calculate difference with requested clock. */
+				diff = absDiff((roundedDiv(dividerClk, divider << shift)), ulRequestClk);
+
+				/* If the difference is less than the current, use it. */
+				if (diff < best_diff) {
+					/* Store best difference. */
+					best_diff = diff;
+
+					/*  Store clock values. */
+					pPLL->dividerClk = dividerClk;
+					pPLL->divider = divider;
+					pPLL->shift = shift;
+				}
+			}
+		}
+	}
+
+	/* Restore frequency from Khz to hz unit */
+	pPLL->dividerClk *= 1000;
+	pPLL->inputFreq *= 1000;
+
+	/* Return actual frequency that the PLL can set */
+	return pPLL->dividerClk / (pPLL->divider << pPLL->shift);
+}
+
+
+static unsigned int voyager_fmtClkReg(struct sm502_pll_value *pPLL)
+{
+	unsigned int ulModeClockReg = 0;
+	unsigned int ulModeClockField = 0;
+
+	ulModeClockReg = PEEK32(CURRENT_POWER_CLOCK);
+
+	if (pPLL->clockType == SM502_PANEL_PLL) {
+		/* If use programmable PLL, disable divider clock and
+		   disable 2X clock.
+		   */
+		ulModeClockReg &= ~(1 << CURRENT_POWER_CLOCK_P2XCLK_DIS_LSB)
+			&  ~(1 << CURRENT_POWER_CLOCK_SEL_LSB)
+			&  ~(1 << CURRENT_POWER_CLOCK_P2XCLK_SELECT_LSB)
+			&  ~(3 << CURRENT_POWER_CLOCK_P2XCLK_DIVIDER_LSB)
+			&  ~(7 << CURRENT_POWER_CLOCK_P2XCLK_SHIFT_LSB);
+
+		ulModeClockField |=
+			(1 << CURRENT_POWER_CLOCK_P2XCLK_DIS_LSB)
+			| (1 << CURRENT_POWER_CLOCK_SEL_LSB);
+	} else if (pPLL->clockType == SM502_PANEL_PLL_2X) {
+		/* If use programmable PLL x 2, disable divider clock.
+		*/
+		ulModeClockReg &= ~(1 << CURRENT_POWER_CLOCK_P2XCLK_DIS_LSB)
+			&  ~(1 << CURRENT_POWER_CLOCK_SEL_LSB)
+			&  ~(1 << CURRENT_POWER_CLOCK_P2XCLK_SELECT_LSB)
+			&  ~(3 << CURRENT_POWER_CLOCK_P2XCLK_DIVIDER_LSB)
+			&  ~(7 << CURRENT_POWER_CLOCK_P2XCLK_SHIFT_LSB);
+
+		ulModeClockField &= (~(1 << CURRENT_POWER_CLOCK_P2XCLK_DIS_LSB));
+		ulModeClockField |= (1 << CURRENT_POWER_CLOCK_SEL_LSB);
+	} else if (pPLL->clockType == SM502_P2XCLK || pPLL->clockType == SM502_P1XCLK) {
+		/* Use either 1X or 2X panel divider clock */
+		ulModeClockReg &= ~(1 << CURRENT_POWER_CLOCK_P2XCLK_DIS_LSB)
+			&  ~(1 << CURRENT_POWER_CLOCK_SEL_LSB)
+			&  ~(1 << CURRENT_POWER_CLOCK_P2XCLK_SELECT_LSB)
+			&  ~(3 << CURRENT_POWER_CLOCK_P2XCLK_DIVIDER_LSB)
+			&  ~(7 << CURRENT_POWER_CLOCK_P2XCLK_SHIFT_LSB);
+		ulModeClockField =
+			(0 << CURRENT_POWER_CLOCK_SEL_LSB)
+			| ((pPLL->clockType == SM502_P2XCLK)
+					? (0 << CURRENT_POWER_CLOCK_P2XCLK_DIS_LSB)
+					: (1 << CURRENT_POWER_CLOCK_P2XCLK_DIS_LSB))
+			| ((pPLL->dividerClk == (pPLL->inputFreq * 12))
+					? (0 << CURRENT_POWER_CLOCK_P2XCLK_SELECT_LSB)
+					: (1 << CURRENT_POWER_CLOCK_P2XCLK_SELECT_LSB))
+			| ((pPLL->divider == 1)
+					? (0 << CURRENT_POWER_CLOCK_P2XCLK_DIVIDER_LSB)
+					: ((pPLL->divider == 3)
+						? (1 << CURRENT_POWER_CLOCK_P2XCLK_DIVIDER_LSB)
+						: (2 << CURRENT_POWER_CLOCK_P2XCLK_DIVIDER_LSB)))
+			| (pPLL->shift << CURRENT_POWER_CLOCK_P2XCLK_SHIFT_LSB);
+	} else if (pPLL->clockType == SM502_V2XCLK || pPLL->clockType == SM502_V1XCLK) {
+		/* Use either 1x or 2x CRT divider clock */
+		ulModeClockReg &= ~(1 << CURRENT_POWER_CLOCK_V2XCLK_DIS_LSB)
+			&  ~(1 << CURRENT_POWER_CLOCK_V2XCLK_SELECT_LSB)
+			&  ~(1 << CURRENT_POWER_CLOCK_V2XCLK_DIVIDER_LSB)
+			&  ~(7 << CURRENT_POWER_CLOCK_V2XCLK_SHIFT_LSB);
+
+		ulModeClockField =
+			((pPLL->clockType == SM502_V2XCLK)
+			 ? (0 << CURRENT_POWER_CLOCK_V2XCLK_DIS_LSB)
+			 : (0 << CURRENT_POWER_CLOCK_V2XCLK_DIS_LSB))
+			| ((pPLL->dividerClk == (pPLL->inputFreq * 12))
+					? (0 << CURRENT_POWER_CLOCK_V2XCLK_SELECT_LSB)
+					: (1 << CURRENT_POWER_CLOCK_V2XCLK_SELECT_LSB))
+			| ((pPLL->divider == 1)
+					? (0 << CURRENT_POWER_CLOCK_V2XCLK_DIVIDER_LSB)
+					: (1 << CURRENT_POWER_CLOCK_V2XCLK_DIVIDER_LSB))
+			| (pPLL->shift << CURRENT_POWER_CLOCK_V2XCLK_SHIFT_LSB);
+	} else if (pPLL->clockType == SM502_MXCLK) {
+		/* 1X Master Clock */
+		ulModeClockReg &= ~(1 << CURRENT_POWER_CLOCK_MCLK_SELECT_LSB)
+			&  ~(1 << CURRENT_POWER_CLOCK_MCLK_DIVIDER_LSB)
+			&  ~(7 << CURRENT_POWER_CLOCK_MCLK_SHIFT_LSB);
+
+		ulModeClockField =
+			((pPLL->dividerClk == (pPLL->inputFreq * 12))
+			 ? (0 << CURRENT_POWER_CLOCK_MCLK_SELECT_LSB)
+			 : (1 << CURRENT_POWER_CLOCK_MCLK_SELECT_LSB))
+			| ((pPLL->divider == 1)
+					? (0 << CURRENT_POWER_CLOCK_MCLK_DIVIDER_LSB)
+					: (1 << CURRENT_POWER_CLOCK_MCLK_DIVIDER_LSB))
+			| (pPLL->shift << CURRENT_POWER_CLOCK_MCLK_SHIFT_LSB);
+	} else {
+		/* 1X Memroy Clock */
+		ulModeClockReg &= ~(1 << CURRENT_POWER_CLOCK_M2XCLK_SELECT_LSB)
+			&  ~(1 << CURRENT_POWER_CLOCK_M2XCLK_DIVIDER_LSB)
+			&  ~(7 << CURRENT_POWER_CLOCK_M2XCLK_SHIFT_LSB);
+
+		ulModeClockField =
+			((pPLL->dividerClk == (pPLL->inputFreq * 12))
+			 ? (0 << CURRENT_POWER_CLOCK_M2XCLK_SELECT_LSB)
+			 : (1 << CURRENT_POWER_CLOCK_M2XCLK_SELECT_LSB))
+			| ((pPLL->divider == 1)
+					? (0 << CURRENT_POWER_CLOCK_M2XCLK_DIVIDER_LSB)
+					: (1 << CURRENT_POWER_CLOCK_M2XCLK_DIVIDER_LSB))
+			| (pPLL->shift << CURRENT_POWER_CLOCK_M2XCLK_SHIFT_LSB);
+	}
+	return ulModeClockReg | ulModeClockField;
+}
+
+static inline void voyager_setCurrentGate(unsigned int gate)
+{
+	unsigned int gate_reg;
+	gate_reg = POWER_MODE0_GATE;
+	POKE32(gate_reg, gate);
+}
+
+static inline void voyager_setCurrentClock(unsigned int clock)
+{
+	unsigned int clock_reg;
+	/* kernel driver always use power mode 0, so cut above crap*/
+	clock_reg = POWER_MODE0_CLOCK;
+	POKE32(clock_reg, clock);
+}
+
+
+
+static void voyager_set_clock(enum sm502_clocktype clksrc, unsigned int req_freq)
+{
+	unsigned int actualClk;
+#if (DEBUG >= 1)
+	static const char *clkNames[] = {
+		[SM502_P2XCLK] = "PANEL CONTROLLER CLOCK",
+		[SM502_V2XCLK] = "CRT CONTROLLER CLOCK",
+		[SM502_MXCLK] = "MAIN ENGINE CLOCK",
+		[SM502_M1XCLK] = "SDRAM CONTROLLER CLOCK",
+		[SM502_P1XCLK] = "x1 panel divider clock",
+		[SM502_V1XCLK] = "x1 CRT divider clock",
+		[SM502_PANEL_PLL] = "Programmable panel pixel clock",
+		[SM502_PANEL_PLL_2X] = "For TV, 2X clock is needed",
+	};
+#endif
+	struct sm502_pll_value pll;
+	ENTER();
+	dbg_msg("Request %s clock to %u hz.\n", clkNames[clksrc], req_freq);
+
+	if (req_freq) {
+		u32 tmp;
+		memset(&pll, 0, sizeof(struct sm502_pll_value));
+		pll.clockType = clksrc;
+		pll.inputFreq = DEFAULT_INPUT_CLOCK;
+
+		switch (clksrc) {
+		case SM502_PANEL_PLL:
+				actualClk = voyager_calcProgPllCtrl(req_freq, &pll);
+				voyager_setCurrentClock(voyager_fmtClkReg(&pll));
+#if 1
+				/* for programable pll, need ox74 be set */
+				tmp =
+					(0 << PROGRAMMABLE_PLL_CONTROL_TSTOE_LSB)|
+					(1 << PROGRAMMABLE_PLL_CONTROL_PON_LSB)|
+					(0 << PROGRAMMABLE_PLL_CONTROL_SEL_LSB)|
+					(pll.M << PROGRAMMABLE_PLL_CONTROL_M_LSB)|
+					(pll.N << PROGRAMMABLE_PLL_CONTROL_N_LSB)|
+					(pll.divBy2 << PROGRAMMABLE_PLL_CONTROL_K_LSB);
+				POKE32(PROGRAMMABLE_PLL_CONTROL, tmp);
+#endif
+				break;
+		case SM502_V1XCLK:
+		case SM502_MXCLK:
+		case SM502_M1XCLK:
+				actualClk = voyager_calcDividerClock(req_freq, &pll);
+				/* set current clock  */
+				voyager_setCurrentClock(voyager_fmtClkReg(&pll));
+				break;
+		default:
+				LEAVE();
+		}
+
+		dbg_msg("actual %s clock ==> %u hz.\n", clkNames[clksrc], actualClk);
+	}
+	LEAVE();
+}
+
+int hw_sm502_inithw(struct lynx_share *share, struct pci_dev *pdev)
+{
+	int ret;
+	ushort mclk, m1xclk;
+	unsigned int reg;
+	struct sm502_share *spec_share;
+	struct init_status502 *parm;
+
+	ENTER();
+
+	ret = 0;
+	reg = PEEK32(DRAM_CTRL);
+	spec_share = container_of(share, struct sm502_share, share);
+	parm = &spec_share->state.initParm;
+
+	/* for easy hardware setting, always use mode0*/
+	POKE32(0x54, 0);
+	if (share->vidmem_size == MB(4)) {
+		/* for sm107, use banks 2*/
+		reg |= 1 << DRAM_CTRL_CPU_BANKS_LSB;
+	} else{
+		reg &= ~(1 << DRAM_CTRL_CPU_BANKS_LSB);
+	}
+
+#ifdef CONFIG_SYS_HAS_CPU_LOONGSON2
+	reg &= ~(1 << DRAM_CTRL_LOCAL);
+#endif
+	POKE32(DRAM_CTRL, reg);
+
+#ifdef CONFIG_SYS_HAS_CPU_LOONGSON2
+	reg |= (1 << DRAM_CTRL_LOCAL);
+	POKE32(DRAM_CTRL, reg);
+#endif
+
+	/* set TFT Panel Type */
+	switch (spec_share->state.pnltype) {
+		/* the enum value are designed to equal to the register value */
+	case sm502_9TFT:
+	case sm502_12TFT:
+	case sm502_24TFT:
+			POKE32(PANEL_DISPLAY_CTRL, PEEK32(PANEL_DISPLAY_CTRL)|
+					(spec_share->state.pnltype << PANEL_DISPLAY_CTRL_TFT_LSB));
+			break;
+	}
+
+	/* 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));
+		dbg_msg("read SYSTEM ctrl (nocrt) == %08x\n", PEEK32(SYSTEM_CTRL));
+	} else{
+		POKE32(MISC_CTRL, PEEK32(MISC_CTRL) & ~(1 << MISC_CTRL_DAC_POWER_LSB));
+		/* turn on dpms */
+		POKE32(SYSTEM_CTRL, PEEK32(SYSTEM_CTRL) & ~(1 << SYSTEM_CTRL_DPMS_LSB));
+		dbg_msg("read SYSTEM ctrl (crt) == %08x\n", PEEK32(SYSTEM_CTRL));
+	}
+
+
+	/* defaulty enable pci burst read and write */
+	reg = PEEK32(SYSTEM_CTRL);
+	POKE32(SYSTEM_CTRL, reg | (1 << SYSTEM_CTRL_PCI_BURST_LSB) | 0);
+
+	/* defaulty open dac power */
+	reg = PEEK32(MISC_CTRL);
+	POKE32(MISC_CTRL, reg & ~(1 << MISC_CTRL_DAC_POWER_LSB));
+
+#if 0
+	/* find below line make system die deadly*/
+	/* shut up all none-graphic-related power gate*/
+	voyager_setCurrentGate(6);
+#endif
+	mclk = parm->master_clk;
+	m1xclk = parm->mem_clk;
+
+	if (mclk < 80) {
+		/*inf_msg("set voyager engine clock to %d mhz\n", mclk);*/
+		voyager_set_clock(SM502_MXCLK, MHZ(mclk));
+	}
+
+	if (m1xclk < 150) {
+		/*inf_msg("set voyager sdram clock to %d mhz\n", m1xclk);*/
+		voyager_set_clock(SM502_M1XCLK, MHZ(m1xclk));
+	}
+
+	if (!share->accel_off) {
+		hw_sm502_initAccel(&share->accel);
+	}
+
+	LEAVE(ret);
+}
+
+resource_size_t hw_sm502_getVMSize(struct lynx_share *share)
+{
+	int idx;
+	static resource_size_t sm501_mem_local[] = {
+		[0] = MB(4),
+		[1] = MB(8),
+		[2] = MB(16),
+		[3] = MB(32),
+		[4] = MB(64),
+		[5] = MB(2),
+	};
+	ENTER();
+	idx = DRAM_CTRL_SIZE_BIT & (PEEK32(DRAM_CTRL) >> DRAM_CTRL_SIZE_LSB);
+	LEAVE(sm501_mem_local[idx]);
+}
+
+int hw_sm502_output_checkMode(struct lynxfb_output *output, struct fb_var_screeninfo *var)
+{
+#if 0
+	ENTER();
+	LEAVE(0);
+#else
+	return 0;
+#endif
+
+}
+
+
+static void voyager_wait_panelvsync(int times)
+{
+	unsigned int status;
+	while (times-- > 0) {
+		/* wait for end of vsync */
+		do {
+			status = 1 & (PEEK32(CMD_INTPR_STATUS) >> CMD_INTPR_STATUS_PANEL_SYNC_LSB);
+		} while (status == CMD_INTPR_STATUS_PANEL_SYNC_ACTIVE);
+
+		/* wait for start of vsync */
+		do {
+			status = 1 & (PEEK32(CMD_INTPR_STATUS) >> CMD_INTPR_STATUS_PANEL_SYNC_LSB);
+		} while (status == CMD_INTPR_STATUS_PANEL_SYNC_INACTIVE);
+	}
+}
+
+static void voyager_panel_power(int open, int times)
+{
+	unsigned int reg = PEEK32(PANEL_DISPLAY_CTRL);
+
+	voyager_wait_panelvsync(4);
+	if (open != 0) {
+		/* turn on fpvdden */
+		reg |= 1 << PANEL_DISPLAY_CTRL_FPVDDEN_LSB;
+		POKE32(PANEL_DISPLAY_CTRL, reg);
+		voyager_wait_panelvsync(times);
+
+		/* turn on fpdata */
+		reg |= 1 << PANEL_DISPLAY_CTRL_DATA_LSB;
+		POKE32(PANEL_DISPLAY_CTRL, reg);
+		voyager_wait_panelvsync(times);
+
+		/* turn on fpvbias */
+		reg |= 1 << PANEL_DISPLAY_CTRL_VBIASEN_LSB;
+		POKE32(PANEL_DISPLAY_CTRL, reg);
+		voyager_wait_panelvsync(times);
+
+		/* turn on fpen */
+		reg |= 1 << PANEL_DISPLAY_CTRL_FPEN_LSB;
+		POKE32(PANEL_DISPLAY_CTRL, reg);
+		voyager_wait_panelvsync(times);
+	} else{
+		/* turn off fpvdden */
+		reg &= ~(1 << PANEL_DISPLAY_CTRL_FPVDDEN_LSB);
+		POKE32(PANEL_DISPLAY_CTRL, reg);
+		voyager_wait_panelvsync(times);
+
+		/* turn off fpdata */
+		reg &= ~(1 << PANEL_DISPLAY_CTRL_DATA_LSB);
+		POKE32(PANEL_DISPLAY_CTRL, reg);
+		voyager_wait_panelvsync(times);
+
+		/* turn off fpvbias */
+		reg &= ~(1 << PANEL_DISPLAY_CTRL_VBIASEN_LSB);
+		POKE32(PANEL_DISPLAY_CTRL, reg);
+		voyager_wait_panelvsync(times);
+
+		/* turn off fpen */
+		reg &= ~(1 << PANEL_DISPLAY_CTRL_FPEN_LSB);
+		POKE32(PANEL_DISPLAY_CTRL, reg);
+		voyager_wait_panelvsync(times);
+	}
+}
+
+int hw_sm502_output_setMode(struct lynxfb_output *output,
+		struct fb_var_screeninfo *var,
+		struct fb_fix_screeninfo *fix)
+{
+	unsigned int reg;
+	ENTER();
+	/*if (output->paths & sm502_panel)*/
+	{
+		reg = PEEK32(PANEL_DISPLAY_CTRL);
+		reg |= 1 << PANEL_DISPLAY_CTRL_TIMING_LSB;
+		reg |= 1 << PANEL_DISPLAY_CTRL_PLANE_LSB;
+		reg |= 0x0f000000;
+		POKE32(PANEL_DISPLAY_CTRL, reg);
+		/*voyager_panel_power(1, 4); *//* open panel sequence */
+	}
+
+	/*if (output->paths & sm502_crt)*/
+	{
+		reg = PEEK32(CRT_DISPLAY_CTRL);
+		if (*output->channel)
+			reg |= 1 << CRT_DISPLAY_CTRL_SELECT_LSB;
+		else{
+			reg &= ~(1 << CRT_DISPLAY_CTRL_SELECT_LSB);
+		}
+		reg |= 1 << CRT_DISPLAY_CTRL_TIMING_LSB;
+		reg |= 1 << CRT_DISPLAY_CTRL_PLANE_LSB;
+		POKE32(CRT_DISPLAY_CTRL, reg);
+	}
+	LEAVE(0);
+}
+
+int hw_sm502_crtc_checkMode(struct lynxfb_crtc *crtc, struct fb_var_screeninfo *var)
+{
+	ENTER();
+	/* video memory check move to upper routine */
+	if (var->bits_per_pixel == 8 ||
+			var->bits_per_pixel == 16 ||
+			var->bits_per_pixel == 32){
+	} else
+		LEAVE(-EINVAL);
+
+	LEAVE(0);
+}
+
+static void set_bpp(enum sm502_channel ctrl, int bpp)
+{
+	unsigned int reg;
+	if (ctrl == sm502_primary) {
+		reg = PEEK32(PANEL_DISPLAY_CTRL);
+		switch (bpp) {
+		case 8:
+		case 16:
+		case 32:
+			reg &= ~(3 >> PANEL_DISPLAY_CTRL_FORMAT_LSB);
+			POKE32(PANEL_DISPLAY_CTRL, reg | ((bpp >> 4) >> PANEL_DISPLAY_CTRL_FORMAT_LSB));
+			break;
+		}
+
+	} else{
+		reg = PEEK32(CRT_DISPLAY_CTRL);
+		switch (bpp) {
+		case 8:
+		case 16:
+		case 32:
+			reg &= ~(3 >> CRT_DISPLAY_CTRL_FORMAT_LSB);
+			POKE32(CRT_DISPLAY_CTRL, reg | ((bpp >> 4) >> CRT_DISPLAY_CTRL_FORMAT_LSB));
+			break;
+		}
+	}
+
+}
+
+static void set_timing(enum sm502_channel ctrl, struct fb_var_screeninfo *var)
+{
+	unsigned int reg, base;
+
+	if (ctrl == sm502_primary) {
+		/* for panel channel, set its paning and rectangle value */
+		POKE32(PANEL_PAN_CTRL, 0);
+		POKE32(PANEL_PLANE_TL, 0);
+		POKE32(PANEL_PLANE_BR, (var->xres - 1) | (var->yres - 1) << 16);
+		base = PANEL_HORIZONTAL_TOTAL;
+	} else{
+		base = CRT_HORIZONTAL_TOTAL;
+	}
+	/* program horizontal total and disp_end */
+	reg = ((h_total(var) - 1) << PANEL_HORIZONTAL_TOTAL_TOTAL_LSB) |
+		((var->xres - 1) << PANEL_HORIZONTAL_TOTAL_DISPLAY_END_LSB);
+
+	POKE32(base + VOYAGER_OFF_DC_H_TOT, reg);
+
+	/* program horizontal sync START and WIDTH */
+	reg = (var->hsync_len << PANEL_HORIZONTAL_SYNC_WIDTH_LSB) |
+		((var->xres + var->right_margin - 1) << PANEL_HORIZONTAL_SYNC_START_LSB);
+	POKE32(base + VOYAGER_OFF_DC_H_SYNC, reg);
+
+	/* program vertical total and disp_end */
+	reg = ((v_total(var) - 1) << PANEL_VERTICAL_TOTAL_TOTAL_LSB) |
+		((var->yres - 1) << PANEL_VERTICAL_TOTAL_DISPLAY_END_LSB);
+
+	POKE32(base + VOYAGER_OFF_DC_V_TOT, reg);
+
+	/* program vertical sync START and WIDTH */
+	reg = (var->vsync_len << PANEL_VERTICAL_SYNC_HEIGHT_LSB) |
+		((var->yres + var->lower_margin - 1) << PANEL_VERTICAL_SYNC_START_LSB);
+	POKE32(base + VOYAGER_OFF_DC_V_SYNC, reg);
+
+}
+
+
+int hw_sm502_crtc_setMode(struct lynxfb_crtc *crtc,
+		struct fb_var_screeninfo *var,
+		struct fb_fix_screeninfo *fix)
+{
+	unsigned int reg, tmp, pixclk;
+	int fmt;
+	struct lynx_share *share;
+	struct lynxfb_par *par;
+	ENTER();
+
+	pixclk = ps_to_hz(var->pixclock);
+	/* set timing first and color format */
+	set_timing(crtc->channel, var);
+	set_bpp(crtc->channel, var->bits_per_pixel);
+
+	par = container_of(crtc, struct lynxfb_par, crtc);
+	share = par->share;
+
+#if 1
+	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);
+	}
+#endif
+
+#if 1
+	/* set start addr, width, offset, etc... */
+	if (crtc->channel == sm502_primary) {
+		/* set pixel clock */
+		voyager_set_clock(SM502_PANEL_PLL, pixclk);
+
+
+		/* set fb address */
+		POKE32(PANEL_FB_ADDRESS, crtc->oScreen);
+
+		/* set windows position and globle width in unit of pixel/line */
+		reg = (var->xoffset << PANEL_WINDOW_WIDTH_X_LSB) |
+			(var->xres_virtual << PANEL_WINDOW_WIDTH_WIDTH_LSB);
+
+		POKE32(PANEL_WINDOW_WIDTH, reg);
+
+		reg = (var->yoffset << PANEL_WINDOW_HEIGHT_Y_LSB) |
+			(var->yres_virtual << PANEL_WINDOW_HEIGHT_HEIGHT_LSB);
+		POKE32(PANEL_WINDOW_HEIGHT, reg);
+
+		/* set fb width and offset */
+		tmp = PADDING(crtc->line_pad,
+				var->xres * (var->bits_per_pixel >> 3));
+		reg = (tmp << PANEL_FB_WIDTH_WIDTH_LSB) |
+			(fix->line_length << PANEL_FB_WIDTH_OFFSET_LSB);
+		POKE32(PANEL_FB_WIDTH, reg);
+	} else{
+		/* set pixel clock */
+		voyager_set_clock(SM502_V1XCLK, pixclk);
+
+		/* set fb address */
+		POKE32(CRT_FB_ADDRESS, crtc->oScreen);
+
+		/* set fb width and offset */
+		tmp = PADDING(crtc->line_pad,
+				var->xres * (var->bits_per_pixel>>3));
+		reg = (tmp << CRT_FB_WIDTH_WIDTH_LSB) |
+			(fix->line_length << CRT_FB_WIDTH_OFFSET_LSB);
+		POKE32(CRT_FB_WIDTH, reg);
+	}
+#endif
+	LEAVE(0);
+}
+
+
+int hw_sm502_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_sm502_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
+		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:
+		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;
+	}
+
+	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))) |
+			(pps << CRT_DISPLAY_CTRL_BLANK_LSB));
+	POKE32(PANEL_DISPLAY_CTRL, (PEEK32(PANEL_DISPLAY_CTRL) & (~(1 << PANEL_DISPLAY_CTRL_DATA_LSB))) |
+			(pps << PANEL_DISPLAY_CTRL_DATA_LSB));
+	POKE32(CRT_DISPLAY_CTRL, (PEEK32(CRT_DISPLAY_CTRL) & (~(1 << CRT_DISPLAY_CTRL_BLANK_LSB))) |
+			(crtdb << CRT_DISPLAY_CTRL_BLANK_LSB));
+	LEAVE(0);
+}
+
+void hw_sm502_crtc_clear(struct lynxfb_crtc *crtc)
+{
+
+}
+
+void hw_sm502_output_clear(struct lynxfb_output *output)
+{
+
+}
+
+void hw_sm502_initAccel(struct lynx_accel *accel)
+{
+	u32 reg;
+	/* enable DE engine */
+	reg |= (PEEK32(CURRENT_POWER_GATE) | (1 << CURRENT_POWER_GATE_2D_LSB));
+	POKE32(POWER_MODE0_GATE, reg);
+
+	/* engine reset */
+	reg = PEEK32(SYSTEM_CTRL);
+	reg |= 3 << SYSTEM_CTRL_DE_ABORT_LSB;
+	POKE32(SYSTEM_CTRL, reg);
+
+	reg = PEEK32(SYSTEM_CTRL);
+	reg &= ~(3 << SYSTEM_CTRL_DE_ABORT_LSB);
+	POKE32(SYSTEM_CTRL, reg);
+
+	/* move 2d engine register setting into accel functions */
+	accel->de_init(accel);
+}
+
+
+/*
+ * return 0:engine is idle
+ * return none-zero: engine always not in idle status
+ * */
+int hw_sm502_deWait()
+{
+	int i = 0x100000;
+	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)) {
+			return 0;
+		}
+	}
+	/* timeout error */
+	return -1;
+}
+
diff --git a/drivers/video/lynxfb/lynx_hw502.h b/drivers/video/lynxfb/lynx_hw502.h
new file mode 100644
index 0000000..d118b55
--- /dev/null
+++ b/drivers/video/lynxfb/lynx_hw502.h
@@ -0,0 +1,145 @@
+/*******************************************************************
+*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_HW502_H__
+#define LYNX_HW502_H__
+#include "lynx_help.h"
+#include "voyager.h"
+
+#define DEFAULT_INPUT_CLOCK 24000000
+#define VGX_MMIO 1
+#define VGX_MEM  2
+
+enum sm502_clocktype{
+    /* Divider clocks */
+	SM502_P2XCLK = 0, /* PANEL CONTROLLER CLOCK */
+	SM502_V2XCLK = 1, /* CRT CONTROLLER CLOCK */
+	SM502_MXCLK = 2, /* MAIN ENGINE CLOCK */
+	SM502_M1XCLK = 3, /* SDRAM CONTROLLER CLOCK */
+
+	/* the following are for sm502 and later */
+    SM502_P1XCLK,       /* x1 panel divider clock */
+    SM502_V1XCLK,       /* x1 CRT divider clock , used for secondary channel  */
+    SM502_PANEL_PLL,    /* Programmable panel pixel clock, used for primary channel  */
+    SM502_PANEL_PLL_2X, /* For TV, 2X clock is needed */
+};
+
+
+enum sm502_pnltype{
+	sm502_24TFT = 0, /* 24 bit tft  */
+	sm502_9TFT = 1, /* 9 bit tft */
+	sm502_12TFT = 2, /* 12 bit tft */
+};
+
+/* vga channel is not concerned  */
+enum sm502_dataflow{
+	sm502_simul_pri, /* primary => all head */
+	sm502_dual_normal, /* primary => panel head and secondary => crt */
+	sm502_single_sec,
+};
+
+
+enum sm502_channel{
+	sm502_primary = 0,
+	/* enum value equal to the register filed data */
+	sm502_secondary = 1,
+};
+
+enum sm502_path{
+	sm502_panel = 1,
+	sm502_crt = 2,
+	sm502_pnc = 3, /* panel and crt */
+};
+
+struct init_status502{
+	ushort powerMode;/* defaultly 0 */
+	/* below clocks are in unit of MHZ*/
+	ushort mem_clk;
+	ushort master_clk;/* 2d engine clock */
+	ushort setAllEngOff;
+	ushort resetMemory;
+};
+
+struct sm502_state{
+	struct init_status502 initParm;
+	enum sm502_pnltype pnltype;
+	enum sm502_dataflow dataflow;
+	int nocrt;/* when in simul mode, nocrt == 1 means only panel output show content */
+};
+
+/* 	sm502_share stands for a presentation of two frame buffer
+	that use one sm502 adaptor */
+
+struct sm502_share{
+	/* it's better to put lynx_share struct to the first place of sm502_share */
+	struct lynx_share share;
+	struct sm502_state state;
+	/* 	0: no hardware cursor
+		1: primary crtc hw cursor enabled,
+		2: secondary crtc hw cursor enabled
+		3: both ctrc hw cursor enabled
+	*/
+	int hwCursor;
+	/* usb always use bottom memory: totalsize - 512kb */
+	int usb_off;
+	int aud_off;
+
+};
+
+struct sm502_pll_value{
+	enum sm502_clocktype clockType;
+	unsigned int inputFreq;
+
+    /* Use this for all clockType != PANEL_PLL */
+    unsigned int dividerClk; /* either x12 or x14 of the input reference crystal */
+    unsigned int divider;
+    unsigned int shift;
+
+    /* Use this when clockType = PANEL_PLL */
+    unsigned int M;
+    unsigned int N;
+    unsigned int divBy2;
+};
+
+int hw_sm502_map(struct lynx_share *share, struct pci_dev *pdev);
+int hw_sm502_inithw(struct lynx_share *, struct pci_dev *);
+int hw_sm502_deWait(void);
+void hw_sm502_initAccel(struct lynx_accel *);
+resource_size_t hw_sm502_getVMSize(struct lynx_share *);
+int hw_sm502_output_checkMode(struct lynxfb_output *, struct fb_var_screeninfo *);
+int hw_sm502_output_setMode(struct lynxfb_output *, struct fb_var_screeninfo *, struct fb_fix_screeninfo *);
+int hw_sm502_crtc_checkMode(struct lynxfb_crtc *, struct fb_var_screeninfo *);
+int hw_sm502_crtc_setMode(struct lynxfb_crtc *, struct fb_var_screeninfo *, struct fb_fix_screeninfo *);
+int hw_sm502_setColReg(struct lynxfb_crtc *, ushort, ushort, ushort, ushort);
+int hw_sm502_setBLANK(struct lynxfb_output *, int);
+void hw_sm502_crtc_clear(struct lynxfb_crtc *);
+void hw_sm502_output_clear(struct lynxfb_output *);
+/*static void sm502fb_wait_panelvsnc(int vsync_count);*/
+extern unsigned long SmRead8(unsigned long nOffset);
+extern unsigned long SmRead16(unsigned long nOffset);
+extern unsigned long SmRead32(unsigned long nOffset);
+extern volatile unsigned char __iomem *SmIoAddress(void);
+extern void SmWrite8(unsigned long nOffset, unsigned long nData);
+extern void SmWrite16(unsigned long nOffset, unsigned long nData);
+extern void SmWrite32(unsigned long nOffset, unsigned long nData);
+extern void SmMemset(unsigned long nOffset, unsigned char val, int count);
+extern void sm501_set_gate(unsigned long gate);
+extern int sm501_unit_power(struct device *, unsigned int, unsigned int);
+extern int sm501_modify_reg(struct device *, unsigned long, unsigned long, unsigned long);
+
+#endif
diff --git a/drivers/video/lynxfb/lynx_hw712.c b/drivers/video/lynxfb/lynx_hw712.c
new file mode 100644
index 0000000..5f4192d
--- /dev/null
+++ b/drivers/video/lynxfb/lynx_hw712.c
@@ -0,0 +1,526 @@
+/*******************************************************************
+*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>
+#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_hw712.h"
+#include "ddk712/ddk712.h"
+#include "lynx_accel.h"
+
+int hw_sm712_map(struct lynx_share *share, struct pci_dev *pdev)
+{
+	int ret;
+	ENTER();
+
+	ret = 0;
+	if (share->devid == 0x712) {
+		share->vidreg_start = pci_resource_start(pdev, 0)+MB(4);
+		share->vidreg_size = MB(4);
+		share->vidmem_start = pci_resource_start(pdev, 0);
+	} else if (share->devid == 0x720) {
+		share->vidreg_start = pci_resource_start(pdev, 0);
+		share->vidreg_size = MB(2);
+		share->vidmem_start = pci_resource_start(pdev, 0) + MB(2);
+	} else{
+		/* do not support other chip currently */
+		return -ENODEV;
+	}
+
+	/* now map mmio*/
+	share->pvReg = ioremap(share->vidreg_start, share->vidreg_size);
+	if (!share->pvReg) {
+		err_msg("mmio failed\n");
+		ret = -EFAULT;
+		goto exit;
+	}
+
+	if (share->devid == 0x720) {
+		share->accel.dprBase = share->pvReg + DE_BASE_ADDR_TYPE3;
+		share->accel.dpPortBase = share->pvReg + DE_PORT_ADDR_TYPE3;
+	} else{
+		share->accel.dprBase = share->pvReg + DE_BASE_ADDR_TYPE2;
+		share->accel.dpPortBase = share->pvReg + DE_PORT_ADDR_TYPE2;
+	}
+
+	ddk712_set_mmio(share->devid, share->pvReg);
+	share->vidmem_size = hw_sm712_getVMSize(share);
+	/* map frame buffer*/
+	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("mapped video memory = %p\n", share->pvMem);
+
+	memset(share->pvMem, 0, share->vidmem_size);
+exit:
+	LEAVE(ret);
+}
+
+
+int hw_sm712_inithw(struct lynx_share *share, struct pci_dev *pdev)
+{
+	init_parm_712 parm;
+	struct sm712_share *spec_share;
+	ENTER();
+	spec_share = container_of(share, struct sm712_share, share);
+	parm.devid = share->devid;
+	parm.memClock = spec_share->mclk;
+	/* a cruel limitation of sm712, burst read make 712 die in x86_64 bit system */
+#if defined(__x86_64__)
+	parm.pci_burst = 2;/* no burst read, only burst write*/
+#else
+	/* enable both read and write */
+	parm.pci_burst = 3;
+#endif
+    parm.lcd = spec_share->lcd;
+	parm.lcd_color.tftColor = spec_share->lcd_color.tftColor;
+	parm.lcd_color.dstnColor = spec_share->lcd_color.dstnColor;
+
+#if defined(__i386__) || defined(__x86_64__)
+	/* enable linear mode and packed pixel format first*/
+	outb_p(0x18, 0x3c4);
+	outb_p(0x11, 0x3c5);
+#else
+	/*
+	 * don't know how to write IO port in other arch/platform
+	 * just use default method as a try
+	 * */
+	outb_p(0x18, 0x3c4);
+	outb_p(0x11, 0x3c5);
+#endif
+
+	ddk712_hw_init(&parm);
+	if (!share->accel_off) {
+		hw_sm712_initAccel(&share->accel, parm.devid);
+	}
+	LEAVE(0);
+}
+
+resource_size_t hw_sm712_getVMSize(struct lynx_share *share)
+{
+	resource_size_t ret;
+	ret = 0;
+	ENTER();
+	if (share->devid == 0x712) {
+		/* sm712 only support 4mb internal video memory */
+		ret = MB(4);
+	} else if (share->devid == 0x720) {
+		/* SM722 only support 8mb internal video memory */
+		ret = MB(8);
+	}
+	LEAVE(ret);
+}
+
+int hw_sm712_output_checkMode(struct lynxfb_output *output,
+								struct fb_var_screeninfo *var)
+{
+	ENTER();
+
+	LEAVE(0);
+}
+
+int hw_sm712_output_setMode(struct lynxfb_output *output,
+							struct fb_var_screeninfo *var,
+							struct fb_fix_screeninfo *fix)
+{
+	struct lynxfb_par *par;
+	struct lynx_share *share;
+	struct sm712_share *spec_share;
+	ENTER();
+
+	par = container_of(output, struct lynxfb_par, output);
+	share = par->share;
+	spec_share = container_of(share, struct sm712_share, share);
+
+	if (output->paths == 1) {
+		/* this is 1st CRT head, and it only connected to CRT channel
+		 * nothing need to set, leave them be what they are
+		 * */
+		inf_msg("1st CRT path <== CRT channel\n");
+	} else if (output->paths == 2) {
+		/* this is Panel head, and it can connected to either CRT or Panel channel*/
+		if (*output->channel == 0) {
+			/* Virtual Refresh Clk should be disabled */
+			inf_msg("2nd CRT/Panel Path <== CRT channel\n");
+			poke_fpr(0x31, peek_fpr(0x31)&0x7f);
+		} else{
+			/* Virtual Clock should be enabled*/
+			poke_fpr(0x31, peek_fpr(0x31)|0x80);
+			inf_msg("2nd CRT/Panel Path <== Panel channel\n");
+		}
+	} else if (output->paths == 3) {
+		/* these are Panel and Crt heads,
+		 * can only connected to CRT channel simutanounsly
+		 * need disable Virtual Clock
+		 * */
+		poke_fpr(0x31, peek_fpr(0x31)&0x7f);
+		inf_msg("1st CRT Path/2nd CRT/Panel Path <== CRT channel\n");
+
+	} else{
+		err_msg("output->path == %d, not valid.\n", output->paths);
+		LEAVE(-EINVAL);
+	}
+
+	LEAVE(0);
+}
+
+int hw_sm712_crtc_checkMode(struct lynxfb_crtc *crtc,
+							struct fb_var_screeninfo *var)
+{
+	int ret;
+	ENTER();
+	switch (var->bits_per_pixel) {
+		/* for crt channel, all pixel format are supported */
+	case 8:
+	case 16:
+			ret = 0;
+			break;
+	case 24:
+	case 32:
+		/* only 8/16 bpp format are supported by virtual clock */
+			if (crtc->channel != 0)
+				ret = -EINVAL;
+			else
+				ret = 0;
+			break;
+	default:
+			ret = -EINVAL;
+			break;
+
+	}
+	LEAVE(ret);
+}
+
+int hw_sm712_crtc_setMode(struct lynxfb_crtc *crtc,
+						struct fb_var_screeninfo *var,
+						struct fb_fix_screeninfo *fix)
+{
+	char tmp;
+	int fmt;
+	unsigned int base, pitch, width;
+	struct lynxfb_par *par;
+	struct lynx_share *share;
+	ENTER();
+
+	par = container_of(crtc, struct lynxfb_par, crtc);
+	share = par->share;
+	/* set timing, use mode table to set mode
+	 * as @var couldn't tell what v-refresh rate it is
+	 * so we assume all modes use 60 hz
+	 * we may need to create a new setmode function for sm712
+	 * like sm750 style, which can use @var parameter directly
+	 * */
+	ddk712_setModeTiming(crtc->channel, var->xres, var->yres, 60);
+
+	if (crtc->channel == 0) {
+		/* sm712 CRT channel */
+		switch (var->bits_per_pixel) {
+		case 8:
+			tmp = 0;
+			break;
+		case 16:
+			tmp = 2;
+			break;
+		case 24:
+			tmp = 4;
+			break;
+		case 32:
+			tmp = 3;
+			break;
+		default:
+			LEAVE(-EINVAL);
+		}
+
+		poke32_vpr(0,
+				(peek32_vpr(0x0)&
+				(~(7 << MISC_GRAPH_VIDEO_CTRL_DATA_FORMAT_LSB))|
+				(tmp << MISC_GRAPH_VIDEO_CTRL_DATA_FORMAT_LSB)));
+	} else{
+		/* sm712 panel channel */
+		switch (var->bits_per_pixel) {
+		case 8:
+				tmp = 0x40;
+		case 16:
+				tmp = 0x0;
+			break;
+		default:
+			LEAVE(-EINVAL);
+		}
+
+		poke_fpr(0x31, (peek_fpr(0x31)&~0x40)|tmp);
+	}
+
+	/* set pitch, width, address stuffs*/
+	base = crtc->oScreen;
+	pitch = fix->line_length;
+	width = var->xres * var->bits_per_pixel / 8;
+
+	base >>= 3;
+	pitch >>= 3;
+	width >>= 3;
+
+	if (crtc->channel == 0) {
+		poke32_vpr(0x0c, base);
+		poke32_vpr(0x10, (width<<16)|(pitch & 0xffff));
+	} else{
+		/* fpr40~43: read fifo base address*/
+		poke_fpr(0x40, base & 0xff);
+		poke_fpr(0x41, (base & 0xff00)>>8);
+		poke_fpr(0x42, base & 0xff);
+		poke_fpr(0x43, (base & 0xff00)>>8);
+
+		/* fpr44, 45:read fifo1 offset */
+		poke_fpr(0x44, pitch & 0xff);
+
+		if (share->devid == PCI_DEVID_LYNX_3DM) {
+			/* not implemented */
+		} else{
+			tmp = (pitch & 0x300) >> 2;
+			tmp |= ((base & 0x70000)>>16)|((base & 0x70000)>>13);
+			/* fpr45: fifo1 offset and fifo1 base address*/
+			poke_fpr(0x45, tmp);
+		}
+		/* found nothing changed of lcd video after fpr46~49 modified */
+
+#if 0
+		/* lcd write start address low of lcd frame buffer*/
+		poke_fpr(0x46, base & 0xff);
+		/* lcd write start address high of lcd frame buffer*/
+		poke_fpr(0x47, (base>>8)&0xff);
+
+		/* write offset of lcd frame buffer*/
+		poke_fpr(0x48, width & 0xff);
+		poke_fpr(0x49, (peek_fpr(0x49)&0xfc)|((width&0x300)>>8));
+#endif
+	}
+#if 1
+	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:
+				fmt = 2;
+				break;
+		case 24:
+				fmt = 3;
+				break;
+		default:
+				fmt = 1;
+				break;
+		}
+		hw_set2dformat(&share->accel, fmt);
+	}
+#endif
+	LEAVE(0);
+}
+
+int hw_sm712_setColReg(struct lynxfb_crtc *crtc, ushort index,
+							ushort red, ushort green, ushort blue)
+{
+	int ret;
+	ENTER();
+	ret = 0;
+	if (crtc->channel == 0) {
+		/* write CRT channel RAM only
+		 * use 8bits RAM
+		 * */
+		poke_ccr(0x66, 0xa8);
+	} else{
+		/* write LCD channel RAM only
+		 * use 8bits RAM
+		 * */
+		poke_ccr(0x66, 0x58);
+	}
+
+	/* DAC mask set to x0ff*/
+	poke8_io(0x3c6, 0xff);
+
+	/* write color code */
+	poke8_io(0x3c8, index);
+
+	/*write color value order by r, g, b*/
+	poke8_io(0x3c9, red);
+	poke8_io(0x3c9, green);
+	poke8_io(0x3c9, blue);
+	LEAVE(ret);
+}
+
+int hw_sm712_setBLANK(struct lynxfb_output *output, int blank)
+{
+	ENTER();
+
+	switch (blank) {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
+	case FB_BLANK_UNBLANK:
+#else
+	case VESA_NO_BLANKING:
+#endif
+			if (output->paths & 1) {
+				/* HPVP */
+				poke_fpr(0x22, peek_fpr(0x22) & 0xcf);
+				/* experiment found fpr31 bit 2 did not affect
+				 * CRT display
+				 * */
+				poke_fpr(0x31, peek_fpr(0x31)|2);
+			}
+
+			if (output->paths & 2) {
+				/* unblank for LCD head */
+				poke_fpr(0x31, peek_fpr(0x31)|1);
+			}
+			break;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
+	case FB_BLANK_NORMAL:
+			if (output->paths & 1) {
+				poke_fpr(0x22, peek_fpr(0x22) & 0xcf);
+				poke_fpr(0x31, peek_fpr(0x31) & ~2);
+			}
+
+			if (output->paths & 2) {
+				/* blank for LCD head */
+				poke_fpr(0x31, peek_fpr(0x31)&~1);
+			}
+			break;
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
+	case FB_BLANK_VSYNC_SUSPEND:
+#else
+	case VESA_VSYNC_SUSPEND:
+#endif
+			if (output->paths & 1) {
+				poke_fpr(0x22, (peek_fpr(0x22)&0xcf)|0x20);
+				poke_fpr(0x31, peek_fpr(0x31) & ~2);
+			}
+			if (output->paths & 2) {
+				poke_fpr(0x31, peek_fpr(0x31)&~1);
+			}
+			break;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
+	case FB_BLANK_HSYNC_SUSPEND:
+#else
+	case VESA_HSYNC_SUSPEND:
+#endif
+			if (output->paths & 1) {
+				poke_fpr(0x22, (peek_fpr(0x22)&0xcf)|0x10);
+				poke_fpr(0x31, peek_fpr(0x31) & ~2);
+			}
+			if (output->paths & 2) {
+				poke_fpr(0x31, peek_fpr(0x31)&~1);
+			}
+			break;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
+	case FB_BLANK_POWERDOWN:
+#else
+	case VESA_POWERDOWN:
+#endif
+			if (output->paths & 1) {
+				poke_fpr(0x22, (peek_fpr(0x22)&0xcf)|0x30);
+				poke_fpr(0x31, peek_fpr(0x31) & ~2);
+			}
+			if (output->paths & 2) {
+				poke_fpr(0x31, peek_fpr(0x31)&~1);
+			}
+			break;
+	}
+	LEAVE(0);
+}
+
+int hw_sm712_deWait()
+{
+	unsigned int loop = 0x100000;
+	/* wait queue , assume PCIRetry is not enabled */
+	while (loop--) {
+		/* see if fifo empty and engine idle */
+		if ((peek_scr(0x16) & 0x08) == 0 &&
+			(peek_scr(0x16) & 0x10) != 0)
+			break;
+	}
+	return !loop;
+}
+
+void hw_sm712_initAccel(struct lynx_accel *accel, int devid)
+{
+	u8 reg;
+	ENTER();
+	/* enable drawing engine */
+	poke_scr(0x21, peek_scr(0x21)&0xf8);
+
+	if (devid == 0x712) {
+	/*by ilena, for bug: system hang
+	 after repeatly unload and load driver on sm722*/
+	/* reset drawing engine */
+		reg = peek_scr(0x15);
+		poke_scr(0x15, reg|0x30);
+		poke_scr(0x15, reg);
+	}
+
+	/* init de register */
+	accel->de_init(accel);
+	LEAVE();
+}
+
+void hw_sm712_crtc_clear(struct lynxfb_crtc *crtc)
+{
+	ENTER();
+	LEAVE();
+}
+
+void hw_sm712_output_clear(struct lynxfb_output *output)
+{
+
+	ENTER();
+	LEAVE();
+}
diff --git a/drivers/video/lynxfb/lynx_hw712.h b/drivers/video/lynxfb/lynx_hw712.h
new file mode 100644
index 0000000..b09c323
--- /dev/null
+++ b/drivers/video/lynxfb/lynx_hw712.h
@@ -0,0 +1,53 @@
+/*******************************************************************
+*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_HW712_H__
+#define LYNX_HW712_H__
+#include "ddk712/ddk712_chip.h"
+
+struct sm712_share{
+	struct lynx_share share;
+	/*
+	 * 0: no hw cursor for crt channel
+	 * not 0: enable hw cursor for crt channel
+	 * */
+	int hwc;
+	unsigned int mclk;/*memory clock*/
+	/* below lcd color stuffs need display.h of 712 ddk*/
+	enum LCD_TYPE lcd;
+	struct {
+	enum TFT_COLOR tftColor;
+	enum DSTN_COLOR dstnColor;
+	} lcd_color;
+};
+
+resource_size_t hw_sm712_getVMSize(struct lynx_share *share);
+int hw_sm712_map(struct lynx_share *share, struct pci_dev *pdev);
+int hw_sm712_inithw(struct lynx_share *, struct pci_dev *);
+int hw_sm712_output_checkMode(struct lynxfb_output *, struct fb_var_screeninfo *);
+int hw_sm712_output_setMode(struct lynxfb_output *, struct fb_var_screeninfo *, struct fb_fix_screeninfo *);
+int hw_sm712_crtc_checkMode(struct lynxfb_crtc *, struct fb_var_screeninfo *);
+int hw_sm712_crtc_setMode(struct lynxfb_crtc *, struct fb_var_screeninfo *, struct fb_fix_screeninfo *);
+int hw_sm712_setColReg(struct lynxfb_crtc *, ushort, ushort, ushort, ushort);
+int hw_sm712_setBLANK(struct lynxfb_output *, int);
+void hw_sm712_initAccel(struct lynx_accel *, int devid);
+void hw_sm712_crtc_clear(struct lynxfb_crtc *);
+void hw_sm712_output_clear(struct lynxfb_output *);
+int hw_sm712_deWait(void);
+
+#endif
diff --git a/drivers/video/lynxfb/lynx_hw750.c b/drivers/video/lynxfb/lynx_hw750.c
new file mode 100644
index 0000000..73939dd
--- /dev/null
+++ b/drivers/video/lynxfb/lynx_hw750.c
@@ -0,0 +1,636 @@
+/*******************************************************************
+*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/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 0
+	ddk750_initDVIDisp();
+#endif
+
+	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 1
+	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);
+	}
+#endif
+
+	/* 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..7359ca2
--- /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)/Lynx EM(712)/lynx 3DM(720/722) voyager(502/107)"
+/*#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
+
diff --git a/drivers/video/lynxfb/voyager.h b/drivers/video/lynxfb/voyager.h
new file mode 100644
index 0000000..3bb96af
--- /dev/null
+++ b/drivers/video/lynxfb/voyager.h
@@ -0,0 +1,167 @@
+/*******************************************************************
+*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.
+*******************************************************************/
+/* sm50x_reg.h
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 or later as
+ * published by the Free Software Foundation.
+ * Silicon Motion SM50x/SM107 register definitions
+*/
+
+#ifndef VOYAGER_H__
+#define VOYAGER_H__
+
+/* common registers for panel and the crt */
+#define VOYAGER_OFF_DC_H_TOT		(0x000)
+#define VOYAGER_OFF_DC_V_TOT		(0x008)
+#define VOYAGER_OFF_DC_H_SYNC		(0x004)
+#define VOYAGER_OFF_DC_V_SYNC		(0x00C)
+
+
+#define VOYAGER_HWC_EN			(1<<31)
+
+#define VOYAGER_OFF_HWC_ADDR		(0x00)
+#define VOYAGER_OFF_HWC_LOC		(0x04)
+#define VOYAGER_OFF_HWC_COLOR_1_2		(0x08)
+#define VOYAGER_OFF_HWC_COLOR_3		(0x0C)
+
+
+
+/*****************************************************************************\
+ *                            SYSTEM CONFIGURATION                           *
+\*****************************************************************************/
+#define SYSTEM_CTRL                                     0x000000
+#define SYSTEM_CTRL_DPMS_LSB                                30
+#define SYSTEM_CTRL_PCI_BURST_LSB                           29
+#define SYSTEM_CTRL_DPMS                                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_DE_ABORT_LSB                        12
+#define SYSTEM_CTRL_DE_FIFO_LSB                         20
+#define SYSTEM_CTRL_DE_FIFO_NOT_EMPTY                   0
+#define SYSTEM_CTRL_DE_FIFO_EMPTY                       1
+#define SYSTEM_CTRL_DE_STATUS_LSB                       19
+#define SYSTEM_CTRL_DE_STATUS_IDLE                      0
+#define SYSTEM_CTRL_DE_STATUS_BUSY                      1
+
+#define MISC_CTRL                                       0x000004
+#define MISC_CTRL_DAC_POWER_LSB                            12
+#define DRAM_CTRL                                       0x000010
+#define DRAM_CTRL_CPU_BANKS_LSB                             19
+#define DRAM_CTRL_SIZE_LSB                                  13
+#define DRAM_CTRL_SIZE_BIT                                  7
+
+#define CMD_INTPR_STATUS                                0x000024
+#define CMD_INTPR_STATUS_PANEL_SYNC_INACTIVE            0
+#define CMD_INTPR_STATUS_PANEL_SYNC_ACTIVE              1
+#define CMD_INTPR_STATUS_PANEL_SYNC_LSB					11
+#define CURRENT_POWER_GATE                              0x000038
+#define CURRENT_POWER_GATE_2D_LSB                           3
+
+#define CURRENT_POWER_CLOCK                             0x00003C
+#define CURRENT_POWER_CLOCK_DIS2XP_LSB                  31
+#define CURRENT_POWER_CLOCK_P2XCLK_DIS_LSB              31
+#define CURRENT_POWER_CLOCK_SEL_LSB                     30
+#define CURRENT_POWER_CLOCK_P2XCLK_SELECT_LSB           29
+#define CURRENT_POWER_CLOCK_P2XCLK_DIVIDER_LSB          27
+#define CURRENT_POWER_CLOCK_P2XCLK_SHIFT_LSB           24
+
+#define CURRENT_POWER_CLOCK_V2XCLK_DIS_LSB              21
+#define CURRENT_POWER_CLOCK_V2XCLK_SELECT_LSB           20
+#define CURRENT_POWER_CLOCK_V2XCLK_DIVIDER_LSB          19
+#define CURRENT_POWER_CLOCK_V2XCLK_SHIFT_LSB            16
+#define CURRENT_POWER_CLOCK_MCLK_SELECT_LSB             12
+#define CURRENT_POWER_CLOCK_MCLK_DIVIDER_LSB            11
+#define CURRENT_POWER_CLOCK_MCLK_SHIFT_LSB              8
+#define CURRENT_POWER_CLOCK_M2XCLK_SELECT_LSB           4
+#define CURRENT_POWER_CLOCK_M2XCLK_DIVIDER_LSB          3
+#define CURRENT_POWER_CLOCK_M2XCLK_SHIFT_LSB            0
+#define POWER_MODE_CTRL                                 0x000054
+#define POWER_MODE0_GATE                                0x000040
+#define POWER_MODE1_GATE                                0x000048
+#define POWER_MODE0_CLOCK                               0x000044
+#define PROGRAMMABLE_PLL_CONTROL                        0x000074
+#define PROGRAMMABLE_PLL_CONTROL_TSTOE_LSB                  20
+#define PROGRAMMABLE_PLL_CONTROL_PON_LSB                    17
+#define PROGRAMMABLE_PLL_CONTROL_SEL_LSB                    16
+#define PROGRAMMABLE_PLL_CONTROL_K_LSB                      15
+#define PROGRAMMABLE_PLL_CONTROL_N_LSB                      8
+#define PROGRAMMABLE_PLL_CONTROL_M_LSB                      0
+/* Panel Graphics Control*/
+#define PANEL_DISPLAY_CTRL                              	0x080000
+#define PANEL_DISPLAY_CTRL_FPEN_LSB                         27
+#define PANEL_DISPLAY_CTRL_VBIASEN_LSB                      26
+#define PANEL_DISPLAY_CTRL_DATA_ENABLE                  1
+#define PANEL_DISPLAY_CTRL_DATA_DISABLE                 0
+#define PANEL_DISPLAY_CTRL_DATA_LSB			                25
+#define PANEL_DISPLAY_CTRL_FPVDDEN_LSB                      24
+#define PANEL_DISPLAY_CTRL_TFT_LSB                          21
+#define PANEL_DISPLAY_CTRL_TIMING_LSB                       8
+#define PANEL_DISPLAY_CTRL_PLANE_LSB                        2
+#define PANEL_DISPLAY_CTRL_FORMAT_LSB                       0
+#define PANEL_PAN_CTRL                                  0x080004
+#define PANEL_FB_ADDRESS                                0x08000C
+#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_BR                                  0x080020
+#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
+/* CRT Graphics Control*/
+#define CRT_DISPLAY_CTRL                                0x080200
+#define CRT_DISPLAY_CTRL_SELECT_LSB                         9
+#define CRT_DISPLAY_CTRL_TIMING_LSB                         8
+#define CRT_DISPLAY_CTRL_PLANE_LSB                          2
+#define CRT_DISPLAY_CTRL_FORMAT_LSB                         0
+
+#define CRT_FB_WIDTH                                    0x080208
+#define CRT_FB_WIDTH_WIDTH_LSB                          16
+#define CRT_DISPLAY_CTRL_BLANK_LSB                      10
+#define CRT_DISPLAY_CTRL_BLANK_ON                       1
+#define CRT_DISPLAY_CTRL_BLANK_OFF                      0
+#define CRT_FB_WIDTH_OFFSET_LSB                         0
+#define CRT_HORIZONTAL_TOTAL                            0x08020C
+#define CRT_FB_ADDRESS                                  0x080204
+#define PANEL_PALETTE_RAM                               0x080400
+#define CRT_PALETTE_RAM                                 0x080C00
+#endif /* _SM50x_H_ */
+
-- 
1.7.5.4


[-- Attachment #3: Type: text/plain, Size: 159 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2012-09-21 15:47 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-08-13  8:56 转发: Siliconmotion new kernel driver initial patch Aaron.Chen  陈俊杰
2012-08-13 18:03 ` Konrad Rzeszutek Wilk
2012-08-13 18:03   ` Konrad Rzeszutek Wilk
2012-08-24  2:35   ` 答复: " Aaron.Chen  陈俊杰
2012-09-21 15:36     ` Konrad Rzeszutek Wilk

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.