@@ -505,6 +505,15 @@ config VIDEO_VIVI
Say Y here if you want to test video apps or debug V4L devices.
In doubt, say N.
+config VIDEO_DM355_AF
+ tristate "DM355 Auto Focus Driver"
+ depends on ARCH_DAVINCI_DM355
+ default y
+ help
+ DM355 Auto Focus Driver. Auto Focus driver is used to support
+ control loop for Auto Focus. It collects metrics about the image or
+ video data
+
source "drivers/media/video/bt8xx/Kconfig"
config VIDEO_PMS
new file mode 100644
@@ -0,0 +1,3 @@
+dm355_af_driver-objs += dm355_af.o dm355_af_hw.o
+obj-$(CONFIG_VIDEO_DM355_AF) += dm355_af_driver.o
+
new file mode 100644
@@ -0,0 +1,849 @@
+/*
+ * 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/platform_device.h>
+#include <linux/major.h>
+#include <linux/device.h>
+#include <media/davinci/dm355_af.h>
+#include <media/davinci/dm355_af_hw.h>
+#include <media/davinci/vpss.h>
+
+struct af_device *af_dev_configptr;
+static struct cdev c_dev;
+static struct class *af_class;
+static dev_t dev;
+struct device *afdev;
+
+/* Inline function to free reserver pages */
+inline void af_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 check paxel parameters */
+static int af_validate_parameters(void)
+{
+ int result = 0;
+
+ /* Check horizontal Count */
+ if ((af_dev_configptr->config->paxel_config.hz_cnt <
+ AF_PAXEL_HORIZONTAL_COUNT_MIN) ||
+ (af_dev_configptr->config->paxel_config.hz_cnt >
+ AF_PAXEL_HORIZONTAL_COUNT_MAX)) {
+ dev_err(afdev, "\n Invalid Parameters");
+ dev_err(afdev, "\n Paxel Horizontal Count"
+ " is incorrect");
+ result = -EINVAL;
+ }
+
+ /* Check Vertical Count */
+ if ((af_dev_configptr->config->paxel_config.vt_cnt <
+ AF_PAXEL_VERTICAL_COUNT_MIN) ||
+ (af_dev_configptr->config->paxel_config.vt_cnt >
+ AF_PAXEL_VERTICAL_COUNT_MAX)) {
+ dev_err(afdev, "\n Invalid Parameters");
+ dev_err(afdev, "\n Paxel Vertical Count"
+ " is incorrect");
+ result = -EINVAL;
+ }
+
+ /* Check line increment */
+ if ((AF_NOT_EVEN ==
+ AF_CHECK_EVEN(
+ af_dev_configptr->config->paxel_config.line_incr)) ||
+ (af_dev_configptr->config->paxel_config.line_incr <
+ AF_LINE_INCR_MIN) ||
+ (af_dev_configptr->config->paxel_config.line_incr >
+ AF_LINE_INCR_MAX)) {
+ dev_err(afdev, "\n Invalid Parameters");
+ dev_err(afdev, "\n Paxel Line Increment"
+ " is incorrect");
+ result = -EINVAL;
+ }
+
+ /* Check width */
+ if ((AF_NOT_EVEN ==
+ AF_CHECK_EVEN(
+ af_dev_configptr->config->paxel_config.width)) ||
+ (af_dev_configptr->config->paxel_config.width <
+ AF_WIDTH_MIN) ||
+ (af_dev_configptr->config->paxel_config.width >
+ AF_WIDTH_MAX)) {
+ dev_err(afdev, "\n Invalid Parameters");
+ dev_err(afdev, "\n Paxel Width is incorrect");
+ result = -EINVAL;
+ }
+
+ /* Check Height */
+ if ((AF_NOT_EVEN ==
+ AF_CHECK_EVEN(
+ af_dev_configptr->config->paxel_config.height)) ||
+ (af_dev_configptr->config->paxel_config.height <
+ AF_HEIGHT_MIN) ||
+ (af_dev_configptr->config->paxel_config.height >
+ AF_HEIGHT_MAX)) {
+ dev_err(afdev, "\n Invalid Parameters");
+ dev_err(afdev, "\n Paxel Height is incorrect");
+ result = -EINVAL;
+ }
+
+ /* Check Horizontal Start */
+ if ((AF_NOT_EVEN ==
+ AF_CHECK_EVEN(
+ af_dev_configptr->config->paxel_config.hz_start)) ||
+ (af_dev_configptr->config->paxel_config.hz_start <
+ (af_dev_configptr->config->iir_config.hz_start_pos + 2)) ||
+ (af_dev_configptr->config->paxel_config.hz_start <
+ AF_HZSTART_MIN) ||
+ (af_dev_configptr->config->paxel_config.hz_start >
+ AF_HZSTART_MAX)) {
+ dev_err(afdev, "\n Invalid Parameters");
+ dev_err(afdev, "\n Paxel horizontal start"
+ "is incorrect");
+ result = -EINVAL;
+ }
+
+ /* Check Vertical Start */
+ if ((af_dev_configptr->config->paxel_config.vt_start <
+ AF_VTSTART_MIN) ||
+ (af_dev_configptr->config->paxel_config.vt_start >
+ AF_VTSTART_MAX)) {
+ dev_err(afdev, "\n Invalid Parameters");
+ dev_err(afdev, "\n Paxel vertical start is incorrect");
+ result = -EINVAL;
+ }
+
+ /* Check Threshold */
+ if ((af_dev_configptr->config->hmf_config.threshold >
+ AF_MEDTH_MAX) &&
+ (af_dev_configptr->config->hmf_config.enable ==
+ H3A_AF_ENABLE)) {
+ dev_err(afdev, "\n Invalid Parameters");
+ dev_err(afdev, "\n Horizontal Median Filter"
+ " Threshold is incorrect");
+ result = -EINVAL;
+ }
+
+ /* Check IIRSH start */
+ if (af_dev_configptr->config->iir_config.hz_start_pos >
+ AF_IIRSH_MAX) {
+ dev_err(afdev, "\n Invalid Parameters");
+ dev_err(afdev, "\n IIR FITLER horizontal"
+ " start position is wrong");
+ result = -EINVAL;
+ }
+
+ /* Verify ALaw */
+ if ((af_dev_configptr->config->alaw_enable <
+ H3A_AF_DISABLE) ||
+ (af_dev_configptr->config->alaw_enable > H3A_AF_ENABLE)) {
+ dev_err(afdev, "\n Invalid Parameters");
+ dev_err(afdev, "\n ALaw Setting is incorrect");
+ result = -EINVAL;
+ }
+
+ /* Check RGB position */
+ if ((af_dev_configptr->config->rgb_pos < GR_GB_BAYER) ||
+ (af_dev_configptr->config->rgb_pos > RB_GG_CUSTOM)) {
+ dev_err(afdev, "\n Invalid Parameters");
+ dev_err(afdev, "\n RGB Position Setting is incorrect");
+ result = -EINVAL;
+ }
+
+ /* Verify Horizontal Median Filter Setting */
+ if ((af_dev_configptr->config->hmf_config.enable < H3A_AF_DISABLE) ||
+ (af_dev_configptr->config->hmf_config.enable >
+ H3A_AF_ENABLE)) {
+ dev_err(afdev, "\n Invalid Parameters");
+ dev_err(afdev, "\n Horizontal Median Filter"
+ " Setting is incorrect");
+ result = -EINVAL;
+ }
+
+ if (((af_dev_configptr->config->paxel_config.vt_cnt) *
+ (af_dev_configptr->config->paxel_config.height) +
+ (af_dev_configptr->config->paxel_config.vt_start)) > 156) {
+ dev_err(afdev, "\n Only 156 Lines are"
+ " supported for CCDC mode");
+ dev_err(afdev, "\n Paxel count * Height"
+ " + vertical Start should not exceed 156");
+ result = -EINVAL;
+ }
+
+ return result;
+}
+
+/* Function to perform hardware set up */
+int af_hardware_setup(void)
+{
+ int result;
+ int buff_size;
+ unsigned long adr, size;
+ unsigned int busyaf;
+
+ /* Get the value of PCR register */
+ busyaf = AF_GET_PCR;
+
+ /* Mask with BUSYAF bit */
+ busyaf = busyaf & AF_BUSYAF;
+
+ /* Shift it 15 times to get value of 1 or 0 */
+ busyaf = busyaf >> 15;
+
+ /*If busy bit is 1 then busy lock registers caanot be configured */
+ if (busyaf == 1) {
+ /* Hardware cannot be configure while engine is busy */
+ dev_err(afdev, "AF_register_setup_ERROR : Engine Busy");
+ dev_err(afdev, "\n Configuration cannot be done ");
+ return -EBUSY;
+ }
+
+ /*Check IIR Coefficient and start Values */
+ result = af_validate_parameters();
+
+ if (result < 0)
+ return result;
+
+ /* Compute buffer size */
+ buff_size =
+ (af_dev_configptr->config->paxel_config.hz_cnt) *
+ (af_dev_configptr->config->paxel_config.vt_cnt) * AF_PAXEL_SIZE;
+
+ /* Deallocate the previosu buffers */
+ if (af_dev_configptr->buff_old)
+ af_free_pages((unsigned long)af_dev_configptr->buff_old,
+ af_dev_configptr->size_paxel);
+
+ /* Free current buffer */
+ if (af_dev_configptr->buff_curr)
+ af_free_pages((unsigned long)af_dev_configptr->buff_curr,
+ af_dev_configptr->size_paxel);
+
+ /* Free application buffers */
+ if (af_dev_configptr->buff_app)
+ af_free_pages((unsigned long)af_dev_configptr->buff_app,
+ af_dev_configptr->size_paxel);
+
+ /* Reallocate the buffer as per new paxel configurations */
+ af_dev_configptr->buff_old =
+ (void *)__get_free_pages(GFP_KERNEL | GFP_DMA,
+ get_order(buff_size));
+
+ if (af_dev_configptr->buff_old == NULL)
+ return -ENOMEM;
+
+ /* allocate the memory for storing old statistics */
+ adr = (unsigned long)af_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 */
+ af_dev_configptr->buff_curr =
+ (void *)__get_free_pages(GFP_KERNEL | GFP_DMA,
+ get_order(buff_size));
+
+ /* Free the previously allocated buffer */
+ if (af_dev_configptr->buff_curr == NULL) {
+ if (af_dev_configptr->buff_old)
+ af_free_pages((unsigned long)af_dev_configptr->
+ buff_old, buff_size);
+ return -ENOMEM;
+ }
+
+ adr = (unsigned long)af_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 old buffer */
+ af_dev_configptr->buff_app =
+ (void *)__get_free_pages(GFP_KERNEL | GFP_DMA,
+ get_order(buff_size));
+
+ if (af_dev_configptr->buff_app == NULL) {
+ /*Free the previously allocated buffer */
+ if (af_dev_configptr->buff_curr)
+ af_free_pages((unsigned long)af_dev_configptr->
+ buff_curr, buff_size);
+ /*Free the previously allocated buffer */
+ if (af_dev_configptr->buff_old)
+ af_free_pages((unsigned long)af_dev_configptr->
+ buff_old, buff_size);
+ return -ENOMEM;
+ }
+
+ adr = (unsigned long)af_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;
+ }
+
+ result = af_register_setup(af_dev_configptr);
+ if (result < 0)
+ return result;
+
+ af_dev_configptr->size_paxel = buff_size;
+
+ /*Set configuration flag to indicate HW setup done */
+ af_dev_configptr->af_config = H3A_AF_CONFIG;
+
+ return 0;
+}
+
+/*
+ * This function called when driver is opened.It creates Channel
+ * Configuration Structure
+ */
+static int af_open(struct inode *inode, struct file *filp)
+{
+ /*Return if device is in use */
+ if (af_dev_configptr->in_use == AF_IN_USE)
+ return -EBUSY;
+ af_dev_configptr->config = NULL;
+
+ /* Allocate memory for Device Structure */
+ af_dev_configptr->config = (struct af_configuration *)
+ kmalloc(sizeof(struct af_configuration), GFP_KERNEL);
+
+ if (af_dev_configptr->config == NULL) {
+ dev_err(afdev, "Error : Kmalloc fail\n");
+ return -ENOMEM;
+ }
+
+ /* Initialize the wait queue */
+ init_waitqueue_head(&(af_dev_configptr->af_wait_queue));
+
+ /* Driver is in use */
+ af_dev_configptr->in_use = AF_IN_USE;
+
+ /* Hardware is not set up */
+ af_dev_configptr->af_config = H3A_AF_CONFIG_NOT_DONE;
+ af_dev_configptr->buffer_filled = 0;
+
+ /* Initialize the mutex */
+ mutex_init(&(af_dev_configptr->read_blocked));
+
+ return 0;
+}
+
+/*
+ * This function called when driver is closed.
+ * It will deallocate all the buffers.
+ */
+static int af_release(struct inode *inode, struct file *filp)
+{
+ af_engine_setup(0);
+
+ /* Free all the buffers */
+ if (af_dev_configptr->buff_curr)
+ af_free_pages((unsigned long)af_dev_configptr->buff_curr,
+ af_dev_configptr->size_paxel);
+
+ /* Free old buffer */
+ if (af_dev_configptr->buff_old)
+ af_free_pages((unsigned long)af_dev_configptr->buff_old,
+ af_dev_configptr->size_paxel);
+
+ /* Free application buffer */
+ if (af_dev_configptr->buff_app)
+ af_free_pages((unsigned long)af_dev_configptr->buff_app,
+ af_dev_configptr->size_paxel);
+
+ /* Release memory for configuration structure of this channel */
+ af_dev_configptr->buff_curr = NULL;
+ af_dev_configptr->buff_old = NULL;
+ af_dev_configptr->buff_app = NULL;
+
+
+ kfree(af_dev_configptr->config);
+
+ af_dev_configptr->config = NULL;
+
+ /* Device is not in use */
+ af_dev_configptr->in_use = AF_NOT_IN_USE;
+
+ return 0;
+}
+
+static void af_platform_release(struct device *device)
+{
+ /* This is called when the reference count goes to zero */
+}
+
+static int af_probe(struct device *device)
+{
+ afdev = device;
+ return 0;
+}
+
+static int af_remove(struct device *device)
+{
+ return 0;
+}
+
+/*
+ * This function will process IOCTL commands sent by the application and
+ * control the device IO operations.
+ */
+static int af_ioctl(struct inode *inode, struct file *filep,
+ unsigned int cmd, unsigned long arg)
+{
+ struct af_configuration afconfig = *(af_dev_configptr->config);
+ int result = 0;
+
+ /* Block the mutex while ioctl is called */
+ result = mutex_lock_interruptible(&af_dev_configptr->read_blocked);
+ if (result)
+ return result;
+
+ /*
+ * Extract the type and number bitfields, and don't
+ * decode wrong cmds return ENOTTY (inappropriate ioctl)
+ */
+ if (_IOC_TYPE(cmd) != AF_MAGIC_NO) {
+ /* Release the mutex */
+ mutex_unlock(&af_dev_configptr->read_blocked);
+ return -ENOTTY;
+ }
+
+ if (_IOC_NR(cmd) > AF_IOC_MAXNR) {
+ /* Release the mutex */
+ mutex_unlock(&af_dev_configptr->read_blocked);
+ return -ENOTTY;
+ }
+
+ /*Use 'access_ok' to validate user space pointer */
+ 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 the mutex */
+ mutex_unlock(&af_dev_configptr->read_blocked);
+ return -EFAULT;
+ }
+
+ switch (cmd) {
+
+ /*
+ * This ioctl is used to perform hardware
+ * set up for AF Engine
+ * It will configura all the registers
+ */
+ case AF_S_PARAM:
+ /* Copy params structure passed by user */
+ if (copy_from_user(af_dev_configptr->config,
+ (struct af_configuration *)arg,
+ sizeof(struct af_configuration))) {
+ /* Release the mutex */
+ mutex_unlock(&af_dev_configptr->read_blocked);
+ return -EFAULT;
+ }
+
+ /* Call AF_hardware_setup to perform register configuration */
+ result = af_hardware_setup();
+ if (!result) {
+ result = af_dev_configptr->size_paxel;
+ } else {
+ dev_err(afdev, "Error : AF_S_PARAM failed");
+ *(af_dev_configptr->config) = afconfig;
+ }
+ break;
+
+ /* This ioctl will get the paramters from application */
+ case AF_G_PARAM:
+ /* Check if Hardware is configured or not */
+ if (af_dev_configptr->af_config == H3A_AF_CONFIG) {
+ if (copy_to_user((struct af_configuration *)arg,
+ af_dev_configptr->config,
+ sizeof(struct af_configuration))) {
+ mutex_unlock(
+ &af_dev_configptr->read_blocked);
+ return -EFAULT;
+ } else
+ result = af_dev_configptr->size_paxel;
+ } else {
+ dev_dbg(afdev, "Error : AF Hardware not configured");
+ result = -EINVAL;
+ }
+
+ break;
+
+ /*
+ * This ioctl will enable AF Engine
+ * if hardware configuration is done
+ */
+ case AF_ENABLE:
+ /* Check if hardware is configured or not */
+ if (af_dev_configptr->af_config == H3A_AF_CONFIG_NOT_DONE) {
+ dev_err(afdev, "Error : AF Hardware not configured");
+ result = -EINVAL;
+ } else
+ af_engine_setup(1);
+ break;
+
+ /* This ioctl will disable AF Engine */
+ case AF_DISABLE:
+ af_engine_setup(0);
+ break;
+
+ default:
+ dev_err(afdev, "Error : Invalid IOCTL!");
+ result = -ENOTTY;
+ break;
+ }
+
+ /* Before returning increment mutex */
+ mutex_unlock(&af_dev_configptr->read_blocked);
+
+ return result;
+}
+
+/* Function will return the statistics to user */
+ssize_t af_read(struct file *filep, char *kbuff, size_t size, loff_t * offset)
+{
+ void *buff_temp;
+ int result = 0;
+ int ret;
+
+ /* mutex will return immediately if read call is busy */
+ ret = mutex_lock_interruptible(&af_dev_configptr->read_blocked);
+ if (ret != 0) {
+ dev_err(afdev, "\n Read Call : busy");
+ return -EBUSY;
+ }
+
+ /*
+ * If no of bytes specified by the user is less
+ * than that of buffer return error
+ */
+ if (size < af_dev_configptr->size_paxel) {
+ dev_err(afdev, "\n Error : Invalid buffer size");
+ mutex_unlock(&(af_dev_configptr->read_blocked));
+ return -1;
+ }
+
+ /*
+ * The value of bufffer_filled flag determines
+ * the status of statistics
+ */
+ if (af_dev_configptr->buffer_filled == 0) {
+ dev_dbg(afdev, "Read call is blocked ................");
+ /* Block the read call until
+ * new statistics are available
+ * or timer expires
+ */
+ wait_event_interruptible_timeout(af_dev_configptr->
+ af_wait_queue,
+ af_dev_configptr->
+ buffer_filled, AF_TIMEOUT);
+ dev_dbg(afdev,
+ "\n Read Call Unblocked..........................");
+ }
+
+ if (af_dev_configptr->buffer_filled == 1) {
+ /*
+ * New Statistics are available
+ * Disable the interrupts while
+ * swapping the buffers */
+ dev_dbg(afdev, "\n Reading.............................");
+ disable_irq(4);
+
+ af_dev_configptr->buffer_filled = 0;
+
+ /* Swap application buffer and old buffer */
+ buff_temp = af_dev_configptr->buff_old;
+ af_dev_configptr->buff_old = af_dev_configptr->buff_app;
+ af_dev_configptr->buff_app = buff_temp;
+
+ dev_dbg(afdev, "\n Reading Done...........................");
+
+ /* Enable the interrupts once swapping is done */
+ enable_irq(4);
+
+ /*
+ * New Statistics are not availaible
+ * copy the application buffer to user
+ * Return the entire statistics to user
+ */
+ if (copy_to_user(kbuff, af_dev_configptr->buff_app,
+ af_dev_configptr->size_paxel)) {
+ /* Release the mutex in case of fault */
+ mutex_unlock(&(af_dev_configptr->read_blocked));
+ return -EFAULT;
+ } else
+ result = af_dev_configptr->size_paxel;
+ }
+
+ /* Release the mutex */
+ mutex_unlock(&(af_dev_configptr->read_blocked));
+ dev_dbg(afdev, "\n Read APPLICATION BUFFER %d",
+ *((int *)((af_dev_configptr->buff_app))));
+
+ return result;
+}
+
+static irqreturn_t af_isr(int irq, void *dev_id)
+{
+ void *buff_temp;
+ int busyaf;
+
+ /* Get the value of PCR register */
+ busyaf = AF_GET_PCR;
+
+ /* If AF Engine has enabled, interrupt is not for AF */
+ if ((busyaf & 0x01) == 0)
+ return IRQ_RETVAL(IRQ_NONE);
+
+ /*
+ * Service the Interrupt
+ * Set buffer filled flag to indicate
+ * statistics are available
+ * Swap current buffer and old buffer
+ */
+ if (af_dev_configptr) {
+ buff_temp = af_dev_configptr->buff_curr;
+ af_dev_configptr->buff_curr = af_dev_configptr->buff_old;
+ af_dev_configptr->buff_old = buff_temp;
+
+ /* Set AF Buf st to current register address */
+ if (af_dev_configptr->buff_curr)
+ af_set_address((unsigned long)
+ virt_to_phys(af_dev_configptr->buff_curr));
+
+ /* Wake up read as new statistics are available */
+ af_dev_configptr->buffer_filled = 1;
+ wake_up(&(af_dev_configptr->af_wait_queue));
+ return IRQ_RETVAL(IRQ_HANDLED);
+ }
+ return IRQ_RETVAL(IRQ_NONE);
+}
+
+/* File Operation Structure */
+static const struct file_operations af_fops = {
+ .owner = THIS_MODULE,
+ .open = af_open,
+ .ioctl = af_ioctl,
+ .read = af_read,
+ .release = af_release
+};
+static struct platform_device afdevice = {
+ .name = "dm355_af",
+ .id = 2,
+ .dev = {
+ .release = af_platform_release,
+ }
+};
+
+static struct device_driver af_driver = {
+ .name = "dm355_af",
+ .bus = &platform_bus_type,
+ .probe = af_probe,
+ .remove = af_remove,
+};
+
+/* Function to register the AF character device driver. */
+#define DRIVERNAME "DM355AF"
+int __init af_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 "af major#: %d, minor# %d\n", MAJOR(dev), MINOR(dev));
+
+ /* allocate memory for device structure and initialize it with 0 */
+ af_dev_configptr = kmalloc(sizeof(struct af_device), GFP_KERNEL);
+ if (!af_dev_configptr) {
+ printk(KERN_ERR "Error : kmalloc fail");
+ unregister_chrdev_region(dev, AF_NR_DEVS);
+ return -ENOMEM;
+ }
+
+ /* Initialize character device */
+ cdev_init(&c_dev, &af_fops);
+ c_dev.owner = THIS_MODULE;
+ c_dev.ops = &af_fops;
+
+ err = cdev_add(&c_dev, dev, 1);
+ if (err) {
+ printk("Error : Error in Adding Davinci AF");
+ unregister_chrdev_region(dev, AF_NR_DEVS);
+ kfree(af_dev_configptr);
+
+ return -err;
+ }
+
+ /* register driver as a platform driver */
+ if (driver_register(&af_driver) != 0) {
+ unregister_chrdev_region(dev, 1);
+ cdev_del(&c_dev);
+ return -EINVAL;
+ }
+
+ /* Register the drive as a platform device */
+ if (platform_device_register(&afdevice) != 0) {
+ driver_unregister(&af_driver);
+ unregister_chrdev_region(dev, 1);
+ cdev_del(&c_dev);
+ return -EINVAL;
+ }
+
+ af_class = class_create(THIS_MODULE, "dm355_af");
+ if (!af_class) {
+ printk("af_init: error in creating device class\n");
+ driver_unregister(&af_driver);
+ platform_device_unregister(&afdevice);
+ unregister_chrdev_region(dev, 1);
+ unregister_chrdev(MAJOR(dev), DRIVERNAME);
+ cdev_del(&c_dev);
+ return -EINVAL;
+ }
+
+ /* register device class */
+ device_create(af_class, NULL, dev, NULL, "dm355_af");
+
+ AF_SETGAMMAWD;
+
+ vpssclk = AF_GETCLKCTRL;
+ vpssclk |= (1 << 4);
+ AF_SETCLKCTRL(vpssclk);
+
+ /* Set up the Interrupt handler for H3AINT interrupt */
+ result = request_irq(4, af_isr, IRQF_SHARED, "dm355h3a_af",
+ (void *)af_dev_configptr);
+
+ if (result != 0) {
+ printk(KERN_ERR "Error : Request IRQ Failed");
+ unregister_chrdev_region(dev, AF_NR_DEVS);
+
+ kfree(af_dev_configptr);
+ device_destroy(af_class, dev);
+ class_destroy(af_class);
+ driver_unregister(&af_driver);
+ platform_device_unregister(&afdevice);
+ cdev_del(&c_dev);
+ return result;
+ }
+
+ /* Initialize device structure */
+ memset((unsigned char *)af_dev_configptr, 0, sizeof(struct af_device));
+
+ af_dev_configptr->in_use = AF_NOT_IN_USE;
+ af_dev_configptr->buffer_filled = 0;
+ return 0;
+}
+
+/*
+ * This function is called by the kernel while unloading the driver.
+ * It will unregister character device driver
+ */
+void __exit af_cleanup(void)
+{
+ /* Return if driver is busy */
+ if (af_dev_configptr->in_use == AF_IN_USE) {
+ printk("Error : Driver in use. Can't remove.");
+ return;
+ }
+
+ free_irq(4, af_dev_configptr);
+
+ /* Free device structure */
+ kfree(af_dev_configptr);
+
+ unregister_chrdev_region(dev, AF_NR_DEVS);
+
+ driver_unregister(&af_driver);
+
+ device_destroy(af_class, dev);
+
+ class_destroy(af_class);
+
+ platform_device_unregister(&afdevice);
+
+ /* Unregistering the driver from the kernel */
+ cdev_del(&c_dev);
+}
+
+module_init(af_init)
+module_exit(af_cleanup)
+MODULE_LICENSE("GPL");
new file mode 100644
@@ -0,0 +1,192 @@
+/*
+ * 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_af_hw.h>
+#include <linux/device.h>
+
+int af_register_setup(struct af_device *af_dev)
+{
+ unsigned int pcr = 0, pax1 = 0, pax2 = 0, paxstart = 0;
+ unsigned int coef = 0;
+ unsigned int base_coef_set0 = 0;
+ unsigned int base_coef_set1 = 0;
+ int index;
+
+ /*
+ * Configure Hardware Registers
+ * Set PCR Register
+ */
+ pcr = regr(AFPCR);
+
+ /* Set Accumulator Mode */
+ if (af_dev->config->mode == ACCUMULATOR_PEAK)
+ pcr |= FVMODE;
+ else
+ pcr &= ~FVMODE;
+
+ /* Set A-law */
+ if (af_dev->config->alaw_enable == H3A_AF_ENABLE)
+ pcr |= AF_ALAW_EN;
+ else
+ pcr &= ~AF_ALAW_EN;
+
+ /* Set RGB Position */
+ pcr &= ~RGBPOS;
+ pcr |= (af_dev->config->rgb_pos) << AF_RGBPOS_SHIFT;
+
+ /* HMF Configurations */
+ if (af_dev->config->hmf_config.enable == H3A_AF_ENABLE) {
+ pcr &= ~AF_MED_EN;
+ /* Enable HMF */
+ pcr |= AF_MED_EN;
+
+ /* Set Median Threshold */
+ pcr &= ~MED_TH;
+ pcr |=
+ (af_dev->config->hmf_config.threshold) << AF_MED_TH_SHIFT;
+ } else
+ pcr &= ~AF_MED_EN;
+
+ /* Set Input Source as CCDC */
+ pcr &= ~AF_INP_SRC;
+ pcr |= (AF_CCDC) << AF_INP_SRC_SHIFT;
+
+ /* Set PCR Register */
+ regw(pcr, AFPCR);
+
+ /*
+ * Configure AFPAX1 Paxel parameter configuration
+ * Set Width in AFPAX1 Register
+ */
+ pax1 &= ~PAXW;
+ pax1 |=
+ (AF_SET_VAL(af_dev->config->paxel_config.width)) << AF_PAXW_SHIFT;
+
+ /* Set height in AFPAX1 */
+ pax1 &= ~PAXH;
+ pax1 |= (AF_SET_VAL(af_dev->config->paxel_config.height));
+
+ regw(pax1, AFPAX1);
+
+ /*
+ * Configure AFPAX2 Register
+ * Set Line Increment in AFPAX2 Register
+ */
+ pax2 &= ~AFINCV;
+ pax2 |=
+ (AF_SET_VAL(af_dev->config->paxel_config.line_incr)) <<
+ AF_LINE_INCR_SHIFT;
+
+ /* Set Vertical Count */
+ pax2 &= ~PAXVC;
+ pax2 |= (af_dev->config->paxel_config.vt_cnt - 1) << AF_VT_COUNT_SHIFT;
+
+ /* Set Horizontal Count */
+ pax2 &= ~PAXHC;
+ pax2 |= (af_dev->config->paxel_config.hz_cnt - 1);
+ regw(pax2, AFPAX2);
+
+ /*
+ * Configure PAXSTART Register
+ *Configure Horizontal Start
+ */
+ paxstart &= ~PAXSH;
+ paxstart |=
+ (af_dev->config->paxel_config.hz_start) << AF_HZ_START_SHIFT;
+
+ /* Configure Vertical Start */
+ paxstart &= ~PAXSV;
+ paxstart |= af_dev->config->paxel_config.vt_start;
+ regw(paxstart, AFPAXSTART);
+
+ /*Set IIRSH Register */
+ regw(af_dev->config->iir_config.hz_start_pos, AFIIRSH);
+
+ /* Set IIR Filter0 Coefficients */
+ base_coef_set0 = AFCOEF010;
+ for (index = 0; index <= 8; index += 2) {
+ coef &= ~COEF_MASK0;
+ coef |= af_dev->config->iir_config.coeff_set0[index];
+ coef &= ~COEF_MASK1;
+ coef |=
+ (af_dev->config->iir_config.
+ coeff_set0[index + 1]) << AF_COEF_SHIFT;
+ regw(coef, base_coef_set0);
+ dev_dbg(afdev, "\n COEF0 %x", regr(base_coef_set0));
+ base_coef_set0 = base_coef_set0 + AFCOEF_OFFSET;
+ }
+
+ /* Set AFCOEF0010 Register */
+ regw(af_dev->config->iir_config.coeff_set0[10], AFCOEF0010);
+
+ /*Set IIR Filter1 Coefficients */
+ base_coef_set1 = AFCOEF110;
+ for (index = 0; index <= 8; index += 2) {
+ coef &= ~COEF_MASK0;
+ coef |= af_dev->config->iir_config.coeff_set1[index];
+ coef &= ~COEF_MASK1;
+ coef |=
+ (af_dev->config->iir_config.
+ coeff_set1[index + 1]) << AF_COEF_SHIFT;
+ regw(coef, base_coef_set1);
+ dev_dbg(afdev, "\n COEF1 %x", regr(base_coef_set1));
+ base_coef_set1 = base_coef_set1 + AFCOEF_OFFSET;
+ }
+
+ /* Set AFCOEF0110 */
+ regw(af_dev->config->iir_config.coeff_set1[10], AFCOEF1010);
+
+ /* Set AFBUFST to Current buffer Physical Address */
+ regw((unsigned int)(virt_to_phys(af_dev->buff_curr)), AFBUFST);
+
+ AF_SETGAMMAWD;
+ dev_dbg(afdev, "\n PCR %x", pcr);
+ dev_dbg(afdev, "\n AFPAX1 %x", regr(AFPAX1));
+ dev_dbg(afdev, "\n PAXSTART %x", paxstart);
+ dev_dbg(afdev, "\n PAX2 %x", regr(AFPAX2));
+ dev_dbg(afdev, "\n COEF 10 %x", regr(AFCOEF0010));
+ dev_dbg(afdev, "\n COEF 10 %x", regr(AFCOEF1010));
+ dev_dbg(afdev, "\n AFBUFST %x", regr(AFBUFST));
+
+ return 0;
+}
+
+/* Function to Enable/Disable AF Engine */
+inline void af_engine_setup(int enable)
+{
+ unsigned int pcr;
+
+ pcr = regr(AFPCR);
+ dev_dbg(afdev, "\nEngine Setup value before PCR : %x", pcr);
+
+ /* Set AF_EN bit in PCR Register */
+ if (enable)
+ pcr |= AF_EN;
+ else
+ pcr &= ~AF_EN;
+
+ regw(pcr, AFPCR);
+
+ dev_dbg(afdev, "\n Engine Setup value after PCR : %x", pcr);
+}
+
+/* Function to set address */
+inline void af_set_address(unsigned long address)
+{
+ regw(address, AFBUFST);
+}
new file mode 100644
@@ -0,0 +1,179 @@
+/*
+ * 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 AF_DM355_DRIVER_H
+#define AF_DM355_DRIVER_H
+
+/* Kernel Header files */
+#include <linux/ioctl.h>
+
+#ifdef __KERNEL__
+#include <linux/kernel.h>
+#include <linux/wait.h>
+#include <linux/mutex.h>
+#include <linux/io.h>
+#endif
+
+#ifdef __KERNEL__
+/* Device Constants */
+#define AF_MAJOR_NUMBER 0
+#define DEVICE_NAME "dm355_af"
+#define AF_NR_DEVS 1
+#define AF_TIMEOUT ((300 * HZ) / 1000)
+#endif
+
+/* Range Constants */
+#define AF_PAXEL_HORIZONTAL_COUNT_MIN 1
+#define AF_PAXEL_HORIZONTAL_COUNT_MAX 36
+#define AF_PAXEL_VERTICAL_COUNT_MIN 1
+#define AF_PAXEL_VERTICAL_COUNT_MAX 128
+#define AF_PAXEL_SIZE 48
+#define AF_WIDTH_MIN 8
+#define AF_WIDTH_MAX 256
+#define AF_LINE_INCR_MIN 2
+#define AF_LINE_INCR_MAX 32
+#define AF_HEIGHT_MIN 2
+#define AF_HEIGHT_MAX 256
+#define AF_HZSTART_MIN 2
+#define AF_HZSTART_MAX 4094
+#define AF_VTSTART_MIN 0
+#define AF_VTSTART_MAX 4095
+#define AF_MEDTH_MAX 255
+#define AF_IIRSH_MAX 4094
+#define AF_COEF_MIN 0xFFFFF800
+#define AF_COEF_MAX 0x000007FF
+#define AF_NUMBER_OF_COEF 11
+
+/* list of ioctls */
+#pragma pack(1)
+#define AF_IOC_MAXNR 5
+#define AF_MAGIC_NO 'a'
+#define AF_S_PARAM _IOWR(AF_MAGIC_NO, 1, struct af_configuration *)
+#define AF_G_PARAM _IOWR(AF_MAGIC_NO, 2, struct af_configuration *)
+#define AF_ENABLE _IO(AF_MAGIC_NO, 3)
+#define AF_DISABLE _IO(AF_MAGIC_NO, 4)
+#pragma pack()
+
+/* enum used for status of specific feature */
+enum h3a_af_enable {
+ H3A_AF_DISABLE = 0,
+ H3A_AF_ENABLE = 1
+};
+
+enum af_config_flag {
+ H3A_AF_CONFIG_NOT_DONE,
+ H3A_AF_CONFIG
+};
+
+struct af_reg_dump {
+ unsigned int addr;
+ unsigned int val;
+};
+
+/* enum used for keep track of whether hardware is used */
+enum af_In_use {
+ AF_NOT_IN_USE = 0,
+ AF_IN_USE = 1
+};
+
+enum af_mode {
+ ACCUMULATOR_SUMMED = 0,
+ ACCUMULATOR_PEAK = 1
+};
+
+/* Red, Green, and blue pixel location in the AF windows */
+enum rgbpos {
+ GR_GB_BAYER = 0, /* GR and GB as Bayer pattern */
+ RG_GB_BAYER = 1, /* RG and GB as Bayer pattern */
+ GR_BG_BAYER = 2, /* GR and BG as Bayer pattern */
+ RG_BG_BAYER = 3, /* RG and BG as Bayer pattern */
+ GG_RB_CUSTOM = 4, /* GG and RB as custom pattern */
+ RB_GG_CUSTOM = 5 /* RB and GG as custom pattern */
+};
+
+/* Contains the information regarding the Horizontal Median Filter */
+struct af_hmf {
+ enum h3a_af_enable enable;
+
+ /* Threshhold Value for orizontal Median Filter */
+ unsigned int threshold;
+};
+
+/* Contains the information regarding the IIR Filters */
+struct af_iir {
+ unsigned int hz_start_pos;
+
+ /* IIR Filter Coefficient for Set 0 */
+ int coeff_set0[AF_NUMBER_OF_COEF];
+
+ /* IIR Filter Coefficient for Set 1 */
+ int coeff_set1[AF_NUMBER_OF_COEF];
+};
+
+/* Contains the information regarding the Paxels Structure in AF Engine */
+struct af_paxel {
+ unsigned int width; /* Width of the Paxel */
+ unsigned int height; /* Height of the Paxel */
+ unsigned int hz_start; /* Horizontal Start Position */
+ unsigned int vt_start; /* Vertical Start Position */
+ unsigned int hz_cnt; /* Horizontal Count */
+ unsigned int vt_cnt; /* vertical Count */
+ unsigned int line_incr; /* Line Increment */
+};
+
+/* Contains the parameters required for hardware set up of AF Engine */
+struct af_configuration {
+ enum h3a_af_enable alaw_enable; /*ALAW status */
+ struct af_hmf hmf_config; /*HMF configurations */
+ enum rgbpos rgb_pos; /*RGB Positions */
+ struct af_iir iir_config; /*IIR filter configurations */
+ struct af_paxel paxel_config; /*Paxel parameters */
+ enum af_mode mode; /*Accumulator mode */
+};
+
+#ifdef __KERNEL__
+/* Structure for device of AF Engine */
+struct af_device {
+ enum af_In_use in_use;
+
+ /*Device configuration structure */
+ struct af_configuration *config;
+ void *buff_old; /*Contains the latest statistics */
+ void *buff_curr; /*Buffer in which HW will */
+
+ /*
+ * Fill the statistics
+ * or HW is already filling statistics
+ */
+
+ void *buff_app;
+
+ /* User space on read call */
+ unsigned int buff_size; /* Size of image buffer */
+ int buffer_filled; /* Flag indicates */
+
+ /*statistics are available */
+ int size_paxel; /*Paxel size in bytes */
+ wait_queue_head_t af_wait_queue; /*Wait queue for driver */
+ /* mutex for driver */
+ struct mutex read_blocked;
+ /* Flag indicates Engine is configured */
+ enum af_config_flag af_config;
+};
+#endif /* __KERNEL__ */
+#endif /* AF_DM355_DRIVER_H */
new file mode 100644
@@ -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
+ */
+
+#ifndef DM355_AF_DRIVER_HW_H
+#define DM355_AF_DRIVER_HW_H
+
+/* Include driver header file */
+#include "dm355_af.h"
+#include <mach/hardware.h>
+
+#ifdef __KERNEL__
+
+/* Register Offsets */
+#define AFPID 0x0 /*Peripheral Revision */
+#define AFPCR 0x00000004 /*Peripheral Control Register */
+#define AFPAX1 0x00000008 /*Setup for the Paxel Configuration */
+#define AFPAX2 0x0000000c /*Setup for the Paxel Configuration */
+#define AFPAXSTART 0x00000010 /*Start Position for Engine Paxels */
+#define AFIIRSH 0x00000014 /*Start Position for IIRSH */
+#define AFBUFST 0x00000018 /*SDRAM/DDRAM Start address */
+
+/*IIR filter coefficient data for SET 0 */
+#define AFCOEF010 0x0000001c
+#define AFCOEF032 0x00000020
+#define AFCOEF054 0x00000024
+#define AFCOEF076 0x00000028
+#define AFCOEF098 0x0000002c
+#define AFCOEF0010 0x00000030
+
+/*IIR filter coefficient data for SET 1 */
+#define AFCOEF110 0x00000034
+#define AFCOEF132 0x00000038
+#define AFCOEF154 0x0000003c
+#define AFCOEF176 0x00000040
+#define AFCOEF198 0x00000044
+#define AFCOEF1010 0x00000048
+
+#define AF_RSDR_ADDR 0x00000060 /*SDRAM/DDRAM Read Address */
+#define AF_RSDR_OFFSET 0x00000064 /*SDRAM/DDRAM Line Offset */
+#define AF_SDR_FRSIZE 0x00000068 /*Frame Size for SDRAM read data */
+
+#define AFCOEF_OFFSET 0x00000004 /* COEFFICIENT BASE ADDRESS */
+
+#define AF_SET_VAL(x) (((x)/2)-1)
+#define AF_NOT_EVEN 1
+#define AF_CHECK_EVEN(x) ((x)%2)
+
+/* PID fields */
+#define AF_TID (0xFF<<16)
+#define AF_CID (0xFF<<8)
+#define AF_PREV 0xFF
+
+/* PCR fields */
+#define AVE2LMT (0x3FF<<22)
+#define AF_INP_SRC (1<<19)
+#define AF_BUSYAEWB (1<<18)
+#define AEW_ALAW_EN (1<<17)
+#define AEW_EN (1<<16)
+#define AF_BUSYAF (1<<15)
+#define FVMODE (1<<14)
+#define RGBPOS (0x7<<11)
+#define MED_TH (0xFF<<3)
+#define AF_MED_EN (1<<2)
+#define AF_ALAW_EN (1<<1)
+#define AF_EN (1<<0)
+
+#define AF_SETGAMMAWD __raw_writel(0x00000010, IO_ADDRESS(0x01C70680))
+
+/* AFPAX1 fields */
+#define PAXW (0x7F<<16)
+#define PAXH 0x7F
+
+#define AF_CCDC 0
+
+/* AFPAX2 fields */
+#define AFINCV (0xF<<13)
+#define PAXVC (0x7F<<6)
+#define PAXHC 0x3F
+
+/* AFPAXSTART fields */
+#define PAXSH (0xFFF<<16)
+#define PAXSV 0xFFF
+
+/* COEFFICIENT MASK */
+#define COEF_MASK0 0xFFF
+#define COEF_MASK1 (0xFFF<<16)
+
+/* SDRAM Frame Size */
+#define AF_SDR_FRSIZE_HSIZE 0xFFF
+#define AF_SDR_FRSIZE_VSIZE (0xFFF<<16)
+#define AF_SDR_FRSIZE_BITSEL (0x7<<28)
+
+/* BIT SHIFTS */
+#define AF_RGBPOS_SHIFT 11
+#define AF_MED_TH_SHIFT 3
+#define AF_PAXW_SHIFT 16
+#define AF_LINE_INCR_SHIFT 13
+#define AF_VT_COUNT_SHIFT 6
+#define AF_HZ_START_SHIFT 16
+#define AF_COEF_SHIFT 16
+#define AF_INP_SRC_SHIFT 19
+#define AF_GETFRAME_SIZE (__raw_readl(IO_ADDRESS(0x01C70910)))
+#define AF_GETINIT_XY (__raw_readl(IO_ADDRESS(0x01C70910)))
+#define AF_INTSTATBASE (IO_ADDRESS(0x01C7080C))
+#define AF_EVNTSELADDR (IO_ADDRESS(0x01C70814))
+#define AF_CLKCTRL_ADDR (IO_ADDRESS(0x01C70004))
+#define AF_GETCLKCTRL __raw_readl(AF_CLKCTRL_ADDR)
+#define AF_SETCLKCTRL(val) __raw_writel(val, AF_CLKCTRL_ADDR)
+
+/* Macros for register read and write */
+#define AF_IOBASE_VADDR IO_ADDRESS(0x01c70080)
+#define regr(reg) __raw_readl((reg) + AF_IOBASE_VADDR)
+#define regw(val, reg) __raw_writel(val, (reg) + AF_IOBASE_VADDR)
+#define AF_GET_PCR __raw_readl(AF_IOBASE_VADDR + AFPCR)
+#define AF_GETINTSTAT __raw_readl(AF_INTSTATBASE)
+
+extern struct device *afdev;
+/* Function declaration */
+int af_register_setup(struct af_device *);
+void af_engine_setup(int);
+void af_set_address(unsigned long);
+
+#endif
+#endif