]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
ENGR00317981: pxp: forward pxp driver to 3.14 kernel
authorShawn Guo <shawn.guo@freescale.com>
Thu, 12 Jun 2014 07:27:57 +0000 (15:27 +0800)
committerNitin Garg <nitin.garg@freescale.com>
Fri, 16 Jan 2015 03:16:22 +0000 (21:16 -0600)
Forward imx_3.10.y pxp driver to 3.14 kernel.

Signed-off-by: Shawn Guo <shawn.guo@freescale.com>
12 files changed:
drivers/dma/Kconfig
drivers/dma/Makefile
drivers/dma/pxp/Makefile [new file with mode: 0644]
drivers/dma/pxp/pxp_device.c [new file with mode: 0644]
drivers/dma/pxp/pxp_dma_v2.c [new file with mode: 0644]
drivers/dma/pxp/regs-pxp_v2.h [new file with mode: 0644]
include/linux/platform_data/dma-imx.h
include/linux/pxp_device.h [new file with mode: 0644]
include/linux/pxp_dma.h [new file with mode: 0644]
include/uapi/linux/Kbuild
include/uapi/linux/pxp_device.h [new file with mode: 0644]
include/uapi/linux/pxp_dma.h [new file with mode: 0644]

index 605b016bcea49dcea25d9515b2cec276ae974372..88a49886e5a1b1b508d01ff58876dd9257c8fa96 100644 (file)
@@ -137,6 +137,19 @@ config MX3_IPU_IRQS
          To avoid bloating the irq_desc[] array we allocate a sufficient
          number of IRQ slots and map them dynamically to specific sources.
 
+config MXC_PXP_V2
+       bool "MXC PxP V2 support"
+       depends on ARM
+       select DMA_ENGINE
+       help
+          Support the PxP (Pixel Pipeline) on i.MX6 DualLite and i.MX6 SoloLite.
+         If unsure, select N.
+
+config MXC_PXP_CLIENT_DEVICE
+       bool "MXC PxP Client Device"
+       default y
+       depends on MXC_PXP_V2
+
 config TXX9_DMAC
        tristate "Toshiba TXx9 SoC DMA support"
        depends on MACH_TX49XX || MACH_TX39XX
index a029d0f4a1be8088c00c459373f469580925d981..0c5ef31087d2683343ed144af5e45ffe952b4730 100644 (file)
@@ -18,6 +18,7 @@ obj-$(CONFIG_MV_XOR) += mv_xor.o
 obj-$(CONFIG_DW_DMAC_CORE) += dw/
 obj-$(CONFIG_AT_HDMAC) += at_hdmac.o
 obj-$(CONFIG_MX3_IPU) += ipu/
+obj-$(CONFIG_MXC_PXP_V2) += pxp/
 obj-$(CONFIG_TXX9_DMAC) += txx9dmac.o
 obj-$(CONFIG_SH_DMAE_BASE) += sh/
 obj-$(CONFIG_COH901318) += coh901318.o coh901318_lli.o
diff --git a/drivers/dma/pxp/Makefile b/drivers/dma/pxp/Makefile
new file mode 100644 (file)
index 0000000..498ccca
--- /dev/null
@@ -0,0 +1,2 @@
+obj-$(CONFIG_MXC_PXP_V2) += pxp_dma_v2.o
+obj-$(CONFIG_MXC_PXP_CLIENT_DEVICE) += pxp_device.o
diff --git a/drivers/dma/pxp/pxp_device.c b/drivers/dma/pxp/pxp_device.c
new file mode 100644 (file)
index 0000000..09b2add
--- /dev/null
@@ -0,0 +1,762 @@
+/*
+ * Copyright (C) 2010-2014 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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/interrupt.h>
+#include <linux/miscdevice.h>
+#include <linux/platform_device.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/delay.h>
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
+#include <linux/sched.h>
+#include <linux/module.h>
+#include <linux/pxp_device.h>
+#include <linux/atomic.h>
+#include <linux/platform_data/dma-imx.h>
+
+#define BUFFER_HASH_ORDER 4
+
+static struct pxp_buffer_hash bufhash;
+static struct pxp_irq_info irq_info[NR_PXP_VIRT_CHANNEL];
+
+static int pxp_ht_create(struct pxp_buffer_hash *hash, int order)
+{
+       unsigned long i;
+       unsigned long table_size;
+
+       table_size = 1U << order;
+
+       hash->order = order;
+       hash->hash_table = kmalloc(sizeof(*hash->hash_table) * table_size, GFP_KERNEL);
+
+       if (!hash->hash_table) {
+               pr_err("%s: Out of memory for hash table\n", __func__);
+               return -ENOMEM;
+       }
+
+       for (i = 0; i < table_size; i++)
+               INIT_HLIST_HEAD(&hash->hash_table[i]);
+
+       return 0;
+}
+
+static int pxp_ht_insert_item(struct pxp_buffer_hash *hash,
+                             struct pxp_buf_obj *new)
+{
+       unsigned long hashkey;
+       struct hlist_head *h_list;
+
+       hashkey = hash_long(new->offset >> PAGE_SHIFT, hash->order);
+       h_list = &hash->hash_table[hashkey];
+
+       spin_lock(&hash->hash_lock);
+       hlist_add_head_rcu(&new->item, h_list);
+       spin_unlock(&hash->hash_lock);
+
+       return 0;
+}
+
+static int pxp_ht_remove_item(struct pxp_buffer_hash *hash,
+                             struct pxp_buf_obj *obj)
+{
+       spin_lock(&hash->hash_lock);
+       hlist_del_init_rcu(&obj->item);
+       spin_unlock(&hash->hash_lock);
+       return 0;
+}
+
+static struct hlist_node *pxp_ht_find_key(struct pxp_buffer_hash *hash,
+                                         unsigned long key)
+{
+       struct pxp_buf_obj *entry;
+       struct hlist_head *h_list;
+       unsigned long hashkey;
+
+       hashkey = hash_long(key, hash->order);
+       h_list = &hash->hash_table[hashkey];
+
+       hlist_for_each_entry_rcu(entry, h_list, item) {
+               if (entry->offset >> PAGE_SHIFT == key)
+                       return &entry->item;
+       }
+
+       return NULL;
+}
+
+static void pxp_ht_destroy(struct pxp_buffer_hash *hash)
+{
+       kfree(hash->hash_table);
+       hash->hash_table = NULL;
+}
+
+static int pxp_buffer_handle_create(struct pxp_file *file_priv,
+                                   struct pxp_buf_obj *obj,
+                                   uint32_t *handlep)
+{
+       int ret;
+
+       idr_preload(GFP_KERNEL);
+       spin_lock(&file_priv->buffer_lock);
+
+       ret = idr_alloc(&file_priv->buffer_idr, obj, 1, 0, GFP_NOWAIT);
+
+       spin_unlock(&file_priv->buffer_lock);
+       idr_preload_end();
+
+       if (ret < 0)
+               return ret;
+
+       *handlep = ret;
+
+       return 0;
+}
+
+static struct pxp_buf_obj *
+pxp_buffer_object_lookup(struct pxp_file *file_priv,
+                        uint32_t handle)
+{
+       struct pxp_buf_obj *obj;
+
+       spin_lock(&file_priv->buffer_lock);
+
+       obj = idr_find(&file_priv->buffer_idr, handle);
+       if (!obj) {
+               spin_unlock(&file_priv->buffer_lock);
+               return NULL;
+       }
+
+       spin_unlock(&file_priv->buffer_lock);
+
+       return obj;
+}
+
+static int pxp_buffer_handle_delete(struct pxp_file *file_priv,
+                                   uint32_t handle)
+{
+       struct pxp_buf_obj *obj;
+
+       spin_lock(&file_priv->buffer_lock);
+
+       obj = idr_find(&file_priv->buffer_idr, handle);
+       if (!obj) {
+               spin_unlock(&file_priv->buffer_lock);
+               return -EINVAL;
+       }
+
+       idr_remove(&file_priv->buffer_idr, handle);
+       spin_unlock(&file_priv->buffer_lock);
+
+       return 0;
+}
+
+static int pxp_channel_handle_create(struct pxp_file *file_priv,
+                                    struct pxp_chan_obj *obj,
+                                    uint32_t *handlep)
+{
+       int ret;
+
+       idr_preload(GFP_KERNEL);
+       spin_lock(&file_priv->channel_lock);
+
+       ret = idr_alloc(&file_priv->channel_idr, obj, 0, 0, GFP_NOWAIT);
+
+       spin_unlock(&file_priv->channel_lock);
+       idr_preload_end();
+
+       if (ret < 0)
+               return ret;
+
+       *handlep = ret;
+
+       return 0;
+}
+
+static struct pxp_chan_obj *
+pxp_channel_object_lookup(struct pxp_file *file_priv,
+                         uint32_t handle)
+{
+       struct pxp_chan_obj *obj;
+
+       spin_lock(&file_priv->channel_lock);
+
+       obj = idr_find(&file_priv->channel_idr, handle);
+       if (!obj) {
+               spin_unlock(&file_priv->channel_lock);
+               return NULL;
+       }
+
+       spin_unlock(&file_priv->channel_lock);
+
+       return obj;
+}
+
+static int pxp_channel_handle_delete(struct pxp_file *file_priv,
+                                    uint32_t handle)
+{
+       struct pxp_chan_obj *obj;
+
+       spin_lock(&file_priv->channel_lock);
+
+       obj = idr_find(&file_priv->channel_idr, handle);
+       if (!obj) {
+               spin_unlock(&file_priv->channel_lock);
+               return -EINVAL;
+       }
+
+       idr_remove(&file_priv->channel_idr, handle);
+       spin_unlock(&file_priv->channel_lock);
+
+       return 0;
+}
+
+static int pxp_alloc_dma_buffer(struct pxp_buf_obj *obj)
+{
+       obj->virtual = dma_alloc_coherent(NULL, PAGE_ALIGN(obj->size),
+                              (dma_addr_t *) (&obj->offset),
+                              GFP_DMA | GFP_KERNEL);
+       pr_debug("[ALLOC] mem alloc phys_addr = 0x%lx\n", obj->offset);
+
+       if (obj->virtual == NULL) {
+               printk(KERN_ERR "Physical memory allocation error!\n");
+               return -1;
+       }
+
+       return 0;
+}
+
+static void pxp_free_dma_buffer(struct pxp_buf_obj *obj)
+{
+       if (obj->virtual != NULL) {
+               dma_free_coherent(0, PAGE_ALIGN(obj->size),
+                                 obj->virtual, (dma_addr_t)obj->offset);
+       }
+}
+
+static int
+pxp_buffer_object_free(int id, void *ptr, void *data)
+{
+       struct pxp_file *file_priv = data;
+       struct pxp_buf_obj *obj = ptr;
+       int ret;
+
+       ret = pxp_buffer_handle_delete(file_priv, obj->handle);
+       if (ret < 0)
+               return ret;
+
+       pxp_ht_remove_item(&bufhash, obj);
+       pxp_free_dma_buffer(obj);
+       kfree(obj);
+
+       return 0;
+}
+
+static int
+pxp_channel_object_free(int id, void *ptr, void *data)
+{
+       struct pxp_file *file_priv = data;
+       struct pxp_chan_obj *obj = ptr;
+       int chan_id;
+
+       chan_id = obj->chan->chan_id;
+       wait_event(irq_info[chan_id].waitq,
+               atomic_read(&irq_info[chan_id].irq_pending) == 0);
+
+       pxp_channel_handle_delete(file_priv, obj->handle);
+       dma_release_channel(obj->chan);
+       kfree(obj);
+
+       return 0;
+}
+
+static void pxp_free_buffers(struct pxp_file *file_priv)
+{
+       idr_for_each(&file_priv->buffer_idr,
+                       &pxp_buffer_object_free, file_priv);
+       idr_destroy(&file_priv->buffer_idr);
+}
+
+static void pxp_free_channels(struct pxp_file *file_priv)
+{
+       idr_for_each(&file_priv->channel_idr,
+                       &pxp_channel_object_free, file_priv);
+       idr_destroy(&file_priv->channel_idr);
+}
+
+/* Callback function triggered after PxP receives an EOF interrupt */
+static void pxp_dma_done(void *arg)
+{
+       struct pxp_tx_desc *tx_desc = to_tx_desc(arg);
+       struct dma_chan *chan = tx_desc->txd.chan;
+       struct pxp_channel *pxp_chan = to_pxp_channel(chan);
+       int chan_id = pxp_chan->dma_chan.chan_id;
+
+       pr_debug("DMA Done ISR, chan_id %d\n", chan_id);
+
+       atomic_dec(&irq_info[chan_id].irq_pending);
+       irq_info[chan_id].hist_status = tx_desc->hist_status;
+
+       wake_up(&(irq_info[chan_id].waitq));
+}
+
+static int pxp_ioc_config_chan(struct pxp_file *priv, unsigned long arg)
+{
+       struct scatterlist sg[3];
+       struct pxp_tx_desc *desc;
+       struct dma_async_tx_descriptor *txd;
+       struct pxp_config_data pxp_conf;
+       dma_cookie_t cookie;
+       int handle, chan_id;
+       int i, length, ret;
+       struct dma_chan *chan;
+       struct pxp_chan_obj *obj;
+
+       ret = copy_from_user(&pxp_conf,
+                            (struct pxp_config_data *)arg,
+                            sizeof(struct pxp_config_data));
+       if (ret)
+               return -EFAULT;
+
+       handle = pxp_conf.handle;
+       obj = pxp_channel_object_lookup(priv, handle);
+       if (!obj)
+               return -EINVAL;
+       chan = obj->chan;
+       chan_id = chan->chan_id;
+
+       sg_init_table(sg, 3);
+
+       txd = chan->device->device_prep_slave_sg(chan,
+                                                sg, 3,
+                                                DMA_TO_DEVICE,
+                                                DMA_PREP_INTERRUPT,
+                                                NULL);
+       if (!txd) {
+               pr_err("Error preparing a DMA transaction descriptor.\n");
+               return -EIO;
+       }
+
+       txd->callback_param = txd;
+       txd->callback = pxp_dma_done;
+
+       desc = to_tx_desc(txd);
+
+       length = desc->len;
+       for (i = 0; i < length; i++) {
+               if (i == 0) {   /* S0 */
+                       memcpy(&desc->proc_data,
+                              &pxp_conf.proc_data,
+                              sizeof(struct pxp_proc_data));
+                       memcpy(&desc->layer_param.s0_param,
+                              &pxp_conf.s0_param,
+                              sizeof(struct pxp_layer_param));
+               } else if (i == 1) {    /* Output */
+                       memcpy(&desc->layer_param.out_param,
+                              &pxp_conf.out_param,
+                              sizeof(struct pxp_layer_param));
+               } else {
+                       /* OverLay */
+                       memcpy(&desc->layer_param.ol_param,
+                              &pxp_conf.ol_param,
+                              sizeof(struct pxp_layer_param));
+               }
+
+               desc = desc->next;
+       }
+
+       cookie = txd->tx_submit(txd);
+       if (cookie < 0) {
+               pr_err("Error tx_submit\n");
+               return -EIO;
+       }
+
+       atomic_inc(&irq_info[chan_id].irq_pending);
+
+       return 0;
+}
+
+static int pxp_device_open(struct inode *inode, struct file *filp)
+{
+       struct pxp_file *priv;
+
+       priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+
+       if (!priv)
+               return -ENOMEM;
+
+       filp->private_data = priv;
+       priv->filp = filp;
+
+       idr_init(&priv->buffer_idr);
+       spin_lock_init(&priv->buffer_lock);
+
+       idr_init(&priv->channel_idr);
+       spin_lock_init(&priv->channel_lock);
+
+       return 0;
+}
+
+static int pxp_device_release(struct inode *inode, struct file *filp)
+{
+       struct pxp_file *priv = filp->private_data;
+
+       if (priv) {
+               pxp_free_channels(priv);
+               pxp_free_buffers(priv);
+               kfree(priv);
+               filp->private_data = NULL;
+       }
+
+       return 0;
+}
+
+static int pxp_device_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       int request_size;
+       struct hlist_node *node;
+       struct pxp_buf_obj *obj;
+
+       request_size = vma->vm_end - vma->vm_start;
+
+       pr_debug("start=0x%x, pgoff=0x%x, size=0x%x\n",
+                (unsigned int)(vma->vm_start), (unsigned int)(vma->vm_pgoff),
+                request_size);
+
+       node = pxp_ht_find_key(&bufhash, vma->vm_pgoff);
+       if (!node)
+               return -EINVAL;
+
+       obj = list_entry(node, struct pxp_buf_obj, item);
+       if (obj->offset + (obj->size >> PAGE_SHIFT) <
+               (vma->vm_pgoff + vma_pages(vma)))
+               return -ENOMEM;
+
+       switch (obj->mem_type) {
+       case MEMORY_TYPE_UNCACHED:
+               vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+               break;
+       case MEMORY_TYPE_WC:
+               vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+               break;
+       case MEMORY_TYPE_CACHED:
+               break;
+       default:
+               pr_err("%s: invalid memory type!\n", __func__);
+               return -EINVAL;
+       }
+
+       return remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
+                              request_size, vma->vm_page_prot) ? -EAGAIN : 0;
+}
+
+static bool chan_filter(struct dma_chan *chan, void *arg)
+{
+       if (imx_dma_is_pxp(chan))
+               return true;
+       else
+               return false;
+}
+
+static long pxp_device_ioctl(struct file *filp,
+                           unsigned int cmd, unsigned long arg)
+{
+       int ret = 0;
+       struct pxp_file *file_priv = filp->private_data;
+
+       switch (cmd) {
+       case PXP_IOC_GET_CHAN:
+               {
+                       int ret;
+                       struct dma_chan *chan = NULL;
+                       dma_cap_mask_t mask;
+                       struct pxp_chan_obj *obj = NULL;
+
+                       pr_debug("drv: PXP_IOC_GET_CHAN Line %d\n", __LINE__);
+
+                       dma_cap_zero(mask);
+                       dma_cap_set(DMA_SLAVE, mask);
+                       dma_cap_set(DMA_PRIVATE, mask);
+
+                       chan = dma_request_channel(mask, chan_filter, NULL);
+                       if (!chan) {
+                               pr_err("Unsccessfully received channel!\n");
+                               return -EBUSY;
+                       }
+
+                       pr_debug("Successfully received channel."
+                                "chan_id %d\n", chan->chan_id);
+
+                       obj = kzalloc(sizeof(*obj), GFP_KERNEL);
+                       if (!obj) {
+                               dma_release_channel(chan);
+                               return -ENOMEM;
+                       }
+                       obj->chan = chan;
+
+                       ret = pxp_channel_handle_create(file_priv, obj,
+                                                       &obj->handle);
+                       if (ret) {
+                               dma_release_channel(chan);
+                               kfree(obj);
+                               return ret;
+                       }
+
+                       init_waitqueue_head(&(irq_info[chan->chan_id].waitq));
+                       if (put_user(obj->handle, (u32 __user *) arg)) {
+                               pxp_channel_handle_delete(file_priv, obj->handle);
+                               dma_release_channel(chan);
+                               kfree(obj);
+                               return -EFAULT;
+                       }
+
+                       break;
+               }
+       case PXP_IOC_PUT_CHAN:
+               {
+                       int handle;
+                       struct pxp_chan_obj *obj;
+
+                       if (get_user(handle, (u32 __user *) arg))
+                               return -EFAULT;
+
+                       pr_debug("%d release handle %d\n", __LINE__, handle);
+
+                       obj = pxp_channel_object_lookup(file_priv, handle);
+                       if (!obj)
+                               return -EINVAL;
+
+                       pxp_channel_handle_delete(file_priv, obj->handle);
+                       dma_release_channel(obj->chan);
+                       kfree(obj);
+
+                       break;
+               }
+       case PXP_IOC_CONFIG_CHAN:
+               {
+                       int ret;
+
+                       ret = pxp_ioc_config_chan(file_priv, arg);
+                       if (ret)
+                               return ret;
+
+                       break;
+               }
+       case PXP_IOC_START_CHAN:
+               {
+                       int handle;
+                       struct pxp_chan_obj *obj = NULL;
+
+                       if (get_user(handle, (u32 __user *) arg))
+                               return -EFAULT;
+
+                       obj = pxp_channel_object_lookup(file_priv, handle);
+                       if (!obj)
+                               return -EINVAL;
+
+                       dma_async_issue_pending(obj->chan);
+
+                       break;
+               }
+       case PXP_IOC_GET_PHYMEM:
+               {
+                       struct pxp_mem_desc buffer;
+                       struct pxp_buf_obj *obj;
+
+                       ret = copy_from_user(&buffer,
+                                            (struct pxp_mem_desc *)arg,
+                                            sizeof(struct pxp_mem_desc));
+                       if (ret)
+                               return -EFAULT;
+
+                       pr_debug("[ALLOC] mem alloc size = 0x%x\n",
+                                buffer.size);
+
+                       obj = kzalloc(sizeof(*obj), GFP_KERNEL);
+                       if (!obj)
+                               return -ENOMEM;
+                       obj->size = buffer.size;
+                       obj->mem_type = buffer.mtype;
+
+                       ret = pxp_alloc_dma_buffer(obj);
+                       if (ret == -1) {
+                               printk(KERN_ERR
+                                      "Physical memory allocation error!\n");
+                               kfree(obj);
+                               return ret;
+                       }
+
+                       ret = pxp_buffer_handle_create(file_priv, obj, &obj->handle);
+                       if (ret) {
+                               pxp_free_dma_buffer(obj);
+                               kfree(obj);
+                               return ret;
+                       }
+                       buffer.handle = obj->handle;
+                       buffer.phys_addr = obj->offset;
+
+                       ret = copy_to_user((void __user *)arg, &buffer,
+                                          sizeof(struct pxp_mem_desc));
+                       if (ret) {
+                               pxp_buffer_handle_delete(file_priv, buffer.handle);
+                               pxp_free_dma_buffer(obj);
+                               kfree(obj);
+                               return -EFAULT;
+                       }
+
+                       pxp_ht_insert_item(&bufhash, obj);
+
+                       break;
+               }
+       case PXP_IOC_PUT_PHYMEM:
+               {
+                       struct pxp_mem_desc pxp_mem;
+                       struct pxp_buf_obj *obj;
+
+                       ret = copy_from_user(&pxp_mem,
+                                            (struct pxp_mem_desc *)arg,
+                                            sizeof(struct pxp_mem_desc));
+                       if (ret)
+                               return -EACCES;
+
+                       obj = pxp_buffer_object_lookup(file_priv, pxp_mem.handle);
+                       if (!obj)
+                               return -EINVAL;
+
+                       ret = pxp_buffer_handle_delete(file_priv, obj->handle);
+                       if (ret)
+                               return ret;
+
+                       pxp_ht_remove_item(&bufhash, obj);
+                       pxp_free_dma_buffer(obj);
+                       kfree(obj);
+
+                       break;
+               }
+       case PXP_IOC_FLUSH_PHYMEM:
+               {
+                       int ret;
+                       struct pxp_mem_flush flush;
+                       struct pxp_buf_obj *obj;
+
+                       ret = copy_from_user(&flush,
+                                            (struct pxp_mem_flush *)arg,
+                                            sizeof(struct pxp_mem_flush));
+                       if (ret)
+                               return -EACCES;
+
+                       obj = pxp_buffer_object_lookup(file_priv, flush.handle);
+                       if (!obj)
+                               return -EINVAL;
+
+                       switch (flush.type) {
+                       case CACHE_CLEAN:
+                               dma_sync_single_for_device(NULL, obj->offset,
+                                               obj->size, DMA_TO_DEVICE);
+                               break;
+                       case CACHE_INVALIDATE:
+                               dma_sync_single_for_device(NULL, obj->offset,
+                                               obj->size, DMA_FROM_DEVICE);
+                               break;
+                       case CACHE_FLUSH:
+                               dma_sync_single_for_device(NULL, obj->offset,
+                                               obj->size, DMA_TO_DEVICE);
+                               dma_sync_single_for_device(NULL, obj->offset,
+                                               obj->size, DMA_FROM_DEVICE);
+                               break;
+                       default:
+                               pr_err("%s: invalid cache flush type\n", __func__);
+                               return -EINVAL;
+                       }
+
+                       break;
+               }
+       case PXP_IOC_WAIT4CMPLT:
+               {
+                       struct pxp_chan_handle chan_handle;
+                       int ret, chan_id, handle;
+                       struct pxp_chan_obj *obj = NULL;
+
+                       ret = copy_from_user(&chan_handle,
+                                            (struct pxp_chan_handle *)arg,
+                                            sizeof(struct pxp_chan_handle));
+                       if (ret)
+                               return -EFAULT;
+
+                       handle = chan_handle.handle;
+                       obj = pxp_channel_object_lookup(file_priv, handle);
+                       if (!obj)
+                               return -EINVAL;
+                       chan_id = obj->chan->chan_id;
+
+                       ret = wait_event_interruptible
+                           (irq_info[chan_id].waitq,
+                            (atomic_read(&irq_info[chan_id].irq_pending) == 0));
+                       if (ret < 0)
+                               return -ERESTARTSYS;
+
+                       chan_handle.hist_status = irq_info[chan_id].hist_status;
+                       ret = copy_to_user((struct pxp_chan_handle *)arg,
+                                          &chan_handle,
+                                          sizeof(struct pxp_chan_handle));
+                       if (ret)
+                               return -EFAULT;
+                       break;
+               }
+       default:
+               break;
+       }
+
+       return 0;
+}
+
+static const struct file_operations pxp_device_fops = {
+       .open = pxp_device_open,
+       .release = pxp_device_release,
+       .unlocked_ioctl = pxp_device_ioctl,
+       .mmap = pxp_device_mmap,
+};
+
+static struct miscdevice pxp_device_miscdev = {
+       .minor = MISC_DYNAMIC_MINOR,
+       .name = "pxp_device",
+       .fops = &pxp_device_fops,
+};
+
+int register_pxp_device(void)
+{
+       int ret;
+
+       ret = misc_register(&pxp_device_miscdev);
+       if (ret)
+               return ret;
+
+       ret = pxp_ht_create(&bufhash, BUFFER_HASH_ORDER);
+       if (ret)
+               return ret;
+       spin_lock_init(&(bufhash.hash_lock));
+
+       pr_debug("PxP_Device registered Successfully\n");
+       return 0;
+}
+
+void unregister_pxp_device(void)
+{
+       pxp_ht_destroy(&bufhash);
+       misc_deregister(&pxp_device_miscdev);
+}
diff --git a/drivers/dma/pxp/pxp_dma_v2.c b/drivers/dma/pxp/pxp_dma_v2.c
new file mode 100644 (file)
index 0000000..0345640
--- /dev/null
@@ -0,0 +1,1840 @@
+/*
+ * Copyright (C) 2010-2014 Freescale Semiconductor, 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
+ *
+ */
+/*
+ * Based on STMP378X PxP driver
+ * Copyright 2008-2009 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+#include <linux/busfreq-imx6.h>
+#include <linux/clk.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmaengine.h>
+#include <linux/freezer.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/kthread.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/pxp_dma.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/timer.h>
+#include <linux/vmalloc.h>
+#include <linux/workqueue.h>
+
+#include "regs-pxp_v2.h"
+
+#define        PXP_DOWNSCALE_THRESHOLD         0x4000
+
+static LIST_HEAD(head);
+static int timeout_in_ms = 600;
+static unsigned int block_size;
+static struct kmem_cache *tx_desc_cache;
+
+struct pxp_dma {
+       struct dma_device dma;
+};
+
+struct pxps {
+       struct platform_device *pdev;
+       struct clk *clk;
+       struct clk *clk_disp_axi;       /* may exist on some SoC for gating */
+       void __iomem *base;
+       int irq;                /* PXP IRQ to the CPU */
+
+       spinlock_t lock;
+       struct mutex clk_mutex;
+       int clk_stat;
+#define        CLK_STAT_OFF            0
+#define        CLK_STAT_ON             1
+       int pxp_ongoing;
+       int lut_state;
+
+       struct device *dev;
+       struct pxp_dma pxp_dma;
+       struct pxp_channel channel[NR_PXP_VIRT_CHANNEL];
+       struct work_struct work;
+
+       /* describes most recent processing configuration */
+       struct pxp_config_data pxp_conf_state;
+
+       /* to turn clock off when pxp is inactive */
+       struct timer_list clk_timer;
+
+       /* for pxp config dispatch asynchronously*/
+       struct task_struct *dispatch;
+       wait_queue_head_t thread_waitq;
+       struct completion complete;
+};
+
+#define to_pxp_dma(d) container_of(d, struct pxp_dma, dma)
+#define to_tx_desc(tx) container_of(tx, struct pxp_tx_desc, txd)
+#define to_pxp_channel(d) container_of(d, struct pxp_channel, dma_chan)
+#define to_pxp(id) container_of(id, struct pxps, pxp_dma)
+
+#define PXP_DEF_BUFS   2
+#define PXP_MIN_PIX    8
+
+/*
+ * PXP common functions
+ */
+static void dump_pxp_reg(struct pxps *pxp)
+{
+       dev_dbg(pxp->dev, "PXP_CTRL 0x%x",
+               __raw_readl(pxp->base + HW_PXP_CTRL));
+       dev_dbg(pxp->dev, "PXP_STAT 0x%x",
+               __raw_readl(pxp->base + HW_PXP_STAT));
+       dev_dbg(pxp->dev, "PXP_OUT_CTRL 0x%x",
+               __raw_readl(pxp->base + HW_PXP_OUT_CTRL));
+       dev_dbg(pxp->dev, "PXP_OUT_BUF 0x%x",
+               __raw_readl(pxp->base + HW_PXP_OUT_BUF));
+       dev_dbg(pxp->dev, "PXP_OUT_BUF2 0x%x",
+               __raw_readl(pxp->base + HW_PXP_OUT_BUF2));
+       dev_dbg(pxp->dev, "PXP_OUT_PITCH 0x%x",
+               __raw_readl(pxp->base + HW_PXP_OUT_PITCH));
+       dev_dbg(pxp->dev, "PXP_OUT_LRC 0x%x",
+               __raw_readl(pxp->base + HW_PXP_OUT_LRC));
+       dev_dbg(pxp->dev, "PXP_OUT_PS_ULC 0x%x",
+               __raw_readl(pxp->base + HW_PXP_OUT_PS_ULC));
+       dev_dbg(pxp->dev, "PXP_OUT_PS_LRC 0x%x",
+               __raw_readl(pxp->base + HW_PXP_OUT_PS_LRC));
+       dev_dbg(pxp->dev, "PXP_OUT_AS_ULC 0x%x",
+               __raw_readl(pxp->base + HW_PXP_OUT_AS_ULC));
+       dev_dbg(pxp->dev, "PXP_OUT_AS_LRC 0x%x",
+               __raw_readl(pxp->base + HW_PXP_OUT_AS_LRC));
+       dev_dbg(pxp->dev, "PXP_PS_CTRL 0x%x",
+               __raw_readl(pxp->base + HW_PXP_PS_CTRL));
+       dev_dbg(pxp->dev, "PXP_PS_BUF 0x%x",
+               __raw_readl(pxp->base + HW_PXP_PS_BUF));
+       dev_dbg(pxp->dev, "PXP_PS_UBUF 0x%x",
+               __raw_readl(pxp->base + HW_PXP_PS_UBUF));
+       dev_dbg(pxp->dev, "PXP_PS_VBUF 0x%x",
+               __raw_readl(pxp->base + HW_PXP_PS_VBUF));
+       dev_dbg(pxp->dev, "PXP_PS_PITCH 0x%x",
+               __raw_readl(pxp->base + HW_PXP_PS_PITCH));
+       dev_dbg(pxp->dev, "PXP_PS_BACKGROUND 0x%x",
+               __raw_readl(pxp->base + HW_PXP_PS_BACKGROUND));
+       dev_dbg(pxp->dev, "PXP_PS_SCALE 0x%x",
+               __raw_readl(pxp->base + HW_PXP_PS_SCALE));
+       dev_dbg(pxp->dev, "PXP_PS_OFFSET 0x%x",
+               __raw_readl(pxp->base + HW_PXP_PS_OFFSET));
+       dev_dbg(pxp->dev, "PXP_PS_CLRKEYLOW 0x%x",
+               __raw_readl(pxp->base + HW_PXP_PS_CLRKEYLOW));
+       dev_dbg(pxp->dev, "PXP_PS_CLRKEYHIGH 0x%x",
+               __raw_readl(pxp->base + HW_PXP_PS_CLRKEYHIGH));
+       dev_dbg(pxp->dev, "PXP_AS_CTRL 0x%x",
+               __raw_readl(pxp->base + HW_PXP_AS_CTRL));
+       dev_dbg(pxp->dev, "PXP_AS_BUF 0x%x",
+               __raw_readl(pxp->base + HW_PXP_AS_BUF));
+       dev_dbg(pxp->dev, "PXP_AS_PITCH 0x%x",
+               __raw_readl(pxp->base + HW_PXP_AS_PITCH));
+       dev_dbg(pxp->dev, "PXP_AS_CLRKEYLOW 0x%x",
+               __raw_readl(pxp->base + HW_PXP_AS_CLRKEYLOW));
+       dev_dbg(pxp->dev, "PXP_AS_CLRKEYHIGH 0x%x",
+               __raw_readl(pxp->base + HW_PXP_AS_CLRKEYHIGH));
+       dev_dbg(pxp->dev, "PXP_CSC1_COEF0 0x%x",
+               __raw_readl(pxp->base + HW_PXP_CSC1_COEF0));
+       dev_dbg(pxp->dev, "PXP_CSC1_COEF1 0x%x",
+               __raw_readl(pxp->base + HW_PXP_CSC1_COEF1));
+       dev_dbg(pxp->dev, "PXP_CSC1_COEF2 0x%x",
+               __raw_readl(pxp->base + HW_PXP_CSC1_COEF2));
+       dev_dbg(pxp->dev, "PXP_CSC2_CTRL 0x%x",
+               __raw_readl(pxp->base + HW_PXP_CSC2_CTRL));
+       dev_dbg(pxp->dev, "PXP_CSC2_COEF0 0x%x",
+               __raw_readl(pxp->base + HW_PXP_CSC2_COEF0));
+       dev_dbg(pxp->dev, "PXP_CSC2_COEF1 0x%x",
+               __raw_readl(pxp->base + HW_PXP_CSC2_COEF1));
+       dev_dbg(pxp->dev, "PXP_CSC2_COEF2 0x%x",
+               __raw_readl(pxp->base + HW_PXP_CSC2_COEF2));
+       dev_dbg(pxp->dev, "PXP_CSC2_COEF3 0x%x",
+               __raw_readl(pxp->base + HW_PXP_CSC2_COEF3));
+       dev_dbg(pxp->dev, "PXP_CSC2_COEF4 0x%x",
+               __raw_readl(pxp->base + HW_PXP_CSC2_COEF4));
+       dev_dbg(pxp->dev, "PXP_CSC2_COEF5 0x%x",
+               __raw_readl(pxp->base + HW_PXP_CSC2_COEF5));
+       dev_dbg(pxp->dev, "PXP_LUT_CTRL 0x%x",
+               __raw_readl(pxp->base + HW_PXP_LUT_CTRL));
+       dev_dbg(pxp->dev, "PXP_LUT_ADDR 0x%x",
+               __raw_readl(pxp->base + HW_PXP_LUT_ADDR));
+       dev_dbg(pxp->dev, "PXP_LUT_DATA 0x%x",
+               __raw_readl(pxp->base + HW_PXP_LUT_DATA));
+       dev_dbg(pxp->dev, "PXP_LUT_EXTMEM 0x%x",
+               __raw_readl(pxp->base + HW_PXP_LUT_EXTMEM));
+       dev_dbg(pxp->dev, "PXP_CFA 0x%x",
+               __raw_readl(pxp->base + HW_PXP_CFA));
+       dev_dbg(pxp->dev, "PXP_HIST_CTRL 0x%x",
+               __raw_readl(pxp->base + HW_PXP_HIST_CTRL));
+       dev_dbg(pxp->dev, "PXP_HIST2_PARAM 0x%x",
+               __raw_readl(pxp->base + HW_PXP_HIST2_PARAM));
+       dev_dbg(pxp->dev, "PXP_HIST4_PARAM 0x%x",
+               __raw_readl(pxp->base + HW_PXP_HIST4_PARAM));
+       dev_dbg(pxp->dev, "PXP_HIST8_PARAM0 0x%x",
+               __raw_readl(pxp->base + HW_PXP_HIST8_PARAM0));
+       dev_dbg(pxp->dev, "PXP_HIST8_PARAM1 0x%x",
+               __raw_readl(pxp->base + HW_PXP_HIST8_PARAM1));
+       dev_dbg(pxp->dev, "PXP_HIST16_PARAM0 0x%x",
+               __raw_readl(pxp->base + HW_PXP_HIST16_PARAM0));
+       dev_dbg(pxp->dev, "PXP_HIST16_PARAM1 0x%x",
+               __raw_readl(pxp->base + HW_PXP_HIST16_PARAM1));
+       dev_dbg(pxp->dev, "PXP_HIST16_PARAM2 0x%x",
+               __raw_readl(pxp->base + HW_PXP_HIST16_PARAM2));
+       dev_dbg(pxp->dev, "PXP_HIST16_PARAM3 0x%x",
+               __raw_readl(pxp->base + HW_PXP_HIST16_PARAM3));
+       dev_dbg(pxp->dev, "PXP_POWER 0x%x",
+               __raw_readl(pxp->base + HW_PXP_POWER));
+       dev_dbg(pxp->dev, "PXP_NEXT 0x%x",
+               __raw_readl(pxp->base + HW_PXP_NEXT));
+       dev_dbg(pxp->dev, "PXP_DEBUGCTRL 0x%x",
+               __raw_readl(pxp->base + HW_PXP_DEBUGCTRL));
+       dev_dbg(pxp->dev, "PXP_DEBUG 0x%x",
+               __raw_readl(pxp->base + HW_PXP_DEBUG));
+       dev_dbg(pxp->dev, "PXP_VERSION 0x%x",
+               __raw_readl(pxp->base + HW_PXP_VERSION));
+}
+
+static bool is_yuv(u32 pix_fmt)
+{
+       if ((pix_fmt == PXP_PIX_FMT_YUYV) |
+           (pix_fmt == PXP_PIX_FMT_UYVY) |
+           (pix_fmt == PXP_PIX_FMT_YVYU) |
+           (pix_fmt == PXP_PIX_FMT_VYUY) |
+           (pix_fmt == PXP_PIX_FMT_Y41P) |
+           (pix_fmt == PXP_PIX_FMT_YUV444) |
+           (pix_fmt == PXP_PIX_FMT_NV12) |
+           (pix_fmt == PXP_PIX_FMT_NV16) |
+           (pix_fmt == PXP_PIX_FMT_NV61) |
+           (pix_fmt == PXP_PIX_FMT_GREY) |
+           (pix_fmt == PXP_PIX_FMT_GY04) |
+           (pix_fmt == PXP_PIX_FMT_YVU410P) |
+           (pix_fmt == PXP_PIX_FMT_YUV410P) |
+           (pix_fmt == PXP_PIX_FMT_YVU420P) |
+           (pix_fmt == PXP_PIX_FMT_YUV420P) |
+           (pix_fmt == PXP_PIX_FMT_YUV420P2) |
+           (pix_fmt == PXP_PIX_FMT_YVU422P) |
+           (pix_fmt == PXP_PIX_FMT_YUV422P)) {
+               return true;
+       } else {
+               return false;
+       }
+}
+
+static void pxp_soft_reset(struct pxps *pxp)
+{
+       __raw_writel(BM_PXP_CTRL_SFTRST, pxp->base + HW_PXP_CTRL_CLR);
+       __raw_writel(BM_PXP_CTRL_CLKGATE, pxp->base + HW_PXP_CTRL_CLR);
+
+       __raw_writel(BM_PXP_CTRL_SFTRST, pxp->base + HW_PXP_CTRL_SET);
+       while (!(__raw_readl(pxp->base + HW_PXP_CTRL) & BM_PXP_CTRL_CLKGATE))
+               dev_dbg(pxp->dev, "%s: wait for clock gate off", __func__);
+
+       __raw_writel(BM_PXP_CTRL_SFTRST, pxp->base + HW_PXP_CTRL_CLR);
+       __raw_writel(BM_PXP_CTRL_CLKGATE, pxp->base + HW_PXP_CTRL_CLR);
+}
+
+static void pxp_set_ctrl(struct pxps *pxp)
+{
+       struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state;
+       struct pxp_proc_data *proc_data = &pxp_conf->proc_data;
+       u32 ctrl;
+       u32 fmt_ctrl;
+       int need_swap = 0;   /* to support YUYV and YVYU formats */
+
+       /* Configure S0 input format */
+       switch (pxp_conf->s0_param.pixel_fmt) {
+       case PXP_PIX_FMT_RGB32:
+               fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__RGB888;
+               break;
+       case PXP_PIX_FMT_RGB565:
+               fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__RGB565;
+               break;
+       case PXP_PIX_FMT_RGB555:
+               fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__RGB555;
+               break;
+       case PXP_PIX_FMT_YUV420P:
+               fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__YUV420;
+               break;
+       case PXP_PIX_FMT_YVU420P:
+               fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__YUV420;
+               break;
+       case PXP_PIX_FMT_GREY:
+               fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__Y8;
+               break;
+       case PXP_PIX_FMT_GY04:
+               fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__Y4;
+               break;
+       case PXP_PIX_FMT_YUV444:
+               fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__YUV1P444;
+               break;
+       case PXP_PIX_FMT_YUV422P:
+               fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__YUV422;
+               break;
+       case PXP_PIX_FMT_UYVY:
+               fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__UYVY1P422;
+               break;
+       case PXP_PIX_FMT_YUYV:
+               fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__UYVY1P422;
+               need_swap = 1;
+               break;
+       case PXP_PIX_FMT_VYUY:
+               fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__VYUY1P422;
+               break;
+       case PXP_PIX_FMT_YVYU:
+               fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__VYUY1P422;
+               need_swap = 1;
+               break;
+       case PXP_PIX_FMT_NV12:
+               fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__YUV2P420;
+               break;
+       case PXP_PIX_FMT_NV21:
+               fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__YVU2P420;
+               break;
+       case PXP_PIX_FMT_NV16:
+               fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__YUV2P422;
+               break;
+       case PXP_PIX_FMT_NV61:
+               fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__YVU2P422;
+               break;
+       default:
+               fmt_ctrl = 0;
+       }
+
+       ctrl = BF_PXP_PS_CTRL_FORMAT(fmt_ctrl) | BF_PXP_PS_CTRL_SWAP(need_swap);
+       __raw_writel(ctrl, pxp->base + HW_PXP_PS_CTRL_SET);
+
+       /* Configure output format based on out_channel format */
+       switch (pxp_conf->out_param.pixel_fmt) {
+       case PXP_PIX_FMT_RGB32:
+               fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__RGB888;
+               break;
+       case PXP_PIX_FMT_BGRA32:
+               fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__ARGB8888;
+               break;
+       case PXP_PIX_FMT_RGB24:
+               fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__RGB888P;
+               break;
+       case PXP_PIX_FMT_RGB565:
+               fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__RGB565;
+               break;
+       case PXP_PIX_FMT_RGB555:
+               fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__RGB555;
+               break;
+       case PXP_PIX_FMT_GREY:
+               fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__Y8;
+               break;
+       case PXP_PIX_FMT_GY04:
+               fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__Y4;
+               break;
+       case PXP_PIX_FMT_UYVY:
+               fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__UYVY1P422;
+               break;
+       case PXP_PIX_FMT_VYUY:
+               fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__VYUY1P422;
+               break;
+       case PXP_PIX_FMT_NV12:
+               fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__YUV2P420;
+               break;
+       case PXP_PIX_FMT_NV21:
+               fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__YVU2P420;
+               break;
+       case PXP_PIX_FMT_NV16:
+               fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__YUV2P422;
+               break;
+       case PXP_PIX_FMT_NV61:
+               fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__YVU2P422;
+               break;
+       default:
+               fmt_ctrl = 0;
+       }
+
+       ctrl = BF_PXP_OUT_CTRL_FORMAT(fmt_ctrl);
+       __raw_writel(ctrl, pxp->base + HW_PXP_OUT_CTRL);
+
+       ctrl = 0;
+       if (proc_data->scaling)
+               ;
+       if (proc_data->vflip)
+               ctrl |= BM_PXP_CTRL_VFLIP;
+       if (proc_data->hflip)
+               ctrl |= BM_PXP_CTRL_HFLIP;
+       if (proc_data->rotate) {
+               ctrl |= BF_PXP_CTRL_ROTATE(proc_data->rotate / 90);
+               if (proc_data->rot_pos)
+                       ctrl |= BM_PXP_CTRL_ROT_POS;
+       }
+
+       /* In default, the block size is set to 8x8
+        * But block size can be set to 16x16 due to
+        * blocksize variable modification
+        */
+       ctrl |= block_size << 23;
+
+       __raw_writel(ctrl, pxp->base + HW_PXP_CTRL);
+}
+
+static int pxp_start(struct pxps *pxp)
+{
+       __raw_writel(BM_PXP_CTRL_IRQ_ENABLE, pxp->base + HW_PXP_CTRL_SET);
+       __raw_writel(BM_PXP_CTRL_ENABLE, pxp->base + HW_PXP_CTRL_SET);
+       dump_pxp_reg(pxp);
+
+       return 0;
+}
+
+static void pxp_set_outbuf(struct pxps *pxp)
+{
+       struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state;
+       struct pxp_layer_param *out_params = &pxp_conf->out_param;
+       struct pxp_proc_data *proc_data = &pxp_conf->proc_data;
+
+       __raw_writel(out_params->paddr, pxp->base + HW_PXP_OUT_BUF);
+
+       if (proc_data->rotate == 90 || proc_data->rotate == 270) {
+               if (proc_data->rot_pos == 1)
+                       __raw_writel(BF_PXP_OUT_LRC_X(proc_data->drect.height - 1) |
+                                       BF_PXP_OUT_LRC_Y(proc_data->drect.width - 1),
+                                       pxp->base + HW_PXP_OUT_LRC);
+               else
+                       __raw_writel(BF_PXP_OUT_LRC_X(proc_data->drect.width - 1) |
+                                       BF_PXP_OUT_LRC_Y(proc_data->drect.height - 1),
+                                       pxp->base + HW_PXP_OUT_LRC);
+       } else
+               __raw_writel(BF_PXP_OUT_LRC_X(proc_data->drect.width - 1) |
+                               BF_PXP_OUT_LRC_Y(proc_data->drect.height - 1),
+                               pxp->base + HW_PXP_OUT_LRC);
+
+       if (out_params->pixel_fmt == PXP_PIX_FMT_RGB24) {
+               __raw_writel(out_params->stride * 3,
+                               pxp->base + HW_PXP_OUT_PITCH);
+       } else if (out_params->pixel_fmt == PXP_PIX_FMT_BGRA32 ||
+                out_params->pixel_fmt == PXP_PIX_FMT_RGB32) {
+               __raw_writel(out_params->stride << 2,
+                               pxp->base + HW_PXP_OUT_PITCH);
+       } else if (out_params->pixel_fmt == PXP_PIX_FMT_RGB565) {
+               __raw_writel(out_params->stride << 1,
+                               pxp->base + HW_PXP_OUT_PITCH);
+       } else if (out_params->pixel_fmt == PXP_PIX_FMT_UYVY ||
+               (out_params->pixel_fmt == PXP_PIX_FMT_VYUY)) {
+               __raw_writel(out_params->stride << 1,
+                               pxp->base + HW_PXP_OUT_PITCH);
+       } else if (out_params->pixel_fmt == PXP_PIX_FMT_GREY ||
+                  out_params->pixel_fmt == PXP_PIX_FMT_NV12 ||
+                  out_params->pixel_fmt == PXP_PIX_FMT_NV21 ||
+                  out_params->pixel_fmt == PXP_PIX_FMT_NV16 ||
+                  out_params->pixel_fmt == PXP_PIX_FMT_NV61) {
+               __raw_writel(out_params->stride,
+                               pxp->base + HW_PXP_OUT_PITCH);
+       } else if (out_params->pixel_fmt == PXP_PIX_FMT_GY04) {
+               __raw_writel(out_params->stride >> 1,
+                               pxp->base + HW_PXP_OUT_PITCH);
+       } else {
+               __raw_writel(0, pxp->base + HW_PXP_OUT_PITCH);
+       }
+
+       /* set global alpha if necessary */
+       if (out_params->global_alpha_enable) {
+               __raw_writel(out_params->global_alpha << 24,
+                               pxp->base + HW_PXP_OUT_CTRL_SET);
+               __raw_writel(BM_PXP_OUT_CTRL_ALPHA_OUTPUT,
+                               pxp->base + HW_PXP_OUT_CTRL_SET);
+       }
+}
+
+static void pxp_set_s0colorkey(struct pxps *pxp)
+{
+       struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state;
+       struct pxp_layer_param *s0_params = &pxp_conf->s0_param;
+
+       /* Low and high are set equal. V4L does not allow a chromakey range */
+       if (s0_params->color_key_enable == 0 || s0_params->color_key == -1) {
+               /* disable color key */
+               __raw_writel(0xFFFFFF, pxp->base + HW_PXP_PS_CLRKEYLOW);
+               __raw_writel(0, pxp->base + HW_PXP_PS_CLRKEYHIGH);
+       } else {
+               __raw_writel(s0_params->color_key,
+                            pxp->base + HW_PXP_PS_CLRKEYLOW);
+               __raw_writel(s0_params->color_key,
+                            pxp->base + HW_PXP_PS_CLRKEYHIGH);
+       }
+}
+
+static void pxp_set_olcolorkey(int layer_no, struct pxps *pxp)
+{
+       struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state;
+       struct pxp_layer_param *ol_params = &pxp_conf->ol_param[layer_no];
+
+       /* Low and high are set equal. V4L does not allow a chromakey range */
+       if (ol_params->color_key_enable != 0 && ol_params->color_key != -1) {
+               __raw_writel(ol_params->color_key,
+                            pxp->base + HW_PXP_AS_CLRKEYLOW);
+               __raw_writel(ol_params->color_key,
+                            pxp->base + HW_PXP_AS_CLRKEYHIGH);
+       } else {
+               /* disable color key */
+               __raw_writel(0xFFFFFF, pxp->base + HW_PXP_AS_CLRKEYLOW);
+               __raw_writel(0, pxp->base + HW_PXP_AS_CLRKEYHIGH);
+       }
+}
+
+static void pxp_set_oln(int layer_no, struct pxps *pxp)
+{
+       struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state;
+       struct pxp_layer_param *olparams_data = &pxp_conf->ol_param[layer_no];
+       dma_addr_t phys_addr = olparams_data->paddr;
+       u32 pitch = olparams_data->stride ? olparams_data->stride :
+                                           olparams_data->width;
+
+       __raw_writel(phys_addr, pxp->base + HW_PXP_AS_BUF);
+
+       /* Fixme */
+       if (olparams_data->width == 0 && olparams_data->height == 0) {
+               __raw_writel(0xffffffff, pxp->base + HW_PXP_OUT_AS_ULC);
+               __raw_writel(0x0, pxp->base + HW_PXP_OUT_AS_LRC);
+       } else {
+               __raw_writel(0x0, pxp->base + HW_PXP_OUT_AS_ULC);
+               if (pxp_conf->proc_data.rotate == 90 ||
+                   pxp_conf->proc_data.rotate == 270) {
+                       if (pxp_conf->proc_data.rot_pos == 1) {
+                               __raw_writel(BF_PXP_OUT_AS_LRC_X(olparams_data->height - 1) |
+                                       BF_PXP_OUT_AS_LRC_Y(olparams_data->width - 1),
+                                       pxp->base + HW_PXP_OUT_AS_LRC);
+                       } else {
+                               __raw_writel(BF_PXP_OUT_AS_LRC_X(olparams_data->width - 1) |
+                                       BF_PXP_OUT_AS_LRC_Y(olparams_data->height - 1),
+                                       pxp->base + HW_PXP_OUT_AS_LRC);
+                       }
+               } else {
+                       __raw_writel(BF_PXP_OUT_AS_LRC_X(olparams_data->width - 1) |
+                               BF_PXP_OUT_AS_LRC_Y(olparams_data->height - 1),
+                               pxp->base + HW_PXP_OUT_AS_LRC);
+               }
+       }
+
+       if ((olparams_data->pixel_fmt == PXP_PIX_FMT_BGRA32) |
+                (olparams_data->pixel_fmt == PXP_PIX_FMT_RGB32)) {
+               __raw_writel(pitch << 2,
+                               pxp->base + HW_PXP_AS_PITCH);
+       } else if (olparams_data->pixel_fmt == PXP_PIX_FMT_RGB565) {
+               __raw_writel(pitch << 1,
+                               pxp->base + HW_PXP_AS_PITCH);
+       } else {
+               __raw_writel(0, pxp->base + HW_PXP_AS_PITCH);
+       }
+}
+
+static void pxp_set_olparam(int layer_no, struct pxps *pxp)
+{
+       struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state;
+       struct pxp_layer_param *olparams_data = &pxp_conf->ol_param[layer_no];
+       u32 olparam;
+
+       olparam = BF_PXP_AS_CTRL_ALPHA(olparams_data->global_alpha);
+       if (olparams_data->pixel_fmt == PXP_PIX_FMT_RGB32) {
+               olparam |=
+                   BF_PXP_AS_CTRL_FORMAT(BV_PXP_AS_CTRL_FORMAT__RGB888);
+       } else if (olparams_data->pixel_fmt == PXP_PIX_FMT_BGRA32) {
+               olparam |=
+                   BF_PXP_AS_CTRL_FORMAT(BV_PXP_AS_CTRL_FORMAT__ARGB8888);
+               if (!olparams_data->combine_enable) {
+                       olparam |=
+                               BF_PXP_AS_CTRL_ALPHA_CTRL
+                               (BV_PXP_AS_CTRL_ALPHA_CTRL__ROPs);
+                       olparam |= 0x3 << 16;
+               }
+       } else if (olparams_data->pixel_fmt == PXP_PIX_FMT_RGB565) {
+               olparam |=
+                   BF_PXP_AS_CTRL_FORMAT(BV_PXP_AS_CTRL_FORMAT__RGB565);
+       }
+       if (olparams_data->global_alpha_enable) {
+               if (olparams_data->global_override) {
+                       olparam |=
+                               BF_PXP_AS_CTRL_ALPHA_CTRL
+                               (BV_PXP_AS_CTRL_ALPHA_CTRL__Override);
+               } else {
+                       olparam |=
+                               BF_PXP_AS_CTRL_ALPHA_CTRL
+                               (BV_PXP_AS_CTRL_ALPHA_CTRL__Multiply);
+               }
+               if (olparams_data->alpha_invert)
+                       olparam |= BM_PXP_AS_CTRL_ALPHA_INVERT;
+       }
+       if (olparams_data->color_key_enable)
+               olparam |= BM_PXP_AS_CTRL_ENABLE_COLORKEY;
+
+       __raw_writel(olparam, pxp->base + HW_PXP_AS_CTRL);
+}
+
+static void pxp_set_s0param(struct pxps *pxp)
+{
+       struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state;
+       struct pxp_proc_data *proc_data = &pxp_conf->proc_data;
+       struct pxp_layer_param *out_params = &pxp_conf->out_param;
+       u32 s0param;
+
+       if (proc_data->drect.left != 0 || proc_data->drect.top != 0) {
+               out_params->paddr += (proc_data->drect.top * out_params->stride +
+                               proc_data->drect.left) * 2;
+               proc_data->drect.left = proc_data->drect.top = 0;
+       }
+
+       /* Since user apps always pass the rotated drect
+        * to this driver, we need to first swap the width
+        * and height which is used to calculate the scale
+        * factors later.
+        */
+       if (proc_data->rotate == 90 || proc_data->rotate == 270) {
+               int temp;
+               temp = proc_data->drect.width;
+               proc_data->drect.width = proc_data->drect.height;
+               proc_data->drect.height = temp;
+       }
+
+       /* contains the coordinate for the PS in the OUTPUT buffer. */
+       if ((pxp_conf->s0_param).width == 0 &&
+               (pxp_conf->s0_param).height == 0) {
+               __raw_writel(0xffffffff, pxp->base + HW_PXP_OUT_PS_ULC);
+               __raw_writel(0x0, pxp->base + HW_PXP_OUT_PS_LRC);
+       } else {
+               s0param = BF_PXP_OUT_PS_ULC_X(proc_data->drect.left);
+               s0param |= BF_PXP_OUT_PS_ULC_Y(proc_data->drect.top);
+               __raw_writel(s0param, pxp->base + HW_PXP_OUT_PS_ULC);
+               /* In PXP, the two different rotation
+                * position requires different settings
+                * on OUT_PS_LRC register
+                */
+               if (proc_data->rot_pos == 1) {
+                       s0param = BF_PXP_OUT_PS_LRC_X(proc_data->drect.left +
+                                       proc_data->drect.height - 1);
+                       s0param |= BF_PXP_OUT_PS_LRC_Y(proc_data->drect.top +
+                                       proc_data->drect.width - 1);
+               } else {
+                       s0param = BF_PXP_OUT_PS_LRC_X(proc_data->drect.left +
+                                       proc_data->drect.width - 1);
+                       s0param |= BF_PXP_OUT_PS_LRC_Y(proc_data->drect.top +
+                                       proc_data->drect.height - 1);
+               }
+               __raw_writel(s0param, pxp->base + HW_PXP_OUT_PS_LRC);
+       }
+}
+
+/* crop behavior is re-designed in h/w. */
+static void pxp_set_s0crop(struct pxps *pxp)
+{
+       /*
+        * place-holder, it's implemented in other functions in this driver.
+        * Refer to "Clipping source images" section in RM for detail.
+        */
+}
+
+static int pxp_set_scaling(struct pxps *pxp)
+{
+       int ret = 0;
+       u32 xscale, yscale, s0scale;
+       u32 decx, decy, xdec = 0, ydec = 0;
+       struct pxp_proc_data *proc_data = &pxp->pxp_conf_state.proc_data;
+       struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state;
+       struct pxp_layer_param *s0_params = &pxp_conf->s0_param;
+
+       proc_data->scaling = 1;
+       decx = proc_data->srect.width / proc_data->drect.width;
+       decy = proc_data->srect.height / proc_data->drect.height;
+       if (decx > 1) {
+               if (decx >= 2 && decx < 4) {
+                       decx = 2;
+                       xdec = 1;
+               } else if (decx >= 4 && decx < 8) {
+                       decx = 4;
+                       xdec = 2;
+               } else if (decx >= 8) {
+                       decx = 8;
+                       xdec = 3;
+               }
+               xscale = proc_data->srect.width * 0x1000 /
+                        (proc_data->drect.width * decx);
+       } else {
+               if (!is_yuv(s0_params->pixel_fmt) ||
+                   (s0_params->pixel_fmt == PXP_PIX_FMT_GREY) ||
+                   (s0_params->pixel_fmt == PXP_PIX_FMT_GY04) ||
+                   (s0_params->pixel_fmt == PXP_PIX_FMT_YUV444))
+                       xscale = (proc_data->srect.width - 1) * 0x1000 /
+                                (proc_data->drect.width - 1);
+               else
+                       xscale = (proc_data->srect.width - 2) * 0x1000 /
+                                (proc_data->drect.width - 1);
+       }
+       if (decy > 1) {
+               if (decy >= 2 && decy < 4) {
+                       decy = 2;
+                       ydec = 1;
+               } else if (decy >= 4 && decy < 8) {
+                       decy = 4;
+                       ydec = 2;
+               } else if (decy >= 8) {
+                       decy = 8;
+                       ydec = 3;
+               }
+               yscale = proc_data->srect.height * 0x1000 /
+                        (proc_data->drect.height * decy);
+       } else
+               yscale = (proc_data->srect.height - 1) * 0x1000 /
+                        (proc_data->drect.height - 1);
+
+       __raw_writel((xdec << 10) | (ydec << 8), pxp->base + HW_PXP_PS_CTRL);
+
+       if (xscale > PXP_DOWNSCALE_THRESHOLD)
+               xscale = PXP_DOWNSCALE_THRESHOLD;
+       if (yscale > PXP_DOWNSCALE_THRESHOLD)
+               yscale = PXP_DOWNSCALE_THRESHOLD;
+       s0scale = BF_PXP_PS_SCALE_YSCALE(yscale) |
+               BF_PXP_PS_SCALE_XSCALE(xscale);
+       __raw_writel(s0scale, pxp->base + HW_PXP_PS_SCALE);
+
+       pxp_set_ctrl(pxp);
+
+       return ret;
+}
+
+static void pxp_set_bg(struct pxps *pxp)
+{
+       __raw_writel(pxp->pxp_conf_state.proc_data.bgcolor,
+                    pxp->base + HW_PXP_PS_BACKGROUND);
+}
+
+static void pxp_set_lut(struct pxps *pxp)
+{
+       struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state;
+       int lut_op = pxp_conf->proc_data.lut_transform;
+       u32 reg_val;
+       int i;
+       bool use_cmap = (lut_op & PXP_LUT_USE_CMAP) ? true : false;
+       u8 *cmap = pxp_conf->proc_data.lut_map;
+       u32 entry_src;
+       u32 pix_val;
+       u8 entry[4];
+
+       /*
+        * If LUT already configured as needed, return...
+        * Unless CMAP is needed and it has been updated.
+        */
+       if ((pxp->lut_state == lut_op) &&
+               !(use_cmap && pxp_conf->proc_data.lut_map_updated))
+               return;
+
+       if (lut_op == PXP_LUT_NONE) {
+               __raw_writel(BM_PXP_LUT_CTRL_BYPASS,
+                            pxp->base + HW_PXP_LUT_CTRL);
+       } else if (((lut_op & PXP_LUT_INVERT) != 0)
+               && ((lut_op & PXP_LUT_BLACK_WHITE) != 0)) {
+               /* Fill out LUT table with inverted monochromized values */
+
+               /* clear bypass bit, set lookup mode & out mode */
+               __raw_writel(BF_PXP_LUT_CTRL_LOOKUP_MODE
+                               (BV_PXP_LUT_CTRL_LOOKUP_MODE__DIRECT_Y8) |
+                               BF_PXP_LUT_CTRL_OUT_MODE
+                               (BV_PXP_LUT_CTRL_OUT_MODE__Y8),
+                               pxp->base + HW_PXP_LUT_CTRL);
+
+               /* Initialize LUT address to 0 and set NUM_BYTES to 0 */
+               __raw_writel(0, pxp->base + HW_PXP_LUT_ADDR);
+
+               /* LUT address pointer auto-increments after each data write */
+               for (pix_val = 0; pix_val < 256; pix_val += 4) {
+                       for (i = 0; i < 4; i++) {
+                               entry_src = use_cmap ?
+                                       cmap[pix_val + i] : pix_val + i;
+                               entry[i] = (entry_src < 0x80) ? 0xFF : 0x00;
+                       }
+                       reg_val = (entry[3] << 24) | (entry[2] << 16) |
+                               (entry[1] << 8) | entry[0];
+                       __raw_writel(reg_val, pxp->base + HW_PXP_LUT_DATA);
+               }
+       } else if ((lut_op & PXP_LUT_INVERT) != 0) {
+               /* Fill out LUT table with 8-bit inverted values */
+
+               /* clear bypass bit, set lookup mode & out mode */
+               __raw_writel(BF_PXP_LUT_CTRL_LOOKUP_MODE
+                               (BV_PXP_LUT_CTRL_LOOKUP_MODE__DIRECT_Y8) |
+                               BF_PXP_LUT_CTRL_OUT_MODE
+                               (BV_PXP_LUT_CTRL_OUT_MODE__Y8),
+                               pxp->base + HW_PXP_LUT_CTRL);
+
+               /* Initialize LUT address to 0 and set NUM_BYTES to 0 */
+               __raw_writel(0, pxp->base + HW_PXP_LUT_ADDR);
+
+               /* LUT address pointer auto-increments after each data write */
+               for (pix_val = 0; pix_val < 256; pix_val += 4) {
+                       for (i = 0; i < 4; i++) {
+                               entry_src = use_cmap ?
+                                       cmap[pix_val + i] : pix_val + i;
+                               entry[i] = ~entry_src & 0xFF;
+                       }
+                       reg_val = (entry[3] << 24) | (entry[2] << 16) |
+                               (entry[1] << 8) | entry[0];
+                       __raw_writel(reg_val, pxp->base + HW_PXP_LUT_DATA);
+               }
+       } else if ((lut_op & PXP_LUT_BLACK_WHITE) != 0) {
+               /* Fill out LUT table with 8-bit monochromized values */
+
+               /* clear bypass bit, set lookup mode & out mode */
+               __raw_writel(BF_PXP_LUT_CTRL_LOOKUP_MODE
+                               (BV_PXP_LUT_CTRL_LOOKUP_MODE__DIRECT_Y8) |
+                               BF_PXP_LUT_CTRL_OUT_MODE
+                               (BV_PXP_LUT_CTRL_OUT_MODE__Y8),
+                               pxp->base + HW_PXP_LUT_CTRL);
+
+               /* Initialize LUT address to 0 and set NUM_BYTES to 0 */
+               __raw_writel(0, pxp->base + HW_PXP_LUT_ADDR);
+
+               /* LUT address pointer auto-increments after each data write */
+               for (pix_val = 0; pix_val < 256; pix_val += 4) {
+                       for (i = 0; i < 4; i++) {
+                               entry_src = use_cmap ?
+                                       cmap[pix_val + i] : pix_val + i;
+                               entry[i] = (entry_src < 0x80) ? 0x00 : 0xFF;
+                       }
+                       reg_val = (entry[3] << 24) | (entry[2] << 16) |
+                               (entry[1] << 8) | entry[0];
+                       __raw_writel(reg_val, pxp->base + HW_PXP_LUT_DATA);
+               }
+       } else if (use_cmap) {
+               /* Fill out LUT table using colormap values */
+
+               /* clear bypass bit, set lookup mode & out mode */
+               __raw_writel(BF_PXP_LUT_CTRL_LOOKUP_MODE
+                               (BV_PXP_LUT_CTRL_LOOKUP_MODE__DIRECT_Y8) |
+                               BF_PXP_LUT_CTRL_OUT_MODE
+                               (BV_PXP_LUT_CTRL_OUT_MODE__Y8),
+                               pxp->base + HW_PXP_LUT_CTRL);
+
+               /* Initialize LUT address to 0 and set NUM_BYTES to 0 */
+               __raw_writel(0, pxp->base + HW_PXP_LUT_ADDR);
+
+               /* LUT address pointer auto-increments after each data write */
+               for (pix_val = 0; pix_val < 256; pix_val += 4) {
+                       for (i = 0; i < 4; i++)
+                               entry[i] = cmap[pix_val + i];
+                       reg_val = (entry[3] << 24) | (entry[2] << 16) |
+                               (entry[1] << 8) | entry[0];
+                       __raw_writel(reg_val, pxp->base + HW_PXP_LUT_DATA);
+               }
+       }
+
+       pxp->lut_state = lut_op;
+}
+
+static void pxp_set_csc(struct pxps *pxp)
+{
+       struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state;
+       struct pxp_layer_param *s0_params = &pxp_conf->s0_param;
+       struct pxp_layer_param *ol_params = &pxp_conf->ol_param[0];
+       struct pxp_layer_param *out_params = &pxp_conf->out_param;
+
+       bool input_is_YUV = is_yuv(s0_params->pixel_fmt);
+       bool output_is_YUV = is_yuv(out_params->pixel_fmt);
+
+       if (input_is_YUV && output_is_YUV) {
+               /*
+                * Input = YUV, Output = YUV
+                * No CSC unless we need to do combining
+                */
+               if (ol_params->combine_enable) {
+                       /* Must convert to RGB for combining with RGB overlay */
+
+                       /* CSC1 - YUV->RGB */
+                       __raw_writel(0x04030000, pxp->base + HW_PXP_CSC1_COEF0);
+                       __raw_writel(0x01230208, pxp->base + HW_PXP_CSC1_COEF1);
+                       __raw_writel(0x076b079c, pxp->base + HW_PXP_CSC1_COEF2);
+
+                       /* CSC2 - RGB->YUV */
+                       __raw_writel(0x4, pxp->base + HW_PXP_CSC2_CTRL);
+                       __raw_writel(0x0096004D, pxp->base + HW_PXP_CSC2_COEF0);
+                       __raw_writel(0x05DA001D, pxp->base + HW_PXP_CSC2_COEF1);
+                       __raw_writel(0x007005B6, pxp->base + HW_PXP_CSC2_COEF2);
+                       __raw_writel(0x057C009E, pxp->base + HW_PXP_CSC2_COEF3);
+                       __raw_writel(0x000005E6, pxp->base + HW_PXP_CSC2_COEF4);
+                       __raw_writel(0x00000000, pxp->base + HW_PXP_CSC2_COEF5);
+               } else {
+                       /* Input & Output both YUV, so bypass both CSCs */
+
+                       /* CSC1 - Bypass */
+                       __raw_writel(0x40000000, pxp->base + HW_PXP_CSC1_COEF0);
+
+                       /* CSC2 - Bypass */
+                       __raw_writel(0x1, pxp->base + HW_PXP_CSC2_CTRL);
+               }
+       } else if (input_is_YUV && !output_is_YUV) {
+               /*
+                * Input = YUV, Output = RGB
+                * Use CSC1 to convert to RGB
+                */
+
+               /* CSC1 - YUV->RGB */
+               __raw_writel(0x84ab01f0, pxp->base + HW_PXP_CSC1_COEF0);
+               __raw_writel(0x01980204, pxp->base + HW_PXP_CSC1_COEF1);
+               __raw_writel(0x0730079c, pxp->base + HW_PXP_CSC1_COEF2);
+
+               /* CSC2 - Bypass */
+               __raw_writel(0x1, pxp->base + HW_PXP_CSC2_CTRL);
+       } else if (!input_is_YUV && output_is_YUV) {
+               /*
+                * Input = RGB, Output = YUV
+                * Use CSC2 to convert to YUV
+                */
+
+               /* CSC1 - Bypass */
+               __raw_writel(0x40000000, pxp->base + HW_PXP_CSC1_COEF0);
+
+               /* CSC2 - RGB->YUV */
+               __raw_writel(0x4, pxp->base + HW_PXP_CSC2_CTRL);
+               __raw_writel(0x0096004D, pxp->base + HW_PXP_CSC2_COEF0);
+               __raw_writel(0x05DA001D, pxp->base + HW_PXP_CSC2_COEF1);
+               __raw_writel(0x007005B6, pxp->base + HW_PXP_CSC2_COEF2);
+               __raw_writel(0x057C009E, pxp->base + HW_PXP_CSC2_COEF3);
+               __raw_writel(0x000005E6, pxp->base + HW_PXP_CSC2_COEF4);
+               __raw_writel(0x00000000, pxp->base + HW_PXP_CSC2_COEF5);
+       } else {
+               /*
+                * Input = RGB, Output = RGB
+                * Input & Output both RGB, so bypass both CSCs
+                */
+
+               /* CSC1 - Bypass */
+               __raw_writel(0x40000000, pxp->base + HW_PXP_CSC1_COEF0);
+
+               /* CSC2 - Bypass */
+               __raw_writel(0x1, pxp->base + HW_PXP_CSC2_CTRL);
+       }
+
+       /* YCrCb colorspace */
+       /* Not sure when we use this...no YCrCb formats are defined for PxP */
+       /*
+          __raw_writel(0x84ab01f0, HW_PXP_CSCCOEFF0_ADDR);
+          __raw_writel(0x01230204, HW_PXP_CSCCOEFF1_ADDR);
+          __raw_writel(0x0730079c, HW_PXP_CSCCOEFF2_ADDR);
+        */
+
+}
+
+static void pxp_set_s0buf(struct pxps *pxp)
+{
+       struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state;
+       struct pxp_layer_param *s0_params = &pxp_conf->s0_param;
+       struct pxp_proc_data *proc_data = &pxp_conf->proc_data;
+       dma_addr_t Y, U, V;
+       dma_addr_t Y1, U1, V1;
+       u32 offset, bpp = 1;
+       u32 pitch = s0_params->stride ? s0_params->stride :
+                                       s0_params->width;
+
+       Y = s0_params->paddr;
+
+       if (s0_params->pixel_fmt == PXP_PIX_FMT_RGB565)
+               bpp = 2;
+       else if (s0_params->pixel_fmt == PXP_PIX_FMT_RGB32)
+               bpp = 4;
+       offset = (proc_data->srect.top * s0_params->width +
+                proc_data->srect.left) * bpp;
+       /* clipping or cropping */
+       Y1 = Y + offset;
+       __raw_writel(Y1, pxp->base + HW_PXP_PS_BUF);
+       if ((s0_params->pixel_fmt == PXP_PIX_FMT_YUV420P) ||
+           (s0_params->pixel_fmt == PXP_PIX_FMT_YVU420P) ||
+           (s0_params->pixel_fmt == PXP_PIX_FMT_GREY)    ||
+           (s0_params->pixel_fmt == PXP_PIX_FMT_YUV422P)) {
+               /* Set to 1 if YUV format is 4:2:2 rather than 4:2:0 */
+               int s = 2;
+               if (s0_params->pixel_fmt == PXP_PIX_FMT_YUV422P)
+                       s = 1;
+
+               offset = proc_data->srect.top * s0_params->width / 4 +
+                        proc_data->srect.left / 2;
+               U = Y + (s0_params->width * s0_params->height);
+               U1 = U + offset;
+               V = U + ((s0_params->width * s0_params->height) >> s);
+               V1 = V + offset;
+               if (s0_params->pixel_fmt == PXP_PIX_FMT_YVU420P) {
+                       __raw_writel(V1, pxp->base + HW_PXP_PS_UBUF);
+                       __raw_writel(U1, pxp->base + HW_PXP_PS_VBUF);
+               } else {
+                       __raw_writel(U1, pxp->base + HW_PXP_PS_UBUF);
+                       __raw_writel(V1, pxp->base + HW_PXP_PS_VBUF);
+               }
+       } else if ((s0_params->pixel_fmt == PXP_PIX_FMT_NV12) ||
+                (s0_params->pixel_fmt == PXP_PIX_FMT_NV21) ||
+                (s0_params->pixel_fmt == PXP_PIX_FMT_NV16) ||
+                (s0_params->pixel_fmt == PXP_PIX_FMT_NV61)) {
+               int s = 2;
+               if ((s0_params->pixel_fmt == PXP_PIX_FMT_NV16) ||
+                   (s0_params->pixel_fmt == PXP_PIX_FMT_NV61))
+                       s = 1;
+
+               offset = (proc_data->srect.top * s0_params->width +
+                         proc_data->srect.left) / s;
+               U = Y + (s0_params->width * s0_params->height);
+               U1 = U + offset;
+
+               __raw_writel(U1, pxp->base + HW_PXP_PS_UBUF);
+       }
+
+       /* TODO: only support RGB565, Y8, Y4, YUV420 */
+       if (s0_params->pixel_fmt == PXP_PIX_FMT_GREY ||
+           s0_params->pixel_fmt == PXP_PIX_FMT_YUV420P ||
+           s0_params->pixel_fmt == PXP_PIX_FMT_YVU420P ||
+           s0_params->pixel_fmt == PXP_PIX_FMT_NV12 ||
+           s0_params->pixel_fmt == PXP_PIX_FMT_NV21 ||
+           s0_params->pixel_fmt == PXP_PIX_FMT_NV16 ||
+           s0_params->pixel_fmt == PXP_PIX_FMT_NV61 ||
+           s0_params->pixel_fmt == PXP_PIX_FMT_YUV422P) {
+               __raw_writel(pitch, pxp->base + HW_PXP_PS_PITCH);
+       }
+       else if (s0_params->pixel_fmt == PXP_PIX_FMT_GY04)
+               __raw_writel(pitch >> 1,
+                               pxp->base + HW_PXP_PS_PITCH);
+       else if (s0_params->pixel_fmt == PXP_PIX_FMT_RGB32 ||
+                        s0_params->pixel_fmt == PXP_PIX_FMT_YUV444)
+               __raw_writel(pitch << 2,
+                               pxp->base + HW_PXP_PS_PITCH);
+       else if (s0_params->pixel_fmt == PXP_PIX_FMT_UYVY ||
+                s0_params->pixel_fmt == PXP_PIX_FMT_YUYV ||
+                s0_params->pixel_fmt == PXP_PIX_FMT_VYUY ||
+                s0_params->pixel_fmt == PXP_PIX_FMT_YVYU)
+               __raw_writel(pitch << 1,
+                               pxp->base + HW_PXP_PS_PITCH);
+       else if (s0_params->pixel_fmt == PXP_PIX_FMT_RGB565)
+               __raw_writel(pitch << 1,
+                               pxp->base + HW_PXP_PS_PITCH);
+       else
+               __raw_writel(0, pxp->base + HW_PXP_PS_PITCH);
+}
+
+/**
+ * pxp_config() - configure PxP for a processing task
+ * @pxps:      PXP context.
+ * @pxp_chan:  PXP channel.
+ * @return:    0 on success or negative error code on failure.
+ */
+static int pxp_config(struct pxps *pxp, struct pxp_channel *pxp_chan)
+{
+       struct pxp_config_data *pxp_conf_data = &pxp->pxp_conf_state;
+       int ol_nr;
+       int i;
+
+       /* Configure PxP regs */
+       pxp_set_ctrl(pxp);
+       pxp_set_s0param(pxp);
+       pxp_set_s0crop(pxp);
+       pxp_set_scaling(pxp);
+       ol_nr = pxp_conf_data->layer_nr - 2;
+       while (ol_nr > 0) {
+               i = pxp_conf_data->layer_nr - 2 - ol_nr;
+               pxp_set_oln(i, pxp);
+               pxp_set_olparam(i, pxp);
+               /* only the color key in higher overlay will take effect. */
+               pxp_set_olcolorkey(i, pxp);
+               ol_nr--;
+       }
+       pxp_set_s0colorkey(pxp);
+       pxp_set_csc(pxp);
+       pxp_set_bg(pxp);
+       pxp_set_lut(pxp);
+
+       pxp_set_s0buf(pxp);
+       pxp_set_outbuf(pxp);
+
+       return 0;
+}
+
+static void pxp_clk_enable(struct pxps *pxp)
+{
+       mutex_lock(&pxp->clk_mutex);
+
+       if (pxp->clk_stat == CLK_STAT_ON) {
+               mutex_unlock(&pxp->clk_mutex);
+               return;
+       }
+
+       pm_runtime_get_sync(pxp->dev);
+
+       if (pxp->clk_disp_axi)
+               clk_prepare_enable(pxp->clk_disp_axi);
+       clk_prepare_enable(pxp->clk);
+       pxp->clk_stat = CLK_STAT_ON;
+
+       mutex_unlock(&pxp->clk_mutex);
+}
+
+static void pxp_clk_disable(struct pxps *pxp)
+{
+       unsigned long flags;
+
+       mutex_lock(&pxp->clk_mutex);
+
+       if (pxp->clk_stat == CLK_STAT_OFF) {
+               mutex_unlock(&pxp->clk_mutex);
+               return;
+       }
+
+       spin_lock_irqsave(&pxp->lock, flags);
+       if ((pxp->pxp_ongoing == 0) && list_empty(&head)) {
+               spin_unlock_irqrestore(&pxp->lock, flags);
+               clk_disable_unprepare(pxp->clk);
+               if (pxp->clk_disp_axi)
+                       clk_disable_unprepare(pxp->clk_disp_axi);
+               pxp->clk_stat = CLK_STAT_OFF;
+       } else
+               spin_unlock_irqrestore(&pxp->lock, flags);
+
+       pm_runtime_put_sync_suspend(pxp->dev);
+
+       mutex_unlock(&pxp->clk_mutex);
+}
+
+static inline void clkoff_callback(struct work_struct *w)
+{
+       struct pxps *pxp = container_of(w, struct pxps, work);
+
+       pxp_clk_disable(pxp);
+}
+
+static void pxp_clkoff_timer(unsigned long arg)
+{
+       struct pxps *pxp = (struct pxps *)arg;
+
+       if ((pxp->pxp_ongoing == 0) && list_empty(&head))
+               schedule_work(&pxp->work);
+       else
+               mod_timer(&pxp->clk_timer,
+                         jiffies + msecs_to_jiffies(timeout_in_ms));
+}
+
+static struct pxp_tx_desc *pxpdma_first_queued(struct pxp_channel *pxp_chan)
+{
+       return list_entry(pxp_chan->queue.next, struct pxp_tx_desc, list);
+}
+
+/* called with pxp_chan->lock held */
+static void __pxpdma_dostart(struct pxp_channel *pxp_chan)
+{
+       struct pxp_dma *pxp_dma = to_pxp_dma(pxp_chan->dma_chan.device);
+       struct pxps *pxp = to_pxp(pxp_dma);
+       struct pxp_tx_desc *desc;
+       struct pxp_tx_desc *child;
+       int i = 0;
+
+       memset(&pxp->pxp_conf_state, 0,  sizeof(struct pxp_config_data));
+       /* S0 */
+       desc = list_first_entry(&head, struct pxp_tx_desc, list);
+       memcpy(&pxp->pxp_conf_state.s0_param,
+              &desc->layer_param.s0_param, sizeof(struct pxp_layer_param));
+       memcpy(&pxp->pxp_conf_state.proc_data,
+              &desc->proc_data, sizeof(struct pxp_proc_data));
+
+       /* Save PxP configuration */
+       list_for_each_entry(child, &desc->tx_list, list) {
+               if (i == 0) {   /* Output */
+                       memcpy(&pxp->pxp_conf_state.out_param,
+                              &child->layer_param.out_param,
+                              sizeof(struct pxp_layer_param));
+               } else {        /* Overlay */
+                       memcpy(&pxp->pxp_conf_state.ol_param[i - 1],
+                              &child->layer_param.ol_param,
+                              sizeof(struct pxp_layer_param));
+               }
+
+               i++;
+       }
+       pr_debug("%s:%d S0 w/h %d/%d paddr %08x\n", __func__, __LINE__,
+                pxp->pxp_conf_state.s0_param.width,
+                pxp->pxp_conf_state.s0_param.height,
+                pxp->pxp_conf_state.s0_param.paddr);
+       pr_debug("%s:%d OUT w/h %d/%d paddr %08x\n", __func__, __LINE__,
+                pxp->pxp_conf_state.out_param.width,
+                pxp->pxp_conf_state.out_param.height,
+                pxp->pxp_conf_state.out_param.paddr);
+}
+
+static void pxpdma_dostart_work(struct pxps *pxp)
+{
+       struct pxp_channel *pxp_chan = NULL;
+       unsigned long flags;
+       struct pxp_tx_desc *desc = NULL;
+
+       spin_lock_irqsave(&pxp->lock, flags);
+
+       desc = list_entry(head.next, struct pxp_tx_desc, list);
+       pxp_chan = to_pxp_channel(desc->txd.chan);
+
+       __pxpdma_dostart(pxp_chan);
+
+       /* Configure PxP */
+       pxp_config(pxp, pxp_chan);
+
+       pxp_start(pxp);
+
+       spin_unlock_irqrestore(&pxp->lock, flags);
+}
+
+static void pxpdma_dequeue(struct pxp_channel *pxp_chan, struct pxps *pxp)
+{
+       unsigned long flags;
+       struct pxp_tx_desc *desc = NULL;
+
+       do {
+               desc = pxpdma_first_queued(pxp_chan);
+               spin_lock_irqsave(&pxp->lock, flags);
+               list_move_tail(&desc->list, &head);
+               spin_unlock_irqrestore(&pxp->lock, flags);
+       } while (!list_empty(&pxp_chan->queue));
+}
+
+static dma_cookie_t pxp_tx_submit(struct dma_async_tx_descriptor *tx)
+{
+       struct pxp_tx_desc *desc = to_tx_desc(tx);
+       struct pxp_channel *pxp_chan = to_pxp_channel(tx->chan);
+       dma_cookie_t cookie;
+
+       dev_dbg(&pxp_chan->dma_chan.dev->device, "received TX\n");
+
+       /* pxp_chan->lock can be taken under ichan->lock, but not v.v. */
+       spin_lock(&pxp_chan->lock);
+
+       cookie = pxp_chan->dma_chan.cookie;
+
+       if (++cookie < 0)
+               cookie = 1;
+
+       /* from dmaengine.h: "last cookie value returned to client" */
+       pxp_chan->dma_chan.cookie = cookie;
+       tx->cookie = cookie;
+
+       /* Here we add the tx descriptor to our PxP task queue. */
+       list_add_tail(&desc->list, &pxp_chan->queue);
+
+       spin_unlock(&pxp_chan->lock);
+
+       dev_dbg(&pxp_chan->dma_chan.dev->device, "done TX\n");
+
+       return cookie;
+}
+
+/**
+ * pxp_init_channel() - initialize a PXP channel.
+ * @pxp_dma:   PXP DMA context.
+ * @pchan:  pointer to the channel object.
+ * @return      0 on success or negative error code on failure.
+ */
+static int pxp_init_channel(struct pxp_dma *pxp_dma,
+                           struct pxp_channel *pxp_chan)
+{
+       int ret = 0;
+
+       /*
+        * We are using _virtual_ channel here.
+        * Each channel contains all parameters of corresponding layers
+        * for one transaction; each layer is represented as one descriptor
+        * (i.e., pxp_tx_desc) here.
+        */
+
+       INIT_LIST_HEAD(&pxp_chan->queue);
+
+       return ret;
+}
+
+static irqreturn_t pxp_irq(int irq, void *dev_id)
+{
+       struct pxps *pxp = dev_id;
+       struct pxp_channel *pxp_chan;
+       struct pxp_tx_desc *desc;
+       struct pxp_tx_desc *child, *_child;
+       dma_async_tx_callback callback;
+       void *callback_param;
+       unsigned long flags;
+       u32 hist_status;
+
+       dump_pxp_reg(pxp);
+
+       hist_status =
+           __raw_readl(pxp->base + HW_PXP_HIST_CTRL) & BM_PXP_HIST_CTRL_STATUS;
+
+       __raw_writel(BM_PXP_STAT_IRQ, pxp->base + HW_PXP_STAT_CLR);
+
+       /* set the SFTRST bit to be 1 to reset
+        * the PXP block to its default state.
+        */
+       pxp_soft_reset(pxp);
+
+       spin_lock_irqsave(&pxp->lock, flags);
+
+       if (list_empty(&head)) {
+               pxp->pxp_ongoing = 0;
+               spin_unlock_irqrestore(&pxp->lock, flags);
+               return IRQ_NONE;
+       }
+
+       /* Get descriptor and call callback */
+       desc = list_entry(head.next, struct pxp_tx_desc, list);
+       pxp_chan = to_pxp_channel(desc->txd.chan);
+
+       pxp_chan->completed = desc->txd.cookie;
+
+       callback = desc->txd.callback;
+       callback_param = desc->txd.callback_param;
+
+       /* Send histogram status back to caller */
+       desc->hist_status = hist_status;
+
+       if ((desc->txd.flags & DMA_PREP_INTERRUPT) && callback)
+               callback(callback_param);
+
+       pxp_chan->status = PXP_CHANNEL_INITIALIZED;
+
+       list_for_each_entry_safe(child, _child, &desc->tx_list, list) {
+               list_del_init(&child->list);
+               kmem_cache_free(tx_desc_cache, (void *)child);
+       }
+       list_del_init(&desc->list);
+       kmem_cache_free(tx_desc_cache, (void *)desc);
+
+       complete(&pxp->complete);
+       pxp->pxp_ongoing = 0;
+       mod_timer(&pxp->clk_timer, jiffies + msecs_to_jiffies(timeout_in_ms));
+
+       spin_unlock_irqrestore(&pxp->lock, flags);
+
+       return IRQ_HANDLED;
+}
+
+/* allocate/free dma tx descriptor dynamically*/
+static struct pxp_tx_desc *pxpdma_desc_alloc(struct pxp_channel *pxp_chan)
+{
+       struct pxp_tx_desc *desc = NULL;
+       struct dma_async_tx_descriptor *txd = NULL;
+
+       desc = kmem_cache_alloc(tx_desc_cache, GFP_KERNEL | __GFP_ZERO);
+       if (desc == NULL)
+               return NULL;
+
+       INIT_LIST_HEAD(&desc->list);
+       INIT_LIST_HEAD(&desc->tx_list);
+       txd = &desc->txd;
+       dma_async_tx_descriptor_init(txd, &pxp_chan->dma_chan);
+       txd->tx_submit = pxp_tx_submit;
+
+       return desc;
+}
+
+/* Allocate and initialise a transfer descriptor. */
+static struct dma_async_tx_descriptor *pxp_prep_slave_sg(struct dma_chan *chan,
+                                                        struct scatterlist
+                                                        *sgl,
+                                                        unsigned int sg_len,
+                                                        enum
+                                                        dma_transfer_direction
+                                                        direction,
+                                                        unsigned long tx_flags,
+                                                        void *context)
+{
+       struct pxp_channel *pxp_chan = to_pxp_channel(chan);
+       struct pxp_dma *pxp_dma = to_pxp_dma(chan->device);
+       struct pxps *pxp = to_pxp(pxp_dma);
+       struct pxp_tx_desc *desc = NULL;
+       struct pxp_tx_desc *first = NULL, *prev = NULL;
+       struct scatterlist *sg;
+       dma_addr_t phys_addr;
+       int i;
+
+       if (direction != DMA_DEV_TO_MEM && direction != DMA_MEM_TO_DEV) {
+               dev_err(chan->device->dev, "Invalid DMA direction %d!\n",
+                       direction);
+               return NULL;
+       }
+
+       if (unlikely(sg_len < 2))
+               return NULL;
+
+       for_each_sg(sgl, sg, sg_len, i) {
+               desc = pxpdma_desc_alloc(pxp_chan);
+               if (!desc) {
+                       dev_err(chan->device->dev, "no enough memory to allocate tx descriptor\n");
+                       return NULL;
+               }
+
+               phys_addr = sg_dma_address(sg);
+
+               if (!first) {
+                       first = desc;
+
+                       desc->layer_param.s0_param.paddr = phys_addr;
+               } else {
+                       list_add_tail(&desc->list, &first->tx_list);
+                       prev->next = desc;
+                       desc->next = NULL;
+
+                       if (i == 1)
+                               desc->layer_param.out_param.paddr = phys_addr;
+                       else
+                               desc->layer_param.ol_param.paddr = phys_addr;
+               }
+
+               prev = desc;
+       }
+
+       pxp->pxp_conf_state.layer_nr = sg_len;
+       first->txd.flags = tx_flags;
+       first->len = sg_len;
+       pr_debug("%s:%d first %p, first->len %d, flags %08x\n",
+                __func__, __LINE__, first, first->len, first->txd.flags);
+
+       return &first->txd;
+}
+
+static void pxp_issue_pending(struct dma_chan *chan)
+{
+       struct pxp_channel *pxp_chan = to_pxp_channel(chan);
+       struct pxp_dma *pxp_dma = to_pxp_dma(chan->device);
+       struct pxps *pxp = to_pxp(pxp_dma);
+
+       spin_lock(&pxp_chan->lock);
+
+       if (list_empty(&pxp_chan->queue)) {
+               spin_unlock(&pxp_chan->lock);
+               return;
+       }
+
+       pxpdma_dequeue(pxp_chan, pxp);
+       pxp_chan->status = PXP_CHANNEL_READY;
+
+       spin_unlock(&pxp_chan->lock);
+
+       pxp_clk_enable(pxp);
+       wake_up_interruptible(&pxp->thread_waitq);
+}
+
+static void __pxp_terminate_all(struct dma_chan *chan)
+{
+       struct pxp_channel *pxp_chan = to_pxp_channel(chan);
+
+       pxp_chan->status = PXP_CHANNEL_INITIALIZED;
+}
+
+static int pxp_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
+                       unsigned long arg)
+{
+       struct pxp_channel *pxp_chan = to_pxp_channel(chan);
+
+       /* Only supports DMA_TERMINATE_ALL */
+       if (cmd != DMA_TERMINATE_ALL)
+               return -ENXIO;
+
+       spin_lock(&pxp_chan->lock);
+       __pxp_terminate_all(chan);
+       spin_unlock(&pxp_chan->lock);
+
+       return 0;
+}
+
+static int pxp_alloc_chan_resources(struct dma_chan *chan)
+{
+       struct pxp_channel *pxp_chan = to_pxp_channel(chan);
+       struct pxp_dma *pxp_dma = to_pxp_dma(chan->device);
+       int ret;
+
+       /* dmaengine.c now guarantees to only offer free channels */
+       BUG_ON(chan->client_count > 1);
+       WARN_ON(pxp_chan->status != PXP_CHANNEL_FREE);
+
+       chan->cookie = 1;
+       pxp_chan->completed = -ENXIO;
+
+       pr_debug("%s dma_chan.chan_id %d\n", __func__, chan->chan_id);
+       ret = pxp_init_channel(pxp_dma, pxp_chan);
+       if (ret < 0)
+               goto err_chan;
+
+       pxp_chan->status = PXP_CHANNEL_INITIALIZED;
+
+       dev_dbg(&chan->dev->device, "Found channel 0x%x, irq %d\n",
+               chan->chan_id, pxp_chan->eof_irq);
+
+       return ret;
+
+err_chan:
+       return ret;
+}
+
+static void pxp_free_chan_resources(struct dma_chan *chan)
+{
+       struct pxp_channel *pxp_chan = to_pxp_channel(chan);
+
+       spin_lock(&pxp_chan->lock);
+
+       __pxp_terminate_all(chan);
+
+       pxp_chan->status = PXP_CHANNEL_FREE;
+
+       spin_unlock(&pxp_chan->lock);
+}
+
+static enum dma_status pxp_tx_status(struct dma_chan *chan,
+                                    dma_cookie_t cookie,
+                                    struct dma_tx_state *txstate)
+{
+       struct pxp_channel *pxp_chan = to_pxp_channel(chan);
+
+       if (cookie != chan->cookie)
+               return DMA_ERROR;
+
+       if (txstate) {
+               txstate->last = pxp_chan->completed;
+               txstate->used = chan->cookie;
+               txstate->residue = 0;
+       }
+       return DMA_SUCCESS;
+}
+
+static int pxp_dma_init(struct pxps *pxp)
+{
+       struct pxp_dma *pxp_dma = &pxp->pxp_dma;
+       struct dma_device *dma = &pxp_dma->dma;
+       int i;
+
+       dma_cap_set(DMA_SLAVE, dma->cap_mask);
+       dma_cap_set(DMA_PRIVATE, dma->cap_mask);
+
+       /* Compulsory common fields */
+       dma->dev = pxp->dev;
+       dma->device_alloc_chan_resources = pxp_alloc_chan_resources;
+       dma->device_free_chan_resources = pxp_free_chan_resources;
+       dma->device_tx_status = pxp_tx_status;
+       dma->device_issue_pending = pxp_issue_pending;
+
+       /* Compulsory for DMA_SLAVE fields */
+       dma->device_prep_slave_sg = pxp_prep_slave_sg;
+       dma->device_control = pxp_control;
+
+       /* Initialize PxP Channels */
+       INIT_LIST_HEAD(&dma->channels);
+       for (i = 0; i < NR_PXP_VIRT_CHANNEL; i++) {
+               struct pxp_channel *pxp_chan = pxp->channel + i;
+               struct dma_chan *dma_chan = &pxp_chan->dma_chan;
+
+               spin_lock_init(&pxp_chan->lock);
+
+               /* Only one EOF IRQ for PxP, shared by all channels */
+               pxp_chan->eof_irq = pxp->irq;
+               pxp_chan->status = PXP_CHANNEL_FREE;
+               pxp_chan->completed = -ENXIO;
+               snprintf(pxp_chan->eof_name, sizeof(pxp_chan->eof_name),
+                        "PXP EOF %d", i);
+
+               dma_chan->device = &pxp_dma->dma;
+               dma_chan->cookie = 1;
+               dma_chan->chan_id = i;
+               list_add_tail(&dma_chan->device_node, &dma->channels);
+       }
+
+       return dma_async_device_register(&pxp_dma->dma);
+}
+
+static ssize_t clk_off_timeout_show(struct device *dev,
+                                   struct device_attribute *attr, char *buf)
+{
+       return sprintf(buf, "%d\n", timeout_in_ms);
+}
+
+static ssize_t clk_off_timeout_store(struct device *dev,
+                                    struct device_attribute *attr,
+                                    const char *buf, size_t count)
+{
+       int val;
+       if (sscanf(buf, "%d", &val) > 0) {
+               timeout_in_ms = val;
+               return count;
+       }
+       return -EINVAL;
+}
+
+static DEVICE_ATTR(clk_off_timeout, 0644, clk_off_timeout_show,
+                  clk_off_timeout_store);
+
+static ssize_t block_size_show(struct device *dev,
+                              struct device_attribute *attr,
+                              char *buf)
+{
+       return sprintf(buf, "%d\n", block_size);
+}
+
+static ssize_t block_size_store(struct device *dev,
+                               struct device_attribute *attr,
+                               const char *buf, size_t count)
+{
+       char **last = NULL;
+
+       block_size = simple_strtoul(buf, last, 0);
+       if (block_size > 1)
+               block_size = 1;
+
+       return count;
+}
+static DEVICE_ATTR(block_size, S_IWUSR | S_IRUGO,
+                  block_size_show, block_size_store);
+
+static const struct of_device_id imx_pxpdma_dt_ids[] = {
+       { .compatible = "fsl,imx6dl-pxp-dma", },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, imx_pxpdma_dt_ids);
+
+static int has_pending_task(struct pxps *pxp, struct pxp_channel *task)
+{
+       int found;
+       unsigned long flags;
+
+       spin_lock_irqsave(&pxp->lock, flags);
+       found = !list_empty(&head);
+       spin_unlock_irqrestore(&pxp->lock, flags);
+
+       return found;
+}
+
+static int pxp_dispatch_thread(void *argv)
+{
+       struct pxps *pxp = (struct pxps *)argv;
+       struct pxp_channel *pending = NULL;
+       unsigned long flags;
+
+       set_freezable();
+
+       while (!kthread_should_stop()) {
+               int ret;
+               ret = wait_event_freezable(pxp->thread_waitq,
+                                       has_pending_task(pxp, pending) ||
+                                       kthread_should_stop());
+               if (ret < 0)
+                       continue;
+
+               if (kthread_should_stop())
+                       break;
+
+               spin_lock_irqsave(&pxp->lock, flags);
+               pxp->pxp_ongoing = 1;
+               spin_unlock_irqrestore(&pxp->lock, flags);
+               init_completion(&pxp->complete);
+               pxpdma_dostart_work(pxp);
+               ret = wait_for_completion_timeout(&pxp->complete, 2 * HZ);
+               if (ret == 0) {
+                       printk(KERN_EMERG "%s: task is timeout\n\n", __func__);
+                       break;
+               }
+       }
+
+       return 0;
+}
+
+static int pxp_probe(struct platform_device *pdev)
+{
+       struct pxps *pxp;
+       struct resource *res;
+       int irq;
+       int err = 0;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       irq = platform_get_irq(pdev, 0);
+       if (!res || irq < 0) {
+               err = -ENODEV;
+               goto exit;
+       }
+
+       pxp = devm_kzalloc(&pdev->dev, sizeof(*pxp), GFP_KERNEL);
+       if (!pxp) {
+               dev_err(&pdev->dev, "failed to allocate control object\n");
+               err = -ENOMEM;
+               goto exit;
+       }
+
+       pxp->dev = &pdev->dev;
+
+       platform_set_drvdata(pdev, pxp);
+       pxp->irq = irq;
+
+       pxp->pxp_ongoing = 0;
+       pxp->lut_state = 0;
+
+       spin_lock_init(&pxp->lock);
+       mutex_init(&pxp->clk_mutex);
+
+       pxp->base = devm_request_and_ioremap(&pdev->dev, res);
+       if (pxp->base == NULL) {
+               dev_err(&pdev->dev, "Couldn't ioremap regs\n");
+               err = -ENODEV;
+               goto exit;
+       }
+
+       pxp->pdev = pdev;
+
+       pxp->clk_disp_axi = devm_clk_get(&pdev->dev, "disp-axi");
+       if (IS_ERR(pxp->clk_disp_axi))
+               pxp->clk_disp_axi = NULL;
+       pxp->clk = devm_clk_get(&pdev->dev, "pxp-axi");
+
+       err = devm_request_irq(&pdev->dev, pxp->irq, pxp_irq, 0,
+                               "pxp-dmaengine", pxp);
+       if (err)
+               goto exit;
+       /* Initialize DMA engine */
+       err = pxp_dma_init(pxp);
+       if (err < 0)
+               goto exit;
+
+       if (device_create_file(&pdev->dev, &dev_attr_clk_off_timeout)) {
+               dev_err(&pdev->dev,
+                       "Unable to create file from clk_off_timeout\n");
+               goto exit;
+       }
+
+       device_create_file(&pdev->dev, &dev_attr_block_size);
+       pxp_clk_enable(pxp);
+       dump_pxp_reg(pxp);
+       pxp_clk_disable(pxp);
+
+       INIT_WORK(&pxp->work, clkoff_callback);
+       init_timer(&pxp->clk_timer);
+       pxp->clk_timer.function = pxp_clkoff_timer;
+       pxp->clk_timer.data = (unsigned long)pxp;
+
+       /* allocate a kernel thread to dispatch pxp conf */
+       pxp->dispatch = kthread_run(pxp_dispatch_thread, pxp, "pxp_dispatch");
+       if (IS_ERR(pxp->dispatch)) {
+               err = PTR_ERR(pxp->dispatch);
+               goto exit;
+       }
+       init_waitqueue_head(&pxp->thread_waitq);
+       tx_desc_cache = kmem_cache_create("tx_desc", sizeof(struct pxp_tx_desc),
+                                         0, SLAB_HWCACHE_ALIGN, NULL);
+       if (!tx_desc_cache) {
+               err = -ENOMEM;
+               goto exit;
+       }
+
+       register_pxp_device();
+
+       pm_runtime_enable(pxp->dev);
+
+exit:
+       if (err)
+               dev_err(&pdev->dev, "Exiting (unsuccessfully) pxp_probe()\n");
+       return err;
+}
+
+static int pxp_remove(struct platform_device *pdev)
+{
+       struct pxps *pxp = platform_get_drvdata(pdev);
+
+       unregister_pxp_device();
+       kmem_cache_destroy(tx_desc_cache);
+       kthread_stop(pxp->dispatch);
+       cancel_work_sync(&pxp->work);
+       del_timer_sync(&pxp->clk_timer);
+       clk_disable_unprepare(pxp->clk);
+       if (pxp->clk_disp_axi)
+               clk_disable_unprepare(pxp->clk_disp_axi);
+       device_remove_file(&pdev->dev, &dev_attr_clk_off_timeout);
+       device_remove_file(&pdev->dev, &dev_attr_block_size);
+       dma_async_device_unregister(&(pxp->pxp_dma.dma));
+
+       return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int pxp_suspend(struct device *dev)
+{
+       struct pxps *pxp = dev_get_drvdata(dev);
+
+       pxp_clk_enable(pxp);
+       while (__raw_readl(pxp->base + HW_PXP_CTRL) & BM_PXP_CTRL_ENABLE)
+               ;
+
+       __raw_writel(BM_PXP_CTRL_SFTRST, pxp->base + HW_PXP_CTRL);
+       pxp_clk_disable(pxp);
+
+       return 0;
+}
+
+static int pxp_resume(struct device *dev)
+{
+       struct pxps *pxp = dev_get_drvdata(dev);
+
+       pxp_clk_enable(pxp);
+       /* Pull PxP out of reset */
+       __raw_writel(0, pxp->base + HW_PXP_CTRL);
+       pxp_clk_disable(pxp);
+
+       return 0;
+}
+#else
+#define        pxp_suspend     NULL
+#define        pxp_resume      NULL
+#endif
+
+#ifdef CONFIG_PM_RUNTIME
+static int pxp_runtime_suspend(struct device *dev)
+{
+       release_bus_freq(BUS_FREQ_HIGH);
+       dev_dbg(dev, "pxp busfreq high release.\n");
+
+       return 0;
+}
+
+static int pxp_runtime_resume(struct device *dev)
+{
+       request_bus_freq(BUS_FREQ_HIGH);
+       dev_dbg(dev, "pxp busfreq high request.\n");
+
+       return 0;
+}
+#else
+#define        pxp_runtime_suspend     NULL
+#define        pxp_runtime_resume      NULL
+#endif
+
+static const struct dev_pm_ops pxp_pm_ops = {
+       SET_RUNTIME_PM_OPS(pxp_runtime_suspend, pxp_runtime_resume, NULL)
+       SET_SYSTEM_SLEEP_PM_OPS(pxp_suspend, pxp_resume)
+};
+
+static struct platform_driver pxp_driver = {
+       .driver = {
+                       .name = "imx-pxp",
+                       .of_match_table = of_match_ptr(imx_pxpdma_dt_ids),
+                       .pm = &pxp_pm_ops,
+                  },
+       .probe = pxp_probe,
+       .remove = pxp_remove,
+};
+
+module_platform_driver(pxp_driver);
+
+
+MODULE_DESCRIPTION("i.MX PxP driver");
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_LICENSE("GPL");
diff --git a/drivers/dma/pxp/regs-pxp_v2.h b/drivers/dma/pxp/regs-pxp_v2.h
new file mode 100644 (file)
index 0000000..8b20dde
--- /dev/null
@@ -0,0 +1,1152 @@
+/*
+ * Freescale PXP Register Definitions
+ *
+ * Copyright (C) 2012-2013 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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
+ *
+ * This file is created by xml file. Don't Edit it.
+ *
+ * Xml Revision: 1.29
+ * Template revision: 1.3
+ */
+
+#ifndef __ARCH_ARM___PXP_H
+#define __ARCH_ARM___PXP_H
+
+#define HW_PXP_CTRL    (0x00000000)
+#define HW_PXP_CTRL_SET        (0x00000004)
+#define HW_PXP_CTRL_CLR        (0x00000008)
+#define HW_PXP_CTRL_TOG        (0x0000000c)
+
+#define BM_PXP_CTRL_SFTRST 0x80000000
+#define BM_PXP_CTRL_CLKGATE 0x40000000
+#define BM_PXP_CTRL_RSVD4 0x20000000
+#define BM_PXP_CTRL_EN_REPEAT 0x10000000
+#define BP_PXP_CTRL_RSVD3      26
+#define BM_PXP_CTRL_RSVD3 0x0C000000
+#define BF_PXP_CTRL_RSVD3(v)  \
+       (((v) << 26) & BM_PXP_CTRL_RSVD3)
+#define BP_PXP_CTRL_INTERLACED_INPUT     24
+#define BM_PXP_CTRL_INTERLACED_INPUT 0x03000000
+#define BF_PXP_CTRL_INTERLACED_INPUT(v)  \
+       (((v) << 24) & BM_PXP_CTRL_INTERLACED_INPUT)
+#define BV_PXP_CTRL_INTERLACED_INPUT__PROGRESSIVE 0x0
+#define BV_PXP_CTRL_INTERLACED_INPUT__FIELD0     0x2
+#define BV_PXP_CTRL_INTERLACED_INPUT__FIELD1     0x3
+#define BM_PXP_CTRL_BLOCK_SIZE 0x00800000
+#define BV_PXP_CTRL_BLOCK_SIZE__8X8   0x0
+#define BV_PXP_CTRL_BLOCK_SIZE__16X16 0x1
+#define BM_PXP_CTRL_ROT_POS 0x00400000
+#define BM_PXP_CTRL_IN_PLACE 0x00200000
+#define BP_PXP_CTRL_RSVD1      12
+#define BM_PXP_CTRL_RSVD1 0x001FF000
+#define BF_PXP_CTRL_RSVD1(v)  \
+       (((v) << 12) & BM_PXP_CTRL_RSVD1)
+#define BM_PXP_CTRL_VFLIP 0x00000800
+#define BM_PXP_CTRL_HFLIP 0x00000400
+#define BP_PXP_CTRL_ROTATE     8
+#define BM_PXP_CTRL_ROTATE 0x00000300
+#define BF_PXP_CTRL_ROTATE(v)  \
+       (((v) << 8) & BM_PXP_CTRL_ROTATE)
+#define BV_PXP_CTRL_ROTATE__ROT_0   0x0
+#define BV_PXP_CTRL_ROTATE__ROT_90  0x1
+#define BV_PXP_CTRL_ROTATE__ROT_180 0x2
+#define BV_PXP_CTRL_ROTATE__ROT_270 0x3
+#define BP_PXP_CTRL_RSVD0      5
+#define BM_PXP_CTRL_RSVD0 0x000000E0
+#define BF_PXP_CTRL_RSVD0(v)  \
+       (((v) << 5) & BM_PXP_CTRL_RSVD0)
+#define BM_PXP_CTRL_ENABLE_LCD_HANDSHAKE 0x00000010
+#define BM_PXP_CTRL_LUT_DMA_IRQ_ENABLE 0x00000008
+#define BM_PXP_CTRL_NEXT_IRQ_ENABLE 0x00000004
+#define BM_PXP_CTRL_IRQ_ENABLE 0x00000002
+#define BM_PXP_CTRL_ENABLE 0x00000001
+
+#define HW_PXP_STAT    (0x00000010)
+#define HW_PXP_STAT_SET        (0x00000014)
+#define HW_PXP_STAT_CLR        (0x00000018)
+#define HW_PXP_STAT_TOG        (0x0000001c)
+
+#define BP_PXP_STAT_BLOCKX     24
+#define BM_PXP_STAT_BLOCKX 0xFF000000
+#define BF_PXP_STAT_BLOCKX(v) \
+       (((v) << 24) & BM_PXP_STAT_BLOCKX)
+#define BP_PXP_STAT_BLOCKY     16
+#define BM_PXP_STAT_BLOCKY 0x00FF0000
+#define BF_PXP_STAT_BLOCKY(v)  \
+       (((v) << 16) & BM_PXP_STAT_BLOCKY)
+#define BP_PXP_STAT_RSVD2      9
+#define BM_PXP_STAT_RSVD2 0x0000FE00
+#define BF_PXP_STAT_RSVD2(v)  \
+       (((v) << 9) & BM_PXP_STAT_RSVD2)
+#define BM_PXP_STAT_LUT_DMA_LOAD_DONE_IRQ 0x00000100
+#define BP_PXP_STAT_AXI_ERROR_ID      4
+#define BM_PXP_STAT_AXI_ERROR_ID 0x000000F0
+#define BF_PXP_STAT_AXI_ERROR_ID(v)  \
+       (((v) << 4) & BM_PXP_STAT_AXI_ERROR_ID)
+#define BM_PXP_STAT_NEXT_IRQ 0x00000008
+#define BM_PXP_STAT_AXI_READ_ERROR 0x00000004
+#define BM_PXP_STAT_AXI_WRITE_ERROR 0x00000002
+#define BM_PXP_STAT_IRQ 0x00000001
+
+#define HW_PXP_OUT_CTRL        (0x00000020)
+#define HW_PXP_OUT_CTRL_SET    (0x00000024)
+#define HW_PXP_OUT_CTRL_CLR    (0x00000028)
+#define HW_PXP_OUT_CTRL_TOG    (0x0000002c)
+
+#define BP_PXP_OUT_CTRL_ALPHA     24
+#define BM_PXP_OUT_CTRL_ALPHA 0xFF000000
+#define BF_PXP_OUT_CTRL_ALPHA(v) \
+       (((v) << 24) & BM_PXP_OUT_CTRL_ALPHA)
+#define BM_PXP_OUT_CTRL_ALPHA_OUTPUT 0x00800000
+#define BP_PXP_OUT_CTRL_RSVD1     10
+#define BM_PXP_OUT_CTRL_RSVD1 0x007FFC00
+#define BF_PXP_OUT_CTRL_RSVD1(v)  \
+       (((v) << 10) & BM_PXP_OUT_CTRL_RSVD1)
+#define BP_PXP_OUT_CTRL_INTERLACED_OUTPUT      8
+#define BM_PXP_OUT_CTRL_INTERLACED_OUTPUT 0x00000300
+#define BF_PXP_OUT_CTRL_INTERLACED_OUTPUT(v)  \
+       (((v) << 8) & BM_PXP_OUT_CTRL_INTERLACED_OUTPUT)
+#define BV_PXP_OUT_CTRL_INTERLACED_OUTPUT__PROGRESSIVE 0x0
+#define BV_PXP_OUT_CTRL_INTERLACED_OUTPUT__FIELD0      0x1
+#define BV_PXP_OUT_CTRL_INTERLACED_OUTPUT__FIELD1      0x2
+#define BV_PXP_OUT_CTRL_INTERLACED_OUTPUT__INTERLACED  0x3
+#define BP_PXP_OUT_CTRL_RSVD0     5
+#define BM_PXP_OUT_CTRL_RSVD0 0x000000E0
+#define BF_PXP_OUT_CTRL_RSVD0(v)  \
+       (((v) << 5) & BM_PXP_OUT_CTRL_RSVD0)
+#define BP_PXP_OUT_CTRL_FORMAT     0
+#define BM_PXP_OUT_CTRL_FORMAT 0x0000001F
+#define BF_PXP_OUT_CTRL_FORMAT(v)  \
+       (((v) << 0) & BM_PXP_OUT_CTRL_FORMAT)
+#define BV_PXP_OUT_CTRL_FORMAT__ARGB8888  0x0
+#define BV_PXP_OUT_CTRL_FORMAT__RGB888   0x4
+#define BV_PXP_OUT_CTRL_FORMAT__RGB888P   0x5
+#define BV_PXP_OUT_CTRL_FORMAT__ARGB1555  0x8
+#define BV_PXP_OUT_CTRL_FORMAT__ARGB4444  0x9
+#define BV_PXP_OUT_CTRL_FORMAT__RGB555   0xC
+#define BV_PXP_OUT_CTRL_FORMAT__RGB444   0xD
+#define BV_PXP_OUT_CTRL_FORMAT__RGB565   0xE
+#define BV_PXP_OUT_CTRL_FORMAT__YUV1P444  0x10
+#define BV_PXP_OUT_CTRL_FORMAT__UYVY1P422 0x12
+#define BV_PXP_OUT_CTRL_FORMAT__VYUY1P422 0x13
+#define BV_PXP_OUT_CTRL_FORMAT__Y8       0x14
+#define BV_PXP_OUT_CTRL_FORMAT__Y4       0x15
+#define BV_PXP_OUT_CTRL_FORMAT__YUV2P422  0x18
+#define BV_PXP_OUT_CTRL_FORMAT__YUV2P420  0x19
+#define BV_PXP_OUT_CTRL_FORMAT__YVU2P422  0x1A
+#define BV_PXP_OUT_CTRL_FORMAT__YVU2P420  0x1B
+
+#define HW_PXP_OUT_BUF (0x00000030)
+
+#define BP_PXP_OUT_BUF_ADDR     0
+#define BM_PXP_OUT_BUF_ADDR 0xFFFFFFFF
+#define BF_PXP_OUT_BUF_ADDR(v)  (v)
+
+#define HW_PXP_OUT_BUF2        (0x00000040)
+
+#define BP_PXP_OUT_BUF2_ADDR     0
+#define BM_PXP_OUT_BUF2_ADDR 0xFFFFFFFF
+#define BF_PXP_OUT_BUF2_ADDR(v)   (v)
+
+#define HW_PXP_OUT_PITCH       (0x00000050)
+
+#define BP_PXP_OUT_PITCH_RSVD     16
+#define BM_PXP_OUT_PITCH_RSVD 0xFFFF0000
+#define BF_PXP_OUT_PITCH_RSVD(v) \
+       (((v) << 16) & BM_PXP_OUT_PITCH_RSVD)
+#define BP_PXP_OUT_PITCH_PITCH     0
+#define BM_PXP_OUT_PITCH_PITCH 0x0000FFFF
+#define BF_PXP_OUT_PITCH_PITCH(v)  \
+       (((v) << 0) & BM_PXP_OUT_PITCH_PITCH)
+
+#define HW_PXP_OUT_LRC (0x00000060)
+
+#define BP_PXP_OUT_LRC_RSVD1     30
+#define BM_PXP_OUT_LRC_RSVD1 0xC0000000
+#define BF_PXP_OUT_LRC_RSVD1(v) \
+       (((v) << 30) & BM_PXP_OUT_LRC_RSVD1)
+#define BP_PXP_OUT_LRC_X      16
+#define BM_PXP_OUT_LRC_X 0x3FFF0000
+#define BF_PXP_OUT_LRC_X(v)  \
+       (((v) << 16) & BM_PXP_OUT_LRC_X)
+#define BP_PXP_OUT_LRC_RSVD0     14
+#define BM_PXP_OUT_LRC_RSVD0 0x0000C000
+#define BF_PXP_OUT_LRC_RSVD0(v)  \
+       (((v) << 14) & BM_PXP_OUT_LRC_RSVD0)
+#define BP_PXP_OUT_LRC_Y      0
+#define BM_PXP_OUT_LRC_Y 0x00003FFF
+#define BF_PXP_OUT_LRC_Y(v)  \
+       (((v) << 0) & BM_PXP_OUT_LRC_Y)
+
+#define HW_PXP_OUT_PS_ULC      (0x00000070)
+
+#define BP_PXP_OUT_PS_ULC_RSVD1      30
+#define BM_PXP_OUT_PS_ULC_RSVD1 0xC0000000
+#define BF_PXP_OUT_PS_ULC_RSVD1(v) \
+       (((v) << 30) & BM_PXP_OUT_PS_ULC_RSVD1)
+#define BP_PXP_OUT_PS_ULC_X     16
+#define BM_PXP_OUT_PS_ULC_X 0x3FFF0000
+#define BF_PXP_OUT_PS_ULC_X(v) \
+       (((v) << 16) & BM_PXP_OUT_PS_ULC_X)
+#define BP_PXP_OUT_PS_ULC_RSVD0      14
+#define BM_PXP_OUT_PS_ULC_RSVD0 0x0000C000
+#define BF_PXP_OUT_PS_ULC_RSVD0(v)  \
+       (((v) << 14) & BM_PXP_OUT_PS_ULC_RSVD0)
+#define BP_PXP_OUT_PS_ULC_Y     0
+#define BM_PXP_OUT_PS_ULC_Y 0x00003FFF
+#define BF_PXP_OUT_PS_ULC_Y(v) \
+       (((v) << 0) & BM_PXP_OUT_PS_ULC_Y)
+
+#define HW_PXP_OUT_PS_LRC      (0x00000080)
+
+#define BP_PXP_OUT_PS_LRC_RSVD1      30
+#define BM_PXP_OUT_PS_LRC_RSVD1 0xC0000000
+#define BF_PXP_OUT_PS_LRC_RSVD1(v) \
+       (((v) << 30) & BM_PXP_OUT_PS_LRC_RSVD1)
+#define BP_PXP_OUT_PS_LRC_X     16
+#define BM_PXP_OUT_PS_LRC_X 0x3FFF0000
+#define BF_PXP_OUT_PS_LRC_X(v) \
+       (((v) << 16) & BM_PXP_OUT_PS_LRC_X)
+#define BP_PXP_OUT_PS_LRC_RSVD0      14
+#define BM_PXP_OUT_PS_LRC_RSVD0 0x0000C000
+#define BF_PXP_OUT_PS_LRC_RSVD0(v)  \
+       (((v) << 14) & BM_PXP_OUT_PS_LRC_RSVD0)
+#define BP_PXP_OUT_PS_LRC_Y     0
+#define BM_PXP_OUT_PS_LRC_Y 0x00003FFF
+#define BF_PXP_OUT_PS_LRC_Y(v) \
+       (((v) << 0) & BM_PXP_OUT_PS_LRC_Y)
+
+#define HW_PXP_OUT_AS_ULC      (0x00000090)
+
+#define BP_PXP_OUT_AS_ULC_RSVD1      30
+#define BM_PXP_OUT_AS_ULC_RSVD1 0xC0000000
+#define BF_PXP_OUT_AS_ULC_RSVD1(v) \
+       (((v) << 30) & BM_PXP_OUT_AS_ULC_RSVD1)
+#define BP_PXP_OUT_AS_ULC_X     16
+#define BM_PXP_OUT_AS_ULC_X 0x3FFF0000
+#define BF_PXP_OUT_AS_ULC_X(v) \
+       (((v) << 16) & BM_PXP_OUT_AS_ULC_X)
+#define BP_PXP_OUT_AS_ULC_RSVD0      14
+#define BM_PXP_OUT_AS_ULC_RSVD0 0x0000C000
+#define BF_PXP_OUT_AS_ULC_RSVD0(v)  \
+       (((v) << 14) & BM_PXP_OUT_AS_ULC_RSVD0)
+#define BP_PXP_OUT_AS_ULC_Y     0
+#define BM_PXP_OUT_AS_ULC_Y 0x00003FFF
+#define BF_PXP_OUT_AS_ULC_Y(v) \
+       (((v) << 0) & BM_PXP_OUT_AS_ULC_Y)
+
+#define HW_PXP_OUT_AS_LRC      (0x000000a0)
+
+#define BP_PXP_OUT_AS_LRC_RSVD1      30
+#define BM_PXP_OUT_AS_LRC_RSVD1 0xC0000000
+#define BF_PXP_OUT_AS_LRC_RSVD1(v) \
+       (((v) << 30) & BM_PXP_OUT_AS_LRC_RSVD1)
+#define BP_PXP_OUT_AS_LRC_X     16
+#define BM_PXP_OUT_AS_LRC_X 0x3FFF0000
+#define BF_PXP_OUT_AS_LRC_X(v) \
+       (((v) << 16) & BM_PXP_OUT_AS_LRC_X)
+#define BP_PXP_OUT_AS_LRC_RSVD0      14
+#define BM_PXP_OUT_AS_LRC_RSVD0 0x0000C000
+#define BF_PXP_OUT_AS_LRC_RSVD0(v)  \
+       (((v) << 14) & BM_PXP_OUT_AS_LRC_RSVD0)
+#define BP_PXP_OUT_AS_LRC_Y     0
+#define BM_PXP_OUT_AS_LRC_Y 0x00003FFF
+#define BF_PXP_OUT_AS_LRC_Y(v) \
+       (((v) << 0) & BM_PXP_OUT_AS_LRC_Y)
+
+#define HW_PXP_PS_CTRL (0x000000b0)
+#define HW_PXP_PS_CTRL_SET     (0x000000b4)
+#define HW_PXP_PS_CTRL_CLR     (0x000000b8)
+#define HW_PXP_PS_CTRL_TOG     (0x000000bc)
+
+#define BP_PXP_PS_CTRL_RSVD1     12
+#define BM_PXP_PS_CTRL_RSVD1 0xFFFFF000
+#define BF_PXP_PS_CTRL_RSVD1(v) \
+       (((v) << 12) & BM_PXP_PS_CTRL_RSVD1)
+#define BP_PXP_PS_CTRL_DECX     10
+#define BM_PXP_PS_CTRL_DECX 0x00000C00
+#define BF_PXP_PS_CTRL_DECX(v) \
+       (((v) << 10) & BM_PXP_PS_CTRL_DECX)
+#define BV_PXP_PS_CTRL_DECX__DISABLE 0x0
+#define BV_PXP_PS_CTRL_DECX__DECX2   0x1
+#define BV_PXP_PS_CTRL_DECX__DECX4   0x2
+#define BV_PXP_PS_CTRL_DECX__DECX8   0x3
+#define BP_PXP_PS_CTRL_DECY     8
+#define BM_PXP_PS_CTRL_DECY 0x00000300
+#define BF_PXP_PS_CTRL_DECY(v) \
+       (((v) << 8) & BM_PXP_PS_CTRL_DECY)
+#define BV_PXP_PS_CTRL_DECY__DISABLE 0x0
+#define BV_PXP_PS_CTRL_DECY__DECY2   0x1
+#define BV_PXP_PS_CTRL_DECY__DECY4   0x2
+#define BV_PXP_PS_CTRL_DECY__DECY8   0x3
+#define BP_PXP_PS_CTRL_SWAP 5
+#define BM_PXP_PS_CTRL_SWAP 0x000000E0
+#define BF_PXP_PS_CTRL_SWAP(v)  \
+       (((v) << 5) & BM_PXP_PS_CTRL_SWAP)
+#define BP_PXP_PS_CTRL_FORMAT     0
+#define BM_PXP_PS_CTRL_FORMAT 0x0000001F
+#define BF_PXP_PS_CTRL_FORMAT(v)  \
+       (((v) << 0) & BM_PXP_PS_CTRL_FORMAT)
+#define BV_PXP_PS_CTRL_FORMAT__RGB888   0x4
+#define BV_PXP_PS_CTRL_FORMAT__RGB555   0xC
+#define BV_PXP_PS_CTRL_FORMAT__RGB444   0xD
+#define BV_PXP_PS_CTRL_FORMAT__RGB565   0xE
+#define BV_PXP_PS_CTRL_FORMAT__YUV1P444  0x10
+#define BV_PXP_PS_CTRL_FORMAT__UYVY1P422 0x12
+#define BV_PXP_PS_CTRL_FORMAT__VYUY1P422 0x13
+#define BV_PXP_PS_CTRL_FORMAT__Y8       0x14
+#define BV_PXP_PS_CTRL_FORMAT__Y4       0x15
+#define BV_PXP_PS_CTRL_FORMAT__YUV2P422  0x18
+#define BV_PXP_PS_CTRL_FORMAT__YUV2P420  0x19
+#define BV_PXP_PS_CTRL_FORMAT__YVU2P422  0x1A
+#define BV_PXP_PS_CTRL_FORMAT__YVU2P420  0x1B
+#define BV_PXP_PS_CTRL_FORMAT__YUV422   0x1E
+#define BV_PXP_PS_CTRL_FORMAT__YUV420   0x1F
+
+#define HW_PXP_PS_BUF  (0x000000c0)
+
+#define BP_PXP_PS_BUF_ADDR     0
+#define BM_PXP_PS_BUF_ADDR 0xFFFFFFFF
+#define BF_PXP_PS_BUF_ADDR(v)  (v)
+
+#define HW_PXP_PS_UBUF (0x000000d0)
+
+#define BP_PXP_PS_UBUF_ADDR     0
+#define BM_PXP_PS_UBUF_ADDR 0xFFFFFFFF
+#define BF_PXP_PS_UBUF_ADDR(v)  (v)
+
+#define HW_PXP_PS_VBUF (0x000000e0)
+
+#define BP_PXP_PS_VBUF_ADDR     0
+#define BM_PXP_PS_VBUF_ADDR 0xFFFFFFFF
+#define BF_PXP_PS_VBUF_ADDR(v)  (v)
+
+#define HW_PXP_PS_PITCH        (0x000000f0)
+
+#define BP_PXP_PS_PITCH_RSVD     16
+#define BM_PXP_PS_PITCH_RSVD 0xFFFF0000
+#define BF_PXP_PS_PITCH_RSVD(v) \
+       (((v) << 16) & BM_PXP_PS_PITCH_RSVD)
+#define BP_PXP_PS_PITCH_PITCH     0
+#define BM_PXP_PS_PITCH_PITCH 0x0000FFFF
+#define BF_PXP_PS_PITCH_PITCH(v)  \
+       (((v) << 0) & BM_PXP_PS_PITCH_PITCH)
+
+#define HW_PXP_PS_BACKGROUND   (0x00000100)
+
+#define BP_PXP_PS_BACKGROUND_RSVD      24
+#define BM_PXP_PS_BACKGROUND_RSVD 0xFF000000
+#define BF_PXP_PS_BACKGROUND_RSVD(v) \
+       (((v) << 24) & BM_PXP_PS_BACKGROUND_RSVD)
+#define BP_PXP_PS_BACKGROUND_COLOR     0
+#define BM_PXP_PS_BACKGROUND_COLOR 0x00FFFFFF
+#define BF_PXP_PS_BACKGROUND_COLOR(v)  \
+       (((v) << 0) & BM_PXP_PS_BACKGROUND_COLOR)
+
+#define HW_PXP_PS_SCALE        (0x00000110)
+
+#define BM_PXP_PS_SCALE_RSVD2 0x80000000
+#define BP_PXP_PS_SCALE_YSCALE     16
+#define BM_PXP_PS_SCALE_YSCALE 0x7FFF0000
+#define BF_PXP_PS_SCALE_YSCALE(v)  \
+       (((v) << 16) & BM_PXP_PS_SCALE_YSCALE)
+#define BM_PXP_PS_SCALE_RSVD1 0x00008000
+#define BP_PXP_PS_SCALE_XSCALE     0
+#define BM_PXP_PS_SCALE_XSCALE 0x00007FFF
+#define BF_PXP_PS_SCALE_XSCALE(v)  \
+       (((v) << 0) & BM_PXP_PS_SCALE_XSCALE)
+
+#define HW_PXP_PS_OFFSET       (0x00000120)
+
+#define BP_PXP_PS_OFFSET_RSVD2     28
+#define BM_PXP_PS_OFFSET_RSVD2 0xF0000000
+#define BF_PXP_PS_OFFSET_RSVD2(v) \
+       (((v) << 28) & BM_PXP_PS_OFFSET_RSVD2)
+#define BP_PXP_PS_OFFSET_YOFFSET      16
+#define BM_PXP_PS_OFFSET_YOFFSET 0x0FFF0000
+#define BF_PXP_PS_OFFSET_YOFFSET(v)  \
+       (((v) << 16) & BM_PXP_PS_OFFSET_YOFFSET)
+#define BP_PXP_PS_OFFSET_RSVD1     12
+#define BM_PXP_PS_OFFSET_RSVD1 0x0000F000
+#define BF_PXP_PS_OFFSET_RSVD1(v)  \
+       (((v) << 12) & BM_PXP_PS_OFFSET_RSVD1)
+#define BP_PXP_PS_OFFSET_XOFFSET      0
+#define BM_PXP_PS_OFFSET_XOFFSET 0x00000FFF
+#define BF_PXP_PS_OFFSET_XOFFSET(v)  \
+       (((v) << 0) & BM_PXP_PS_OFFSET_XOFFSET)
+
+#define HW_PXP_PS_CLRKEYLOW    (0x00000130)
+
+#define BP_PXP_PS_CLRKEYLOW_RSVD1      24
+#define BM_PXP_PS_CLRKEYLOW_RSVD1 0xFF000000
+#define BF_PXP_PS_CLRKEYLOW_RSVD1(v) \
+       (((v) << 24) & BM_PXP_PS_CLRKEYLOW_RSVD1)
+#define BP_PXP_PS_CLRKEYLOW_PIXEL      0
+#define BM_PXP_PS_CLRKEYLOW_PIXEL 0x00FFFFFF
+#define BF_PXP_PS_CLRKEYLOW_PIXEL(v)  \
+       (((v) << 0) & BM_PXP_PS_CLRKEYLOW_PIXEL)
+
+#define HW_PXP_PS_CLRKEYHIGH   (0x00000140)
+
+#define BP_PXP_PS_CLRKEYHIGH_RSVD1     24
+#define BM_PXP_PS_CLRKEYHIGH_RSVD1 0xFF000000
+#define BF_PXP_PS_CLRKEYHIGH_RSVD1(v) \
+       (((v) << 24) & BM_PXP_PS_CLRKEYHIGH_RSVD1)
+#define BP_PXP_PS_CLRKEYHIGH_PIXEL     0
+#define BM_PXP_PS_CLRKEYHIGH_PIXEL 0x00FFFFFF
+#define BF_PXP_PS_CLRKEYHIGH_PIXEL(v)  \
+       (((v) << 0) & BM_PXP_PS_CLRKEYHIGH_PIXEL)
+
+#define HW_PXP_AS_CTRL (0x00000150)
+
+#define BP_PXP_AS_CTRL_RSVD1     21
+#define BM_PXP_AS_CTRL_RSVD1 0xFFE00000
+#define BF_PXP_AS_CTRL_RSVD1(v) \
+       (((v) << 21) & BM_PXP_AS_CTRL_RSVD1)
+#define BM_PXP_AS_CTRL_ALPHA_INVERT 0x00100000
+#define BP_PXP_AS_CTRL_ROP     16
+#define BM_PXP_AS_CTRL_ROP 0x000F0000
+#define BF_PXP_AS_CTRL_ROP(v)  \
+       (((v) << 16) & BM_PXP_AS_CTRL_ROP)
+#define BV_PXP_AS_CTRL_ROP__MASKAS     0x0
+#define BV_PXP_AS_CTRL_ROP__MASKNOTAS  0x1
+#define BV_PXP_AS_CTRL_ROP__MASKASNOT  0x2
+#define BV_PXP_AS_CTRL_ROP__MERGEAS    0x3
+#define BV_PXP_AS_CTRL_ROP__MERGENOTAS 0x4
+#define BV_PXP_AS_CTRL_ROP__MERGEASNOT 0x5
+#define BV_PXP_AS_CTRL_ROP__NOTCOPYAS  0x6
+#define BV_PXP_AS_CTRL_ROP__NOT        0x7
+#define BV_PXP_AS_CTRL_ROP__NOTMASKAS  0x8
+#define BV_PXP_AS_CTRL_ROP__NOTMERGEAS 0x9
+#define BV_PXP_AS_CTRL_ROP__XORAS      0xA
+#define BV_PXP_AS_CTRL_ROP__NOTXORAS   0xB
+#define BP_PXP_AS_CTRL_ALPHA     8
+#define BM_PXP_AS_CTRL_ALPHA 0x0000FF00
+#define BF_PXP_AS_CTRL_ALPHA(v)  \
+       (((v) << 8) & BM_PXP_AS_CTRL_ALPHA)
+#define BP_PXP_AS_CTRL_FORMAT     4
+#define BM_PXP_AS_CTRL_FORMAT 0x000000F0
+#define BF_PXP_AS_CTRL_FORMAT(v)  \
+       (((v) << 4) & BM_PXP_AS_CTRL_FORMAT)
+#define BV_PXP_AS_CTRL_FORMAT__ARGB8888 0x0
+#define BV_PXP_AS_CTRL_FORMAT__RGB888  0x4
+#define BV_PXP_AS_CTRL_FORMAT__ARGB1555 0x8
+#define BV_PXP_AS_CTRL_FORMAT__ARGB4444 0x9
+#define BV_PXP_AS_CTRL_FORMAT__RGB555  0xC
+#define BV_PXP_AS_CTRL_FORMAT__RGB444  0xD
+#define BV_PXP_AS_CTRL_FORMAT__RGB565  0xE
+#define BM_PXP_AS_CTRL_ENABLE_COLORKEY 0x00000008
+#define BP_PXP_AS_CTRL_ALPHA_CTRL      1
+#define BM_PXP_AS_CTRL_ALPHA_CTRL 0x00000006
+#define BF_PXP_AS_CTRL_ALPHA_CTRL(v)  \
+       (((v) << 1) & BM_PXP_AS_CTRL_ALPHA_CTRL)
+#define BV_PXP_AS_CTRL_ALPHA_CTRL__Embedded 0x0
+#define BV_PXP_AS_CTRL_ALPHA_CTRL__Override 0x1
+#define BV_PXP_AS_CTRL_ALPHA_CTRL__Multiply 0x2
+#define BV_PXP_AS_CTRL_ALPHA_CTRL__ROPs     0x3
+#define BM_PXP_AS_CTRL_RSVD0 0x00000001
+
+#define HW_PXP_AS_BUF  (0x00000160)
+
+#define BP_PXP_AS_BUF_ADDR     0
+#define BM_PXP_AS_BUF_ADDR 0xFFFFFFFF
+#define BF_PXP_AS_BUF_ADDR(v)  (v)
+
+#define HW_PXP_AS_PITCH        (0x00000170)
+
+#define BP_PXP_AS_PITCH_RSVD     16
+#define BM_PXP_AS_PITCH_RSVD 0xFFFF0000
+#define BF_PXP_AS_PITCH_RSVD(v) \
+       (((v) << 16) & BM_PXP_AS_PITCH_RSVD)
+#define BP_PXP_AS_PITCH_PITCH     0
+#define BM_PXP_AS_PITCH_PITCH 0x0000FFFF
+#define BF_PXP_AS_PITCH_PITCH(v)  \
+       (((v) << 0) & BM_PXP_AS_PITCH_PITCH)
+
+#define HW_PXP_AS_CLRKEYLOW    (0x00000180)
+
+#define BP_PXP_AS_CLRKEYLOW_RSVD1      24
+#define BM_PXP_AS_CLRKEYLOW_RSVD1 0xFF000000
+#define BF_PXP_AS_CLRKEYLOW_RSVD1(v) \
+       (((v) << 24) & BM_PXP_AS_CLRKEYLOW_RSVD1)
+#define BP_PXP_AS_CLRKEYLOW_PIXEL      0
+#define BM_PXP_AS_CLRKEYLOW_PIXEL 0x00FFFFFF
+#define BF_PXP_AS_CLRKEYLOW_PIXEL(v)  \
+       (((v) << 0) & BM_PXP_AS_CLRKEYLOW_PIXEL)
+
+#define HW_PXP_AS_CLRKEYHIGH   (0x00000190)
+
+#define BP_PXP_AS_CLRKEYHIGH_RSVD1     24
+#define BM_PXP_AS_CLRKEYHIGH_RSVD1 0xFF000000
+#define BF_PXP_AS_CLRKEYHIGH_RSVD1(v) \
+       (((v) << 24) & BM_PXP_AS_CLRKEYHIGH_RSVD1)
+#define BP_PXP_AS_CLRKEYHIGH_PIXEL     0
+#define BM_PXP_AS_CLRKEYHIGH_PIXEL 0x00FFFFFF
+#define BF_PXP_AS_CLRKEYHIGH_PIXEL(v)  \
+       (((v) << 0) & BM_PXP_AS_CLRKEYHIGH_PIXEL)
+
+#define HW_PXP_CSC1_COEF0      (0x000001a0)
+
+#define BM_PXP_CSC1_COEF0_YCBCR_MODE 0x80000000
+#define BM_PXP_CSC1_COEF0_BYPASS 0x40000000
+#define BM_PXP_CSC1_COEF0_RSVD1 0x20000000
+#define BP_PXP_CSC1_COEF0_C0     18
+#define BM_PXP_CSC1_COEF0_C0 0x1FFC0000
+#define BF_PXP_CSC1_COEF0_C0(v)  \
+       (((v) << 18) & BM_PXP_CSC1_COEF0_C0)
+#define BP_PXP_CSC1_COEF0_UV_OFFSET     9
+#define BM_PXP_CSC1_COEF0_UV_OFFSET 0x0003FE00
+#define BF_PXP_CSC1_COEF0_UV_OFFSET(v) \
+       (((v) << 9) & BM_PXP_CSC1_COEF0_UV_OFFSET)
+#define BP_PXP_CSC1_COEF0_Y_OFFSET     0
+#define BM_PXP_CSC1_COEF0_Y_OFFSET 0x000001FF
+#define BF_PXP_CSC1_COEF0_Y_OFFSET(v)  \
+       (((v) << 0) & BM_PXP_CSC1_COEF0_Y_OFFSET)
+
+#define HW_PXP_CSC1_COEF1      (0x000001b0)
+
+#define BP_PXP_CSC1_COEF1_RSVD1      27
+#define BM_PXP_CSC1_COEF1_RSVD1 0xF8000000
+#define BF_PXP_CSC1_COEF1_RSVD1(v) \
+       (((v) << 27) & BM_PXP_CSC1_COEF1_RSVD1)
+#define BP_PXP_CSC1_COEF1_C1     16
+#define BM_PXP_CSC1_COEF1_C1 0x07FF0000
+#define BF_PXP_CSC1_COEF1_C1(v)  \
+       (((v) << 16) & BM_PXP_CSC1_COEF1_C1)
+#define BP_PXP_CSC1_COEF1_RSVD0      11
+#define BM_PXP_CSC1_COEF1_RSVD0 0x0000F800
+#define BF_PXP_CSC1_COEF1_RSVD0(v)  \
+       (((v) << 11) & BM_PXP_CSC1_COEF1_RSVD0)
+#define BP_PXP_CSC1_COEF1_C4     0
+#define BM_PXP_CSC1_COEF1_C4 0x000007FF
+#define BF_PXP_CSC1_COEF1_C4(v)  \
+       (((v) << 0) & BM_PXP_CSC1_COEF1_C4)
+
+#define HW_PXP_CSC1_COEF2      (0x000001c0)
+
+#define BP_PXP_CSC1_COEF2_RSVD1      27
+#define BM_PXP_CSC1_COEF2_RSVD1 0xF8000000
+#define BF_PXP_CSC1_COEF2_RSVD1(v) \
+       (((v) << 27) & BM_PXP_CSC1_COEF2_RSVD1)
+#define BP_PXP_CSC1_COEF2_C2     16
+#define BM_PXP_CSC1_COEF2_C2 0x07FF0000
+#define BF_PXP_CSC1_COEF2_C2(v)  \
+       (((v) << 16) & BM_PXP_CSC1_COEF2_C2)
+#define BP_PXP_CSC1_COEF2_RSVD0      11
+#define BM_PXP_CSC1_COEF2_RSVD0 0x0000F800
+#define BF_PXP_CSC1_COEF2_RSVD0(v)  \
+       (((v) << 11) & BM_PXP_CSC1_COEF2_RSVD0)
+#define BP_PXP_CSC1_COEF2_C3     0
+#define BM_PXP_CSC1_COEF2_C3 0x000007FF
+#define BF_PXP_CSC1_COEF2_C3(v)  \
+       (((v) << 0) & BM_PXP_CSC1_COEF2_C3)
+
+#define HW_PXP_CSC2_CTRL       (0x000001d0)
+
+#define BP_PXP_CSC2_CTRL_RSVD     3
+#define BM_PXP_CSC2_CTRL_RSVD 0xFFFFFFF8
+#define BF_PXP_CSC2_CTRL_RSVD(v) \
+       (((v) << 3) & BM_PXP_CSC2_CTRL_RSVD)
+#define BP_PXP_CSC2_CTRL_CSC_MODE      1
+#define BM_PXP_CSC2_CTRL_CSC_MODE 0x00000006
+#define BF_PXP_CSC2_CTRL_CSC_MODE(v)  \
+       (((v) << 1) & BM_PXP_CSC2_CTRL_CSC_MODE)
+#define BV_PXP_CSC2_CTRL_CSC_MODE__YUV2RGB   0x0
+#define BV_PXP_CSC2_CTRL_CSC_MODE__YCbCr2RGB 0x1
+#define BV_PXP_CSC2_CTRL_CSC_MODE__RGB2YUV   0x2
+#define BV_PXP_CSC2_CTRL_CSC_MODE__RGB2YCbCr 0x3
+#define BM_PXP_CSC2_CTRL_BYPASS 0x00000001
+
+#define HW_PXP_CSC2_COEF0      (0x000001e0)
+
+#define BP_PXP_CSC2_COEF0_RSVD1      27
+#define BM_PXP_CSC2_COEF0_RSVD1 0xF8000000
+#define BF_PXP_CSC2_COEF0_RSVD1(v) \
+       (((v) << 27) & BM_PXP_CSC2_COEF0_RSVD1)
+#define BP_PXP_CSC2_COEF0_A2     16
+#define BM_PXP_CSC2_COEF0_A2 0x07FF0000
+#define BF_PXP_CSC2_COEF0_A2(v)  \
+       (((v) << 16) & BM_PXP_CSC2_COEF0_A2)
+#define BP_PXP_CSC2_COEF0_RSVD0      11
+#define BM_PXP_CSC2_COEF0_RSVD0 0x0000F800
+#define BF_PXP_CSC2_COEF0_RSVD0(v)  \
+       (((v) << 11) & BM_PXP_CSC2_COEF0_RSVD0)
+#define BP_PXP_CSC2_COEF0_A1     0
+#define BM_PXP_CSC2_COEF0_A1 0x000007FF
+#define BF_PXP_CSC2_COEF0_A1(v)  \
+       (((v) << 0) & BM_PXP_CSC2_COEF0_A1)
+
+#define HW_PXP_CSC2_COEF1      (0x000001f0)
+
+#define BP_PXP_CSC2_COEF1_RSVD1      27
+#define BM_PXP_CSC2_COEF1_RSVD1 0xF8000000
+#define BF_PXP_CSC2_COEF1_RSVD1(v) \
+       (((v) << 27) & BM_PXP_CSC2_COEF1_RSVD1)
+#define BP_PXP_CSC2_COEF1_B1     16
+#define BM_PXP_CSC2_COEF1_B1 0x07FF0000
+#define BF_PXP_CSC2_COEF1_B1(v)  \
+       (((v) << 16) & BM_PXP_CSC2_COEF1_B1)
+#define BP_PXP_CSC2_COEF1_RSVD0      11
+#define BM_PXP_CSC2_COEF1_RSVD0 0x0000F800
+#define BF_PXP_CSC2_COEF1_RSVD0(v)  \
+       (((v) << 11) & BM_PXP_CSC2_COEF1_RSVD0)
+#define BP_PXP_CSC2_COEF1_A3     0
+#define BM_PXP_CSC2_COEF1_A3 0x000007FF
+#define BF_PXP_CSC2_COEF1_A3(v)  \
+       (((v) << 0) & BM_PXP_CSC2_COEF1_A3)
+
+#define HW_PXP_CSC2_COEF2      (0x00000200)
+
+#define BP_PXP_CSC2_COEF2_RSVD1      27
+#define BM_PXP_CSC2_COEF2_RSVD1 0xF8000000
+#define BF_PXP_CSC2_COEF2_RSVD1(v) \
+       (((v) << 27) & BM_PXP_CSC2_COEF2_RSVD1)
+#define BP_PXP_CSC2_COEF2_B3     16
+#define BM_PXP_CSC2_COEF2_B3 0x07FF0000
+#define BF_PXP_CSC2_COEF2_B3(v)  \
+       (((v) << 16) & BM_PXP_CSC2_COEF2_B3)
+#define BP_PXP_CSC2_COEF2_RSVD0      11
+#define BM_PXP_CSC2_COEF2_RSVD0 0x0000F800
+#define BF_PXP_CSC2_COEF2_RSVD0(v)  \
+       (((v) << 11) & BM_PXP_CSC2_COEF2_RSVD0)
+#define BP_PXP_CSC2_COEF2_B2     0
+#define BM_PXP_CSC2_COEF2_B2 0x000007FF
+#define BF_PXP_CSC2_COEF2_B2(v)  \
+       (((v) << 0) & BM_PXP_CSC2_COEF2_B2)
+
+#define HW_PXP_CSC2_COEF3      (0x00000210)
+
+#define BP_PXP_CSC2_COEF3_RSVD1      27
+#define BM_PXP_CSC2_COEF3_RSVD1 0xF8000000
+#define BF_PXP_CSC2_COEF3_RSVD1(v) \
+       (((v) << 27) & BM_PXP_CSC2_COEF3_RSVD1)
+#define BP_PXP_CSC2_COEF3_C2     16
+#define BM_PXP_CSC2_COEF3_C2 0x07FF0000
+#define BF_PXP_CSC2_COEF3_C2(v)  \
+       (((v) << 16) & BM_PXP_CSC2_COEF3_C2)
+#define BP_PXP_CSC2_COEF3_RSVD0      11
+#define BM_PXP_CSC2_COEF3_RSVD0 0x0000F800
+#define BF_PXP_CSC2_COEF3_RSVD0(v)  \
+       (((v) << 11) & BM_PXP_CSC2_COEF3_RSVD0)
+#define BP_PXP_CSC2_COEF3_C1     0
+#define BM_PXP_CSC2_COEF3_C1 0x000007FF
+#define BF_PXP_CSC2_COEF3_C1(v)  \
+       (((v) << 0) & BM_PXP_CSC2_COEF3_C1)
+
+#define HW_PXP_CSC2_COEF4      (0x00000220)
+
+#define BP_PXP_CSC2_COEF4_RSVD1      25
+#define BM_PXP_CSC2_COEF4_RSVD1 0xFE000000
+#define BF_PXP_CSC2_COEF4_RSVD1(v) \
+       (((v) << 25) & BM_PXP_CSC2_COEF4_RSVD1)
+#define BP_PXP_CSC2_COEF4_D1     16
+#define BM_PXP_CSC2_COEF4_D1 0x01FF0000
+#define BF_PXP_CSC2_COEF4_D1(v)  \
+       (((v) << 16) & BM_PXP_CSC2_COEF4_D1)
+#define BP_PXP_CSC2_COEF4_RSVD0      11
+#define BM_PXP_CSC2_COEF4_RSVD0 0x0000F800
+#define BF_PXP_CSC2_COEF4_RSVD0(v)  \
+       (((v) << 11) & BM_PXP_CSC2_COEF4_RSVD0)
+#define BP_PXP_CSC2_COEF4_C3     0
+#define BM_PXP_CSC2_COEF4_C3 0x000007FF
+#define BF_PXP_CSC2_COEF4_C3(v)  \
+       (((v) << 0) & BM_PXP_CSC2_COEF4_C3)
+
+#define HW_PXP_CSC2_COEF5      (0x00000230)
+
+#define BP_PXP_CSC2_COEF5_RSVD1      25
+#define BM_PXP_CSC2_COEF5_RSVD1 0xFE000000
+#define BF_PXP_CSC2_COEF5_RSVD1(v) \
+       (((v) << 25) & BM_PXP_CSC2_COEF5_RSVD1)
+#define BP_PXP_CSC2_COEF5_D3     16
+#define BM_PXP_CSC2_COEF5_D3 0x01FF0000
+#define BF_PXP_CSC2_COEF5_D3(v)  \
+       (((v) << 16) & BM_PXP_CSC2_COEF5_D3)
+#define BP_PXP_CSC2_COEF5_RSVD0      9
+#define BM_PXP_CSC2_COEF5_RSVD0 0x0000FE00
+#define BF_PXP_CSC2_COEF5_RSVD0(v)  \
+       (((v) << 9) & BM_PXP_CSC2_COEF5_RSVD0)
+#define BP_PXP_CSC2_COEF5_D2     0
+#define BM_PXP_CSC2_COEF5_D2 0x000001FF
+#define BF_PXP_CSC2_COEF5_D2(v)  \
+       (((v) << 0) & BM_PXP_CSC2_COEF5_D2)
+
+#define HW_PXP_LUT_CTRL        (0x00000240)
+
+#define BM_PXP_LUT_CTRL_BYPASS 0x80000000
+#define BP_PXP_LUT_CTRL_RSVD3     26
+#define BM_PXP_LUT_CTRL_RSVD3 0x7C000000
+#define BF_PXP_LUT_CTRL_RSVD3(v)  \
+       (((v) << 26) & BM_PXP_LUT_CTRL_RSVD3)
+#define BP_PXP_LUT_CTRL_LOOKUP_MODE     24
+#define BM_PXP_LUT_CTRL_LOOKUP_MODE 0x03000000
+#define BF_PXP_LUT_CTRL_LOOKUP_MODE(v) \
+       (((v) << 24) & BM_PXP_LUT_CTRL_LOOKUP_MODE)
+#define BV_PXP_LUT_CTRL_LOOKUP_MODE__CACHE_RGB565  0x0
+#define BV_PXP_LUT_CTRL_LOOKUP_MODE__DIRECT_Y8    0x1
+#define BV_PXP_LUT_CTRL_LOOKUP_MODE__DIRECT_RGB444 0x2
+#define BV_PXP_LUT_CTRL_LOOKUP_MODE__DIRECT_RGB454 0x3
+#define BP_PXP_LUT_CTRL_RSVD2     18
+#define BM_PXP_LUT_CTRL_RSVD2 0x00FC0000
+#define BF_PXP_LUT_CTRL_RSVD2(v)  \
+       (((v) << 18) & BM_PXP_LUT_CTRL_RSVD2)
+#define BP_PXP_LUT_CTRL_OUT_MODE      16
+#define BM_PXP_LUT_CTRL_OUT_MODE 0x00030000
+#define BF_PXP_LUT_CTRL_OUT_MODE(v)  \
+       (((v) << 16) & BM_PXP_LUT_CTRL_OUT_MODE)
+#define BV_PXP_LUT_CTRL_OUT_MODE__RESERVED    0x0
+#define BV_PXP_LUT_CTRL_OUT_MODE__Y8         0x1
+#define BV_PXP_LUT_CTRL_OUT_MODE__RGBW4444CFA 0x2
+#define BV_PXP_LUT_CTRL_OUT_MODE__RGB888      0x3
+#define BP_PXP_LUT_CTRL_RSVD1     11
+#define BM_PXP_LUT_CTRL_RSVD1 0x0000F800
+#define BF_PXP_LUT_CTRL_RSVD1(v)  \
+       (((v) << 11) & BM_PXP_LUT_CTRL_RSVD1)
+#define BM_PXP_LUT_CTRL_SEL_8KB 0x00000400
+#define BM_PXP_LUT_CTRL_LRU_UPD 0x00000200
+#define BM_PXP_LUT_CTRL_INVALID 0x00000100
+#define BP_PXP_LUT_CTRL_RSVD0     1
+#define BM_PXP_LUT_CTRL_RSVD0 0x000000FE
+#define BF_PXP_LUT_CTRL_RSVD0(v)  \
+       (((v) << 1) & BM_PXP_LUT_CTRL_RSVD0)
+#define BM_PXP_LUT_CTRL_DMA_START 0x00000001
+
+#define HW_PXP_LUT_ADDR        (0x00000250)
+
+#define BM_PXP_LUT_ADDR_RSVD2 0x80000000
+#define BP_PXP_LUT_ADDR_NUM_BYTES      16
+#define BM_PXP_LUT_ADDR_NUM_BYTES 0x7FFF0000
+#define BF_PXP_LUT_ADDR_NUM_BYTES(v)  \
+       (((v) << 16) & BM_PXP_LUT_ADDR_NUM_BYTES)
+#define BP_PXP_LUT_ADDR_RSVD1     14
+#define BM_PXP_LUT_ADDR_RSVD1 0x0000C000
+#define BF_PXP_LUT_ADDR_RSVD1(v)  \
+       (((v) << 14) & BM_PXP_LUT_ADDR_RSVD1)
+#define BP_PXP_LUT_ADDR_ADDR     0
+#define BM_PXP_LUT_ADDR_ADDR 0x00003FFF
+#define BF_PXP_LUT_ADDR_ADDR(v)  \
+       (((v) << 0) & BM_PXP_LUT_ADDR_ADDR)
+
+#define HW_PXP_LUT_DATA        (0x00000260)
+
+#define BP_PXP_LUT_DATA_DATA     0
+#define BM_PXP_LUT_DATA_DATA 0xFFFFFFFF
+#define BF_PXP_LUT_DATA_DATA(v)   (v)
+
+#define HW_PXP_LUT_EXTMEM      (0x00000270)
+
+#define BP_PXP_LUT_EXTMEM_ADDR     0
+#define BM_PXP_LUT_EXTMEM_ADDR 0xFFFFFFFF
+#define BF_PXP_LUT_EXTMEM_ADDR(v)   (v)
+
+#define HW_PXP_CFA     (0x00000280)
+
+#define BP_PXP_CFA_DATA      0
+#define BM_PXP_CFA_DATA 0xFFFFFFFF
+#define BF_PXP_CFA_DATA(v)   (v)
+
+#define HW_PXP_HIST_CTRL       (0x00000290)
+
+#define BP_PXP_HIST_CTRL_RSVD     6
+#define BM_PXP_HIST_CTRL_RSVD 0xFFFFFFC0
+#define BF_PXP_HIST_CTRL_RSVD(v) \
+       (((v) << 6) & BM_PXP_HIST_CTRL_RSVD)
+#define BP_PXP_HIST_CTRL_PANEL_MODE     4
+#define BM_PXP_HIST_CTRL_PANEL_MODE 0x00000030
+#define BF_PXP_HIST_CTRL_PANEL_MODE(v) \
+       (((v) << 4) & BM_PXP_HIST_CTRL_PANEL_MODE)
+#define BV_PXP_HIST_CTRL_PANEL_MODE__GRAY4  0x0
+#define BV_PXP_HIST_CTRL_PANEL_MODE__GRAY8  0x1
+#define BV_PXP_HIST_CTRL_PANEL_MODE__GRAY16 0x2
+#define BV_PXP_HIST_CTRL_PANEL_MODE__GRAY32 0x3
+#define BP_PXP_HIST_CTRL_STATUS      0
+#define BM_PXP_HIST_CTRL_STATUS 0x0000000F
+#define BF_PXP_HIST_CTRL_STATUS(v)  \
+       (((v) << 0) & BM_PXP_HIST_CTRL_STATUS)
+
+#define HW_PXP_HIST2_PARAM     (0x000002a0)
+
+#define BP_PXP_HIST2_PARAM_RSVD      16
+#define BM_PXP_HIST2_PARAM_RSVD 0xFFFF0000
+#define BF_PXP_HIST2_PARAM_RSVD(v) \
+       (((v) << 16) & BM_PXP_HIST2_PARAM_RSVD)
+#define BP_PXP_HIST2_PARAM_RSVD1      13
+#define BM_PXP_HIST2_PARAM_RSVD1 0x0000E000
+#define BF_PXP_HIST2_PARAM_RSVD1(v)  \
+       (((v) << 13) & BM_PXP_HIST2_PARAM_RSVD1)
+#define BP_PXP_HIST2_PARAM_VALUE1      8
+#define BM_PXP_HIST2_PARAM_VALUE1 0x00001F00
+#define BF_PXP_HIST2_PARAM_VALUE1(v)  \
+       (((v) << 8) & BM_PXP_HIST2_PARAM_VALUE1)
+#define BP_PXP_HIST2_PARAM_RSVD0      5
+#define BM_PXP_HIST2_PARAM_RSVD0 0x000000E0
+#define BF_PXP_HIST2_PARAM_RSVD0(v)  \
+       (((v) << 5) & BM_PXP_HIST2_PARAM_RSVD0)
+#define BP_PXP_HIST2_PARAM_VALUE0      0
+#define BM_PXP_HIST2_PARAM_VALUE0 0x0000001F
+#define BF_PXP_HIST2_PARAM_VALUE0(v)  \
+       (((v) << 0) & BM_PXP_HIST2_PARAM_VALUE0)
+
+#define HW_PXP_HIST4_PARAM     (0x000002b0)
+
+#define BP_PXP_HIST4_PARAM_RSVD3      29
+#define BM_PXP_HIST4_PARAM_RSVD3 0xE0000000
+#define BF_PXP_HIST4_PARAM_RSVD3(v) \
+       (((v) << 29) & BM_PXP_HIST4_PARAM_RSVD3)
+#define BP_PXP_HIST4_PARAM_VALUE3      24
+#define BM_PXP_HIST4_PARAM_VALUE3 0x1F000000
+#define BF_PXP_HIST4_PARAM_VALUE3(v)  \
+       (((v) << 24) & BM_PXP_HIST4_PARAM_VALUE3)
+#define BP_PXP_HIST4_PARAM_RSVD2      21
+#define BM_PXP_HIST4_PARAM_RSVD2 0x00E00000
+#define BF_PXP_HIST4_PARAM_RSVD2(v)  \
+       (((v) << 21) & BM_PXP_HIST4_PARAM_RSVD2)
+#define BP_PXP_HIST4_PARAM_VALUE2      16
+#define BM_PXP_HIST4_PARAM_VALUE2 0x001F0000
+#define BF_PXP_HIST4_PARAM_VALUE2(v)  \
+       (((v) << 16) & BM_PXP_HIST4_PARAM_VALUE2)
+#define BP_PXP_HIST4_PARAM_RSVD1      13
+#define BM_PXP_HIST4_PARAM_RSVD1 0x0000E000
+#define BF_PXP_HIST4_PARAM_RSVD1(v)  \
+       (((v) << 13) & BM_PXP_HIST4_PARAM_RSVD1)
+#define BP_PXP_HIST4_PARAM_VALUE1      8
+#define BM_PXP_HIST4_PARAM_VALUE1 0x00001F00
+#define BF_PXP_HIST4_PARAM_VALUE1(v)  \
+       (((v) << 8) & BM_PXP_HIST4_PARAM_VALUE1)
+#define BP_PXP_HIST4_PARAM_RSVD0      5
+#define BM_PXP_HIST4_PARAM_RSVD0 0x000000E0
+#define BF_PXP_HIST4_PARAM_RSVD0(v)  \
+       (((v) << 5) & BM_PXP_HIST4_PARAM_RSVD0)
+#define BP_PXP_HIST4_PARAM_VALUE0      0
+#define BM_PXP_HIST4_PARAM_VALUE0 0x0000001F
+#define BF_PXP_HIST4_PARAM_VALUE0(v)  \
+       (((v) << 0) & BM_PXP_HIST4_PARAM_VALUE0)
+
+#define HW_PXP_HIST8_PARAM0    (0x000002c0)
+
+#define BP_PXP_HIST8_PARAM0_RSVD3      29
+#define BM_PXP_HIST8_PARAM0_RSVD3 0xE0000000
+#define BF_PXP_HIST8_PARAM0_RSVD3(v) \
+       (((v) << 29) & BM_PXP_HIST8_PARAM0_RSVD3)
+#define BP_PXP_HIST8_PARAM0_VALUE3     24
+#define BM_PXP_HIST8_PARAM0_VALUE3 0x1F000000
+#define BF_PXP_HIST8_PARAM0_VALUE3(v)  \
+       (((v) << 24) & BM_PXP_HIST8_PARAM0_VALUE3)
+#define BP_PXP_HIST8_PARAM0_RSVD2      21
+#define BM_PXP_HIST8_PARAM0_RSVD2 0x00E00000
+#define BF_PXP_HIST8_PARAM0_RSVD2(v)  \
+       (((v) << 21) & BM_PXP_HIST8_PARAM0_RSVD2)
+#define BP_PXP_HIST8_PARAM0_VALUE2     16
+#define BM_PXP_HIST8_PARAM0_VALUE2 0x001F0000
+#define BF_PXP_HIST8_PARAM0_VALUE2(v)  \
+       (((v) << 16) & BM_PXP_HIST8_PARAM0_VALUE2)
+#define BP_PXP_HIST8_PARAM0_RSVD1      13
+#define BM_PXP_HIST8_PARAM0_RSVD1 0x0000E000
+#define BF_PXP_HIST8_PARAM0_RSVD1(v)  \
+       (((v) << 13) & BM_PXP_HIST8_PARAM0_RSVD1)
+#define BP_PXP_HIST8_PARAM0_VALUE1     8
+#define BM_PXP_HIST8_PARAM0_VALUE1 0x00001F00
+#define BF_PXP_HIST8_PARAM0_VALUE1(v)  \
+       (((v) << 8) & BM_PXP_HIST8_PARAM0_VALUE1)
+#define BP_PXP_HIST8_PARAM0_RSVD0      5
+#define BM_PXP_HIST8_PARAM0_RSVD0 0x000000E0
+#define BF_PXP_HIST8_PARAM0_RSVD0(v)  \
+       (((v) << 5) & BM_PXP_HIST8_PARAM0_RSVD0)
+#define BP_PXP_HIST8_PARAM0_VALUE0     0
+#define BM_PXP_HIST8_PARAM0_VALUE0 0x0000001F
+#define BF_PXP_HIST8_PARAM0_VALUE0(v)  \
+       (((v) << 0) & BM_PXP_HIST8_PARAM0_VALUE0)
+
+#define HW_PXP_HIST8_PARAM1    (0x000002d0)
+
+#define BP_PXP_HIST8_PARAM1_RSVD7      29
+#define BM_PXP_HIST8_PARAM1_RSVD7 0xE0000000
+#define BF_PXP_HIST8_PARAM1_RSVD7(v) \
+       (((v) << 29) & BM_PXP_HIST8_PARAM1_RSVD7)
+#define BP_PXP_HIST8_PARAM1_VALUE7     24
+#define BM_PXP_HIST8_PARAM1_VALUE7 0x1F000000
+#define BF_PXP_HIST8_PARAM1_VALUE7(v)  \
+       (((v) << 24) & BM_PXP_HIST8_PARAM1_VALUE7)
+#define BP_PXP_HIST8_PARAM1_RSVD6      21
+#define BM_PXP_HIST8_PARAM1_RSVD6 0x00E00000
+#define BF_PXP_HIST8_PARAM1_RSVD6(v)  \
+       (((v) << 21) & BM_PXP_HIST8_PARAM1_RSVD6)
+#define BP_PXP_HIST8_PARAM1_VALUE6     16
+#define BM_PXP_HIST8_PARAM1_VALUE6 0x001F0000
+#define BF_PXP_HIST8_PARAM1_VALUE6(v)  \
+       (((v) << 16) & BM_PXP_HIST8_PARAM1_VALUE6)
+#define BP_PXP_HIST8_PARAM1_RSVD5      13
+#define BM_PXP_HIST8_PARAM1_RSVD5 0x0000E000
+#define BF_PXP_HIST8_PARAM1_RSVD5(v)  \
+       (((v) << 13) & BM_PXP_HIST8_PARAM1_RSVD5)
+#define BP_PXP_HIST8_PARAM1_VALUE5     8
+#define BM_PXP_HIST8_PARAM1_VALUE5 0x00001F00
+#define BF_PXP_HIST8_PARAM1_VALUE5(v)  \
+       (((v) << 8) & BM_PXP_HIST8_PARAM1_VALUE5)
+#define BP_PXP_HIST8_PARAM1_RSVD4      5
+#define BM_PXP_HIST8_PARAM1_RSVD4 0x000000E0
+#define BF_PXP_HIST8_PARAM1_RSVD4(v)  \
+       (((v) << 5) & BM_PXP_HIST8_PARAM1_RSVD4)
+#define BP_PXP_HIST8_PARAM1_VALUE4     0
+#define BM_PXP_HIST8_PARAM1_VALUE4 0x0000001F
+#define BF_PXP_HIST8_PARAM1_VALUE4(v)  \
+       (((v) << 0) & BM_PXP_HIST8_PARAM1_VALUE4)
+
+#define HW_PXP_HIST16_PARAM0   (0x000002e0)
+
+#define BP_PXP_HIST16_PARAM0_RSVD3     29
+#define BM_PXP_HIST16_PARAM0_RSVD3 0xE0000000
+#define BF_PXP_HIST16_PARAM0_RSVD3(v) \
+       (((v) << 29) & BM_PXP_HIST16_PARAM0_RSVD3)
+#define BP_PXP_HIST16_PARAM0_VALUE3     24
+#define BM_PXP_HIST16_PARAM0_VALUE3 0x1F000000
+#define BF_PXP_HIST16_PARAM0_VALUE3(v) \
+       (((v) << 24) & BM_PXP_HIST16_PARAM0_VALUE3)
+#define BP_PXP_HIST16_PARAM0_RSVD2     21
+#define BM_PXP_HIST16_PARAM0_RSVD2 0x00E00000
+#define BF_PXP_HIST16_PARAM0_RSVD2(v)  \
+       (((v) << 21) & BM_PXP_HIST16_PARAM0_RSVD2)
+#define BP_PXP_HIST16_PARAM0_VALUE2     16
+#define BM_PXP_HIST16_PARAM0_VALUE2 0x001F0000
+#define BF_PXP_HIST16_PARAM0_VALUE2(v) \
+       (((v) << 16) & BM_PXP_HIST16_PARAM0_VALUE2)
+#define BP_PXP_HIST16_PARAM0_RSVD1     13
+#define BM_PXP_HIST16_PARAM0_RSVD1 0x0000E000
+#define BF_PXP_HIST16_PARAM0_RSVD1(v)  \
+       (((v) << 13) & BM_PXP_HIST16_PARAM0_RSVD1)
+#define BP_PXP_HIST16_PARAM0_VALUE1     8
+#define BM_PXP_HIST16_PARAM0_VALUE1 0x00001F00
+#define BF_PXP_HIST16_PARAM0_VALUE1(v) \
+       (((v) << 8) & BM_PXP_HIST16_PARAM0_VALUE1)
+#define BP_PXP_HIST16_PARAM0_RSVD0     5
+#define BM_PXP_HIST16_PARAM0_RSVD0 0x000000E0
+#define BF_PXP_HIST16_PARAM0_RSVD0(v)  \
+       (((v) << 5) & BM_PXP_HIST16_PARAM0_RSVD0)
+#define BP_PXP_HIST16_PARAM0_VALUE0     0
+#define BM_PXP_HIST16_PARAM0_VALUE0 0x0000001F
+#define BF_PXP_HIST16_PARAM0_VALUE0(v) \
+       (((v) << 0) & BM_PXP_HIST16_PARAM0_VALUE0)
+
+#define HW_PXP_HIST16_PARAM1   (0x000002f0)
+
+#define BP_PXP_HIST16_PARAM1_RSVD7     29
+#define BM_PXP_HIST16_PARAM1_RSVD7 0xE0000000
+#define BF_PXP_HIST16_PARAM1_RSVD7(v) \
+       (((v) << 29) & BM_PXP_HIST16_PARAM1_RSVD7)
+#define BP_PXP_HIST16_PARAM1_VALUE7     24
+#define BM_PXP_HIST16_PARAM1_VALUE7 0x1F000000
+#define BF_PXP_HIST16_PARAM1_VALUE7(v) \
+       (((v) << 24) & BM_PXP_HIST16_PARAM1_VALUE7)
+#define BP_PXP_HIST16_PARAM1_RSVD6     21
+#define BM_PXP_HIST16_PARAM1_RSVD6 0x00E00000
+#define BF_PXP_HIST16_PARAM1_RSVD6(v)  \
+       (((v) << 21) & BM_PXP_HIST16_PARAM1_RSVD6)
+#define BP_PXP_HIST16_PARAM1_VALUE6     16
+#define BM_PXP_HIST16_PARAM1_VALUE6 0x001F0000
+#define BF_PXP_HIST16_PARAM1_VALUE6(v) \
+       (((v) << 16) & BM_PXP_HIST16_PARAM1_VALUE6)
+#define BP_PXP_HIST16_PARAM1_RSVD5     13
+#define BM_PXP_HIST16_PARAM1_RSVD5 0x0000E000
+#define BF_PXP_HIST16_PARAM1_RSVD5(v)  \
+       (((v) << 13) & BM_PXP_HIST16_PARAM1_RSVD5)
+#define BP_PXP_HIST16_PARAM1_VALUE5     8
+#define BM_PXP_HIST16_PARAM1_VALUE5 0x00001F00
+#define BF_PXP_HIST16_PARAM1_VALUE5(v) \
+       (((v) << 8) & BM_PXP_HIST16_PARAM1_VALUE5)
+#define BP_PXP_HIST16_PARAM1_RSVD4     5
+#define BM_PXP_HIST16_PARAM1_RSVD4 0x000000E0
+#define BF_PXP_HIST16_PARAM1_RSVD4(v)  \
+       (((v) << 5) & BM_PXP_HIST16_PARAM1_RSVD4)
+#define BP_PXP_HIST16_PARAM1_VALUE4     0
+#define BM_PXP_HIST16_PARAM1_VALUE4 0x0000001F
+#define BF_PXP_HIST16_PARAM1_VALUE4(v) \
+       (((v) << 0) & BM_PXP_HIST16_PARAM1_VALUE4)
+
+#define HW_PXP_HIST16_PARAM2   (0x00000300)
+
+#define BP_PXP_HIST16_PARAM2_RSVD11     29
+#define BM_PXP_HIST16_PARAM2_RSVD11 0xE0000000
+#define BF_PXP_HIST16_PARAM2_RSVD11(v) \
+       (((v) << 29) & BM_PXP_HIST16_PARAM2_RSVD11)
+#define BP_PXP_HIST16_PARAM2_VALUE11     24
+#define BM_PXP_HIST16_PARAM2_VALUE11 0x1F000000
+#define BF_PXP_HIST16_PARAM2_VALUE11(v)  \
+       (((v) << 24) & BM_PXP_HIST16_PARAM2_VALUE11)
+#define BP_PXP_HIST16_PARAM2_RSVD10     21
+#define BM_PXP_HIST16_PARAM2_RSVD10 0x00E00000
+#define BF_PXP_HIST16_PARAM2_RSVD10(v) \
+       (((v) << 21) & BM_PXP_HIST16_PARAM2_RSVD10)
+#define BP_PXP_HIST16_PARAM2_VALUE10     16
+#define BM_PXP_HIST16_PARAM2_VALUE10 0x001F0000
+#define BF_PXP_HIST16_PARAM2_VALUE10(v)  \
+       (((v) << 16) & BM_PXP_HIST16_PARAM2_VALUE10)
+#define BP_PXP_HIST16_PARAM2_RSVD9     13
+#define BM_PXP_HIST16_PARAM2_RSVD9 0x0000E000
+#define BF_PXP_HIST16_PARAM2_RSVD9(v)  \
+       (((v) << 13) & BM_PXP_HIST16_PARAM2_RSVD9)
+#define BP_PXP_HIST16_PARAM2_VALUE9     8
+#define BM_PXP_HIST16_PARAM2_VALUE9 0x00001F00
+#define BF_PXP_HIST16_PARAM2_VALUE9(v) \
+       (((v) << 8) & BM_PXP_HIST16_PARAM2_VALUE9)
+#define BP_PXP_HIST16_PARAM2_RSVD8     5
+#define BM_PXP_HIST16_PARAM2_RSVD8 0x000000E0
+#define BF_PXP_HIST16_PARAM2_RSVD8(v)  \
+       (((v) << 5) & BM_PXP_HIST16_PARAM2_RSVD8)
+#define BP_PXP_HIST16_PARAM2_VALUE8     0
+#define BM_PXP_HIST16_PARAM2_VALUE8 0x0000001F
+#define BF_PXP_HIST16_PARAM2_VALUE8(v) \
+       (((v) << 0) & BM_PXP_HIST16_PARAM2_VALUE8)
+
+#define HW_PXP_HIST16_PARAM3   (0x00000310)
+
+#define BP_PXP_HIST16_PARAM3_RSVD15     29
+#define BM_PXP_HIST16_PARAM3_RSVD15 0xE0000000
+#define BF_PXP_HIST16_PARAM3_RSVD15(v) \
+       (((v) << 29) & BM_PXP_HIST16_PARAM3_RSVD15)
+#define BP_PXP_HIST16_PARAM3_VALUE15     24
+#define BM_PXP_HIST16_PARAM3_VALUE15 0x1F000000
+#define BF_PXP_HIST16_PARAM3_VALUE15(v)  \
+       (((v) << 24) & BM_PXP_HIST16_PARAM3_VALUE15)
+#define BP_PXP_HIST16_PARAM3_RSVD14     21
+#define BM_PXP_HIST16_PARAM3_RSVD14 0x00E00000
+#define BF_PXP_HIST16_PARAM3_RSVD14(v) \
+       (((v) << 21) & BM_PXP_HIST16_PARAM3_RSVD14)
+#define BP_PXP_HIST16_PARAM3_VALUE14     16
+#define BM_PXP_HIST16_PARAM3_VALUE14 0x001F0000
+#define BF_PXP_HIST16_PARAM3_VALUE14(v)  \
+       (((v) << 16) & BM_PXP_HIST16_PARAM3_VALUE14)
+#define BP_PXP_HIST16_PARAM3_RSVD13     13
+#define BM_PXP_HIST16_PARAM3_RSVD13 0x0000E000
+#define BF_PXP_HIST16_PARAM3_RSVD13(v) \
+       (((v) << 13) & BM_PXP_HIST16_PARAM3_RSVD13)
+#define BP_PXP_HIST16_PARAM3_VALUE13     8
+#define BM_PXP_HIST16_PARAM3_VALUE13 0x00001F00
+#define BF_PXP_HIST16_PARAM3_VALUE13(v)  \
+       (((v) << 8) & BM_PXP_HIST16_PARAM3_VALUE13)
+#define BP_PXP_HIST16_PARAM3_RSVD12     5
+#define BM_PXP_HIST16_PARAM3_RSVD12 0x000000E0
+#define BF_PXP_HIST16_PARAM3_RSVD12(v) \
+       (((v) << 5) & BM_PXP_HIST16_PARAM3_RSVD12)
+#define BP_PXP_HIST16_PARAM3_VALUE12     0
+#define BM_PXP_HIST16_PARAM3_VALUE12 0x0000001F
+#define BF_PXP_HIST16_PARAM3_VALUE12(v)  \
+       (((v) << 0) & BM_PXP_HIST16_PARAM3_VALUE12)
+
+#define HW_PXP_POWER   (0x00000320)
+
+#define BP_PXP_POWER_CTRL      12
+#define BM_PXP_POWER_CTRL 0xFFFFF000
+#define BF_PXP_POWER_CTRL(v) \
+       (((v) << 12) & BM_PXP_POWER_CTRL)
+#define BP_PXP_POWER_ROT_MEM_LP_STATE     9
+#define BM_PXP_POWER_ROT_MEM_LP_STATE 0x00000E00
+#define BF_PXP_POWER_ROT_MEM_LP_STATE(v)  \
+       (((v) << 9) & BM_PXP_POWER_ROT_MEM_LP_STATE)
+#define BV_PXP_POWER_ROT_MEM_LP_STATE__NONE 0x0
+#define BV_PXP_POWER_ROT_MEM_LP_STATE__LS   0x1
+#define BV_PXP_POWER_ROT_MEM_LP_STATE__DS   0x2
+#define BV_PXP_POWER_ROT_MEM_LP_STATE__SD   0x4
+#define BP_PXP_POWER_LUT_LP_STATE_WAY1_BANKN     6
+#define BM_PXP_POWER_LUT_LP_STATE_WAY1_BANKN 0x000001C0
+#define BF_PXP_POWER_LUT_LP_STATE_WAY1_BANKN(v)  \
+       (((v) << 6) & BM_PXP_POWER_LUT_LP_STATE_WAY1_BANKN)
+#define BV_PXP_POWER_LUT_LP_STATE_WAY1_BANKN__NONE 0x0
+#define BV_PXP_POWER_LUT_LP_STATE_WAY1_BANKN__LS   0x1
+#define BV_PXP_POWER_LUT_LP_STATE_WAY1_BANKN__DS   0x2
+#define BV_PXP_POWER_LUT_LP_STATE_WAY1_BANKN__SD   0x4
+#define BP_PXP_POWER_LUT_LP_STATE_WAY0_BANKN     3
+#define BM_PXP_POWER_LUT_LP_STATE_WAY0_BANKN 0x00000038
+#define BF_PXP_POWER_LUT_LP_STATE_WAY0_BANKN(v)  \
+       (((v) << 3) & BM_PXP_POWER_LUT_LP_STATE_WAY0_BANKN)
+#define BV_PXP_POWER_LUT_LP_STATE_WAY0_BANKN__NONE 0x0
+#define BV_PXP_POWER_LUT_LP_STATE_WAY0_BANKN__LS   0x1
+#define BV_PXP_POWER_LUT_LP_STATE_WAY0_BANKN__DS   0x2
+#define BV_PXP_POWER_LUT_LP_STATE_WAY0_BANKN__SD   0x4
+#define BP_PXP_POWER_LUT_LP_STATE_WAY0_BANK0     0
+#define BM_PXP_POWER_LUT_LP_STATE_WAY0_BANK0 0x00000007
+#define BF_PXP_POWER_LUT_LP_STATE_WAY0_BANK0(v)  \
+       (((v) << 0) & BM_PXP_POWER_LUT_LP_STATE_WAY0_BANK0)
+#define BV_PXP_POWER_LUT_LP_STATE_WAY0_BANK0__NONE 0x0
+#define BV_PXP_POWER_LUT_LP_STATE_WAY0_BANK0__LS   0x1
+#define BV_PXP_POWER_LUT_LP_STATE_WAY0_BANK0__DS   0x2
+#define BV_PXP_POWER_LUT_LP_STATE_WAY0_BANK0__SD   0x4
+
+#define HW_PXP_NEXT    (0x00000400)
+
+#define BP_PXP_NEXT_POINTER     2
+#define BM_PXP_NEXT_POINTER 0xFFFFFFFC
+#define BF_PXP_NEXT_POINTER(v) \
+       (((v) << 2) & BM_PXP_NEXT_POINTER)
+#define BM_PXP_NEXT_RSVD 0x00000002
+#define BM_PXP_NEXT_ENABLED 0x00000001
+
+#define HW_PXP_DEBUGCTRL       (0x00000410)
+
+#define BP_PXP_DEBUGCTRL_RSVD     12
+#define BM_PXP_DEBUGCTRL_RSVD 0xFFFFF000
+#define BF_PXP_DEBUGCTRL_RSVD(v) \
+       (((v) << 12) & BM_PXP_DEBUGCTRL_RSVD)
+#define BP_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT      8
+#define BM_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT 0x00000F00
+#define BF_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT(v)  \
+       (((v) << 8) & BM_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT)
+#define BV_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT__NONE     0x0
+#define BV_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT__MISS_CNT 0x1
+#define BV_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT__HIT_CNT  0x2
+#define BV_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT__LAT_CNT  0x4
+#define BV_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT__MAX_LAT  0x8
+#define BP_PXP_DEBUGCTRL_SELECT      0
+#define BM_PXP_DEBUGCTRL_SELECT 0x000000FF
+#define BF_PXP_DEBUGCTRL_SELECT(v)  \
+       (((v) << 0) & BM_PXP_DEBUGCTRL_SELECT)
+#define BV_PXP_DEBUGCTRL_SELECT__NONE       0x0
+#define BV_PXP_DEBUGCTRL_SELECT__CTRL       0x1
+#define BV_PXP_DEBUGCTRL_SELECT__PSBUF      0x2
+#define BV_PXP_DEBUGCTRL_SELECT__PSBAX      0x3
+#define BV_PXP_DEBUGCTRL_SELECT__PSBAY      0x4
+#define BV_PXP_DEBUGCTRL_SELECT__ASBUF      0x5
+#define BV_PXP_DEBUGCTRL_SELECT__ROTATION    0x6
+#define BV_PXP_DEBUGCTRL_SELECT__OUTBUF0     0x7
+#define BV_PXP_DEBUGCTRL_SELECT__OUTBUF1     0x8
+#define BV_PXP_DEBUGCTRL_SELECT__OUTBUF2     0x9
+#define BV_PXP_DEBUGCTRL_SELECT__LUT_STAT    0x10
+#define BV_PXP_DEBUGCTRL_SELECT__LUT_MISS    0x11
+#define BV_PXP_DEBUGCTRL_SELECT__LUT_HIT     0x12
+#define BV_PXP_DEBUGCTRL_SELECT__LUT_LAT     0x13
+#define BV_PXP_DEBUGCTRL_SELECT__LUT_MAX_LAT 0x14
+
+#define HW_PXP_DEBUG   (0x00000420)
+
+#define BP_PXP_DEBUG_DATA      0
+#define BM_PXP_DEBUG_DATA 0xFFFFFFFF
+#define BF_PXP_DEBUG_DATA(v)   (v)
+
+#define HW_PXP_VERSION (0x00000430)
+
+#define BP_PXP_VERSION_MAJOR     24
+#define BM_PXP_VERSION_MAJOR 0xFF000000
+#define BF_PXP_VERSION_MAJOR(v) \
+       (((v) << 24) & BM_PXP_VERSION_MAJOR)
+#define BP_PXP_VERSION_MINOR     16
+#define BM_PXP_VERSION_MINOR 0x00FF0000
+#define BF_PXP_VERSION_MINOR(v)  \
+       (((v) << 16) & BM_PXP_VERSION_MINOR)
+#define BP_PXP_VERSION_STEP     0
+#define BM_PXP_VERSION_STEP 0x0000FFFF
+#define BF_PXP_VERSION_STEP(v) \
+       (((v) << 0) & BM_PXP_VERSION_STEP)
+#endif /* __ARCH_ARM___PXP_H */
index bcbc6c3c14c0da82547b861e7108ccee41351f71..0eff734f88c49302b789fc811093a105b85f8e7b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2004-2009 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2004-2013 Freescale Semiconductor, Inc. All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -59,6 +59,11 @@ static inline int imx_dma_is_ipu(struct dma_chan *chan)
        return !strcmp(dev_name(chan->device->dev), "ipu-core");
 }
 
+static inline int imx_dma_is_pxp(struct dma_chan *chan)
+{
+       return strstr(dev_name(chan->device->dev), "pxp") != NULL;
+}
+
 static inline int imx_dma_is_general_purpose(struct dma_chan *chan)
 {
        return !strcmp(chan->device->dev->driver->name, "imx-sdma") ||
diff --git a/include/linux/pxp_device.h b/include/linux/pxp_device.h
new file mode 100644 (file)
index 0000000..df185c4
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2013-2014 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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 _PXP_DEVICE
+#define _PXP_DEVICE
+
+#include <linux/idr.h>
+#include <linux/hash.h>
+#include <uapi/linux/pxp_device.h>
+
+struct pxp_irq_info {
+       wait_queue_head_t waitq;
+       atomic_t irq_pending;
+       int hist_status;
+};
+
+struct pxp_buffer_hash {
+       struct hlist_head *hash_table;
+       u32 order;
+       spinlock_t hash_lock;
+};
+
+struct pxp_buf_obj {
+       uint32_t handle;
+
+       uint32_t size;
+       uint32_t mem_type;
+
+       unsigned long offset;
+       void *virtual;
+
+       struct hlist_node item;
+};
+
+struct pxp_chan_obj {
+       uint32_t handle;
+       struct dma_chan *chan;
+};
+
+/* File private data */
+struct pxp_file {
+       struct file *filp;
+
+       /* record allocated dma buffer */
+       struct idr buffer_idr;
+       spinlock_t buffer_lock;
+
+       /* record allocated dma channel */
+       struct idr channel_idr;
+       spinlock_t channel_lock;
+};
+
+#endif
diff --git a/include/linux/pxp_dma.h b/include/linux/pxp_dma.h
new file mode 100644 (file)
index 0000000..0961753
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2010-2013 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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 _PXP_DMA
+#define _PXP_DMA
+
+#include <uapi/linux/pxp_dma.h>
+
+struct pxp_tx_desc {
+       struct dma_async_tx_descriptor txd;
+       struct list_head tx_list;
+       struct list_head list;
+       int len;
+       union {
+               struct pxp_layer_param s0_param;
+               struct pxp_layer_param out_param;
+               struct pxp_layer_param ol_param;
+       } layer_param;
+       struct pxp_proc_data proc_data;
+
+       u32 hist_status;        /* Histogram output status */
+
+       struct pxp_tx_desc *next;
+};
+
+struct pxp_channel {
+       struct dma_chan dma_chan;
+       dma_cookie_t completed; /* last completed cookie */
+       enum pxp_channel_status status;
+       void *client;           /* Only one client per channel */
+       unsigned int n_tx_desc;
+       struct pxp_tx_desc *desc;       /* allocated tx-descriptors */
+       struct list_head queue; /* queued tx-descriptors */
+       struct list_head list;  /* track queued channel number */
+       spinlock_t lock;        /* protects sg[0,1], queue,
+                                * status, cookie, free_list
+                                */
+       int active_buffer;
+       unsigned int eof_irq;
+       char eof_name[16];      /* EOF IRQ name for request_irq()  */
+};
+
+#define to_tx_desc(tx) container_of(tx, struct pxp_tx_desc, txd)
+#define to_pxp_channel(d) container_of(d, struct pxp_channel, dma_chan)
+
+void pxp_txd_ack(struct dma_async_tx_descriptor *txd,
+                struct pxp_channel *pxp_chan);
+
+#ifdef CONFIG_MXC_PXP_CLIENT_DEVICE
+int register_pxp_device(void);
+void unregister_pxp_device(void);
+#else
+int register_pxp_device(void) { return 0; }
+void unregister_pxp_device(void) {}
+#endif
+
+#endif
index 9feeb905ab4a608d8bc6da40919410583d4db1e8..4a840852bb92bd7143d5eec5a60959373ef9c476 100644 (file)
@@ -319,6 +319,8 @@ header-y += pps.h
 header-y += prctl.h
 header-y += ptp_clock.h
 header-y += ptrace.h
+header-y += pxp_dma.h
+header-y += pxp_device.h
 header-y += qnx4_fs.h
 header-y += qnxtypes.h
 header-y += quota.h
diff --git a/include/uapi/linux/pxp_device.h b/include/uapi/linux/pxp_device.h
new file mode 100644 (file)
index 0000000..fce89ce
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2013-2014 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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 _UAPI_PXP_DEVICE
+#define _UAPI_PXP_DEVICE
+
+#include <linux/pxp_dma.h>
+
+struct pxp_chan_handle {
+       unsigned int handle;
+       int hist_status;
+};
+
+struct pxp_mem_desc {
+       unsigned int handle;
+       unsigned int size;
+       dma_addr_t phys_addr;
+       unsigned int virt_uaddr;                /* virtual user space address */
+       unsigned int mtype;
+};
+
+struct pxp_mem_flush {
+       unsigned int handle;
+       unsigned int type;
+};
+
+#define PXP_IOC_MAGIC  'P'
+
+#define PXP_IOC_GET_CHAN      _IOR(PXP_IOC_MAGIC, 0, struct pxp_mem_desc)
+#define PXP_IOC_PUT_CHAN      _IOW(PXP_IOC_MAGIC, 1, struct pxp_mem_desc)
+#define PXP_IOC_CONFIG_CHAN   _IOW(PXP_IOC_MAGIC, 2, struct pxp_mem_desc)
+#define PXP_IOC_START_CHAN    _IOW(PXP_IOC_MAGIC, 3, struct pxp_mem_desc)
+#define PXP_IOC_GET_PHYMEM    _IOWR(PXP_IOC_MAGIC, 4, struct pxp_mem_desc)
+#define PXP_IOC_PUT_PHYMEM    _IOW(PXP_IOC_MAGIC, 5, struct pxp_mem_desc)
+#define PXP_IOC_WAIT4CMPLT    _IOWR(PXP_IOC_MAGIC, 6, struct pxp_mem_desc)
+#define PXP_IOC_FLUSH_PHYMEM   _IOR(PXP_IOC_MAGIC, 7, struct pxp_mem_flush)
+
+/* Memory types supported*/
+#define MEMORY_TYPE_UNCACHED 0x0
+#define MEMORY_TYPE_WC      0x1
+#define MEMORY_TYPE_CACHED   0x2
+
+/* Cache flush operations */
+#define CACHE_CLEAN      0x1
+#define CACHE_INVALIDATE 0x2
+#define CACHE_FLUSH      0x4
+
+#endif
diff --git a/include/uapi/linux/pxp_dma.h b/include/uapi/linux/pxp_dma.h
new file mode 100644 (file)
index 0000000..1e462f4
--- /dev/null
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2013-2014 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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 _UAPI_PXP_DMA
+#define _UAPI_PXP_DMA
+
+#include <linux/posix_types.h>
+#include <linux/types.h>
+
+#ifndef __KERNEL__
+typedef unsigned long dma_addr_t;
+typedef unsigned char bool;
+#endif
+
+/*  PXP Pixel format definitions */
+/*  Four-character-code (FOURCC) */
+#define fourcc(a, b, c, d)\
+       (((__u32)(a)<<0)|((__u32)(b)<<8)|((__u32)(c)<<16)|((__u32)(d)<<24))
+
+/*!
+ * @name PXP Pixel Formats
+ *
+ * Pixel formats are defined with ASCII FOURCC code. The pixel format codes are
+ * the same used by V4L2 API.
+ */
+
+/*! @} */
+/*! @name RGB Formats */
+/*! @{ */
+#define PXP_PIX_FMT_RGB332  fourcc('R', 'G', 'B', '1') /*!<  8  RGB-3-3-2    */
+#define PXP_PIX_FMT_RGB555  fourcc('R', 'G', 'B', 'O') /*!< 16  RGB-5-5-5    */
+#define PXP_PIX_FMT_RGB565  fourcc('R', 'G', 'B', 'P') /*!< 1 6  RGB-5-6-5   */
+#define PXP_PIX_FMT_RGB666  fourcc('R', 'G', 'B', '6') /*!< 18  RGB-6-6-6    */
+#define PXP_PIX_FMT_BGR666  fourcc('B', 'G', 'R', '6') /*!< 18  BGR-6-6-6    */
+#define PXP_PIX_FMT_BGR24   fourcc('B', 'G', 'R', '3') /*!< 24  BGR-8-8-8    */
+#define PXP_PIX_FMT_RGB24   fourcc('R', 'G', 'B', '3') /*!< 24  RGB-8-8-8    */
+#define PXP_PIX_FMT_BGR32   fourcc('B', 'G', 'R', '4') /*!< 32  BGR-8-8-8-8  */
+#define PXP_PIX_FMT_BGRA32  fourcc('B', 'G', 'R', 'A') /*!< 32  BGR-8-8-8-8  */
+#define PXP_PIX_FMT_RGB32   fourcc('R', 'G', 'B', '4') /*!< 32  RGB-8-8-8-8  */
+#define PXP_PIX_FMT_RGBA32  fourcc('R', 'G', 'B', 'A') /*!< 32  RGB-8-8-8-8  */
+#define PXP_PIX_FMT_ABGR32  fourcc('A', 'B', 'G', 'R') /*!< 32  ABGR-8-8-8-8 */
+/*! @} */
+/*! @name YUV Interleaved Formats */
+/*! @{ */
+#define PXP_PIX_FMT_YUYV    fourcc('Y', 'U', 'Y', 'V') /*!< 16 YUV 4:2:2 */
+#define PXP_PIX_FMT_UYVY    fourcc('U', 'Y', 'V', 'Y') /*!< 16 YUV 4:2:2 */
+#define PXP_PIX_FMT_VYUY    fourcc('V', 'Y', 'U', 'Y')  /*!< 16 YVU 4:2:2 */
+#define PXP_PIX_FMT_YVYU    fourcc('Y', 'V', 'Y', 'U')  /*!< 16 YVU 4:2:2 */
+#define PXP_PIX_FMT_Y41P    fourcc('Y', '4', '1', 'P') /*!< 12 YUV 4:1:1 */
+#define PXP_PIX_FMT_YUV444  fourcc('Y', '4', '4', '4') /*!< 24 YUV 4:4:4 */
+/* two planes -- one Y, one Cb + Cr interleaved  */
+#define PXP_PIX_FMT_NV12    fourcc('N', 'V', '1', '2') /* 12  Y/CbCr 4:2:0  */
+#define PXP_PIX_FMT_NV21    fourcc('N', 'V', '2', '1') /* 12  Y/CbCr 4:2:0  */
+#define PXP_PIX_FMT_NV16    fourcc('N', 'V', '1', '6') /* 12  Y/CbCr 4:2:2  */
+#define PXP_PIX_FMT_NV61    fourcc('N', 'V', '6', '1') /* 12  Y/CbCr 4:2:2  */
+/*! @} */
+/*! @name YUV Planar Formats */
+/*! @{ */
+#define PXP_PIX_FMT_GREY    fourcc('G', 'R', 'E', 'Y') /*!< 8  Greyscale */
+#define PXP_PIX_FMT_GY04    fourcc('G', 'Y', '0', '4') /*!< 4  Greyscale */
+#define PXP_PIX_FMT_YVU410P fourcc('Y', 'V', 'U', '9') /*!< 9  YVU 4:1:0 */
+#define PXP_PIX_FMT_YUV410P fourcc('Y', 'U', 'V', '9') /*!< 9  YUV 4:1:0 */
+#define PXP_PIX_FMT_YVU420P fourcc('Y', 'V', '1', '2') /*!< 12 YVU 4:2:0 */
+#define PXP_PIX_FMT_YUV420P fourcc('I', '4', '2', '0') /*!< 12 YUV 4:2:0 */
+#define PXP_PIX_FMT_YUV420P2 fourcc('Y', 'U', '1', '2')        /*!< 12 YUV 4:2:0 */
+#define PXP_PIX_FMT_YVU422P fourcc('Y', 'V', '1', '6') /*!< 16 YVU 4:2:2 */
+#define PXP_PIX_FMT_YUV422P fourcc('4', '2', '2', 'P') /*!< 16 YUV 4:2:2 */
+/*! @} */
+
+#define PXP_LUT_NONE                   0x0
+#define PXP_LUT_INVERT                 0x1
+#define PXP_LUT_BLACK_WHITE            0x2
+#define PXP_LUT_USE_CMAP               0x4
+
+#define NR_PXP_VIRT_CHANNEL    16
+
+/* Order significant! */
+enum pxp_channel_status {
+       PXP_CHANNEL_FREE,
+       PXP_CHANNEL_INITIALIZED,
+       PXP_CHANNEL_READY,
+};
+
+struct rect {
+       int top;                /* Upper left coordinate of rectangle */
+       int left;
+       int width;
+       int height;
+};
+
+struct pxp_layer_param {
+       unsigned short width;
+       unsigned short height;
+       unsigned short stride; /* aka pitch */
+       unsigned int pixel_fmt;
+
+       /* layers combining parameters
+        * (these are ignored for S0 and output
+        * layers, and only apply for OL layer)
+        */
+       bool combine_enable;
+       unsigned int color_key_enable;
+       unsigned int color_key;
+       bool global_alpha_enable;
+       /* global alpha is either override or multiply */
+       bool global_override;
+       unsigned char global_alpha;
+       bool alpha_invert;
+       bool local_alpha_enable;
+
+       dma_addr_t paddr;
+};
+
+struct pxp_proc_data {
+       /* S0 Transformation Info */
+       int scaling;
+       int hflip;
+       int vflip;
+       int rotate;
+       int rot_pos;
+       int yuv;
+
+       /* Source rectangle (srect) defines the sub-rectangle
+        * within S0 to undergo processing.
+        */
+       struct rect srect;
+       /* Dest rect (drect) defines how to position the processed
+        * source rectangle (after resizing) within the output frame,
+        * whose dimensions are defined in pxp->pxp_conf_state.out_param
+        */
+       struct rect drect;
+
+       /* Current S0 configuration */
+       unsigned int bgcolor;
+
+       /* Output overlay support */
+       int overlay_state;
+
+       /* LUT transformation on Y data */
+       int lut_transform;
+       unsigned char *lut_map; /* 256 entries */
+       bool lut_map_updated; /* Map recently changed */
+       bool combine_enable;
+};
+
+struct pxp_config_data {
+       struct pxp_layer_param s0_param;
+       struct pxp_layer_param ol_param[8];
+       struct pxp_layer_param out_param;
+       struct pxp_proc_data proc_data;
+       int layer_nr;
+
+       /* Users don't touch */
+       int handle;
+};
+
+
+#endif