aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Chen <b02280@freescale.com>2011-09-06 14:06:09 +0800
committerEric Miao <eric.miao@linaro.org>2011-10-21 11:10:23 +0800
commit74b0c30a8d1b4085988eef731e17e20a880ff8fb (patch)
tree0911fb2e615d4e88d9284b249977602164ecf4b0
parent2884c12eb455a87e1c66f12be67595ecfbb734d0 (diff)
ENGR00155146 ipuv3: use mutex instead of spin lock
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>
-rw-r--r--drivers/mxc/ipu3/ipu_capture.c163
-rw-r--r--drivers/mxc/ipu3/ipu_common.c523
-rw-r--r--drivers/mxc/ipu3/ipu_device.c22
-rw-r--r--drivers/mxc/ipu3/ipu_disp.c259
-rw-r--r--drivers/mxc/ipu3/ipu_param_mem.h154
-rw-r--r--drivers/mxc/ipu3/ipu_prv.h18
6 files changed, 572 insertions, 567 deletions
diff --git a/drivers/mxc/ipu3/ipu_capture.c b/drivers/mxc/ipu3/ipu_capture.c
index 88b1a3954ae..2399cb88d35 100644
--- a/drivers/mxc/ipu3/ipu_capture.c
+++ b/drivers/mxc/ipu3/ipu_capture.c
@@ -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);
}
/*!
diff --git a/drivers/mxc/ipu3/ipu_common.c b/drivers/mxc/ipu3/ipu_common.c
index 3e099d9e0f1..2a1eecda3d5 100644
--- a/drivers/mxc/ipu3/ipu_common.c
+++ b/drivers/mxc/ipu3/ipu_common.c
@@ -30,11 +30,12 @@
#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));
diff --git a/drivers/mxc/ipu3/ipu_device.c b/drivers/mxc/ipu3/ipu_device.c
index c00f0df9859..526fb4c950e 100644
--- a/drivers/mxc/ipu3/ipu_device.c
+++ b/drivers/mxc/ipu3/ipu_device.c
@@ -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);
diff --git a/drivers/mxc/ipu3/ipu_disp.c b/drivers/mxc/ipu3/ipu_disp.c
index 12e36e28c2d..25d17ca5862 100644
--- a/drivers/mxc/ipu3/ipu_disp.c
+++ b/drivers/mxc/ipu3/ipu_disp.c
@@ -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)
diff --git a/drivers/mxc/ipu3/ipu_param_mem.h b/drivers/mxc/ipu3/ipu_param_mem.h
index d7167f7831e..d2ad2695b68 100644
--- a/drivers/mxc/ipu3/ipu_param_mem.h
+++ b/drivers/mxc/ipu3/ipu_param_mem.h
@@ -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
diff --git a/drivers/mxc/ipu3/ipu_prv.h b/drivers/mxc/ipu3/ipu_prv.h
index dfb7b38bc44..fdb48458761 100644
--- a/drivers/mxc/ipu3/ipu_prv.h
+++ b/drivers/mxc/ipu3/ipu_prv.h
@@ -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__ */