]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
ENGR00155146 ipuv3: use mutex instead of spin lock
authorJason Chen <b02280@freescale.com>
Tue, 6 Sep 2011 06:06:09 +0000 (14:06 +0800)
committerLothar Waßmann <LW@KARO-electronics.de>
Fri, 24 May 2013 06:33:12 +0000 (08:33 +0200)
keep spin lock for irq function, but use mutex replace other
splin lock to provide better sync method.
Add _ipu_get/put function to check clock enable.

Signed-off-by: Jason Chen <b02280@freescale.com>
drivers/mxc/ipu3/ipu_capture.c
drivers/mxc/ipu3/ipu_common.c
drivers/mxc/ipu3/ipu_device.c
drivers/mxc/ipu3/ipu_disp.c
drivers/mxc/ipu3/ipu_param_mem.h
drivers/mxc/ipu3/ipu_prv.h

index 88b1a3954ae567fca62e6448227431812286081c..2399cb88d35197363e9ac74baae94422564f8376 100644 (file)
@@ -50,7 +50,6 @@ ipu_csi_init_interface(struct ipu_soc *ipu, uint16_t width, uint16_t height,
 {
        uint32_t data = 0;
        uint32_t csi = cfg_param.csi;
-       unsigned long lock_flags;
 
        /* Set SENS_DATA_FORMAT bits (8, 9 and 10)
           RGB or YUV444 is 0 which is current value in data so not set
@@ -94,10 +93,9 @@ ipu_csi_init_interface(struct ipu_soc *ipu, uint16_t width, uint16_t height,
                cfg_param.force_eof << CSI_SENS_CONF_FORCE_EOF_SHIFT |
                cfg_param.data_en_pol << CSI_SENS_CONF_DATA_EN_POL_SHIFT;
 
-       if (!ipu->clk_enabled)
-               clk_enable(ipu->ipu_clk);
+       _ipu_get(ipu);
 
-       spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
+       _ipu_lock(ipu);
 
        ipu_csi_write(ipu, csi, data, CSI_SENS_CONF);
 
@@ -136,11 +134,10 @@ ipu_csi_init_interface(struct ipu_soc *ipu, uint16_t width, uint16_t height,
                        ipu_csi_write(ipu, csi, 0x40596, CSI_CCIR_CODE_2);
                        ipu_csi_write(ipu, csi, 0xFF0000, CSI_CCIR_CODE_3);
                } else {
-                       spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
                        dev_err(ipu->dev, "Unsupported CCIR656 interlaced "
                                        "video mode\n");
-                       if (!ipu->clk_enabled)
-                               clk_disable(ipu->ipu_clk);
+                       _ipu_unlock(ipu);
+                       _ipu_put(ipu);
                        return -EINVAL;
                }
                _ipu_csi_ccir_err_detection_enable(ipu, csi);
@@ -165,10 +162,9 @@ ipu_csi_init_interface(struct ipu_soc *ipu, uint16_t width, uint16_t height,
        dev_dbg(ipu->dev, "CSI_ACT_FRM_SIZE = 0x%08X\n",
                ipu_csi_read(ipu, csi, CSI_ACT_FRM_SIZE));
 
-       spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
+       _ipu_unlock(ipu);
 
-       if (!ipu->clk_enabled)
-               clk_disable(ipu->ipu_clk);
+       _ipu_put(ipu);
 
        return 0;
 }
@@ -254,21 +250,18 @@ EXPORT_SYMBOL(ipu_csi_enable_mclk);
 void ipu_csi_get_window_size(struct ipu_soc *ipu, uint32_t *width, uint32_t *height, uint32_t csi)
 {
        uint32_t reg;
-       unsigned long lock_flags;
 
-       if (!ipu->clk_enabled)
-               clk_enable(ipu->ipu_clk);
+       _ipu_get(ipu);
 
-       spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
+       _ipu_lock(ipu);
 
        reg = ipu_csi_read(ipu, csi, CSI_ACT_FRM_SIZE);
        *width = (reg & 0xFFFF) + 1;
        *height = (reg >> 16 & 0xFFFF) + 1;
 
-       spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
+       _ipu_unlock(ipu);
 
-       if (!ipu->clk_enabled)
-               clk_disable(ipu->ipu_clk);
+       _ipu_put(ipu);
 }
 EXPORT_SYMBOL(ipu_csi_get_window_size);
 
@@ -282,19 +275,15 @@ EXPORT_SYMBOL(ipu_csi_get_window_size);
  */
 void ipu_csi_set_window_size(struct ipu_soc *ipu, uint32_t width, uint32_t height, uint32_t csi)
 {
-       unsigned long lock_flags;
+       _ipu_get(ipu);
 
-       if (!ipu->clk_enabled)
-               clk_enable(ipu->ipu_clk);
-
-       spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
+       _ipu_lock(ipu);
 
        ipu_csi_write(ipu, csi, (width - 1) | (height - 1) << 16, CSI_ACT_FRM_SIZE);
 
-       spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
+       _ipu_unlock(ipu);
 
-       if (!ipu->clk_enabled)
-               clk_disable(ipu->ipu_clk);
+       _ipu_put(ipu);
 }
 EXPORT_SYMBOL(ipu_csi_set_window_size);
 
@@ -309,22 +298,19 @@ EXPORT_SYMBOL(ipu_csi_set_window_size);
 void ipu_csi_set_window_pos(struct ipu_soc *ipu, uint32_t left, uint32_t top, uint32_t csi)
 {
        uint32_t temp;
-       unsigned long lock_flags;
 
-       if (!ipu->clk_enabled)
-               clk_enable(ipu->ipu_clk);
+       _ipu_get(ipu);
 
-       spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
+       _ipu_lock(ipu);
 
        temp = ipu_csi_read(ipu, csi, CSI_OUT_FRM_CTRL);
        temp &= ~(CSI_HSC_MASK | CSI_VSC_MASK);
        temp |= ((top << CSI_VSC_SHIFT) | (left << CSI_HSC_SHIFT));
        ipu_csi_write(ipu, csi, temp, CSI_OUT_FRM_CTRL);
 
-       spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
+       _ipu_unlock(ipu);
 
-       if (!ipu->clk_enabled)
-               clk_disable(ipu->ipu_clk);
+       _ipu_put(ipu);
 }
 EXPORT_SYMBOL(ipu_csi_set_window_pos);
 
@@ -338,21 +324,10 @@ EXPORT_SYMBOL(ipu_csi_set_window_pos);
 void _ipu_csi_horizontal_downsize_enable(struct ipu_soc *ipu, uint32_t csi)
 {
        uint32_t temp;
-       unsigned long lock_flags;
-
-       if (!ipu->clk_enabled)
-               clk_enable(ipu->ipu_clk);
-
-       spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
 
        temp = ipu_csi_read(ipu, csi, CSI_OUT_FRM_CTRL);
        temp |= CSI_HORI_DOWNSIZE_EN;
        ipu_csi_write(ipu, csi, temp, CSI_OUT_FRM_CTRL);
-
-       spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
-
-       if (!ipu->clk_enabled)
-               clk_disable(ipu->ipu_clk);
 }
 
 /*!
@@ -365,21 +340,10 @@ void _ipu_csi_horizontal_downsize_enable(struct ipu_soc *ipu, uint32_t csi)
 void _ipu_csi_horizontal_downsize_disable(struct ipu_soc *ipu, uint32_t csi)
 {
        uint32_t temp;
-       unsigned long lock_flags;
-
-       if (!ipu->clk_enabled)
-               clk_enable(ipu->ipu_clk);
-
-       spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
 
        temp = ipu_csi_read(ipu, csi, CSI_OUT_FRM_CTRL);
        temp &= ~CSI_HORI_DOWNSIZE_EN;
        ipu_csi_write(ipu, csi, temp, CSI_OUT_FRM_CTRL);
-
-       spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
-
-       if (!ipu->clk_enabled)
-               clk_disable(ipu->ipu_clk);
 }
 
 /*!
@@ -392,21 +356,10 @@ void _ipu_csi_horizontal_downsize_disable(struct ipu_soc *ipu, uint32_t csi)
 void _ipu_csi_vertical_downsize_enable(struct ipu_soc *ipu, uint32_t csi)
 {
        uint32_t temp;
-       unsigned long lock_flags;
-
-       if (!ipu->clk_enabled)
-               clk_enable(ipu->ipu_clk);
-
-       spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
 
        temp = ipu_csi_read(ipu, csi, CSI_OUT_FRM_CTRL);
        temp |= CSI_VERT_DOWNSIZE_EN;
        ipu_csi_write(ipu, csi, temp, CSI_OUT_FRM_CTRL);
-
-       spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
-
-       if (!ipu->clk_enabled)
-               clk_disable(ipu->ipu_clk);
 }
 
 /*!
@@ -419,25 +372,14 @@ void _ipu_csi_vertical_downsize_enable(struct ipu_soc *ipu, uint32_t csi)
 void _ipu_csi_vertical_downsize_disable(struct ipu_soc *ipu, uint32_t csi)
 {
        uint32_t temp;
-       unsigned long lock_flags;
-
-       if (!ipu->clk_enabled)
-               clk_enable(ipu->ipu_clk);
-
-       spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
 
        temp = ipu_csi_read(ipu, csi, CSI_OUT_FRM_CTRL);
        temp &= ~CSI_VERT_DOWNSIZE_EN;
        ipu_csi_write(ipu, csi, temp, CSI_OUT_FRM_CTRL);
-
-       spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
-
-       if (!ipu->clk_enabled)
-               clk_disable(ipu->ipu_clk);
 }
 
 /*!
- * ipu_csi_set_test_generator
+ * _ipu_csi_set_test_generator
  *
  * @param      ipu             ipu handler
  * @param      active       1 for active and 0 for inactive
@@ -448,16 +390,10 @@ void _ipu_csi_vertical_downsize_disable(struct ipu_soc *ipu, uint32_t csi)
  * @param      pixel_clk   desired pixel clock frequency in Hz
  * @param       csi          csi 0 or csi 1
  */
-void ipu_csi_set_test_generator(struct ipu_soc *ipu, bool active, uint32_t r_value,
+void _ipu_csi_set_test_generator(struct ipu_soc *ipu, bool active, uint32_t r_value,
        uint32_t g_value, uint32_t b_value, uint32_t pix_clk, uint32_t csi)
 {
        uint32_t temp;
-       unsigned long lock_flags;
-
-       if (!ipu->clk_enabled)
-               clk_enable(ipu->ipu_clk);
-
-       spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
 
        temp = ipu_csi_read(ipu, csi, CSI_TST_CTRL);
 
@@ -476,13 +412,7 @@ void ipu_csi_set_test_generator(struct ipu_soc *ipu, bool active, uint32_t r_val
                        (b_value << CSI_TEST_GEN_B_SHIFT);
                ipu_csi_write(ipu, csi, temp, CSI_TST_CTRL);
        }
-
-       spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
-
-       if (!ipu->clk_enabled)
-               clk_disable(ipu->ipu_clk);
 }
-EXPORT_SYMBOL(ipu_csi_set_test_generator);
 
 /*!
  * _ipu_csi_ccir_err_detection_en
@@ -496,15 +426,10 @@ void _ipu_csi_ccir_err_detection_enable(struct ipu_soc *ipu, uint32_t csi)
 {
        uint32_t temp;
 
-       if (!ipu->clk_enabled)
-               clk_enable(ipu->ipu_clk);
-
        temp = ipu_csi_read(ipu, csi, CSI_CCIR_CODE_1);
        temp |= CSI_CCIR_ERR_DET_EN;
        ipu_csi_write(ipu, csi, temp, CSI_CCIR_CODE_1);
 
-       if (!ipu->clk_enabled)
-               clk_disable(ipu->ipu_clk);
 }
 
 /*!
@@ -519,15 +444,10 @@ void _ipu_csi_ccir_err_detection_disable(struct ipu_soc *ipu, uint32_t csi)
 {
        uint32_t temp;
 
-       if (!ipu->clk_enabled)
-               clk_enable(ipu->ipu_clk);
-
        temp = ipu_csi_read(ipu, csi, CSI_CCIR_CODE_1);
        temp &= ~CSI_CCIR_ERR_DET_EN;
        ipu_csi_write(ipu, csi, temp, CSI_CCIR_CODE_1);
 
-       if (!ipu->clk_enabled)
-               clk_disable(ipu->ipu_clk);
 }
 
 /*!
@@ -544,18 +464,12 @@ int _ipu_csi_set_mipi_di(struct ipu_soc *ipu, uint32_t num, uint32_t di_val, uin
 {
        uint32_t temp;
        int retval = 0;
-       unsigned long lock_flags;
 
        if (di_val > 0xFFL) {
                retval = -EINVAL;
                goto err;
        }
 
-       if (!ipu->clk_enabled)
-               clk_enable(ipu->ipu_clk);
-
-       spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
-
        temp = ipu_csi_read(ipu, csi, CSI_MIPI_DI);
 
        switch (num) {
@@ -583,9 +497,6 @@ int _ipu_csi_set_mipi_di(struct ipu_soc *ipu, uint32_t num, uint32_t di_val, uin
                retval = -EINVAL;
        }
 
-       spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
-       if (!ipu->clk_enabled)
-               clk_disable(ipu->ipu_clk);
 err:
        return retval;
 }
@@ -606,27 +517,18 @@ int _ipu_csi_set_skip_isp(struct ipu_soc *ipu, uint32_t skip, uint32_t max_ratio
 {
        uint32_t temp;
        int retval = 0;
-       unsigned long lock_flags;
 
        if (max_ratio > 5) {
                retval = -EINVAL;
                goto err;
        }
 
-       if (!ipu->clk_enabled)
-               clk_enable(ipu->ipu_clk);
-
-       spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
-
        temp = ipu_csi_read(ipu, csi, CSI_SKIP);
        temp &= ~(CSI_MAX_RATIO_SKIP_ISP_MASK | CSI_SKIP_ISP_MASK);
        temp |= (max_ratio << CSI_MAX_RATIO_SKIP_ISP_SHIFT) |
                (skip << CSI_SKIP_ISP_SHIFT);
        ipu_csi_write(ipu, csi, temp, CSI_SKIP);
 
-       spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
-       if (!ipu->clk_enabled)
-               clk_disable(ipu->ipu_clk);
 err:
        return retval;
 }
@@ -649,18 +551,12 @@ int _ipu_csi_set_skip_smfc(struct ipu_soc *ipu, uint32_t skip,
 {
        uint32_t temp;
        int retval = 0;
-       unsigned long lock_flags;
 
        if (max_ratio > 5 || id > 3) {
                retval = -EINVAL;
                goto err;
        }
 
-       if (!ipu->clk_enabled)
-               clk_enable(ipu->ipu_clk);
-
-       spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
-
        temp = ipu_csi_read(ipu, csi, CSI_SKIP);
        temp &= ~(CSI_MAX_RATIO_SKIP_SMFC_MASK | CSI_ID_2_SKIP_MASK |
                        CSI_SKIP_SMFC_MASK);
@@ -669,10 +565,6 @@ int _ipu_csi_set_skip_smfc(struct ipu_soc *ipu, uint32_t skip,
                        (skip << CSI_SKIP_SMFC_SHIFT);
        ipu_csi_write(ipu, csi, temp, CSI_SKIP);
 
-       spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
-
-       if (!ipu->clk_enabled)
-               clk_disable(ipu->ipu_clk);
 err:
        return retval;
 }
@@ -730,12 +622,6 @@ void _ipu_smfc_init(struct ipu_soc *ipu, ipu_channel_t channel, uint32_t mipi_id
 void _ipu_smfc_set_wmc(struct ipu_soc *ipu, ipu_channel_t channel, bool set, uint32_t level)
 {
        uint32_t temp;
-       unsigned long lock_flags;
-
-       if (!ipu->clk_enabled)
-               clk_enable(ipu->ipu_clk);
-
-       spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
 
        temp = ipu_smfc_read(ipu, SMFC_WMC);
 
@@ -781,10 +667,6 @@ void _ipu_smfc_set_wmc(struct ipu_soc *ipu, ipu_channel_t channel, bool set, uin
        }
 
        ipu_smfc_write(ipu, temp, SMFC_WMC);
-
-       spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
-       if (!ipu->clk_enabled)
-               clk_disable(ipu->ipu_clk);
 }
 
 /*!
@@ -798,9 +680,6 @@ void _ipu_smfc_set_wmc(struct ipu_soc *ipu, ipu_channel_t channel, bool set, uin
 void _ipu_smfc_set_burst_size(struct ipu_soc *ipu, ipu_channel_t channel, uint32_t bs)
 {
        uint32_t temp;
-       unsigned long lock_flags;
-
-       spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
 
        temp = ipu_smfc_read(ipu, SMFC_BS);
 
@@ -826,8 +705,6 @@ void _ipu_smfc_set_burst_size(struct ipu_soc *ipu, ipu_channel_t channel, uint32
        }
 
        ipu_smfc_write(ipu, temp, SMFC_BS);
-
-       spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
 }
 
 /*!
index 3e099d9e0f1dcdc4b08360b4ba6397d65b1c2a90..2a1eecda3d5cf129d501287cbf87066ea750dee0 100644 (file)
 #include <linux/irqdesc.h>
 #include <linux/ipu.h>
 #include <linux/clk.h>
-#include <linux/clkdev.h>
 #include <mach/clock.h>
 #include <mach/hardware.h>
 #include <mach/ipu-v3.h>
 #include <mach/devices-common.h>
+#include <asm/cacheflush.h>
+#include <linux/delay.h>
 
 #include "ipu_prv.h"
 #include "ipu_regs.h"
@@ -112,156 +113,10 @@ static int ipu_reset(struct ipu_soc *ipu)
        return 0;
 }
 
-static inline struct ipu_soc *pixelclk2ipu(struct clk *clk)
-{
-       struct ipu_soc *ipu;
-       struct clk *base = clk - clk->id;
-
-       ipu = container_of(base, struct ipu_soc, pixel_clk[0]);
-
-       return ipu;
-}
-
-static unsigned long _ipu_pixel_clk_get_rate(struct clk *clk)
-{
-       struct ipu_soc *ipu = pixelclk2ipu(clk);
-       u32 div = ipu_di_read(ipu, clk->id, DI_BS_CLKGEN0);
-       if (div == 0)
-               return 0;
-       return  (clk_get_rate(clk->parent) * 16) / div;
-}
-
-static unsigned long _ipu_pixel_clk_round_rate(struct clk *clk, unsigned long rate)
-{
-       u32 div;
-       u32 parent_rate = clk_get_rate(clk->parent) * 16;
-       /*
-        * Calculate divider
-        * Fractional part is 4 bits,
-        * so simply multiply by 2^4 to get fractional part.
-        */
-       div = parent_rate / rate;
-
-       if (div < 0x10)            /* Min DI disp clock divider is 1 */
-               div = 0x10;
-       if (div & ~0xFEF)
-               div &= 0xFF8;
-       else {
-               /* Round up divider if it gets us closer to desired pix clk */
-               if ((div & 0xC) == 0xC) {
-                       div += 0x10;
-                       div &= ~0xF;
-               }
-       }
-       return parent_rate / div;
-}
-
-static int _ipu_pixel_clk_set_rate(struct clk *clk, unsigned long rate)
-{
-       struct ipu_soc *ipu = pixelclk2ipu(clk);
-       u32 div = (clk_get_rate(clk->parent) * 16) / rate;
-       unsigned long lock_flags;
-
-       /* Round up divider if it gets us closer to desired pix clk */
-       if ((div & 0xC) == 0xC) {
-               div += 0x10;
-               div &= ~0xF;
-       }
-
-       spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
-       ipu_di_write(ipu, clk->id, div, DI_BS_CLKGEN0);
-
-       /* Setup pixel clock timing */
-       /* FIXME: needs to be more flexible */
-       /* Down time is half of period */
-       ipu_di_write(ipu, clk->id, (div / 16) << 16, DI_BS_CLKGEN1);
-       spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
-
-       return 0;
-}
-
-static int _ipu_pixel_clk_enable(struct clk *clk)
-{
-       struct ipu_soc *ipu = pixelclk2ipu(clk);
-       u32 disp_gen = ipu_cm_read(ipu, IPU_DISP_GEN);
-       disp_gen |= clk->id ? DI1_COUNTER_RELEASE : DI0_COUNTER_RELEASE;
-       ipu_cm_write(ipu, disp_gen, IPU_DISP_GEN);
-
-       return 0;
-}
-
-static void _ipu_pixel_clk_disable(struct clk *clk)
-{
-       struct ipu_soc *ipu = pixelclk2ipu(clk);
-
-       u32 disp_gen = ipu_cm_read(ipu, IPU_DISP_GEN);
-       disp_gen &= clk->id ? ~DI1_COUNTER_RELEASE : ~DI0_COUNTER_RELEASE;
-       ipu_cm_write(ipu, disp_gen, IPU_DISP_GEN);
-}
-
-static int _ipu_pixel_clk_set_parent(struct clk *clk, struct clk *parent)
-{
-       struct ipu_soc *ipu = pixelclk2ipu(clk);
-       unsigned long lock_flags;
-       u32 di_gen;
-
-       spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
-       di_gen = ipu_di_read(ipu, clk->id, DI_GENERAL);
-       if (parent == ipu->ipu_clk)
-               di_gen &= ~DI_GEN_DI_CLK_EXT;
-       else if (!IS_ERR(ipu->di_clk[clk->id]) && parent == ipu->di_clk[clk->id])
-               di_gen |= DI_GEN_DI_CLK_EXT;
-       else {
-               spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
-               return -EINVAL;
-       }
-
-       ipu_di_write(ipu, clk->id, di_gen, DI_GENERAL);
-       spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
-       return 0;
-}
-
-#ifdef CONFIG_CLK_DEBUG
-#define __INIT_CLK_DEBUG(n)    .name = #n,
-#else
-#define __INIT_CLK_DEBUG(n)
-#endif
 static int __devinit ipu_clk_setup_enable(struct ipu_soc *ipu,
                struct platform_device *pdev)
 {
        struct imx_ipuv3_platform_data *plat_data = pdev->dev.platform_data;
-       static struct clk ipu_pixel_clk[] = {
-               {
-                       __INIT_CLK_DEBUG(pixel_clk_0)
-                               .id = 0,
-                       .get_rate = _ipu_pixel_clk_get_rate,
-                       .set_rate = _ipu_pixel_clk_set_rate,
-                       .round_rate = _ipu_pixel_clk_round_rate,
-                       .set_parent = _ipu_pixel_clk_set_parent,
-                       .enable = _ipu_pixel_clk_enable,
-                       .disable = _ipu_pixel_clk_disable,
-               },
-               {
-                       __INIT_CLK_DEBUG(pixel_clk_1)
-                               .id = 1,
-                       .get_rate = _ipu_pixel_clk_get_rate,
-                       .set_rate = _ipu_pixel_clk_set_rate,
-                       .round_rate = _ipu_pixel_clk_round_rate,
-                       .set_parent = _ipu_pixel_clk_set_parent,
-                       .enable = _ipu_pixel_clk_enable,
-                       .disable = _ipu_pixel_clk_disable,
-               },
-       };
-       static struct clk_lookup ipu_lookups[] = {
-               {
-                       .dev_id = NULL,
-                       .con_id = "pixel_clk_0",
-               },
-               {
-                       .dev_id = NULL,
-                       .con_id = "pixel_clk_1",
-               },
-       };
        char ipu_clk[] = "ipu1_clk";
        char di0_clk[] = "ipu1_di0_clk";
        char di1_clk[] = "ipu1_di1_clk";
@@ -477,6 +332,33 @@ struct ipu_soc *ipu_get_soc(int id)
        else
                return &(ipu_array[id]);
 }
+EXPORT_SYMBOL_GPL(ipu_get_soc);
+
+void _ipu_lock(struct ipu_soc *ipu)
+{
+       /*TODO:remove in_irq() condition after v4l2 driver rewrite*/
+       if (!in_irq() && !in_softirq())
+               mutex_lock(&ipu->mutex_lock);
+}
+
+void _ipu_unlock(struct ipu_soc *ipu)
+{
+       /*TODO:remove in_irq() condition after v4l2 driver rewrite*/
+       if (!in_irq() && !in_softirq())
+               mutex_unlock(&ipu->mutex_lock);
+}
+
+void _ipu_get(struct ipu_soc *ipu)
+{
+       if (atomic_inc_return(&ipu->ipu_use_count) == 1)
+               clk_enable(ipu->ipu_clk);
+}
+
+void _ipu_put(struct ipu_soc *ipu)
+{
+       if (atomic_dec_return(&ipu->ipu_use_count) == 0)
+               clk_disable(ipu->ipu_clk);
+}
 
 /*!
  * This function is called by the driver framework to initialize the IPU
@@ -501,7 +383,9 @@ static int __devinit ipu_probe(struct platform_device *pdev)
        ipu = &ipu_array[pdev->id];
        memset(ipu, 0, sizeof(struct ipu_soc));
 
-       spin_lock_init(&ipu->ipu_lock);
+       spin_lock_init(&ipu->spin_lock);
+       mutex_init(&ipu->mutex_lock);
+       atomic_set(&ipu->ipu_use_count, 0);
 
        g_ipu_hw_rev = plat_data->rev;
 
@@ -734,19 +618,15 @@ int32_t ipu_init_channel(struct ipu_soc *ipu, ipu_channel_t channel, ipu_channel
        int ret = 0;
        uint32_t ipu_conf;
        uint32_t reg;
-       unsigned long lock_flags;
 
        dev_dbg(ipu->dev, "init channel = %d\n", IPU_CHAN_ID(channel));
 
-       if (ipu->clk_enabled == false) {
-               ipu->clk_enabled = true;
-               clk_enable(ipu->ipu_clk);
-       }
+       _ipu_get(ipu);
 
-       spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
+       _ipu_lock(ipu);
 
        if (ipu->channel_init_mask & (1L << IPU_CHAN_ID(channel))) {
-               dev_err(ipu->dev, "Warning: channel already initialized %d\n",
+               dev_warn(ipu->dev, "Warning: channel already initialized %d\n",
                        IPU_CHAN_ID(channel));
        }
 
@@ -990,13 +870,12 @@ int32_t ipu_init_channel(struct ipu_soc *ipu, ipu_channel_t channel, ipu_channel
                break;
        }
 
-       /* Enable IPU sub module */
        ipu->channel_init_mask |= 1L << IPU_CHAN_ID(channel);
 
        ipu_cm_write(ipu, ipu_conf, IPU_CONF);
 
 err:
-       spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
+       _ipu_unlock(ipu);
        return ret;
 }
 EXPORT_SYMBOL(ipu_init_channel);
@@ -1009,17 +888,16 @@ EXPORT_SYMBOL(ipu_init_channel);
  */
 void ipu_uninit_channel(struct ipu_soc *ipu, ipu_channel_t channel)
 {
-       unsigned long lock_flags;
        uint32_t reg;
        uint32_t in_dma, out_dma = 0;
        uint32_t ipu_conf;
 
-       spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
+       _ipu_lock(ipu);
 
        if ((ipu->channel_init_mask & (1L << IPU_CHAN_ID(channel))) == 0) {
                dev_err(ipu->dev, "Channel already uninitialized %d\n",
                        IPU_CHAN_ID(channel));
-               spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
+               _ipu_unlock(ipu);
                return;
        }
 
@@ -1033,7 +911,7 @@ void ipu_uninit_channel(struct ipu_soc *ipu, ipu_channel_t channel)
                dev_err(ipu->dev,
                        "Channel %d is not disabled, disable first\n",
                        IPU_CHAN_ID(channel));
-               spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
+               _ipu_unlock(ipu);
                return;
        }
 
@@ -1168,8 +1046,6 @@ void ipu_uninit_channel(struct ipu_soc *ipu, ipu_channel_t channel)
                break;
        }
 
-       ipu->channel_init_mask &= ~(1L << IPU_CHAN_ID(channel));
-
        if (ipu->ic_use_count == 0)
                ipu_conf &= ~IPU_CONF_IC_EN;
        if (ipu->vdi_use_count == 0) {
@@ -1196,12 +1072,11 @@ void ipu_uninit_channel(struct ipu_soc *ipu, ipu_channel_t channel)
 
        ipu_cm_write(ipu, ipu_conf, IPU_CONF);
 
-       spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
+       ipu->channel_init_mask &= ~(1L << IPU_CHAN_ID(channel));
 
-       if (ipu_conf == 0) {
-               clk_disable(ipu->ipu_clk);
-               ipu->clk_enabled = false;
-       }
+       _ipu_unlock(ipu);
+
+       _ipu_put(ipu);
 
        WARN_ON(ipu->ic_use_count < 0);
        WARN_ON(ipu->vdi_use_count < 0);
@@ -1267,7 +1142,6 @@ int32_t ipu_init_channel_buffer(struct ipu_soc *ipu, ipu_channel_t channel,
                                dma_addr_t phyaddr_2,
                                uint32_t u, uint32_t v)
 {
-       unsigned long lock_flags;
        uint32_t reg;
        uint32_t dma_chan;
        uint32_t burst_size;
@@ -1303,6 +1177,8 @@ int32_t ipu_init_channel_buffer(struct ipu_soc *ipu, ipu_channel_t channel,
                return -EINVAL;
        }
 
+       _ipu_lock(ipu);
+
        /* Build parameter memory data for DMA channel */
        _ipu_ch_param_init(ipu, dma_chan, pixel_fmt, width, height, stride, u, v, 0,
                           phyaddr_0, phyaddr_1, phyaddr_2);
@@ -1335,10 +1211,8 @@ int32_t ipu_init_channel_buffer(struct ipu_soc *ipu, ipu_channel_t channel,
                _ipu_ch_param_set_block_mode(ipu, dma_chan);
        } else if (_ipu_is_dmfc_chan(dma_chan)) {
                burst_size = _ipu_ch_param_get_burst_size(ipu, dma_chan);
-               spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
                _ipu_dmfc_set_wait4eot(ipu, dma_chan, width);
                _ipu_dmfc_set_burst_size(ipu, dma_chan, burst_size);
-               spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
        }
 
        if (_ipu_disp_chan_is_interlaced(ipu, channel) ||
@@ -1360,13 +1234,84 @@ int32_t ipu_init_channel_buffer(struct ipu_soc *ipu, ipu_channel_t channel,
                _ipu_smfc_set_burst_size(ipu, channel, burst_size-1);
        }
 
-       if (idma_is_set(ipu, IDMAC_CHA_PRI, dma_chan) && !cpu_is_mx53()
-               && !cpu_is_mx6q())
-               _ipu_ch_param_set_high_priority(ipu, dma_chan);
+       /* AXI-id */
+       if (idma_is_set(ipu, IDMAC_CHA_PRI, dma_chan)) {
+               unsigned reg = IDMAC_CH_LOCK_EN_1;
+               uint32_t value = 0;
+               if (cpu_is_mx53() || cpu_is_mx6q()) {
+                       _ipu_ch_param_set_axi_id(ipu, dma_chan, 0);
+                       switch (dma_chan) {
+                       case 5:
+                               value = 0x3;
+                               break;
+                       case 11:
+                               value = 0x3 << 2;
+                               break;
+                       case 12:
+                               value = 0x3 << 4;
+                               break;
+                       case 14:
+                               value = 0x3 << 6;
+                               break;
+                       case 15:
+                               value = 0x3 << 8;
+                               break;
+                       case 20:
+                               value = 0x3 << 10;
+                               break;
+                       case 21:
+                               value = 0x3 << 12;
+                               break;
+                       case 22:
+                               value = 0x3 << 14;
+                               break;
+                       case 23:
+                               value = 0x3 << 16;
+                               break;
+                       case 27:
+                               value = 0x3 << 18;
+                               break;
+                       case 28:
+                               value = 0x3 << 20;
+                               break;
+                       case 45:
+                               reg = IDMAC_CH_LOCK_EN_2;
+                               value = 0x3 << 0;
+                               break;
+                       case 46:
+                               reg = IDMAC_CH_LOCK_EN_2;
+                               value = 0x3 << 2;
+                               break;
+                       case 47:
+                               reg = IDMAC_CH_LOCK_EN_2;
+                               value = 0x3 << 4;
+                               break;
+                       case 48:
+                               reg = IDMAC_CH_LOCK_EN_2;
+                               value = 0x3 << 6;
+                               break;
+                       case 49:
+                               reg = IDMAC_CH_LOCK_EN_2;
+                               value = 0x3 << 8;
+                               break;
+                       case 50:
+                               reg = IDMAC_CH_LOCK_EN_2;
+                               value = 0x3 << 10;
+                               break;
+                       default:
+                               break;
+                       }
+                       value |= ipu_idmac_read(ipu, reg);
+                       ipu_idmac_write(ipu, value, reg);
+               } else
+                       _ipu_ch_param_set_axi_id(ipu, dma_chan, 1);
+       } else {
+               if (cpu_is_mx6q())
+                       _ipu_ch_param_set_axi_id(ipu, dma_chan, 1);
+       }
 
        _ipu_ch_param_dump(ipu, dma_chan);
 
-       spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
        if (phyaddr_2 && g_ipu_hw_rev >= 2) {
                reg = ipu_cm_read(ipu, IPU_CHA_DB_MODE_SEL(dma_chan));
                reg &= ~idma_mask(dma_chan);
@@ -1402,7 +1347,8 @@ int32_t ipu_init_channel_buffer(struct ipu_soc *ipu, ipu_channel_t channel,
                                IPU_CHA_CUR_BUF(dma_chan));
 
        }
-       spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
+
+       _ipu_unlock(ipu);
 
        return 0;
 }
@@ -1430,12 +1376,12 @@ int32_t ipu_update_channel_buffer(struct ipu_soc *ipu, ipu_channel_t channel,
 {
        uint32_t reg;
        int ret = 0;
-       unsigned long lock_flags;
        uint32_t dma_chan = channel_2_dma(channel, type);
+
        if (dma_chan == IDMA_CHAN_INVALID)
                return -EINVAL;
 
-       spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
+       _ipu_lock(ipu);
 
        if (bufNum == 0)
                reg = ipu_cm_read(ipu, IPU_CHA_BUF0_RDY(dma_chan));
@@ -1449,7 +1395,8 @@ int32_t ipu_update_channel_buffer(struct ipu_soc *ipu, ipu_channel_t channel,
        else
                ret = -EACCES;
 
-       spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
+       _ipu_unlock(ipu);
+
        return ret;
 }
 EXPORT_SYMBOL(ipu_update_channel_buffer);
@@ -1500,13 +1447,12 @@ int32_t ipu_update_channel_offset(struct ipu_soc *ipu,
                                uint32_t vertical_offset, uint32_t horizontal_offset)
 {
        int ret = 0;
-       unsigned long lock_flags;
        uint32_t dma_chan = channel_2_dma(channel, type);
 
        if (dma_chan == IDMA_CHAN_INVALID)
                return -EINVAL;
 
-       spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
+       _ipu_lock(ipu);
 
        if ((ipu_cm_read(ipu, IPU_CHA_BUF0_RDY(dma_chan)) & idma_mask(dma_chan)) ||
            (ipu_cm_read(ipu, IPU_CHA_BUF1_RDY(dma_chan)) & idma_mask(dma_chan)) ||
@@ -1518,7 +1464,7 @@ int32_t ipu_update_channel_offset(struct ipu_soc *ipu,
                _ipu_ch_offset_update(ipu, dma_chan, pixel_fmt, width, height, stride,
                                      u, v, 0, vertical_offset, horizontal_offset);
 
-       spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
+       _ipu_unlock(ipu);
        return ret;
 }
 EXPORT_SYMBOL(ipu_update_channel_offset);
@@ -1541,13 +1487,12 @@ int32_t ipu_select_buffer(struct ipu_soc *ipu, ipu_channel_t channel,
                        ipu_buffer_t type, uint32_t bufNum)
 {
        uint32_t dma_chan = channel_2_dma(channel, type);
-       unsigned long lock_flags;
 
        if (dma_chan == IDMA_CHAN_INVALID)
                return -EINVAL;
 
        /* Mark buffer to be ready. */
-       spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
+       _ipu_lock(ipu);
        if (bufNum == 0)
                ipu_cm_write(ipu, idma_mask(dma_chan),
                             IPU_CHA_BUF0_RDY(dma_chan));
@@ -1557,7 +1502,7 @@ int32_t ipu_select_buffer(struct ipu_soc *ipu, ipu_channel_t channel,
        else
                ipu_cm_write(ipu, idma_mask(dma_chan),
                             IPU_CHA_BUF2_RDY(dma_chan));
-       spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
+       _ipu_unlock(ipu);
        return 0;
 }
 EXPORT_SYMBOL(ipu_select_buffer);
@@ -1579,15 +1524,14 @@ int32_t ipu_select_multi_vdi_buffer(struct ipu_soc *ipu, uint32_t bufNum)
                idma_mask(channel_2_dma(MEM_VDI_PRP_VF_MEM_P, IPU_INPUT_BUFFER))|
                idma_mask(dma_chan)|
                idma_mask(channel_2_dma(MEM_VDI_PRP_VF_MEM_N, IPU_INPUT_BUFFER));
-       unsigned long lock_flags;
 
        /* Mark buffers to be ready. */
-       spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
+       _ipu_lock(ipu);
        if (bufNum == 0)
                ipu_cm_write(ipu, mask_bit, IPU_CHA_BUF0_RDY(dma_chan));
        else
                ipu_cm_write(ipu, mask_bit, IPU_CHA_BUF1_RDY(dma_chan));
-       spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
+       _ipu_unlock(ipu);
        return 0;
 }
 EXPORT_SYMBOL(ipu_select_multi_vdi_buffer);
@@ -1620,13 +1564,12 @@ static int disp_src_sel[] = { 0, 6, 7, 8, 3, 4, 5, NA, NA, NA,
 int32_t ipu_link_channels(struct ipu_soc *ipu, ipu_channel_t src_ch, ipu_channel_t dest_ch)
 {
        int retval = 0;
-       unsigned long lock_flags;
        uint32_t fs_proc_flow1;
        uint32_t fs_proc_flow2;
        uint32_t fs_proc_flow3;
        uint32_t fs_disp_flow1;
 
-       spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
+       _ipu_lock(ipu);
 
        fs_proc_flow1 = ipu_cm_read(ipu, IPU_FS_PROC_FLOW1);
        fs_proc_flow2 = ipu_cm_read(ipu, IPU_FS_PROC_FLOW2);
@@ -1801,7 +1744,7 @@ int32_t ipu_link_channels(struct ipu_soc *ipu, ipu_channel_t src_ch, ipu_channel
        ipu_cm_write(ipu, fs_disp_flow1, IPU_FS_DISP_FLOW1);
 
 err:
-       spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
+       _ipu_unlock(ipu);
        return retval;
 }
 EXPORT_SYMBOL(ipu_link_channels);
@@ -1823,13 +1766,12 @@ EXPORT_SYMBOL(ipu_link_channels);
 int32_t ipu_unlink_channels(struct ipu_soc *ipu, ipu_channel_t src_ch, ipu_channel_t dest_ch)
 {
        int retval = 0;
-       unsigned long lock_flags;
        uint32_t fs_proc_flow1;
        uint32_t fs_proc_flow2;
        uint32_t fs_proc_flow3;
        uint32_t fs_disp_flow1;
 
-       spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
+       _ipu_lock(ipu);
 
        fs_proc_flow1 = ipu_cm_read(ipu, IPU_FS_PROC_FLOW1);
        fs_proc_flow2 = ipu_cm_read(ipu, IPU_FS_PROC_FLOW2);
@@ -1932,7 +1874,7 @@ int32_t ipu_unlink_channels(struct ipu_soc *ipu, ipu_channel_t src_ch, ipu_chann
        ipu_cm_write(ipu, fs_disp_flow1, IPU_FS_DISP_FLOW1);
 
 err:
-       spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
+       _ipu_unlock(ipu);
        return retval;
 }
 EXPORT_SYMBOL(ipu_unlink_channels);
@@ -1977,19 +1919,18 @@ EXPORT_SYMBOL(ipu_is_channel_busy);
 int32_t ipu_enable_channel(struct ipu_soc *ipu, ipu_channel_t channel)
 {
        uint32_t reg;
-       unsigned long lock_flags;
        uint32_t ipu_conf;
        uint32_t in_dma;
        uint32_t out_dma;
        uint32_t sec_dma;
        uint32_t thrd_dma;
 
-       spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
+       _ipu_lock(ipu);
 
        if (ipu->channel_enable_mask & (1L << IPU_CHAN_ID(channel))) {
                dev_err(ipu->dev, "Warning: channel already enabled %d\n",
                        IPU_CHAN_ID(channel));
-               spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
+               _ipu_unlock(ipu);
                return -EACCES;
        }
 
@@ -2071,7 +2012,7 @@ int32_t ipu_enable_channel(struct ipu_soc *ipu, ipu_channel_t channel)
 
        ipu->channel_enable_mask |= 1L << IPU_CHAN_ID(channel);
 
-       spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
+       _ipu_unlock(ipu);
 
        return 0;
 }
@@ -2124,16 +2065,14 @@ EXPORT_SYMBOL(ipu_check_buffer_ready);
  *                             ready state.
  *
  */
-void ipu_clear_buffer_ready(struct ipu_soc *ipu, ipu_channel_t channel, ipu_buffer_t type,
+void _ipu_clear_buffer_ready(struct ipu_soc *ipu, ipu_channel_t channel, ipu_buffer_t type,
                uint32_t bufNum)
 {
-       unsigned long lock_flags;
        uint32_t dma_ch = channel_2_dma(channel, type);
 
        if (!idma_is_valid(dma_ch))
                return;
 
-       spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
        ipu_cm_write(ipu, 0xF0300000, IPU_GPR); /* write one to clear */
        if (bufNum == 0)
                ipu_cm_write(ipu, idma_mask(dma_ch),
@@ -2145,17 +2084,16 @@ void ipu_clear_buffer_ready(struct ipu_soc *ipu, ipu_channel_t channel, ipu_buff
                ipu_cm_write(ipu, idma_mask(dma_ch),
                                IPU_CHA_BUF2_RDY(dma_ch));
        ipu_cm_write(ipu, 0x0, IPU_GPR); /* write one to set */
-       spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
 }
-EXPORT_SYMBOL(ipu_clear_buffer_ready);
 
-static irqreturn_t disable_chan_irq_handler(int irq, void *dev_id)
+void ipu_clear_buffer_ready(struct ipu_soc *ipu, ipu_channel_t channel, ipu_buffer_t type,
+               uint32_t bufNum)
 {
-       struct completion *comp = dev_id;
-
-       complete(comp);
-       return IRQ_HANDLED;
+       _ipu_lock(ipu);
+       _ipu_clear_buffer_ready(ipu, channel, type, bufNum);
+       _ipu_unlock(ipu);
 }
+EXPORT_SYMBOL(ipu_clear_buffer_ready);
 
 /*!
  * This function disables a logical channel.
@@ -2172,24 +2110,21 @@ static irqreturn_t disable_chan_irq_handler(int irq, void *dev_id)
 int32_t ipu_disable_channel(struct ipu_soc *ipu, ipu_channel_t channel, bool wait_for_stop)
 {
        uint32_t reg;
-       unsigned long lock_flags;
        uint32_t in_dma;
        uint32_t out_dma;
        uint32_t sec_dma = NO_DMA;
        uint32_t thrd_dma = NO_DMA;
        uint16_t fg_pos_x, fg_pos_y;
 
-       spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
+       _ipu_lock(ipu);
 
        if ((ipu->channel_enable_mask & (1L << IPU_CHAN_ID(channel))) == 0) {
                dev_err(ipu->dev, "Channel already disabled %d\n",
                        IPU_CHAN_ID(channel));
-               spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
+               _ipu_unlock(ipu);
                return -EACCES;
        }
 
-       spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
-
        /* Get input and output dma channels */
        out_dma = channel_2_dma(channel, IPU_OUTPUT_BUFFER);
        in_dma = channel_2_dma(channel, IPU_VIDEO_IN_BUFFER);
@@ -2197,8 +2132,10 @@ int32_t ipu_disable_channel(struct ipu_soc *ipu, ipu_channel_t channel, bool wai
        if ((idma_is_valid(in_dma) &&
                !idma_is_set(ipu, IDMAC_CHA_EN, in_dma))
                && (idma_is_valid(out_dma) &&
-               !idma_is_set(ipu, IDMAC_CHA_EN, out_dma)))
+               !idma_is_set(ipu, IDMAC_CHA_EN, out_dma))) {
+               _ipu_unlock(ipu);
                return -EINVAL;
+       }
 
        if (ipu->sec_chan_en[IPU_CHAN_ID(channel)])
                sec_dma = channel_2_dma(channel, IPU_GRAPH_IN_BUFFER);
@@ -2210,8 +2147,8 @@ int32_t ipu_disable_channel(struct ipu_soc *ipu, ipu_channel_t channel, bool wai
        if ((channel == MEM_BG_SYNC) || (channel == MEM_FG_SYNC) ||
            (channel == MEM_DC_SYNC)) {
                if (channel == MEM_FG_SYNC) {
-                       ipu_disp_get_window_pos(ipu, channel, &fg_pos_x, &fg_pos_y);
-                       ipu_disp_set_window_pos(ipu, channel, 0, 0);
+                       _ipu_disp_get_window_pos(ipu, channel, &fg_pos_x, &fg_pos_y);
+                       _ipu_disp_set_window_pos(ipu, channel, 0, 0);
                }
 
                _ipu_dp_dc_disable(ipu, channel, false);
@@ -2242,8 +2179,8 @@ int32_t ipu_disable_channel(struct ipu_soc *ipu, ipu_channel_t channel, bool wai
                        idma_is_set(ipu, IDMAC_CHA_BUSY, sec_dma)) ||
                        (ipu->thrd_chan_en[IPU_CHAN_ID(channel)] &&
                        idma_is_set(ipu, IDMAC_CHA_BUSY, thrd_dma))) {
-                       uint32_t ret, irq = 0xffffffff;
-                       DECLARE_COMPLETION_ONSTACK(disable_comp);
+                       uint32_t irq = 0xffffffff;
+                       int timeout = 50;
 
                        if (idma_is_set(ipu, IDMAC_CHA_BUSY, out_dma))
                                irq = out_dma;
@@ -2263,24 +2200,22 @@ int32_t ipu_disable_channel(struct ipu_soc *ipu, ipu_channel_t channel, bool wai
 
                        dev_err(ipu->dev, "warning: channel %d busy, need wait\n", irq);
 
-                       ret = ipu_request_irq(ipu, irq, disable_chan_irq_handler, 0, NULL, &disable_comp);
-                       if (ret < 0) {
-                               dev_err(ipu->dev, "irq %d in use\n", irq);
-                               break;
-                       } else {
-                               ret = wait_for_completion_timeout(&disable_comp, msecs_to_jiffies(200));
-                               ipu_free_irq(ipu, irq, &disable_comp);
-                               if (ret == 0) {
+                       ipu_cm_write(ipu, IPUIRQ_2_MASK(irq),
+                                       IPUIRQ_2_STATREG(irq));
+                       while ((ipu_cm_read(ipu, IPUIRQ_2_STATREG(irq)) &
+                                               IPUIRQ_2_MASK(irq)) == 0) {
+                               msleep(10);
+                               timeout -= 10;
+                               if (timeout <= 0) {
                                        ipu_dump_registers(ipu);
                                        dev_err(ipu->dev, "warning: disable ipu dma channel %d during its busy state\n", irq);
                                        break;
                                }
                        }
+
                }
        }
 
-       spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
-
        if ((channel == MEM_BG_SYNC) || (channel == MEM_FG_SYNC) ||
            (channel == MEM_DC_SYNC)) {
                reg = ipu_idmac_read(ipu, IDMAC_WM_EN(in_dma));
@@ -2325,31 +2260,31 @@ int32_t ipu_disable_channel(struct ipu_soc *ipu, ipu_channel_t channel, bool wai
                ipu_cm_write(ipu, idma_mask(thrd_dma), IPU_CHA_CUR_BUF(thrd_dma));
        }
 
-       ipu->channel_enable_mask &= ~(1L << IPU_CHAN_ID(channel));
-
-       spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
+       if (channel == MEM_FG_SYNC)
+               _ipu_disp_set_window_pos(ipu, channel, fg_pos_x, fg_pos_y);
 
        /* Set channel buffers NOT to be ready */
        if (idma_is_valid(in_dma)) {
-               ipu_clear_buffer_ready(ipu, channel, IPU_VIDEO_IN_BUFFER, 0);
-               ipu_clear_buffer_ready(ipu, channel, IPU_VIDEO_IN_BUFFER, 1);
-               ipu_clear_buffer_ready(ipu, channel, IPU_VIDEO_IN_BUFFER, 2);
+               _ipu_clear_buffer_ready(ipu, channel, IPU_VIDEO_IN_BUFFER, 0);
+               _ipu_clear_buffer_ready(ipu, channel, IPU_VIDEO_IN_BUFFER, 1);
+               _ipu_clear_buffer_ready(ipu, channel, IPU_VIDEO_IN_BUFFER, 2);
        }
        if (idma_is_valid(out_dma)) {
-               ipu_clear_buffer_ready(ipu, channel, IPU_OUTPUT_BUFFER, 0);
-               ipu_clear_buffer_ready(ipu, channel, IPU_OUTPUT_BUFFER, 1);
+               _ipu_clear_buffer_ready(ipu, channel, IPU_OUTPUT_BUFFER, 0);
+               _ipu_clear_buffer_ready(ipu, channel, IPU_OUTPUT_BUFFER, 1);
        }
        if (ipu->sec_chan_en[IPU_CHAN_ID(channel)] && idma_is_valid(sec_dma)) {
-               ipu_clear_buffer_ready(ipu, channel, IPU_GRAPH_IN_BUFFER, 0);
-               ipu_clear_buffer_ready(ipu, channel, IPU_GRAPH_IN_BUFFER, 1);
+               _ipu_clear_buffer_ready(ipu, channel, IPU_GRAPH_IN_BUFFER, 0);
+               _ipu_clear_buffer_ready(ipu, channel, IPU_GRAPH_IN_BUFFER, 1);
        }
        if (ipu->thrd_chan_en[IPU_CHAN_ID(channel)] && idma_is_valid(thrd_dma)) {
-               ipu_clear_buffer_ready(ipu, channel, IPU_ALPHA_IN_BUFFER, 0);
-               ipu_clear_buffer_ready(ipu, channel, IPU_ALPHA_IN_BUFFER, 1);
+               _ipu_clear_buffer_ready(ipu, channel, IPU_ALPHA_IN_BUFFER, 0);
+               _ipu_clear_buffer_ready(ipu, channel, IPU_ALPHA_IN_BUFFER, 1);
        }
 
-       if (channel == MEM_FG_SYNC)
-               ipu_disp_set_window_pos(ipu, channel, fg_pos_x, fg_pos_y);
+       ipu->channel_enable_mask &= ~(1L << IPU_CHAN_ID(channel));
+
+       _ipu_unlock(ipu);
 
        return 0;
 }
@@ -2367,14 +2302,13 @@ EXPORT_SYMBOL(ipu_disable_channel);
 int32_t ipu_enable_csi(struct ipu_soc *ipu, uint32_t csi)
 {
        uint32_t reg;
-       unsigned long lock_flags;
 
        if (csi > 1) {
                dev_err(ipu->dev, "Wrong csi num_%d\n", csi);
                return -EINVAL;
        }
 
-       spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
+       _ipu_lock(ipu);
        ipu->csi_use_count[csi]++;
 
        if (ipu->csi_use_count[csi] == 1) {
@@ -2384,7 +2318,7 @@ int32_t ipu_enable_csi(struct ipu_soc *ipu, uint32_t csi)
                else
                        ipu_cm_write(ipu, reg | IPU_CONF_CSI1_EN, IPU_CONF);
        }
-       spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
+       _ipu_unlock(ipu);
        return 0;
 }
 EXPORT_SYMBOL(ipu_enable_csi);
@@ -2401,16 +2335,14 @@ EXPORT_SYMBOL(ipu_enable_csi);
 int32_t ipu_disable_csi(struct ipu_soc *ipu, uint32_t csi)
 {
        uint32_t reg;
-       unsigned long lock_flags;
 
        if (csi > 1) {
                dev_err(ipu->dev, "Wrong csi num_%d\n", csi);
                return -EINVAL;
        }
 
-       spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
+       _ipu_lock(ipu);
        ipu->csi_use_count[csi]--;
-
        if (ipu->csi_use_count[csi] == 0) {
                reg = ipu_cm_read(ipu, IPU_CONF);
                if (csi == 0)
@@ -2418,7 +2350,7 @@ int32_t ipu_disable_csi(struct ipu_soc *ipu, uint32_t csi)
                else
                        ipu_cm_write(ipu, reg & ~IPU_CONF_CSI1_EN, IPU_CONF);
        }
-       spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
+       _ipu_unlock(ipu);
        return 0;
 }
 EXPORT_SYMBOL(ipu_disable_csi);
@@ -2432,10 +2364,14 @@ static irqreturn_t ipu_irq_handler(int irq, void *desc)
        uint32_t int_stat;
        const int err_reg[] = { 5, 6, 9, 10, 0 };
        const int int_reg[] = { 1, 2, 3, 4, 11, 12, 13, 14, 15, 0 };
+       unsigned long lock_flags;
 
        for (i = 0;; i++) {
                if (err_reg[i] == 0)
                        break;
+
+               spin_lock_irqsave(&ipu->spin_lock, lock_flags);
+
                int_stat = ipu_cm_read(ipu, IPU_INT_STAT(err_reg[i]));
                int_stat &= ipu_cm_read(ipu, IPU_INT_CTRL(err_reg[i]));
                if (int_stat) {
@@ -2448,14 +2384,18 @@ static irqreturn_t ipu_irq_handler(int irq, void *desc)
                            ipu_cm_read(ipu, IPU_INT_CTRL(err_reg[i])) & ~int_stat;
                        ipu_cm_write(ipu, int_stat, IPU_INT_CTRL(err_reg[i]));
                }
+
+               spin_unlock_irqrestore(&ipu->spin_lock, lock_flags);
        }
 
        for (i = 0;; i++) {
                if (int_reg[i] == 0)
                        break;
+               spin_lock_irqsave(&ipu->spin_lock, lock_flags);
                int_stat = ipu_cm_read(ipu, IPU_INT_STAT(int_reg[i]));
                int_stat &= ipu_cm_read(ipu, IPU_INT_CTRL(int_reg[i]));
                ipu_cm_write(ipu, int_stat, IPU_INT_STAT(int_reg[i]));
+               spin_unlock_irqrestore(&ipu->spin_lock, lock_flags);
                while ((line = ffs(int_stat)) != 0) {
                        line--;
                        int_stat &= ~(1UL << line);
@@ -2483,18 +2423,17 @@ void ipu_enable_irq(struct ipu_soc *ipu, uint32_t irq)
        uint32_t reg;
        unsigned long lock_flags;
 
-       if (!ipu->clk_enabled)
-               clk_enable(ipu->ipu_clk);
+       _ipu_get(ipu);
 
-       spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
+       spin_lock_irqsave(&ipu->spin_lock, lock_flags);
 
        reg = ipu_cm_read(ipu, IPUIRQ_2_CTRLREG(irq));
        reg |= IPUIRQ_2_MASK(irq);
        ipu_cm_write(ipu, reg, IPUIRQ_2_CTRLREG(irq));
 
-       spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
-       if (!ipu->clk_enabled)
-               clk_disable(ipu->ipu_clk);
+       spin_unlock_irqrestore(&ipu->spin_lock, lock_flags);
+
+       _ipu_put(ipu);
 }
 EXPORT_SYMBOL(ipu_enable_irq);
 
@@ -2511,18 +2450,17 @@ void ipu_disable_irq(struct ipu_soc *ipu, uint32_t irq)
        uint32_t reg;
        unsigned long lock_flags;
 
-       if (!ipu->clk_enabled)
-               clk_enable(ipu->ipu_clk);
+       _ipu_get(ipu);
 
-       spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
+       spin_lock_irqsave(&ipu->spin_lock, lock_flags);
 
        reg = ipu_cm_read(ipu, IPUIRQ_2_CTRLREG(irq));
        reg &= ~IPUIRQ_2_MASK(irq);
        ipu_cm_write(ipu, reg, IPUIRQ_2_CTRLREG(irq));
 
-       spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
-       if (!ipu->clk_enabled)
-               clk_disable(ipu->ipu_clk);
+       spin_unlock_irqrestore(&ipu->spin_lock, lock_flags);
+
+       _ipu_put(ipu);
 }
 EXPORT_SYMBOL(ipu_disable_irq);
 
@@ -2536,13 +2474,17 @@ EXPORT_SYMBOL(ipu_disable_irq);
  */
 void ipu_clear_irq(struct ipu_soc *ipu, uint32_t irq)
 {
-       if (!ipu->clk_enabled)
-               clk_enable(ipu->ipu_clk);
+       unsigned long lock_flags;
+
+       _ipu_get(ipu);
+
+       spin_lock_irqsave(&ipu->spin_lock, lock_flags);
 
        ipu_cm_write(ipu, IPUIRQ_2_MASK(irq), IPUIRQ_2_STATREG(irq));
 
-       if (!ipu->clk_enabled)
-               clk_disable(ipu->ipu_clk);
+       spin_unlock_irqrestore(&ipu->spin_lock, lock_flags);
+
+       _ipu_put(ipu);
 }
 EXPORT_SYMBOL(ipu_clear_irq);
 
@@ -2560,13 +2502,11 @@ bool ipu_get_irq_status(struct ipu_soc *ipu, uint32_t irq)
 {
        uint32_t reg;
 
-       if (!ipu->clk_enabled)
-               clk_enable(ipu->ipu_clk);
+       _ipu_get(ipu);
 
        reg = ipu_cm_read(ipu, IPUIRQ_2_STATREG(irq));
 
-       if (!ipu->clk_enabled)
-               clk_disable(ipu->ipu_clk);
+       _ipu_put(ipu);
 
        if (reg & IPUIRQ_2_MASK(irq))
                return true;
@@ -2604,12 +2544,14 @@ int ipu_request_irq(struct ipu_soc *ipu, uint32_t irq,
 
        BUG_ON(irq >= IPU_IRQ_COUNT);
 
-       spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
+       _ipu_get(ipu);
+
+       spin_lock_irqsave(&ipu->spin_lock, lock_flags);
 
        if (ipu->irq_list[irq].handler != NULL) {
                dev_err(ipu->dev,
                        "handler already installed on irq %d\n", irq);
-               spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
+               spin_unlock_irqrestore(&ipu->spin_lock, lock_flags);
                return -EINVAL;
        }
 
@@ -2618,7 +2560,12 @@ int ipu_request_irq(struct ipu_soc *ipu, uint32_t irq,
        ipu->irq_list[irq].dev_id = dev_id;
        ipu->irq_list[irq].name = devname;
 
-       spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
+       /* clear irq stat for previous use */
+       ipu_cm_write(ipu, IPUIRQ_2_MASK(irq), IPUIRQ_2_STATREG(irq));
+
+       spin_unlock_irqrestore(&ipu->spin_lock, lock_flags);
+
+       _ipu_put(ipu);
 
        ipu_enable_irq(ipu, irq);       /* enable the interrupt */
 
@@ -2640,10 +2587,14 @@ EXPORT_SYMBOL(ipu_request_irq);
  */
 void ipu_free_irq(struct ipu_soc *ipu, uint32_t irq, void *dev_id)
 {
+       unsigned long lock_flags;
+
        ipu_disable_irq(ipu, irq);      /* disable the interrupt */
 
+       spin_lock_irqsave(&ipu->spin_lock, lock_flags);
        if (ipu->irq_list[irq].dev_id == dev_id)
                ipu->irq_list[irq].handler = NULL;
+       spin_unlock_irqrestore(&ipu->spin_lock, lock_flags);
 }
 EXPORT_SYMBOL(ipu_free_irq);
 
@@ -2712,27 +2663,22 @@ uint32_t _ipu_channel_status(struct ipu_soc *ipu, ipu_channel_t channel)
 int32_t ipu_swap_channel(struct ipu_soc *ipu, ipu_channel_t from_ch, ipu_channel_t to_ch)
 {
        uint32_t reg;
-       unsigned long lock_flags;
 
        int from_dma = channel_2_dma(from_ch, IPU_INPUT_BUFFER);
        int to_dma = channel_2_dma(to_ch, IPU_INPUT_BUFFER);
 
-       /* enable target channel */
-       spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
+       _ipu_lock(ipu);
 
+       /* enable target channel */
        reg = ipu_idmac_read(ipu, IDMAC_CHA_EN(to_dma));
        ipu_idmac_write(ipu, reg | idma_mask(to_dma), IDMAC_CHA_EN(to_dma));
 
        ipu->channel_enable_mask |= 1L << IPU_CHAN_ID(to_ch);
 
-       spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
-
        /* switch dp dc */
        _ipu_dp_dc_disable(ipu, from_ch, true);
 
        /* disable source channel */
-       spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
-
        reg = ipu_idmac_read(ipu, IDMAC_CHA_EN(from_dma));
        ipu_idmac_write(ipu, reg & ~idma_mask(from_dma), IDMAC_CHA_EN(from_dma));
        ipu_cm_write(ipu, idma_mask(from_dma), IPU_CHA_CUR_BUF(from_dma));
@@ -2741,11 +2687,11 @@ int32_t ipu_swap_channel(struct ipu_soc *ipu, ipu_channel_t from_ch, ipu_channel
 
        ipu->channel_enable_mask &= ~(1L << IPU_CHAN_ID(from_ch));
 
-       spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
+       _ipu_clear_buffer_ready(ipu, from_ch, IPU_VIDEO_IN_BUFFER, 0);
+       _ipu_clear_buffer_ready(ipu, from_ch, IPU_VIDEO_IN_BUFFER, 1);
+       _ipu_clear_buffer_ready(ipu, from_ch, IPU_VIDEO_IN_BUFFER, 2);
 
-       ipu_clear_buffer_ready(ipu, from_ch, IPU_VIDEO_IN_BUFFER, 0);
-       ipu_clear_buffer_ready(ipu, from_ch, IPU_VIDEO_IN_BUFFER, 1);
-       ipu_clear_buffer_ready(ipu, from_ch, IPU_VIDEO_IN_BUFFER, 2);
+       _ipu_unlock(ipu);
 
        return 0;
 }
@@ -2826,18 +2772,12 @@ bool ipu_pixel_format_has_alpha(uint32_t fmt)
        return false;
 }
 
-void ipu_set_csc_coefficients(struct ipu_soc *ipu, ipu_channel_t channel, int32_t param[][3])
-{
-       _ipu_dp_set_csc_coefficients(ipu, channel, param);
-}
-EXPORT_SYMBOL(ipu_set_csc_coefficients);
-
 static int ipu_suspend(struct platform_device *pdev, pm_message_t state)
 {
        struct imx_ipuv3_platform_data *plat_data = pdev->dev.platform_data;
        struct ipu_soc *ipu = platform_get_drvdata(pdev);
 
-       if (ipu->ipu_use_count) {
+       if (atomic_read(&ipu->ipu_use_count)) {
                /* save and disable enabled channels*/
                ipu->idma_enable_reg[0] = ipu_idmac_read(ipu, IDMAC_CHA_EN(0));
                ipu->idma_enable_reg[1] = ipu_idmac_read(ipu, IDMAC_CHA_EN(32));
@@ -2918,8 +2858,7 @@ static int ipu_resume(struct platform_device *pdev)
        if (plat_data->pg)
                plat_data->pg(0);
 
-       if (ipu->ipu_use_count) {
-
+       if (atomic_read(&ipu->ipu_use_count)) {
                /* restore buf ready regs */
                ipu_cm_write(ipu, ipu->buf_ready_reg[0], IPU_CHA_BUF0_RDY(0));
                ipu_cm_write(ipu, ipu->buf_ready_reg[1], IPU_CHA_BUF0_RDY(32));
index c00f0df98595b72b0bd5318d028243108c0ac98a..526fb4c950eb36d10f50207ce1fb842a8709be8e 100644 (file)
@@ -1713,7 +1713,6 @@ static void do_task(struct ipu_soc *ipu, struct ipu_task_entry *t)
        dev_dbg(t->dev, "[0x%p]task irq is %d\n", (void *)t, irq);
 
        init_completion(&comp);
-       ipu_clear_irq(ipu, irq);
        ret = ipu_request_irq(ipu, irq, task_irq_handler, 0, NULL, &comp);
        if (ret < 0) {
                t->state = STATE_IRQ_FAIL;
@@ -1768,27 +1767,6 @@ static void do_task(struct ipu_soc *ipu, struct ipu_task_entry *t)
                t->state = STATE_IRQ_TIMEOUT;
 
        ipu_free_irq(ipu, irq, &comp);
-       if (t->set.task & IC_VF) {
-               ipu_clear_irq(ipu, IPU_IRQ_PRP_IN_EOF);
-               ipu_clear_irq(ipu, IPU_IRQ_PRP_VF_OUT_EOF);
-       } else if (t->set.task & IC_PP) {
-               ipu_clear_irq(ipu, IPU_IRQ_PP_IN_EOF);
-               ipu_clear_irq(ipu, IPU_IRQ_PP_OUT_EOF);
-       } else if (t->set.task & VDI_VF) {
-               ipu_clear_irq(ipu, IPU_IRQ_VDI_C_IN_EOF);
-               if (deinterlace_3_field(t)) {
-                       ipu_clear_irq(ipu, IPU_IRQ_VDI_P_IN_EOF);
-                       ipu_clear_irq(ipu, IPU_IRQ_VDI_N_IN_EOF);
-               }
-               ipu_clear_irq(ipu, IPU_IRQ_PRP_VF_OUT_EOF);
-       }
-       if (t->set.task & ROT_VF) {
-               ipu_clear_irq(ipu, IPU_IRQ_PRP_VF_ROT_IN_EOF);
-               ipu_clear_irq(ipu, IPU_IRQ_PRP_VF_ROT_OUT_EOF);
-       } else if (t->set.task & ROT_PP) {
-               ipu_clear_irq(ipu, IPU_IRQ_PP_ROT_IN_EOF);
-               ipu_clear_irq(ipu, IPU_IRQ_PP_ROT_OUT_EOF);
-       }
 
        if (only_ic(t->set.mode)) {
                ipu_disable_channel(ipu, t->set.ic_chan, true);
index 12e36e28c2d091e3a670eed497beec7e57608677..25d17ca5862b972f958314f48b0652076fbc6d8d 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/io.h>
 #include <linux/ipu.h>
 #include <linux/clk.h>
+#include <linux/err.h>
 #include <asm/atomic.h>
 #include <mach/clock.h>
 #include "ipu_prv.h"
@@ -45,6 +46,147 @@ struct dp_csc_param_t {
 #define DC_DISP_ID_SERIAL      2
 #define DC_DISP_ID_ASYNC       3
 
+static inline struct ipu_soc *pixelclk2ipu(struct clk *clk)
+{
+       struct ipu_soc *ipu;
+       struct clk *base = clk - clk->id;
+
+       ipu = container_of(base, struct ipu_soc, pixel_clk[0]);
+
+       return ipu;
+}
+
+static unsigned long _ipu_pixel_clk_get_rate(struct clk *clk)
+{
+       struct ipu_soc *ipu = pixelclk2ipu(clk);
+       u32 div = ipu_di_read(ipu, clk->id, DI_BS_CLKGEN0);
+       if (div == 0)
+               return 0;
+       return  (clk_get_rate(clk->parent) * 16) / div;
+}
+
+static unsigned long _ipu_pixel_clk_round_rate(struct clk *clk, unsigned long rate)
+{
+       u32 div;
+       u32 parent_rate = clk_get_rate(clk->parent) * 16;
+       /*
+        * Calculate divider
+        * Fractional part is 4 bits,
+        * so simply multiply by 2^4 to get fractional part.
+        */
+       div = parent_rate / rate;
+
+       if (div < 0x10)            /* Min DI disp clock divider is 1 */
+               div = 0x10;
+       if (div & ~0xFEF)
+               div &= 0xFF8;
+       else {
+               /* Round up divider if it gets us closer to desired pix clk */
+               if ((div & 0xC) == 0xC) {
+                       div += 0x10;
+                       div &= ~0xF;
+               }
+       }
+       return parent_rate / div;
+}
+
+static int _ipu_pixel_clk_set_rate(struct clk *clk, unsigned long rate)
+{
+       struct ipu_soc *ipu = pixelclk2ipu(clk);
+       u32 div = (clk_get_rate(clk->parent) * 16) / rate;
+
+       /* Round up divider if it gets us closer to desired pix clk */
+       if ((div & 0xC) == 0xC) {
+               div += 0x10;
+               div &= ~0xF;
+       }
+
+       ipu_di_write(ipu, clk->id, div, DI_BS_CLKGEN0);
+
+       /* Setup pixel clock timing */
+       /* FIXME: needs to be more flexible */
+       /* Down time is half of period */
+       ipu_di_write(ipu, clk->id, (div / 16) << 16, DI_BS_CLKGEN1);
+
+       return 0;
+}
+
+static int _ipu_pixel_clk_enable(struct clk *clk)
+{
+       struct ipu_soc *ipu = pixelclk2ipu(clk);
+       u32 disp_gen = ipu_cm_read(ipu, IPU_DISP_GEN);
+       disp_gen |= clk->id ? DI1_COUNTER_RELEASE : DI0_COUNTER_RELEASE;
+       ipu_cm_write(ipu, disp_gen, IPU_DISP_GEN);
+
+       return 0;
+}
+
+static void _ipu_pixel_clk_disable(struct clk *clk)
+{
+       struct ipu_soc *ipu = pixelclk2ipu(clk);
+
+       u32 disp_gen = ipu_cm_read(ipu, IPU_DISP_GEN);
+       disp_gen &= clk->id ? ~DI1_COUNTER_RELEASE : ~DI0_COUNTER_RELEASE;
+       ipu_cm_write(ipu, disp_gen, IPU_DISP_GEN);
+}
+
+static int _ipu_pixel_clk_set_parent(struct clk *clk, struct clk *parent)
+{
+       struct ipu_soc *ipu = pixelclk2ipu(clk);
+       u32 di_gen;
+
+       di_gen = ipu_di_read(ipu, clk->id, DI_GENERAL);
+       if (parent == ipu->ipu_clk)
+               di_gen &= ~DI_GEN_DI_CLK_EXT;
+       else if (!IS_ERR(ipu->di_clk[clk->id]) && parent == ipu->di_clk[clk->id])
+               di_gen |= DI_GEN_DI_CLK_EXT;
+       else {
+               return -EINVAL;
+       }
+
+       ipu_di_write(ipu, clk->id, di_gen, DI_GENERAL);
+       return 0;
+}
+
+#ifdef CONFIG_CLK_DEBUG
+#define __INIT_CLK_DEBUG(n)    .name = #n,
+#else
+#define __INIT_CLK_DEBUG(n)
+#endif
+struct clk ipu_pixel_clk[] = {
+       {
+               __INIT_CLK_DEBUG(pixel_clk_0)
+                       .id = 0,
+               .get_rate = _ipu_pixel_clk_get_rate,
+               .set_rate = _ipu_pixel_clk_set_rate,
+               .round_rate = _ipu_pixel_clk_round_rate,
+               .set_parent = _ipu_pixel_clk_set_parent,
+               .enable = _ipu_pixel_clk_enable,
+               .disable = _ipu_pixel_clk_disable,
+       },
+       {
+               __INIT_CLK_DEBUG(pixel_clk_1)
+                       .id = 1,
+               .get_rate = _ipu_pixel_clk_get_rate,
+               .set_rate = _ipu_pixel_clk_set_rate,
+               .round_rate = _ipu_pixel_clk_round_rate,
+               .set_parent = _ipu_pixel_clk_set_parent,
+               .enable = _ipu_pixel_clk_enable,
+               .disable = _ipu_pixel_clk_disable,
+       },
+};
+
+struct clk_lookup ipu_lookups[] = {
+       {
+               .dev_id = NULL,
+               .con_id = "pixel_clk_0",
+       },
+       {
+               .dev_id = NULL,
+               .con_id = "pixel_clk_1",
+       },
+};
+
 int dmfc_type_setup;
 
 void _ipu_dmfc_init(struct ipu_soc *ipu, int dmfc_type, int first)
@@ -764,7 +906,6 @@ static irqreturn_t dc_irq_handler(int irq, void *dev_id)
 void _ipu_dp_dc_disable(struct ipu_soc *ipu, ipu_channel_t channel, bool swap)
 {
        int ret;
-       unsigned long lock_flags;
        uint32_t reg;
        uint32_t csc;
        uint32_t dc_chan;
@@ -783,8 +924,6 @@ void _ipu_dp_dc_disable(struct ipu_soc *ipu, ipu_channel_t channel, bool swap)
                /* Disable FG channel */
                dc_chan = 5;
 
-               spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
-
                reg = ipu_dp_read(ipu, DP_COM_CONF(DP_SYNC));
                csc = reg & DP_COM_CONF_CSC_DEF_MASK;
                if (csc == DP_COM_CONF_CSC_DEF_FG)
@@ -796,8 +935,6 @@ void _ipu_dp_dc_disable(struct ipu_soc *ipu, ipu_channel_t channel, bool swap)
                reg = ipu_cm_read(ipu, IPU_SRM_PRI2) | 0x8;
                ipu_cm_write(ipu, reg, IPU_SRM_PRI2);
 
-               spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
-
                ipu_cm_write(ipu, IPUIRQ_2_MASK(IPU_IRQ_DP_SF_END),
                             IPUIRQ_2_STATREG(IPU_IRQ_DP_SF_END));
                while ((ipu_cm_read(ipu, IPUIRQ_2_STATREG(IPU_IRQ_DP_SF_END)) &
@@ -813,7 +950,6 @@ void _ipu_dp_dc_disable(struct ipu_soc *ipu, ipu_channel_t channel, bool swap)
        }
 
        init_completion(&ipu->dc_comp);
-       ipu_clear_irq(ipu, irq);
        ret = ipu_request_irq(ipu, irq, dc_irq_handler, 0, NULL, ipu);
        if (ret < 0) {
                dev_err(ipu->dev, "DC irq %d in use\n", irq);
@@ -824,14 +960,12 @@ void _ipu_dp_dc_disable(struct ipu_soc *ipu, ipu_channel_t channel, bool swap)
        dev_dbg(ipu->dev, "DC stop timeout - %d * 10ms\n", 5 - ret);
 
        if (ipu->dc_swap) {
-               spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
                /* Swap DC channel 1 and 5 settings, and disable old dc chan */
                reg = ipu_dc_read(ipu, DC_WR_CH_CONF(dc_chan));
                ipu_dc_write(ipu, reg, DC_WR_CH_CONF(6 - dc_chan));
                reg &= ~DC_WR_CH_CONF_PROG_TYPE_MASK;
                reg ^= DC_WR_CH_CONF_PROG_DI_ID;
                ipu_dc_write(ipu, reg, DC_WR_CH_CONF(dc_chan));
-               spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
        } else
                /* Clock is already off because it must be done quickly, but
                   we need to fix the ref count */
@@ -971,6 +1105,12 @@ void _ipu_dp_set_csc_coefficients(struct ipu_soc *ipu, ipu_channel_t channel, in
        __ipu_dp_csc_setup(ipu, dp, dp_csc_param, true);
 }
 
+void ipu_set_csc_coefficients(struct ipu_soc *ipu, ipu_channel_t channel, int32_t param[][3])
+{
+       _ipu_dp_set_csc_coefficients(ipu, channel, param);
+}
+EXPORT_SYMBOL(ipu_set_csc_coefficients);
+
 /*!
  * This function is called to adapt synchronous LCD panel to IPU restriction.
  *
@@ -1038,7 +1178,6 @@ int32_t ipu_init_sync_panel(struct ipu_soc *ipu, int disp, uint32_t pixel_clk,
                            uint16_t v_sync_width, uint16_t v_end_width,
                            uint32_t v_to_h_sync, ipu_di_signal_cfg_t sig)
 {
-       unsigned long lock_flags;
        uint32_t field0_offset = 0;
        uint32_t field1_offset;
        uint32_t reg;
@@ -1108,7 +1247,7 @@ int32_t ipu_init_sync_panel(struct ipu_soc *ipu, int disp, uint32_t pixel_clk,
        /* Get integer portion of divider */
        div = clk_get_rate(clk_get_parent(&ipu->pixel_clk[disp])) / rounded_pixel_clk;
 
-       spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
+       _ipu_lock(ipu);
 
        _ipu_di_data_wave_config(ipu, disp, SYNC_WAVE, div - 1, div - 1);
        _ipu_di_data_pin_config(ipu, disp, SYNC_WAVE, DI_PIN15, 3, 0, div * 2);
@@ -1116,7 +1255,7 @@ int32_t ipu_init_sync_panel(struct ipu_soc *ipu, int disp, uint32_t pixel_clk,
        map = _ipu_pixfmt_to_map(pixel_fmt);
        if (map < 0) {
                dev_dbg(ipu->dev, "IPU_DISP: No MAP\n");
-               spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
+               _ipu_unlock(ipu);
                return -EINVAL;
        }
 
@@ -1503,7 +1642,7 @@ int32_t ipu_init_sync_panel(struct ipu_soc *ipu, int disp, uint32_t pixel_clk,
 
        ipu_dc_write(ipu, width, DC_DISP_CONF2(DC_DISP_ID_SYNC(disp)));
 
-       spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
+       _ipu_unlock(ipu);
 
        return 0;
 }
@@ -1511,14 +1650,13 @@ EXPORT_SYMBOL(ipu_init_sync_panel);
 
 void ipu_uninit_sync_panel(struct ipu_soc *ipu, int disp)
 {
-       unsigned long lock_flags;
        uint32_t reg;
        uint32_t di_gen;
 
        if ((disp != 0) || (disp != 1))
                return;
 
-       spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
+       _ipu_lock(ipu);
 
        di_gen = ipu_di_read(ipu, disp, DI_GENERAL);
        di_gen |= 0x3ff | DI_GEN_POLARITY_DISP_CLK;
@@ -1528,14 +1666,13 @@ void ipu_uninit_sync_panel(struct ipu_soc *ipu, int disp)
        reg |= 0x3ffffff;
        ipu_di_write(ipu, disp, reg, DI_POL);
 
-       spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
+       _ipu_unlock(ipu);
 }
 EXPORT_SYMBOL(ipu_uninit_sync_panel);
 
 int ipu_init_async_panel(struct ipu_soc *ipu, int disp, int type, uint32_t cycle_time,
                         uint32_t pixel_fmt, ipu_adc_sig_cfg_t sig)
 {
-       unsigned long lock_flags;
        int map;
        u32 ser_conf = 0;
        u32 div;
@@ -1549,7 +1686,7 @@ int ipu_init_async_panel(struct ipu_soc *ipu, int disp, int type, uint32_t cycle
        if (map < 0)
                return -EINVAL;
 
-       spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
+       _ipu_lock(ipu);
 
        if (type == IPU_PANEL_SERIAL) {
                ipu_di_write(ipu, disp, (div << 24) | ((sig.ifc_width - 1) << 4),
@@ -1578,7 +1715,7 @@ int ipu_init_async_panel(struct ipu_soc *ipu, int disp, int type, uint32_t cycle
                ipu_di_write(ipu, disp, ser_conf, DI_SER_CONF);
        }
 
-       spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
+       _ipu_unlock(ipu);
        return 0;
 }
 EXPORT_SYMBOL(ipu_init_async_panel);
@@ -1603,7 +1740,6 @@ int32_t ipu_disp_set_global_alpha(struct ipu_soc *ipu, ipu_channel_t channel,
 {
        uint32_t reg;
        uint32_t flow;
-       unsigned long lock_flags;
        bool bg_chan;
 
        if (channel == MEM_BG_SYNC || channel == MEM_FG_SYNC)
@@ -1621,9 +1757,9 @@ int32_t ipu_disp_set_global_alpha(struct ipu_soc *ipu, ipu_channel_t channel,
        else
                bg_chan = false;
 
-       if (!ipu->clk_enabled)
-               clk_enable(ipu->ipu_clk);
-       spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
+       _ipu_get(ipu);
+
+       _ipu_lock(ipu);
 
        if (bg_chan) {
                reg = ipu_dp_read(ipu, DP_COM_CONF(flow));
@@ -1648,9 +1784,9 @@ int32_t ipu_disp_set_global_alpha(struct ipu_soc *ipu, ipu_channel_t channel,
        reg = ipu_cm_read(ipu, IPU_SRM_PRI2) | 0x8;
        ipu_cm_write(ipu, reg, IPU_SRM_PRI2);
 
-       spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
-       if (!ipu->clk_enabled)
-               clk_disable(ipu->ipu_clk);
+       _ipu_unlock(ipu);
+
+       _ipu_put(ipu);
 
        return 0;
 }
@@ -1674,7 +1810,6 @@ int32_t ipu_disp_set_color_key(struct ipu_soc *ipu, ipu_channel_t channel,
        uint32_t reg, flow;
        int y, u, v;
        int red, green, blue;
-       unsigned long lock_flags;
 
        if (channel == MEM_BG_SYNC || channel == MEM_FG_SYNC)
                flow = DP_SYNC;
@@ -1685,10 +1820,9 @@ int32_t ipu_disp_set_color_key(struct ipu_soc *ipu, ipu_channel_t channel,
        else
                return -EINVAL;
 
-       if (!ipu->clk_enabled)
-               clk_enable(ipu->ipu_clk);
+       _ipu_get(ipu);
 
-       spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
+       _ipu_lock(ipu);
 
        ipu->color_key_4rgb = true;
        /* Transform color key from rgb to yuv if CSC is enabled */
@@ -1727,9 +1861,9 @@ int32_t ipu_disp_set_color_key(struct ipu_soc *ipu, ipu_channel_t channel,
        reg = ipu_cm_read(ipu, IPU_SRM_PRI2) | 0x8;
        ipu_cm_write(ipu, reg, IPU_SRM_PRI2);
 
-       spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
-       if (!ipu->clk_enabled)
-               clk_disable(ipu->ipu_clk);
+       _ipu_unlock(ipu);
+
+       _ipu_put(ipu);
 
        return 0;
 }
@@ -1752,7 +1886,6 @@ EXPORT_SYMBOL(ipu_disp_set_color_key);
 int32_t ipu_disp_set_gamma_correction(struct ipu_soc *ipu, ipu_channel_t channel, bool enable, int constk[], int slopek[])
 {
        uint32_t reg, flow, i;
-       unsigned long lock_flags;
 
        if (channel == MEM_BG_SYNC || channel == MEM_FG_SYNC)
                flow = DP_SYNC;
@@ -1763,9 +1896,9 @@ int32_t ipu_disp_set_gamma_correction(struct ipu_soc *ipu, ipu_channel_t channel
        else
                return -EINVAL;
 
-       if (!ipu->clk_enabled)
-               clk_enable(ipu->ipu_clk);
-       spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
+       _ipu_get(ipu);
+
+       _ipu_lock(ipu);
 
        for (i = 0; i < 8; i++)
                ipu_dp_write(ipu, (constk[2*i] & 0x1ff) | ((constk[2*i+1] & 0x1ff) << 16), DP_GAMMA_C(flow, i));
@@ -1786,9 +1919,9 @@ int32_t ipu_disp_set_gamma_correction(struct ipu_soc *ipu, ipu_channel_t channel
        reg = ipu_cm_read(ipu, IPU_SRM_PRI2) | 0x8;
        ipu_cm_write(ipu, reg, IPU_SRM_PRI2);
 
-       spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
-       if (!ipu->clk_enabled)
-               clk_disable(ipu->ipu_clk);
+       _ipu_unlock(ipu);
+
+       _ipu_put(ipu);
 
        return 0;
 }
@@ -1809,11 +1942,10 @@ EXPORT_SYMBOL(ipu_disp_set_gamma_correction);
  *
  * @return      Returns 0 on success or negative error code on fail
  */
-int32_t ipu_disp_set_window_pos(struct ipu_soc *ipu, ipu_channel_t channel,
+int32_t _ipu_disp_set_window_pos(struct ipu_soc *ipu, ipu_channel_t channel,
                                int16_t x_pos, int16_t y_pos)
 {
        u32 reg;
-       unsigned long lock_flags;
        uint32_t flow = 0;
        uint32_t dp_srm_shift;
 
@@ -1829,11 +1961,6 @@ int32_t ipu_disp_set_window_pos(struct ipu_soc *ipu, ipu_channel_t channel,
        } else
                return -EINVAL;
 
-       if (!ipu->clk_enabled)
-               clk_enable(ipu->ipu_clk);
-
-       spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
-
        ipu_dp_write(ipu, (x_pos << 16) | y_pos, DP_FG_POS(flow));
 
        if (ipu_is_channel_busy(ipu, channel)) {
@@ -1847,19 +1974,27 @@ int32_t ipu_disp_set_window_pos(struct ipu_soc *ipu, ipu_channel_t channel,
                ipu_cm_write(ipu, reg, IPU_SRM_PRI2);
        }
 
-       spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
-       if (!ipu->clk_enabled)
-               clk_disable(ipu->ipu_clk);
-
        return 0;
 }
+
+int32_t ipu_disp_set_window_pos(struct ipu_soc *ipu, ipu_channel_t channel,
+                               int16_t x_pos, int16_t y_pos)
+{
+       int ret;
+
+       _ipu_get(ipu);
+       _ipu_lock(ipu);
+       ret = _ipu_disp_set_window_pos(ipu, channel, x_pos, y_pos);
+       _ipu_unlock(ipu);
+       _ipu_put(ipu);
+       return ret;
+}
 EXPORT_SYMBOL(ipu_disp_set_window_pos);
 
-int32_t ipu_disp_get_window_pos(struct ipu_soc *ipu, ipu_channel_t channel,
+int32_t _ipu_disp_get_window_pos(struct ipu_soc *ipu, ipu_channel_t channel,
                                int16_t *x_pos, int16_t *y_pos)
 {
        u32 reg;
-       unsigned long lock_flags;
        uint32_t flow = 0;
 
        if (channel == MEM_FG_SYNC)
@@ -1871,21 +2006,25 @@ int32_t ipu_disp_get_window_pos(struct ipu_soc *ipu, ipu_channel_t channel,
        else
                return -EINVAL;
 
-       if (!ipu->clk_enabled)
-               clk_enable(ipu->ipu_clk);
-       spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
-
        reg = ipu_dp_read(ipu, DP_FG_POS(flow));
 
        *x_pos = (reg >> 16) & 0x7FF;
        *y_pos = reg & 0x7FF;
 
-       spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
-       if (!ipu->clk_enabled)
-               clk_disable(ipu->ipu_clk);
-
        return 0;
 }
+int32_t ipu_disp_get_window_pos(struct ipu_soc *ipu, ipu_channel_t channel,
+                               int16_t *x_pos, int16_t *y_pos)
+{
+       int ret;
+
+       _ipu_get(ipu);
+       _ipu_lock(ipu);
+       ret = _ipu_disp_get_window_pos(ipu, channel, x_pos, y_pos);
+       _ipu_unlock(ipu);
+       _ipu_put(ipu);
+       return ret;
+}
 EXPORT_SYMBOL(ipu_disp_get_window_pos);
 
 void ipu_disp_direct_write(struct ipu_soc *ipu, ipu_channel_t channel, u32 value, u32 offset)
index d7167f7831e49401062718b2316610658f1f2aed..d2ad2695b682c0c45665df91f323cdadf700a2ac 100644 (file)
@@ -41,6 +41,24 @@ struct ipu_ch_param {
        } \
 }
 
+#define ipu_ch_param_set_field_io(base, w, bit, size, v) { \
+       int i = (bit) / 32; \
+       int off = (bit) % 32; \
+       unsigned reg_offset; \
+       u32 temp; \
+       reg_offset = sizeof(struct ipu_ch_param_word) * w / 4; \
+       reg_offset += i; \
+       temp = readl((u32 *)base + reg_offset); \
+       temp |= (v) << off; \
+       writel(temp, (u32 *)base + reg_offset); \
+       if (((bit)+(size)-1)/32 > i) { \
+               reg_offset++; \
+               temp = readl((u32 *)base + reg_offset); \
+               temp |= (v) >> (off ? (32 - off) : 0); \
+               writel(temp, (u32 *)base + reg_offset); \
+       } \
+}
+
 #define ipu_ch_param_mod_field(base, w, bit, size, v) { \
        int i = (bit) / 32; \
        int off = (bit) % 32; \
@@ -56,6 +74,27 @@ struct ipu_ch_param {
        } \
 }
 
+#define ipu_ch_param_mod_field_io(base, w, bit, size, v) { \
+       int i = (bit) / 32; \
+       int off = (bit) % 32; \
+       u32 mask = (1UL << size) - 1; \
+       unsigned reg_offset; \
+       u32 temp; \
+       reg_offset = sizeof(struct ipu_ch_param_word) * w / 4; \
+       reg_offset += i; \
+       temp = readl((u32 *)base + reg_offset); \
+       temp &= ~(mask << off); \
+       temp |= (v) << off; \
+       writel(temp, (u32 *)base + reg_offset); \
+       if (((bit)+(size)-1)/32 > i) { \
+               reg_offset++; \
+               temp = readl((u32 *)base + reg_offset); \
+               temp &= ~(mask >> (32 - off)); \
+               temp |= ((v) >> (off ? (32 - off) : 0)); \
+               writel(temp, (u32 *)base + reg_offset); \
+       } \
+}
+
 #define ipu_ch_param_read_field(base, w, bit, size) ({ \
        u32 temp2; \
        int i = (bit) / 32; \
@@ -71,6 +110,25 @@ struct ipu_ch_param {
        temp1; \
 })
 
+#define ipu_ch_param_read_field_io(base, w, bit, size) ({ \
+       u32 temp1, temp2; \
+       int i = (bit) / 32; \
+       int off = (bit) % 32; \
+       u32 mask = (1UL << size) - 1; \
+       unsigned reg_offset; \
+       reg_offset = sizeof(struct ipu_ch_param_word) * w / 4; \
+       reg_offset += i; \
+       temp1 = readl((u32 *)base + reg_offset); \
+       temp1 = mask & (temp1 >> off); \
+       if (((bit)+(size)-1)/32 > i) { \
+               reg_offset++; \
+               temp2 = readl((u32 *)base + reg_offset); \
+               temp2 &= mask >> (off ? (32 - off) : 0); \
+               temp1 |= temp2 << (off ? (32 - off) : 0); \
+       } \
+       temp1; \
+})
+
 static inline int __ipu_ch_get_third_buf_cpmem_num(int ch)
 {
        switch (ch) {
@@ -126,35 +184,35 @@ static inline void _ipu_ch_param_dump(struct ipu_soc *ipu, int ch)
                 p->word[1].data[0], p->word[1].data[1], p->word[1].data[2],
                 p->word[1].data[3], p->word[1].data[4]);
        dev_dbg(ipu->dev, "PFS 0x%x, ",
-                ipu_ch_param_read_field(ipu_ch_param_addr(ipu, ch), 1, 85, 4));
+                ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 85, 4));
        dev_dbg(ipu->dev, "BPP 0x%x, ",
-                ipu_ch_param_read_field(ipu_ch_param_addr(ipu, ch), 0, 107, 3));
+                ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 0, 107, 3));
        dev_dbg(ipu->dev, "NPB 0x%x\n",
-                ipu_ch_param_read_field(ipu_ch_param_addr(ipu, ch), 1, 78, 7));
+                ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 78, 7));
 
        dev_dbg(ipu->dev, "FW %d, ",
-                ipu_ch_param_read_field(ipu_ch_param_addr(ipu, ch), 0, 125, 13));
+                ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 0, 125, 13));
        dev_dbg(ipu->dev, "FH %d, ",
-                ipu_ch_param_read_field(ipu_ch_param_addr(ipu, ch), 0, 138, 12));
+                ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 0, 138, 12));
        dev_dbg(ipu->dev, "Stride %d\n",
-                ipu_ch_param_read_field(ipu_ch_param_addr(ipu, ch), 1, 102, 14));
+                ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 102, 14));
 
        dev_dbg(ipu->dev, "Width0 %d+1, ",
-                ipu_ch_param_read_field(ipu_ch_param_addr(ipu, ch), 1, 116, 3));
+                ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 116, 3));
        dev_dbg(ipu->dev, "Width1 %d+1, ",
-                ipu_ch_param_read_field(ipu_ch_param_addr(ipu, ch), 1, 119, 3));
+                ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 119, 3));
        dev_dbg(ipu->dev, "Width2 %d+1, ",
-                ipu_ch_param_read_field(ipu_ch_param_addr(ipu, ch), 1, 122, 3));
+                ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 122, 3));
        dev_dbg(ipu->dev, "Width3 %d+1, ",
-                ipu_ch_param_read_field(ipu_ch_param_addr(ipu, ch), 1, 125, 3));
+                ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 125, 3));
        dev_dbg(ipu->dev, "Offset0 %d, ",
-                ipu_ch_param_read_field(ipu_ch_param_addr(ipu, ch), 1, 128, 5));
+                ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 128, 5));
        dev_dbg(ipu->dev, "Offset1 %d, ",
-                ipu_ch_param_read_field(ipu_ch_param_addr(ipu, ch), 1, 133, 5));
+                ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 133, 5));
        dev_dbg(ipu->dev, "Offset2 %d, ",
-                ipu_ch_param_read_field(ipu_ch_param_addr(ipu, ch), 1, 138, 5));
+                ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 138, 5));
        dev_dbg(ipu->dev, "Offset3 %d\n",
-                ipu_ch_param_read_field(ipu_ch_param_addr(ipu, ch), 1, 143, 5));
+                ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 143, 5));
 }
 
 static inline void _ipu_ch_param_init(struct ipu_soc *ipu, int ch,
@@ -392,24 +450,24 @@ static inline void _ipu_ch_param_set_burst_size(struct ipu_soc *ipu,
 {
        int32_t sub_ch = 0;
 
-       ipu_ch_param_mod_field(ipu_ch_param_addr(ipu, ch), 1, 78, 7,
+       ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 1, 78, 7,
                               burst_pixels - 1);
 
        sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
        if (sub_ch <= 0)
                return;
-       ipu_ch_param_mod_field(ipu_ch_param_addr(ipu, sub_ch), 1, 78, 7,
+       ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 1, 78, 7,
                               burst_pixels - 1);
 };
 
 static inline int _ipu_ch_param_get_burst_size(struct ipu_soc *ipu, uint32_t ch)
 {
-       return ipu_ch_param_read_field(ipu_ch_param_addr(ipu, ch), 1, 78, 7) + 1;
+       return ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 78, 7) + 1;
 };
 
 static inline int _ipu_ch_param_get_bpp(struct ipu_soc *ipu, uint32_t ch)
 {
-       return ipu_ch_param_read_field(ipu_ch_param_addr(ipu, ch), 0, 107, 3);
+       return ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 0, 107, 3);
 };
 
 static inline void _ipu_ch_param_set_buffer(struct ipu_soc *ipu, uint32_t ch,
@@ -422,7 +480,7 @@ static inline void _ipu_ch_param_set_buffer(struct ipu_soc *ipu, uint32_t ch,
                bufNum = 0;
        }
 
-       ipu_ch_param_mod_field(ipu_ch_param_addr(ipu, ch), 1, 29 * bufNum, 29,
+       ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 1, 29 * bufNum, 29,
                               phyaddr / 8);
 };
 
@@ -432,24 +490,24 @@ static inline void _ipu_ch_param_set_rotation(struct ipu_soc *ipu, uint32_t ch,
        u32 temp_rot = bitrev8(rot) >> 5;
        int32_t sub_ch = 0;
 
-       ipu_ch_param_mod_field(ipu_ch_param_addr(ipu, ch), 0, 119, 3, temp_rot);
+       ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 0, 119, 3, temp_rot);
 
        sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
        if (sub_ch <= 0)
                return;
-       ipu_ch_param_mod_field(ipu_ch_param_addr(ipu, sub_ch), 0, 119, 3, temp_rot);
+       ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 0, 119, 3, temp_rot);
 };
 
 static inline void _ipu_ch_param_set_block_mode(struct ipu_soc *ipu, uint32_t ch)
 {
        int32_t sub_ch = 0;
 
-       ipu_ch_param_mod_field(ipu_ch_param_addr(ipu, ch), 0, 117, 2, 1);
+       ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 0, 117, 2, 1);
 
        sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
        if (sub_ch <= 0)
                return;
-       ipu_ch_param_mod_field(ipu_ch_param_addr(ipu, sub_ch), 0, 117, 2, 1);
+       ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 0, 117, 2, 1);
 };
 
 static inline void _ipu_ch_param_set_alpha_use_separate_channel(struct ipu_soc *ipu,
@@ -459,9 +517,9 @@ static inline void _ipu_ch_param_set_alpha_use_separate_channel(struct ipu_soc *
        int32_t sub_ch = 0;
 
        if (option) {
-               ipu_ch_param_mod_field(ipu_ch_param_addr(ipu, ch), 1, 89, 1, 1);
+               ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 1, 89, 1, 1);
        } else {
-               ipu_ch_param_mod_field(ipu_ch_param_addr(ipu, ch), 1, 89, 1, 0);
+               ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 1, 89, 1, 0);
        }
 
        sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
@@ -469,9 +527,9 @@ static inline void _ipu_ch_param_set_alpha_use_separate_channel(struct ipu_soc *
                return;
 
        if (option) {
-               ipu_ch_param_mod_field(ipu_ch_param_addr(ipu, sub_ch), 1, 89, 1, 1);
+               ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 1, 89, 1, 1);
        } else {
-               ipu_ch_param_mod_field(ipu_ch_param_addr(ipu, sub_ch), 1, 89, 1, 0);
+               ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 1, 89, 1, 0);
        }
 };
 
@@ -479,12 +537,12 @@ static inline void _ipu_ch_param_set_alpha_condition_read(struct ipu_soc *ipu, u
 {
        int32_t sub_ch = 0;
 
-       ipu_ch_param_mod_field(ipu_ch_param_addr(ipu, ch), 1, 149, 1, 1);
+       ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 1, 149, 1, 1);
 
        sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
        if (sub_ch <= 0)
                return;
-       ipu_ch_param_mod_field(ipu_ch_param_addr(ipu, sub_ch), 1, 149, 1, 1);
+       ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 1, 149, 1, 1);
 };
 
 static inline void _ipu_ch_param_set_alpha_buffer_memory(struct ipu_soc *ipu, uint32_t ch)
@@ -511,12 +569,12 @@ static inline void _ipu_ch_param_set_alpha_buffer_memory(struct ipu_soc *ipu, ui
                return;
        }
 
-       ipu_ch_param_mod_field(ipu_ch_param_addr(ipu, ch), 1, 90, 3, alp_mem_idx);
+       ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 1, 90, 3, alp_mem_idx);
 
        sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
        if (sub_ch <= 0)
                return;
-       ipu_ch_param_mod_field(ipu_ch_param_addr(ipu, sub_ch), 1, 90, 3, alp_mem_idx);
+       ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 1, 90, 3, alp_mem_idx);
 };
 
 static inline void _ipu_ch_param_set_interlaced_scan(struct ipu_soc *ipu, uint32_t ch)
@@ -526,10 +584,10 @@ static inline void _ipu_ch_param_set_interlaced_scan(struct ipu_soc *ipu, uint32
 
        sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
 
-       ipu_ch_param_set_field(ipu_ch_param_addr(ipu, ch), 0, 113, 1, 1);
+       ipu_ch_param_set_field_io(ipu_ch_param_addr(ipu, ch), 0, 113, 1, 1);
        if (sub_ch > 0)
-               ipu_ch_param_set_field(ipu_ch_param_addr(ipu, sub_ch), 0, 113, 1, 1);
-       stride = ipu_ch_param_read_field(ipu_ch_param_addr(ipu, ch), 1, 102, 14) + 1;
+               ipu_ch_param_set_field_io(ipu_ch_param_addr(ipu, sub_ch), 0, 113, 1, 1);
+       stride = ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 102, 14) + 1;
        /* ILO is 20-bit and 8-byte aligned */
        if (stride/8 > 0xfffff)
                dev_warn(ipu->dev,
@@ -537,27 +595,29 @@ static inline void _ipu_ch_param_set_interlaced_scan(struct ipu_soc *ipu, uint32
        if (stride%8)
                dev_warn(ipu->dev,
                         "IDMAC%d's ILO is not 8-byte aligned\n", ch);
-       ipu_ch_param_mod_field(ipu_ch_param_addr(ipu, ch), 1, 58, 20, stride / 8);
+       ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 1, 58, 20, stride / 8);
        if (sub_ch > 0)
-               ipu_ch_param_mod_field(ipu_ch_param_addr(ipu, sub_ch), 1, 58, 20,
+               ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 1, 58, 20,
                                       stride / 8);
        stride *= 2;
-       ipu_ch_param_mod_field(ipu_ch_param_addr(ipu, ch), 1, 102, 14, stride - 1);
+       ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 1, 102, 14, stride - 1);
        if (sub_ch > 0)
-               ipu_ch_param_mod_field(ipu_ch_param_addr(ipu, sub_ch), 1, 102, 14,
+               ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 1, 102, 14,
                                       stride - 1);
 };
 
-static inline void _ipu_ch_param_set_high_priority(struct ipu_soc *ipu, uint32_t ch)
+static inline void _ipu_ch_param_set_axi_id(struct ipu_soc *ipu, uint32_t ch, uint32_t id)
 {
        int32_t sub_ch = 0;
 
-       ipu_ch_param_mod_field(ipu_ch_param_addr(ipu, ch), 1, 93, 2, 1);
+       id %= 4;
+
+       ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 1, 93, 2, id);
 
        sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
        if (sub_ch <= 0)
                return;
-       ipu_ch_param_mod_field(ipu_ch_param_addr(ipu, sub_ch), 1, 93, 2, 1);
+       ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 1, 93, 2, id);
 };
 
 /* IDMAC U/V offset changing support */
@@ -713,26 +773,26 @@ static inline void _ipu_ch_offset_update(struct ipu_soc *ipu,
                dev_warn(ipu->dev,
                        "IDMAC%d's V offset is not 8-byte aligned\n", ch);
 
-       ipu_ch_param_mod_field(ipu_ch_param_addr(ipu, ch), 0, 46, 22, u_offset / 8);
-       ipu_ch_param_mod_field(ipu_ch_param_addr(ipu, ch), 0, 68, 22, v_offset / 8);
+       ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 0, 46, 22, u_offset / 8);
+       ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 0, 68, 22, v_offset / 8);
 
        sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
        if (sub_ch <= 0)
                return;
-       ipu_ch_param_mod_field(ipu_ch_param_addr(ipu, sub_ch), 0, 46, 22, u_offset / 8);
-       ipu_ch_param_mod_field(ipu_ch_param_addr(ipu, sub_ch), 0, 68, 22, v_offset / 8);
+       ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 0, 46, 22, u_offset / 8);
+       ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 0, 68, 22, v_offset / 8);
 };
 
 static inline void _ipu_ch_params_set_alpha_width(struct ipu_soc *ipu, uint32_t ch, int alpha_width)
 {
        int32_t sub_ch = 0;
 
-       ipu_ch_param_set_field(ipu_ch_param_addr(ipu, ch), 1, 125, 3, alpha_width - 1);
+       ipu_ch_param_set_field_io(ipu_ch_param_addr(ipu, ch), 1, 125, 3, alpha_width - 1);
 
        sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
        if (sub_ch <= 0)
                return;
-       ipu_ch_param_set_field(ipu_ch_param_addr(ipu, sub_ch), 1, 125, 3, alpha_width - 1);
+       ipu_ch_param_set_field_io(ipu_ch_param_addr(ipu, sub_ch), 1, 125, 3, alpha_width - 1);
 };
 
 #endif
index dfb7b38bc44c7c7cfafef084a615b11ee6876fd6..fdb48458761d075b25aaca6ae8b793c33d8c53ee 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/types.h>
 #include <linux/device.h>
 #include <mach/clock.h>
+#include <linux/clkdev.h>
 #include <linux/interrupt.h>
 #include <linux/fsl_devices.h>
 
@@ -27,6 +28,8 @@
 
 /* Globals */
 extern int dmfc_type_setup;
+extern struct clk ipu_pixel_clk[];
+extern struct clk_lookup ipu_lookups[];
 
 #define IDMA_CHAN_INVALID      0xFF
 #define HIGH_RESOLUTION_WIDTH  1024
@@ -50,7 +53,6 @@ enum csc_type_t {
 struct ipu_soc {
        /*clk*/
        struct clk *ipu_clk;
-       bool clk_enabled;
        struct clk *di_clk[2];
        struct clk *csi_clk[2];
        struct clk pixel_clk[2];
@@ -76,7 +78,6 @@ struct ipu_soc {
        u32 *disp_base[2];
        u32 *vdi_reg;
 
-       spinlock_t ipu_lock;
        struct device *dev;
 
        ipu_channel_t csi_channel[2];
@@ -89,6 +90,7 @@ struct ipu_soc {
        uint32_t channel_enable_mask;
 
        /*use count*/
+       atomic_t ipu_use_count;
        int dc_use_count;
        int dp_use_count;
        int dmfc_use_count;
@@ -99,6 +101,9 @@ struct ipu_soc {
        int di_use_count[2];
        int csi_use_count[2];
 
+       struct mutex mutex_lock;
+       spinlock_t spin_lock;
+
        int dmfc_size_28;
        int dmfc_size_29;
        int dmfc_size_24;
@@ -315,5 +320,12 @@ void _ipu_csi_ccir_err_detection_disable(struct ipu_soc *ipu, uint32_t csi);
 void _ipu_smfc_init(struct ipu_soc *ipu, ipu_channel_t channel, uint32_t mipi_id, uint32_t csi);
 void _ipu_smfc_set_burst_size(struct ipu_soc *ipu, ipu_channel_t channel, uint32_t bs);
 void _ipu_dp_set_csc_coefficients(struct ipu_soc *ipu, ipu_channel_t channel, int32_t param[][3]);
-
+int32_t _ipu_disp_set_window_pos(struct ipu_soc *ipu, ipu_channel_t channel,
+               int16_t x_pos, int16_t y_pos);
+int32_t _ipu_disp_get_window_pos(struct ipu_soc *ipu, ipu_channel_t channel,
+               int16_t *x_pos, int16_t *y_pos);
+void _ipu_get(struct ipu_soc *ipu);
+void _ipu_put(struct ipu_soc *ipu);
+void _ipu_lock(struct ipu_soc *ipu);
+void _ipu_unlock(struct ipu_soc *ipu);
 #endif                         /* __INCLUDE_IPU_PRV_H__ */