diff mbox

DaVinci: DM355 AEW driver

Message ID 1249321376-9091-1-git-send-email-s-paulraj@ti.com (mailing list archive)
State RFC
Headers show

Commit Message

s-paulraj@ti.com Aug. 3, 2009, 5:42 p.m. UTC
From: Sandeep Paulraj <s-paulraj@ti.com>

The patch adds support for the DM355 AEW driver

Signed-off-by: Sandeep Paulraj <s-paulraj@ti.com>
---
This patch is dependent on the VPFE patches aubmitted by Murali Karicheri.
Those patches are not yet in the Davinci GIT so this patch will not compile
These patches can be found at
http://arago-project.org/git/people/?p=sneha/linux-davinci-staging.git;a=summary
Test applications for AEW driver can be found at
http://arago-project.org/git/people/?p=murali/linux-davinci-examples.git;a=summary
This AEW driver patch is not meant for upstream submission
 drivers/media/video/Kconfig                |    8 +
 drivers/media/video/davinci/Makefile       |    3 +-
 drivers/media/video/davinci/dm355_aew.c    |  847 ++++++++++++++++++++++++++++
 drivers/media/video/davinci/dm355_aew_hw.c |  139 +++++
 include/media/davinci/dm355_aew.h          |  153 +++++
 include/media/davinci/dm355_aew_hw.h       |  120 ++++
 6 files changed, 1269 insertions(+), 1 deletions(-)
 create mode 100644 drivers/media/video/davinci/dm355_aew.c
 create mode 100644 drivers/media/video/davinci/dm355_aew_hw.c
 create mode 100644 include/media/davinci/dm355_aew.h
 create mode 100644 include/media/davinci/dm355_aew_hw.h
diff mbox

Patch

diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index e772b52..44d61b2 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -514,6 +514,14 @@  config VIDEO_DM355_AF
 	  control loop for Auto Focus. It collects metrics about the image or
 	  video data
 
+config VIDEO_DM355_AEW
+	tristate "DM355 Auto exposure /White Balance Driver"
+	depends on ARCH_DAVINCI_DM355
+	help
+	  DM355 Auto Exposure and Auto White Balance driver is used to support
+	  the control loops for Auto Exposure and Auto White Balance. It collects
+	  metrics about the image or video data
+
 source "drivers/media/video/bt8xx/Kconfig"
 
 config VIDEO_PMS
diff --git a/drivers/media/video/davinci/Makefile b/drivers/media/video/davinci/Makefile
index 17b3ab9..f859345 100644
--- a/drivers/media/video/davinci/Makefile
+++ b/drivers/media/video/davinci/Makefile
@@ -1,3 +1,4 @@ 
 dm355_af_driver-objs		+= dm355_af.o dm355_af_hw.o
 obj-$(CONFIG_VIDEO_DM355_AF)	+= dm355_af_driver.o
-
+dm355_aew_driver-objs		+= dm355_aew.o dm355_aew_hw.o
+obj-$(CONFIG_VIDEO_DM355_AEW)	+= dm355_aew_driver.o
diff --git a/drivers/media/video/davinci/dm355_aew.c b/drivers/media/video/davinci/dm355_aew.c
new file mode 100644
index 0000000..c9d3890
--- /dev/null
+++ b/drivers/media/video/davinci/dm355_aew.c
@@ -0,0 +1,847 @@ 
+/*
+ * Copyright (C) 2009 Texas Instruments Inc
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/cdev.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
+#include <linux/uaccess.h>
+#include <linux/wait.h>
+#include <linux/mutex.h>
+#include <linux/platform_device.h>
+#include <linux/major.h>
+#include <linux/device.h>
+#include <media/davinci/dm355_aew.h>
+#include <media/davinci/dm355_aew_hw.h>
+#include <media/davinci/vpss.h>
+
+static struct class *aew_class;
+struct aew_device *aew_dev_configptr;
+struct device *aewdev;
+static dev_t dev;
+static struct cdev c_dev;
+
+int aew_validate_parameters(void)
+{
+	int result = 0;
+
+	/* Check horizontal Count */
+	if ((aew_dev_configptr->config->window_config.hz_cnt <
+		AEW_WINDOW_HORIZONTAL_COUNT_MIN) ||
+		(aew_dev_configptr->config->window_config.hz_cnt >
+		AEW_WINDOW_HORIZONTAL_COUNT_MAX)) {
+			dev_err(aewdev, "\n Horizontal Count"
+				" is incorrect");
+			result = -EINVAL;
+	}
+
+	/* Check Vertical Count */
+	if ((aew_dev_configptr->config->window_config.vt_cnt <
+		AEW_WINDOW_VERTICAL_COUNT_MIN) ||
+		(aew_dev_configptr->config->window_config.vt_cnt >
+		AEW_WINDOW_VERTICAL_COUNT_MAX)) {
+			dev_err(aewdev, "\n Vertical Count"
+				" is incorrect");
+			result = -EINVAL;
+	}
+
+	/* Check line increment */
+	if ((AEW_NOT_EVEN ==
+		AEW_CHECK_EVEN(aew_dev_configptr->config->window_config.
+		hz_line_incr)) ||
+		(aew_dev_configptr->config->window_config.hz_line_incr <
+		AEW_HZ_LINEINCR_MIN) ||
+		(aew_dev_configptr->config->window_config.hz_line_incr >
+		AEW_HZ_LINEINCR_MAX)) {
+			dev_err(aewdev, "\n Invalid Parameters");
+			dev_err(aewdev, "\n Horizontal Line"
+				" Increment is incorrect");
+			result = -EINVAL;
+	}
+
+	/* Check line increment */
+	if ((AEW_NOT_EVEN ==
+		AEW_CHECK_EVEN(aew_dev_configptr->config->window_config.
+		vt_line_incr)) ||
+		(aew_dev_configptr->config->window_config.vt_line_incr <
+		AEW_VT_LINEINCR_MIN) ||
+		(aew_dev_configptr->config->window_config.vt_line_incr >
+		AEW_VT_LINEINCR_MAX)) {
+			dev_err(aewdev, "\n Invalid Parameters");
+			dev_err(aewdev, "\n Vertical Line"
+				" Increment is incorrect");
+			result = -EINVAL;
+	}
+
+	/* Check width */
+	if ((AEW_NOT_EVEN ==
+		AEW_CHECK_EVEN(aew_dev_configptr->config->window_config.
+		width)) ||
+		(aew_dev_configptr->config->window_config.width <
+		AEW_WIDTH_MIN) ||
+		(aew_dev_configptr->config->window_config.width >
+		AEW_WIDTH_MAX)) {
+			dev_err(aewdev, "\n Width is incorrect");
+
+			result = -EINVAL;
+	}
+
+	/* Check Height */
+	if ((AEW_NOT_EVEN ==
+		AEW_CHECK_EVEN(aew_dev_configptr->config->window_config.
+		height)) || (aew_dev_configptr->config->window_config.height <
+		AEW_HEIGHT_MIN) ||
+		(aew_dev_configptr->config->window_config.height >
+		AEW_HEIGHT_MAX)) {
+			dev_err(aewdev, "\n height incorrect");
+			result = -EINVAL;
+	}
+
+	/* Check Horizontal Start */
+	if ((aew_dev_configptr->config->window_config.hz_start <
+		AEW_HZSTART_MIN) ||
+		(aew_dev_configptr->config->window_config.hz_start >
+		AEW_HZSTART_MAX)) {
+			dev_err(aewdev, "\n horizontal start"
+				" is  incorrect");
+			result = -EINVAL;
+	}
+
+	if ((aew_dev_configptr->config->window_config.vt_start >
+	     AEW_VTSTART_MAX)) {
+		dev_err(aewdev, "\n Vertical start is  incorrect");
+		result = -EINVAL;
+	}
+
+	if ((aew_dev_configptr->config->alaw_enable > H3A_AEW_ENABLE) ||
+		(aew_dev_configptr->config->alaw_enable < H3A_AEW_DISABLE)) {
+		dev_err(aewdev, "\n A Law setting is incorrect");
+		result = -EINVAL;
+	}
+
+	if (aew_dev_configptr->config->saturation_limit > AEW_AVELMT_MAX) {
+		dev_err(aewdev, "\n Saturation Limit is incorrect");
+		result = -EINVAL;
+	}
+
+	/* Check Black Window Height */
+	if (AEW_NOT_EVEN ==
+		AEW_CHECK_EVEN(aew_dev_configptr->config->blackwindow_config.
+		height) ||
+		(aew_dev_configptr->config->blackwindow_config.height <
+		AEW_BLKWINHEIGHT_MIN) ||
+		(aew_dev_configptr->config->blackwindow_config.height >
+		AEW_BLKWINHEIGHT_MAX)) {
+			dev_err(aewdev, "\n Black Window height incorrect");
+			result = -EINVAL;
+	}
+
+	/* Check Black Window Height */
+	if ((AEW_NOT_EVEN ==
+		AEW_CHECK_EVEN(aew_dev_configptr->config->blackwindow_config.
+		height)) ||
+		(aew_dev_configptr->config->blackwindow_config.vt_start <
+		AEW_BLKWINVTSTART_MIN) ||
+		(aew_dev_configptr->config->blackwindow_config.vt_start >
+		AEW_BLKWINVTSTART_MAX)) {
+			dev_err(aewdev, "\n Black Window vertical"
+				" Start is incorrect");
+			result = -EINVAL;
+	}
+
+	if (((aew_dev_configptr->config->window_config.vt_cnt) *
+		(aew_dev_configptr->config->window_config.height) +
+		(aew_dev_configptr->config->window_config.vt_start)) > 156) {
+			dev_err(aewdev, "\n Only 156 Lines are"
+				" supported for CCDC mode");
+			dev_err(aewdev, "\n Vertical count * Height +"
+				" vertical Start should not exceed 156");
+		result = -EINVAL;
+	}
+
+	return result;
+}
+
+/* inline function to free reserver pages */
+inline void aew_free_pages(unsigned long addr, unsigned long bufsize)
+{
+	unsigned long tempaddr;
+	unsigned long size;
+
+	tempaddr = addr;
+	if (!addr)
+		return;
+
+	size = PAGE_SIZE << (get_order(bufsize));
+	while (size > 0) {
+		ClearPageReserved(virt_to_page(addr));
+		addr += PAGE_SIZE;
+		size -= PAGE_SIZE;
+	}
+
+	free_pages(tempaddr, get_order(bufsize));
+}
+
+/* Function to perform hardware Configuration */
+int aew_hardware_setup(void)
+{
+	int result;
+	int buff_size = 0;
+	unsigned long adr;
+	unsigned long size;
+	unsigned int busyaew;
+
+	/* Get the value of PCR register */
+	busyaew = AEW_GET_PCR;
+
+	/* Mask with BUSYAF bit */
+	busyaew = busyaew & AEW_BUSYAEWB;
+
+	/* Shift it 18 times to get value of 1 or 0 */
+	busyaew = busyaew >> AEW_BUSYAEWB_SHIFT;
+
+	/* If H3A Engine is busy then return */
+	if (busyaew == 1) {
+		dev_err(aewdev, "\n Error : AEW Engine is busy");
+		return -EBUSY;
+	}
+
+	result = aew_validate_parameters();
+
+	dev_dbg(aewdev, "Result =  %d\n", result);
+	if (result < 0) {
+		dev_err(aewdev, "Error : Parameters are incorrect \n");
+		return result;
+	}
+
+	/* Deallocate the previously allocated buffers */
+	if (aew_dev_configptr->buff_old)
+		aew_free_pages((unsigned long)aew_dev_configptr->buff_old,
+			aew_dev_configptr->size_window);
+
+	if (aew_dev_configptr->buff_curr)
+		aew_free_pages((unsigned long)aew_dev_configptr->
+			buff_curr, aew_dev_configptr->size_window);
+
+	if (aew_dev_configptr->buff_app)
+		aew_free_pages((unsigned long)aew_dev_configptr->
+			buff_app, aew_dev_configptr->size_window);
+
+	/*
+	 * Allocat the buffers as per the new buffer size
+	 * Allocate memory for old buffer
+	 */
+	buff_size = (aew_dev_configptr->config->window_config.hz_cnt) *
+			(aew_dev_configptr->config->window_config.vt_cnt) *
+			AEW_WINDOW_SIZE;
+
+	aew_dev_configptr->buff_old = (void *)__get_free_pages(GFP_KERNEL |
+					GFP_DMA, get_order(buff_size));
+
+	if (aew_dev_configptr->buff_old == NULL)
+		return -ENOMEM;
+
+	/* Make pages reserved so that they will be swapped out */
+	adr = (unsigned long)aew_dev_configptr->buff_old;
+	size = PAGE_SIZE << (get_order(buff_size));
+
+	while (size > 0) {
+		/*
+		 * Make sure the frame buffers
+		 * are never swapped out of memory
+		 */
+		SetPageReserved(virt_to_page(adr));
+		adr += PAGE_SIZE;
+		size -= PAGE_SIZE;
+	}
+
+	/*Allocate memory for current buffer */
+	aew_dev_configptr->buff_curr = (void *)__get_free_pages(GFP_KERNEL |
+					GFP_DMA, get_order(buff_size));
+
+	if (aew_dev_configptr->buff_curr == NULL) {
+		/* Free all  buffer that are allocated */
+		if (aew_dev_configptr->buff_old)
+			aew_free_pages((unsigned long)aew_dev_configptr->
+					buff_old, buff_size);
+		return -ENOMEM;
+	}
+
+	/* Make pages reserved so that they will be swapped out */
+	adr = (unsigned long)aew_dev_configptr->buff_curr;
+	size = PAGE_SIZE << (get_order(buff_size));
+	while (size > 0) {
+		/*
+		 * Make sure the frame buffers
+		 * are never swapped out of memory
+		 */
+		SetPageReserved(virt_to_page(adr));
+		adr += PAGE_SIZE;
+		size -= PAGE_SIZE;
+	}
+
+	/* Allocate memory for application buffer */
+	aew_dev_configptr->buff_app = (void *)__get_free_pages(GFP_KERNEL |
+					GFP_DMA, get_order(buff_size));
+
+	if (aew_dev_configptr->buff_app == NULL) {
+		/* Free all buffer that were allocated previously */
+		if (aew_dev_configptr->buff_old)
+			aew_free_pages((unsigned long)aew_dev_configptr->
+				       buff_old, buff_size);
+		if (aew_dev_configptr->buff_curr)
+			aew_free_pages((unsigned long)aew_dev_configptr->
+				       buff_curr, buff_size);
+		return -ENOMEM;
+	}
+
+	/* Make pages reserved so that they will be swapped out */
+	adr = (unsigned long)aew_dev_configptr->buff_app;
+	size = PAGE_SIZE << (get_order(buff_size));
+	while (size > 0) {
+		/*
+		 * Make sure the frame buffers
+		 * are never swapped out of memory
+		 */
+		SetPageReserved(virt_to_page(adr));
+		adr += PAGE_SIZE;
+		size -= PAGE_SIZE;
+	}
+
+	/* Set the registers */
+	aew_register_setup(aew_dev_configptr);
+	aew_dev_configptr->size_window = buff_size;
+	aew_dev_configptr->aew_config = H3A_AEW_CONFIG;
+
+	return 0;
+}
+
+static int aew_open(struct inode *inode, struct file *filp)
+{
+	/* Return if Device is in use (Single Channel Support is provided) */
+	if (aew_dev_configptr->in_use == AEW_IN_USE)
+		return -EBUSY;
+
+	/* Set the aew_dev_configptr structure */
+	aew_dev_configptr->config = NULL;
+
+	/* Allocate memory for configuration  structure of this channel */
+	aew_dev_configptr->config = (struct aew_configuration *)
+		kmalloc(sizeof(struct aew_configuration), GFP_KERNEL);
+
+	if (aew_dev_configptr->config == NULL) {
+		dev_err(aewdev, "Error : Kmalloc fail\n");
+		return -ENOMEM;
+	}
+
+	/* Initiaze the wait queue */
+	init_waitqueue_head(&(aew_dev_configptr->aew_wait_queue));
+
+	/* Device is in use */
+	aew_dev_configptr->in_use = AEW_IN_USE;
+
+	/* No Hardware Set up done */
+	aew_dev_configptr->aew_config = H3A_AEW_CONFIG_NOT_DONE;
+
+	/* No statistics are available */
+	aew_dev_configptr->buffer_filled = 0;
+
+	/* Set Window Size to 0 */
+	aew_dev_configptr->size_window = 0;
+
+	/* Initialize the mutex */
+	mutex_init(&(aew_dev_configptr->read_blocked));
+
+	return 0;
+}
+
+static void aew_platform_release(struct device *device)
+{
+	/* This is called when the reference count goes to zero */
+}
+
+static int aew_probe(struct device *device)
+{
+	aewdev = device;
+	return 0;
+}
+
+static int aew_remove(struct device *device)
+{
+	return 0;
+}
+
+/* This Function is called when driver is closed */
+static int aew_release(struct inode *inode, struct file *filp)
+{
+	aew_engine_setup(0);
+
+	/* The Application has closed device so device is not in use */
+	aew_dev_configptr->in_use = AEW_NOT_IN_USE;
+
+	/* Release memory for configuration structure of this channel */
+	kfree(aew_dev_configptr->config);
+
+	/* Free Old Buffer */
+	if (aew_dev_configptr->buff_old)
+		aew_free_pages((unsigned long)aew_dev_configptr->buff_old,
+			aew_dev_configptr->size_window);
+
+	/* Free Current Buffer */
+	if (aew_dev_configptr->buff_curr)
+		aew_free_pages((unsigned long)aew_dev_configptr->
+			buff_curr, aew_dev_configptr->size_window);
+
+	/* Free Application Buffer */
+	if (aew_dev_configptr->buff_app)
+		aew_free_pages((unsigned long)aew_dev_configptr->buff_app,
+			aew_dev_configptr->size_window);
+
+	aew_dev_configptr->buff_old	= NULL;
+	aew_dev_configptr->buff_curr	= NULL;
+	aew_dev_configptr->config	= NULL;
+	aew_dev_configptr->buff_app	= NULL;
+
+	return 0;
+}
+
+/*
+ * This function will process IOCTL commands sent by the application and
+ * control the devices IO operations.
+ */
+static int aew_ioctl(struct inode *inode, struct file *filep,
+		     unsigned int cmd, unsigned long arg)
+{
+	/* Stores Previous Configurations */
+	struct aew_configuration aewconfig = *(aew_dev_configptr->config);
+	int result = 0;
+
+	/* Decrement the mutex */
+	result = mutex_lock_interruptible(&aew_dev_configptr->read_blocked);
+	if (result)
+		return result;
+
+	/*
+	 * Extract the type and number bitfields and
+	 * don't decode wrong cmds
+	 * verify the magic number
+	 */
+	if (_IOC_TYPE(cmd) != AEW_MAGIC_NO) {
+		mutex_unlock(&aew_dev_configptr->read_blocked);
+		return -ENOTTY;
+	}
+
+	/* verify the command number */
+	if (_IOC_NR(cmd) > AEW_IOC_MAXNR) {
+		/* Release mutex in case of fault */
+		mutex_unlock(&aew_dev_configptr->read_blocked);
+		return -ENOTTY;
+	}
+
+	/* check for the permission of the operation */
+	if (_IOC_DIR(cmd) & _IOC_READ)
+		result = !access_ok(VERIFY_WRITE, (void __user *)arg,
+				_IOC_SIZE(cmd));
+	else if (_IOC_DIR(cmd) & _IOC_WRITE)
+		result = !access_ok(VERIFY_READ, (void __user *)arg,
+				_IOC_SIZE(cmd));
+
+	if (result) {
+		/* Release mutex in case of fault */
+		mutex_unlock(&aew_dev_configptr->read_blocked);
+		return -EFAULT;
+	}
+
+	/* Switch according to IOCTL command */
+	switch (cmd) {
+		/*
+		 * This ioctl is used to perform hardware set up
+		 * and will set all the regiseters for AF engine
+		 */
+	case AEW_S_PARAM:
+
+		/* Copy config structure passed by user */
+		if (copy_from_user(aew_dev_configptr->config,
+				   (struct aew_configuration *)arg,
+				   sizeof(struct aew_configuration))) {
+			*(aew_dev_configptr->config) = aewconfig;
+			mutex_unlock(&aew_dev_configptr->read_blocked);
+			return -EFAULT;
+		}
+
+		/* Call aew_hardware_setup to perform register configuration */
+		result = aew_hardware_setup();
+		if (!result) {
+			/*
+			 * Hardware Set up is successful
+			 * Return the no of bytes required for buffer
+			 */
+			result = aew_dev_configptr->size_window;
+		} else {
+			/* Change Configuration Structure to original */
+			*(aew_dev_configptr->config) = aewconfig;
+			dev_err(aewdev, "Error : AEW_S_PARAM  failed\n");
+		}
+
+		break;
+
+		/* This ioctl is used to return parameters in user space */
+	case AEW_G_PARAM:
+		if (aew_dev_configptr->aew_config == H3A_AEW_CONFIG) {
+			if (copy_to_user
+			    ((struct aew_configuration *)arg,
+			     aew_dev_configptr->config,
+			     sizeof(struct aew_configuration))) {
+				mutex_unlock(&aew_dev_configptr->read_blocked);
+				return -EFAULT;
+			} else
+				result = aew_dev_configptr->size_window;
+		} else {
+			dev_err(aewdev,
+				"Error : AEW Hardware is not configured.\n");
+			result = -EINVAL;
+		}
+		break;
+
+		/* This ioctl is used to enable AEW Engine */
+	case AEW_ENABLE:
+		/*Enable AEW Engine if Hardware set up is done */
+		if (aew_dev_configptr->aew_config == H3A_AEW_CONFIG_NOT_DONE) {
+			dev_err(aewdev,
+				"Error : AEW Hardware is not configured.\n");
+			result = -EINVAL;
+		} else
+			/* Enable AF Engine */
+			aew_engine_setup(1);
+		break;
+
+		/* This ioctl is used to disable AEW Engine */
+	case AEW_DISABLE:
+		/* Disable AEW Engine */
+		aew_engine_setup(0);
+		break;
+
+		/* Invalid Command */
+	default:
+		dev_err(aewdev, "Error: It should not come here!!\n");
+		result = -ENOTTY;
+		break;
+	}
+
+	/*Release the mutex */
+	mutex_unlock(&aew_dev_configptr->read_blocked);
+
+	return result;
+}
+
+/* This function will return statistics to user */
+static ssize_t aew_read(struct file *filep, char *kbuff,
+			size_t size, loff_t *offset)
+{
+	void *buffer_temp;
+	int result = 0;
+	int ret;
+
+	/* Mutex will return immediately if read call is busy */
+	ret = mutex_lock_interruptible(&(aew_dev_configptr->read_blocked));
+	if (ret != 0) {
+		dev_dbg(aewdev, "Read Call : busy  : %d\n", ret);
+		return -EBUSY;
+	}
+
+	/* First Check the size given by user */
+	if (size < aew_dev_configptr->size_window) {
+		/*
+		 * Return Failure to applicaiton
+		 * if size is less than required size
+		 */
+		dev_dbg(aewdev, "Error : Invalid size of buffer\n");
+		mutex_unlock(&(aew_dev_configptr->read_blocked));
+		return -1;
+	}
+
+	/*
+	 * The value of buffer_filled flag determines
+	 * the status of statistics
+	 */
+	if (aew_dev_configptr->buffer_filled == 0) {
+		/* Decrement the mutex */
+		dev_dbg(aewdev, "READ CALL IS BLOCKED............\n");
+		/* Block the read call */
+		wait_event_interruptible_timeout(aew_dev_configptr->
+						 aew_wait_queue,
+						 aew_dev_configptr->
+						 buffer_filled, AEW_TIMEOUT);
+		dev_dbg(aewdev, "Read Call is unbloked and waking up.....\n");
+		dev_dbg(aewdev, "Buffer Filled.... %d\n",
+			aew_dev_configptr->buffer_filled);
+	}
+
+	if (aew_dev_configptr->buffer_filled == 1) {
+		/* Disable the interrupts and then swap the buffers */
+		dev_dbg(aewdev, "READING............\n");
+		disable_irq(4);
+
+		/* New Statistics are availaible */
+		aew_dev_configptr->buffer_filled = 0;
+
+		/* Swap application buffer and old buffer */
+		buffer_temp = aew_dev_configptr->buff_old;
+		aew_dev_configptr->buff_old = aew_dev_configptr->buff_app;
+		aew_dev_configptr->buff_app = buffer_temp;
+
+		/* Interrupts are enabled */
+		enable_irq(4);
+
+		/*
+		 * Copy the entire statistics located in application
+		 * buffer to user space
+		 */
+		if (copy_to_user(kbuff, aew_dev_configptr->buff_app,
+				 aew_dev_configptr->size_window)) {
+			dev_err(aewdev, "Error : Read Fault\n");
+			mutex_unlock(&(aew_dev_configptr->read_blocked));
+			return -EFAULT;
+		} else
+			result = aew_dev_configptr->size_window;
+
+		dev_dbg(aewdev, "Reading Done........................\n");
+	}
+
+	dev_dbg(aewdev, "APP BUFF VALUE %x\n",
+		(*((unsigned int *)(aew_dev_configptr->buff_app))));
+
+	/* Increment the mutex */
+	mutex_unlock(&(aew_dev_configptr->read_blocked));
+
+	return result;
+}
+
+/* This function will handle interrupt generated by H3A Engine */
+static irqreturn_t aew_isr(int irq, void *dev_id)
+{
+	/* Busy AF Bit */
+	unsigned int busyaew;
+
+	/* Temporary Buffer for Swapping */
+	void *buffer_temp;
+
+	/* Get the value of PCR register */
+	busyaew = AEW_GET_PCR;
+
+	/* If AEW engine is not enabled, interrupt is not for AEW */
+	if (((busyaew & 0x10000) >> 16) == 0)
+		return IRQ_RETVAL(IRQ_NONE);
+
+	/*
+	 * Interrupt is generated by AEW, so Service the Interrupt
+	 * Swap current buffer and old buffer
+	 */
+	if (aew_dev_configptr) {
+		buffer_temp = aew_dev_configptr->buff_curr;
+		aew_dev_configptr->buff_curr = aew_dev_configptr->buff_old;
+		aew_dev_configptr->buff_old = buffer_temp;
+
+		/* Set the AEWBUFSTAT Register to current buffer Address */
+		aew_set_address((unsigned
+			long)(virt_to_phys(aew_dev_configptr->buff_curr)));
+
+		/*
+		 * Set buffer filled flag to indicate
+		 * statistics are available
+		 */
+		aew_dev_configptr->buffer_filled = 1;
+
+		/*
+		 * New statistics are available
+		 * Wake up the read call
+		 */
+		wake_up(&(aew_dev_configptr->aew_wait_queue));
+
+		return IRQ_RETVAL(IRQ_HANDLED);
+	}
+	return IRQ_RETVAL(IRQ_NONE);
+}
+
+/* File Operation Structure */
+static const struct file_operations aew_fops = {
+	.owner		= THIS_MODULE,
+	.open		= aew_open,
+	.read		= aew_read,
+	.ioctl		= aew_ioctl,
+	.release	= aew_release,
+};
+
+static struct platform_device aewdevice = {
+	.name	= "dm355_aew",
+	.id	= 2,
+	.dev	= {
+		.release = aew_platform_release,
+	}
+};
+
+static struct device_driver aew_driver = {
+	.name	= "dm355_aew",
+	.bus	= &platform_bus_type,
+	.probe	= aew_probe,
+	.remove	= aew_remove,
+};
+
+#define DRIVERNAME  "DM355AEW"
+/* Function to register the AF character device driver */
+int __init aew_init(void)
+{
+	int err;
+	int result = 0;
+	unsigned int vpssclk;
+
+	/*
+	 * Register the driver in the kernel
+	 * dynmically get the major number for
+	 * the driver using alloc_chrdev_region function
+	 */
+	result = alloc_chrdev_region(&dev, 0, 1, DRIVERNAME);
+
+	if (result < 0) {
+		printk(KERN_ERR "Error :  Could not register character device");
+		return -ENODEV;
+	}
+
+	printk(KERN_INFO "aew major#: %d, minor# %d\n", MAJOR(dev), MINOR(dev));
+
+	/* Allocate memory for device structure and initialize it with 0 */
+	aew_dev_configptr = kmalloc(sizeof(struct aew_device), GFP_KERNEL);
+	if (!aew_dev_configptr) {
+		printk(KERN_ERR "Error : kmalloc fail");
+		unregister_chrdev_region(dev, AEW_NR_DEVS);
+		return -ENOMEM;
+	}
+
+	/* Initialize character device */
+	cdev_init(&c_dev, &aew_fops);
+	c_dev.owner = THIS_MODULE;
+	c_dev.ops = &aew_fops;
+
+	err = cdev_add(&c_dev, dev, 1);
+	if (err) {
+		printk(KERN_ERR "Error : Error in  Adding Davinci AEW");
+		unregister_chrdev_region(dev, AEW_NR_DEVS);
+		kfree(aew_dev_configptr);
+		return -err;
+	}
+
+	/* Register driver as a platform driver */
+	if (driver_register(&aew_driver) != 0) {
+		unregister_chrdev_region(dev, 1);
+		cdev_del(&c_dev);
+		return -EINVAL;
+	}
+
+	/* Register the drive as a platform device */
+	if (platform_device_register(&aewdevice) != 0) {
+		driver_unregister(&aew_driver);
+		unregister_chrdev_region(dev, 1);
+		cdev_del(&c_dev);
+		return -EINVAL;
+	}
+
+	aew_class = class_create(THIS_MODULE, "dm355_aew");
+	if (!aew_class) {
+		printk("aew_init: error in creating device class\n");
+		driver_unregister(&aew_driver);
+		platform_device_unregister(&aewdevice);
+		unregister_chrdev_region(dev, 1);
+		unregister_chrdev(MAJOR(dev), DRIVERNAME);
+		cdev_del(&c_dev);
+		return -EINVAL;
+	}
+
+	device_create(aew_class, NULL, dev, NULL, "dm355_aew");
+
+	/* AEW_SELINT(interrupt_no) */
+	AEW_SETGAMMAWD;
+	vpssclk = AEW_GETCLKCTRL;
+	vpssclk |= (1 << 4);
+	AEW_SETCLKCTRL(vpssclk);
+	/* Set up the Interrupt handler for H3AINT interrupt */
+	result = request_irq(4, aew_isr, IRQF_SHARED, "dm355h3a_aew",
+				(void *)aew_dev_configptr);
+
+	if (result != 0) {
+		printk(KERN_ERR "Error : Request IRQ Failed");
+		unregister_chrdev_region(dev, AEW_NR_DEVS);
+		device_destroy(aew_class, dev);
+		class_destroy(aew_class);
+		kfree(aew_dev_configptr);
+		driver_unregister(&aew_driver);
+		platform_device_unregister(&aewdevice);
+		cdev_del(&c_dev);
+		return result;
+	}
+
+	/* Initialize device structure */
+	memset(aew_dev_configptr, 0, sizeof(struct aew_device));
+
+	aew_dev_configptr->in_use = AEW_NOT_IN_USE;
+	aew_dev_configptr->buffer_filled = 0;
+
+	return 0;
+}
+
+/*
+ * This Function is called by the kernel while unloading the driver
+ * This will unregister the Character Device Driver
+ */
+void __exit aew_cleanup(void)
+{
+	/* Device is in use */
+	if (aew_dev_configptr->in_use == AEW_IN_USE) {
+		printk("Error : Driver in use");
+		return;
+	}
+
+	free_irq(4, aew_dev_configptr);
+
+	/* Free device structure */
+	kfree(aew_dev_configptr);
+
+	aew_dev_configptr = NULL;
+	unregister_chrdev_region(dev, AEW_NR_DEVS);
+
+	driver_unregister(&aew_driver);
+
+	device_destroy(aew_class, dev);
+
+	class_destroy(aew_class);
+
+	platform_device_unregister(&aewdevice);
+
+	cdev_del(&c_dev);
+
+	/* Unregistering the driver from the kernel */
+	unregister_chrdev(MAJOR(dev), DEVICE_NAME);
+}
+
+module_init(aew_init)
+module_exit(aew_cleanup)
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/davinci/dm355_aew_hw.c b/drivers/media/video/davinci/dm355_aew_hw.c
new file mode 100644
index 0000000..7208cf1
--- /dev/null
+++ b/drivers/media/video/davinci/dm355_aew_hw.c
@@ -0,0 +1,139 @@ 
+/*
+ * Copyright (C) 2009 Texas Instruments Inc
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <media/davinci/dm355_aew.h>
+#include <media/davinci/dm355_aew_hw.h>
+#include <linux/device.h>
+
+int aew_register_setup(struct aew_device *aew_dev)
+{
+	unsigned int pcr = 0, win1 = 0, winstart = 0, blkwin = 0, subwin = 0;
+
+	/* Set up the registers */
+	pcr = regr(AEWPCR);
+
+	/* Enable A Law */
+	if (aew_dev->config->alaw_enable == H3A_AEW_ENABLE)
+		pcr |= AEW_ALAW_EN;
+	else
+		pcr &= ~AEW_ALAW_EN;
+
+	/*Configure Saturation limit */
+	pcr &= ~AVE2LMT;
+	pcr |= aew_dev->config->saturation_limit << AEW_AVE2LMT_SHIFT;
+
+	/* Set Input Source */
+	pcr &= ~AEW_INP_SRC;
+	pcr |= (AEW_CCDC) << AEW_INP_SRC_SHIFT;
+
+	regw(pcr, AEWPCR);
+
+	/* Configure Window Width in AEWWIN1 register */
+	win1 = 0;
+	win1 |= ((AEW_SET_VAL(aew_dev->config->window_config.height)) <<
+		AEW_WINH_SHIFT);
+
+	/* Configure Window height in AEWWIN1 register */
+	win1 |= ((AEW_SET_VAL(aew_dev->config->window_config.width)) <<
+		AEW_WINW_SHIFT);
+
+	/* Configure Window vertical count in AEWWIN2 register */
+	win1 |= ((aew_dev->config->window_config).vt_cnt - 1) <<
+		AEW_VT_COUNT_SHIFT;
+
+	/* Configure Window horizontal count in AEWWIN1 register */
+	win1 |= ((aew_dev->config->window_config).hz_cnt - 1);
+
+	/* Configure Window vertical start in AEWWIN1 register */
+	regw(win1, AEWWIN1);
+
+	/* Window Start parameter configuration */
+	winstart &= ~WINSV;
+	winstart |= (aew_dev->config->window_config).vt_start <<
+			AEW_VT_START_SHIFT;
+
+	/* Configure Window horizontal start  in AEWWIN2 register */
+	winstart &= ~WINSH;
+	winstart |= (aew_dev->config->window_config).hz_start;
+	regw(winstart, AEWINSTART);
+
+	/*
+	 * Window Line Increment configuration
+	 * Configure vertical line increment in AEWSUBWIN
+	 */
+	subwin &= ~AEWINCV;
+	subwin |= (AEW_SET_VAL(aew_dev->config->window_config.
+			 vt_line_incr) << AEW_LINE_INCR_SHIFT);
+
+	/* Configuring Horizontal Line increment in AEWSUBWIN */
+	subwin &= ~AEWINCH;
+	subwin |= (AEW_SET_VAL(aew_dev->config->window_config.hz_line_incr));
+
+	regw(subwin, AEWSUBWIN);
+
+	/*
+	 * Black Window Configuration
+	 * Configure vertical start and height in AEWWINBLK
+	 */
+	blkwin &= ~BLKWINSV;
+	blkwin |= (aew_dev->config->blackwindow_config).
+			vt_start << AEW_BLKWIN_VT_START_SHIFT;
+
+	/* Configure height in Black window */
+	blkwin &= ~BLKWINH;
+	blkwin |= (AEW_SET_VAL(aew_dev->config->blackwindow_config.height));
+			regw(blkwin, AEWINBLK);
+
+	/* Set AFBUFST to Current buffer Physical Address */
+	regw((unsigned int)(virt_to_phys(aew_dev->buff_curr)), AEWBUFST);
+	dev_dbg(aewdev, "\n PCR is %x", regr(AEWPCR));
+	dev_dbg(aewdev, "\n SUBWIN is %x", regr(AEWSUBWIN));
+	dev_dbg(aewdev, "\n WINSTART is %x", regr(AEWINSTART));
+	dev_dbg(aewdev, "\n WINBLK is %x", regr(AEWINBLK));
+	dev_dbg(aewdev, "\n WIN1  is %x", regr(AEWWIN1));
+	dev_dbg(aewdev, "\n AEWBUST %x", regr(AEWBUFST));
+
+	AEW_SETGAMMAWD;
+
+	return 0;
+}
+
+/* Function to enable/ disable AEW Engine */
+inline void aew_engine_setup(int value)
+{
+	unsigned int pcr;
+
+	dev_dbg(aewdev, "\nAEW_REG(PCR) Before Setting %x", regr(AEWPCR));
+
+	/* Read Pcr Register */
+	pcr = regr(AEWPCR);
+	pcr &= ~AEW_EN;
+	pcr |= (value << AEW_EN_SHIFT);
+
+	/*Set AF_EN bit in PCR Register */
+	regw(pcr, AEWPCR);
+
+	dev_dbg(aewdev, "\nAfter Setting %d : PCR VALUE %x", value,
+		regr(AEWPCR));
+}
+
+/* Function used to set adddress */
+inline void aew_set_address(unsigned long address)
+{
+	regw(address, AEWBUFST);
+}
diff --git a/include/media/davinci/dm355_aew.h b/include/media/davinci/dm355_aew.h
new file mode 100644
index 0000000..1c65285
--- /dev/null
+++ b/include/media/davinci/dm355_aew.h
@@ -0,0 +1,153 @@ 
+/*
+ * Copyright (C) 2009 Texas Instruments Inc
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef DM355_AEW_DRIVER_H
+#define DM355_AEW_DRIVER_H
+
+#include <linux/ioctl.h>
+
+#ifdef __KERNEL__
+#include <linux/kernel.h>
+#include <linux/wait.h>
+#include <linux/semaphore.h>
+#include <linux/mutex.h>
+#include <linux/io.h>
+#include <linux/fcntl.h>
+#endif
+
+/* Driver Range Constants*/
+#define AEW_WINDOW_VERTICAL_COUNT_MIN		1
+#define AEW_WINDOW_VERTICAL_COUNT_MAX		128
+#define AEW_WINDOW_HORIZONTAL_COUNT_MIN		2
+#define AEW_WINDOW_HORIZONTAL_COUNT_MAX		36
+#define AEW_WINDOW_SIZE				18
+#define AEW_WIDTH_MIN				8
+#define AEW_WIDTH_MAX				256
+#define AEW_AVELMT_MAX				1023
+#define AEW_HZ_LINEINCR_MIN			2
+#define AEW_HZ_LINEINCR_MAX			32
+#define AEW_VT_LINEINCR_MIN			2
+#define AEW_VT_LINEINCR_MAX			32
+#define AEW_HEIGHT_MIN				2
+#define AEW_HEIGHT_MAX				256
+#define AEW_HZSTART_MIN				0
+#define AEW_HZSTART_MAX				4095
+#define AEW_VTSTART_MIN				0
+#define AEW_VTSTART_MAX				4095
+#define AEW_BLKWINHEIGHT_MIN			2
+#define AEW_BLKWINHEIGHT_MAX			256
+#define AEW_BLKWINVTSTART_MIN			0
+#define AEW_BLKWINVTSTART_MAX			4095
+
+#ifdef __KERNEL__
+
+/* Device Constants*/
+#define AEW_NR_DEVS		1
+#define DEVICE_NAME		"dm355_aew"
+#define AEW_MAJOR_NUMBER	0
+#define AEW_IOC_MAXNR		4
+#define AEW_TIMEOUT		(300 * HZ / 1000)
+#endif
+
+/* List of ioctls */
+#pragma pack(1)
+#define AEW_MAGIC_NO    'e'
+#define AEW_S_PARAM	_IOWR(AEW_MAGIC_NO , 1 , struct aew_configuration *)
+#define AEW_G_PARAM	_IOWR(AEW_MAGIC_NO , 2 , struct aew_configuration *)
+#define AEW_ENABLE	_IO(AEW_MAGIC_NO , 3)
+#define AEW_DISABLE	_IO(AEW_MAGIC_NO , 4)
+#pragma pack()
+
+/*Enum for device usage*/
+enum aew_In_use {
+	AEW_NOT_IN_USE = 0,	/* Device is not in use */
+	AEW_IN_USE = 1		/* Device in use */
+};
+
+/*Enum for Enable/Disable specific feature*/
+enum aew_alaw_enable {
+	H3A_AEW_ENABLE = 1,
+	H3A_AEW_DISABLE = 0
+};
+
+enum aew_config_flag {
+	H3A_AEW_CONFIG_NOT_DONE,
+	H3A_AEW_CONFIG
+};
+
+/* Contains the information regarding Window Structure in AEW Engine */
+struct aew_window {
+	unsigned int width;		/* Width of the window */
+	unsigned int height;		/* Height of the window */
+	unsigned int hz_start;		/* Horizontal Start of the window */
+	unsigned int vt_start;		/* Vertical Start of the window */
+	unsigned int hz_cnt;		/* Horizontal Count */
+	unsigned int vt_cnt;		/* Vertical Count */
+	unsigned int hz_line_incr;	/* Horizontal Line Increment */
+	unsigned int vt_line_incr;	/* Vertical Line Increment */
+};
+
+/* Contains the information regarding the AEW Black Window Structure*/
+struct aew_black_window {
+	unsigned int height;	/* Height of the Black Window */
+	unsigned int vt_start;	/* Vertical Start of the black Window */
+};
+
+enum _aew_input_src {
+	AEW_CCDC = 0,
+	AEW_SDRAM = 1
+} aew_input_src_t;
+
+/* Contains configuration required for setup of AEW engine*/
+struct aew_configuration {
+	enum aew_alaw_enable alaw_enable;		/* A-law status */
+	int saturation_limit;			/* Saturation Limit */
+	struct aew_window window_config;	/* Window for AEW Engine */
+	struct aew_black_window blackwindow_config;	/* Black Window */
+};
+
+#ifdef __KERNEL__
+/* Contains information about device structure of AEW*/
+struct aew_device {
+	enum aew_In_use in_use;			/* Driver usage flag */
+	struct aew_configuration *config;	/* Device configuration */
+	void *buff_old;			/* Contains latest statistics */
+	void *buff_curr;		/* Buffer in which HW will */
+
+	/*
+	 * Fill the statistics
+	 * or HW is already filling
+	 * statistics
+	 */
+
+	void *buff_app;		/* Buffer which will be passed */
+
+	int buffer_filled;	/* Flag indicates statistics */
+
+	unsigned int size_window;
+	wait_queue_head_t aew_wait_queue;
+	struct mutex read_blocked;
+
+	/* Flag indicates Engine is configured */
+	enum aew_config_flag aew_config;
+};
+
+int aew_hardware_setup(void);
+int aew_validate_parameters(void);
+#endif
+#endif
diff --git a/include/media/davinci/dm355_aew_hw.h b/include/media/davinci/dm355_aew_hw.h
new file mode 100644
index 0000000..2ad2398
--- /dev/null
+++ b/include/media/davinci/dm355_aew_hw.h
@@ -0,0 +1,120 @@ 
+/*
+ * Copyright (C) 2009 Texas Instruments Inc
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef DM355_AEW_DRIVER_HW_H
+#define DM355_AEW_DRIVER_HW_H
+
+/* Include Files */
+#include <mach/hardware.h>
+
+#ifdef __KERNEL__
+
+/* Register Offsets */
+#define AEWPID		0x00000000	/*Peripheral Revision */
+#define AEWPCR		0x00000004	/*Peripheral Control Register */
+#define AEWWIN1		0x0000004c	/*Configuration for AE/AWB Windows */
+#define AEWINSTART	0x00000050	/*Start position for AE/AWB Windows */
+
+/* Start position and height for black line of AE/AWB Windows */
+#define AEWINBLK	0x00000054
+
+/* Configuration for subsampled data in AE/AWB windows */
+#define AEWSUBWIN       0x00000058
+
+/* SDRAM/DDRAM Start address for AEW Engine */
+#define AEWBUFST	0x0000005c
+
+#define AEW_RSDR_ADDR	0x00000060	/*SDRAM/DDRAM Read Address */
+#define AEW_RSDR_OFFSET	0x00000064	/*SDRAM/DDRAM Line Offset */
+#define AEW_SDR_FRSIZE	0x00000068	/*Frame Size for SDRAM read data */
+
+/* PID fields */
+#define AEW_TID		(0xFF << 16)
+#define AEW_CID		(0xFF << 8)
+#define AEW_PREV	0xFF
+
+/* PCR FIELDS */
+#define AVE2LMT			(0x3ff << 22)	/* Saturation Limit */
+#define AEW_SDR_FETCH_ENABLE	(1 << 21)
+#define AEW_INP_WIDTH		(1 << 20)
+#define AEW_INP_SRC		(1 << 19)
+#define AEW_ALAW_EN		(1 << 17)	/* Alaw Enable/Disable Bit */
+#define AEW_BUSYAF		(1 << 15)	/* Busy Bit for AF */
+#define AEW_BUSYAEWB		(1 << 18)	/* Busy bit for AEW */
+#define AEW_EN			(1 << 16)	/* AEW Engine Enable/Disable */
+
+/* AEWWIN1 fields */
+#define WINH			(0x7F << 24)	/* Window Height */
+#define WINW			(0x7f << 13)	/* Window Width */
+#define WINVC			(0x7f << 6)	/* Window vertical Count */
+#define WINHC			0x3f		/* Window Horizontal Count */
+
+/* AEWWINSTART fields */
+#define WINSV			(0xfff << 16)	/* Window Vertical Start */
+#define WINSH			0xfff		/* Window Horizontal start */
+
+/* AEWWINBLK fields */
+#define BLKWINSV		(0xfff << 16)	/* Black Window Start */
+#define BLKWINH			0x7f		/* Black Window height */
+
+/* AEWSUBWIN fields */
+#define AEWINCV             	(0xf << 8)	/* Vertical Lime Increment */
+#define AEWINCH			0xf		/*Horizontal Line Increment */
+
+/* BIT POSITIONS */
+#define AEW_AVE2LMT_SHIFT		22
+#define AEW_WINH_SHIFT			24
+#define AEW_WINW_SHIFT			13
+#define AEW_VT_COUNT_SHIFT		6
+#define AEW_VT_START_SHIFT		16
+#define AEW_LINE_INCR_SHIFT		8
+#define AEW_BLKWIN_VT_START_SHIFT	16
+#define AEW_EN_SHIFT			16
+#define AEW_BUSYAEWB_SHIFT		18
+#define AEW_INP_SRC_SHIFT		19
+#define AEW_SET_VAL(x)			(((x) / 2) - 1)
+#define AEW_NOT_EVEN			1
+#define AEW_CHECK_EVEN(x)		((x) % 2)
+
+#define AEW_CCDC		0
+#define AEW_INTSTATBASE		(IO_ADDRESS(0x01C7080C))
+#define AEW_EVNTSELADDR		(IO_ADDRESS(0x01C70814))
+#define AEW_GETINTSTAT		__raw_readl(AEW_INTSTATBASE)
+#define AEW_SETGAMMAWD		__raw_writel(0x00000010 ,\
+					IO_ADDRESS(0x01C70680))
+#define	AEW_CLKCTRL_ADDR	(IO_ADDRESS(0x01C70004))
+#define AEW_GETCLKCTRL		__raw_readl(AEW_CLKCTRL_ADDR)
+#define AEW_SETCLKCTRL(val)	__raw_writel(val , AEW_CLKCTRL_ADDR)
+#define AEW_IOBASE_VADDR 	(IO_ADDRESS(0x01c70080))
+
+#define regw(val, reg)		__raw_writel(val , (reg + AEW_IOBASE_VADDR))
+#define regr(reg)		__raw_readl(reg + AEW_IOBASE_VADDR)
+#define AEW_GETEVNT		__raw_readl(AEW_EVNTSELADDR)
+#define AEW_GET_PCR		__raw_readl(AEW_IOBASE_VADDR + AEWPCR);
+
+#define isbusy()			(regr(AEWPCR) & 0x40000)
+
+extern struct device *aewdev;
+
+/* Function Declaration */
+int aew_register_setup(struct aew_device *);
+void aew_engine_setup(int);
+void aew_set_address(unsigned long);
+
+#endif
+#endif