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