From 74b0c30a8d1b4085988eef731e17e20a880ff8fb Mon Sep 17 00:00:00 2001 From: Jason Chen Date: Tue, 6 Sep 2011 14:06:09 +0800 Subject: 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 --- drivers/mxc/ipu3/ipu_capture.c | 163 ++---------- drivers/mxc/ipu3/ipu_common.c | 523 +++++++++++++++++---------------------- drivers/mxc/ipu3/ipu_device.c | 22 -- drivers/mxc/ipu3/ipu_disp.c | 259 ++++++++++++++----- drivers/mxc/ipu3/ipu_param_mem.h | 154 ++++++++---- drivers/mxc/ipu3/ipu_prv.h | 18 +- 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 #include #include -#include #include #include #include #include +#include +#include #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 #include #include +#include #include #include #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 #include #include +#include #include #include @@ -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__ */ -- cgit v1.2.3