diff options
Diffstat (limited to 'drivers/mxc/ipu3')
-rw-r--r-- | drivers/mxc/ipu3/ipu_capture.c | 118 | ||||
-rw-r--r-- | drivers/mxc/ipu3/ipu_common.c | 40 | ||||
-rw-r--r-- | drivers/mxc/ipu3/ipu_disp.c | 142 | ||||
-rw-r--r-- | drivers/mxc/ipu3/ipu_regs.h | 1 |
4 files changed, 88 insertions, 213 deletions
diff --git a/drivers/mxc/ipu3/ipu_capture.c b/drivers/mxc/ipu3/ipu_capture.c index b9967135eac1..e801705f8fe9 100644 --- a/drivers/mxc/ipu3/ipu_capture.c +++ b/drivers/mxc/ipu3/ipu_capture.c @@ -26,7 +26,6 @@ #include <linux/delay.h> #include <linux/ipu.h> #include <linux/clk.h> -#include <mach/mxc_dvfs.h> #include "ipu_prv.h" #include "ipu_regs.h" @@ -94,12 +93,6 @@ ipu_csi_init_interface(uint16_t width, uint16_t height, uint32_t pixel_fmt, cfg_param.force_eof << CSI_SENS_CONF_FORCE_EOF_SHIFT | cfg_param.data_en_pol << CSI_SENS_CONF_DATA_EN_POL_SHIFT; - if (g_ipu_clk_enabled == false) { - stop_dvfs_per(); - g_ipu_clk_enabled = true; - clk_enable(g_ipu_clk); - } - spin_lock_irqsave(&ipu_lock, lock_flags); __raw_writel(data, CSI_SENS_CONF(csi)); @@ -185,13 +178,36 @@ int _ipu_csi_mclk_set(uint32_t pixel_clk, uint32_t csi) */ int ipu_csi_enable_mclk(int csi, bool flag, bool wait) { + struct clk *clk; if (flag) { - clk_enable(g_csi_clk[csi]); + if (cpu_is_mx53()) { + if (csi == 0) { + clk = clk_get(NULL, "ssi_ext1_clk"); + clk_enable(clk); + clk_put(clk); + } else { + pr_err("invalid csi num %d\n", csi); + return -EINVAL; + } + } else + // CCWMX51 - Both CSIs from master clock 0 + clk_enable(g_csi_clk[0]); if (wait == true) msleep(10); } else { - clk_disable(g_csi_clk[csi]); + if (cpu_is_mx53()) { + if (csi == 0) { + clk = clk_get(NULL, "ssi_ext1_clk"); + clk_disable(clk); + clk_put(clk); + } else { + pr_err("invalid csi num %d\n", csi); + return -EINVAL; + } + } else + // CCWMX51 - Both CSIs from master clock 0 + clk_disable(g_csi_clk[0]); } return 0; @@ -210,12 +226,6 @@ void ipu_csi_get_window_size(uint32_t *width, uint32_t *height, uint32_t csi) uint32_t reg; unsigned long lock_flags; - if (g_ipu_clk_enabled == false) { - stop_dvfs_per(); - g_ipu_clk_enabled = true; - clk_enable(g_ipu_clk); - } - spin_lock_irqsave(&ipu_lock, lock_flags); reg = __raw_readl(CSI_ACT_FRM_SIZE(csi)); @@ -237,12 +247,6 @@ void ipu_csi_set_window_size(uint32_t width, uint32_t height, uint32_t csi) { unsigned long lock_flags; - if (g_ipu_clk_enabled == false) { - stop_dvfs_per(); - g_ipu_clk_enabled = true; - clk_enable(g_ipu_clk); - } - spin_lock_irqsave(&ipu_lock, lock_flags); __raw_writel((width - 1) | (height - 1) << 16, CSI_ACT_FRM_SIZE(csi)); @@ -263,12 +267,6 @@ void ipu_csi_set_window_pos(uint32_t left, uint32_t top, uint32_t csi) uint32_t temp; unsigned long lock_flags; - if (g_ipu_clk_enabled == false) { - stop_dvfs_per(); - g_ipu_clk_enabled = true; - clk_enable(g_ipu_clk); - } - spin_lock_irqsave(&ipu_lock, lock_flags); temp = __raw_readl(CSI_OUT_FRM_CTRL(csi)); @@ -291,12 +289,6 @@ void _ipu_csi_horizontal_downsize_enable(uint32_t csi) uint32_t temp; unsigned long lock_flags; - if (g_ipu_clk_enabled == false) { - stop_dvfs_per(); - g_ipu_clk_enabled = true; - clk_enable(g_ipu_clk); - } - spin_lock_irqsave(&ipu_lock, lock_flags); temp = __raw_readl(CSI_OUT_FRM_CTRL(csi)); @@ -317,12 +309,6 @@ void _ipu_csi_horizontal_downsize_disable(uint32_t csi) uint32_t temp; unsigned long lock_flags; - if (g_ipu_clk_enabled == false) { - stop_dvfs_per(); - g_ipu_clk_enabled = true; - clk_enable(g_ipu_clk); - } - spin_lock_irqsave(&ipu_lock, lock_flags); temp = __raw_readl(CSI_OUT_FRM_CTRL(csi)); @@ -343,12 +329,6 @@ void _ipu_csi_vertical_downsize_enable(uint32_t csi) uint32_t temp; unsigned long lock_flags; - if (g_ipu_clk_enabled == false) { - stop_dvfs_per(); - g_ipu_clk_enabled = true; - clk_enable(g_ipu_clk); - } - spin_lock_irqsave(&ipu_lock, lock_flags); temp = __raw_readl(CSI_OUT_FRM_CTRL(csi)); @@ -369,12 +349,6 @@ void _ipu_csi_vertical_downsize_disable(uint32_t csi) uint32_t temp; unsigned long lock_flags; - if (g_ipu_clk_enabled == false) { - stop_dvfs_per(); - g_ipu_clk_enabled = true; - clk_enable(g_ipu_clk); - } - spin_lock_irqsave(&ipu_lock, lock_flags); temp = __raw_readl(CSI_OUT_FRM_CTRL(csi)); @@ -401,12 +375,6 @@ void ipu_csi_set_test_generator(bool active, uint32_t r_value, uint32_t temp; unsigned long lock_flags; - if (g_ipu_clk_enabled == false) { - stop_dvfs_per(); - g_ipu_clk_enabled = true; - clk_enable(g_ipu_clk); - } - spin_lock_irqsave(&ipu_lock, lock_flags); temp = __raw_readl(CSI_TST_CTRL(csi)); @@ -442,12 +410,6 @@ void _ipu_csi_ccir_err_detection_enable(uint32_t csi) { uint32_t temp; - if (g_ipu_clk_enabled == false) { - stop_dvfs_per(); - g_ipu_clk_enabled = true; - clk_enable(g_ipu_clk); - } - temp = __raw_readl(CSI_CCIR_CODE_1(csi)); temp |= CSI_CCIR_ERR_DET_EN; __raw_writel(temp, CSI_CCIR_CODE_1(csi)); @@ -464,12 +426,6 @@ void _ipu_csi_ccir_err_detection_disable(uint32_t csi) { uint32_t temp; - if (g_ipu_clk_enabled == false) { - stop_dvfs_per(); - g_ipu_clk_enabled = true; - clk_enable(g_ipu_clk); - } - temp = __raw_readl(CSI_CCIR_CODE_1(csi)); temp &= ~CSI_CCIR_ERR_DET_EN; __raw_writel(temp, CSI_CCIR_CODE_1(csi)); @@ -495,12 +451,6 @@ int _ipu_csi_set_mipi_di(uint32_t num, uint32_t di_val, uint32_t csi) goto err; } - if (g_ipu_clk_enabled == false) { - stop_dvfs_per(); - g_ipu_clk_enabled = true; - clk_enable(g_ipu_clk); - } - spin_lock_irqsave(&ipu_lock, lock_flags); temp = __raw_readl(CSI_MIPI_DI(csi)); @@ -558,12 +508,6 @@ int _ipu_csi_set_skip_isp(uint32_t skip, uint32_t max_ratio, uint32_t csi) goto err; } - if (g_ipu_clk_enabled == false) { - stop_dvfs_per(); - g_ipu_clk_enabled = true; - clk_enable(g_ipu_clk); - } - spin_lock_irqsave(&ipu_lock, lock_flags); temp = __raw_readl(CSI_SKIP(csi)); @@ -601,12 +545,6 @@ int _ipu_csi_set_skip_smfc(uint32_t skip, uint32_t max_ratio, goto err; } - if (g_ipu_clk_enabled == false) { - stop_dvfs_per(); - g_ipu_clk_enabled = true; - clk_enable(g_ipu_clk); - } - spin_lock_irqsave(&ipu_lock, lock_flags); temp = __raw_readl(CSI_SKIP(csi)); @@ -674,12 +612,6 @@ void _ipu_smfc_set_wmc(ipu_channel_t channel, bool set, uint32_t level) uint32_t temp; unsigned long lock_flags; - if (g_ipu_clk_enabled == false) { - stop_dvfs_per(); - g_ipu_clk_enabled = true; - clk_enable(g_ipu_clk); - } - spin_lock_irqsave(&ipu_lock, lock_flags); temp = __raw_readl(SMFC_WMC); diff --git a/drivers/mxc/ipu3/ipu_common.c b/drivers/mxc/ipu3/ipu_common.c index b1b8a8b39ae1..eae3b549d765 100644 --- a/drivers/mxc/ipu3/ipu_common.c +++ b/drivers/mxc/ipu3/ipu_common.c @@ -354,8 +354,8 @@ static int ipu_probe(struct platform_device *pdev) g_di_clk[0] = plat_data->di_clk[0]; g_di_clk[1] = plat_data->di_clk[1]; - g_csi_clk[0] = plat_data->csi_clk[0]; - g_csi_clk[1] = plat_data->csi_clk[1]; + g_csi_clk[0] = clk_get(&pdev->dev, "csi_mclk1"); + g_csi_clk[1] = clk_get(&pdev->dev, "csi_mclk2"); __raw_writel(0x807FFFFF, IPU_MEM_RST); while (__raw_readl(IPU_MEM_RST) & 0x80000000) ; @@ -1883,29 +1883,29 @@ int32_t ipu_disable_channel(ipu_channel_t channel, bool wait_for_stop) if ((channel == MEM_BG_SYNC) || (channel == MEM_FG_SYNC) || (channel == MEM_DC_SYNC)) { - if (channel == MEM_FG_SYNC) - ipu_disp_set_window_pos(channel, 0, 0); + int timeout = 50; + int irq; _ipu_dp_dc_disable(channel, false); /* - * wait for BG channel EOF then disable FG-IDMAC, - * it avoid FG NFB4EOF error. + * wait for display channel EOF then disable IDMAC, + * it avoid NFB4EOF error. */ - if (channel == MEM_FG_SYNC) { - int timeout = 50; - - __raw_writel(IPUIRQ_2_MASK(IPU_IRQ_BG_SYNC_EOF), - IPUIRQ_2_STATREG(IPU_IRQ_BG_SYNC_EOF)); - while ((__raw_readl(IPUIRQ_2_STATREG(IPU_IRQ_BG_SYNC_EOF)) & - IPUIRQ_2_MASK(IPU_IRQ_BG_SYNC_EOF)) == 0) { - msleep(10); - timeout -= 10; - if (timeout <= 0) { - dev_err(g_ipu_dev, "warning: wait for bg sync eof timeout\n"); - break; - } - } + if (channel == MEM_BG_SYNC) + irq = IPU_IRQ_BG_SYNC_EOF; + if (channel == MEM_FG_SYNC) + irq = IPU_IRQ_FG_SYNC_EOF; + else + irq = IPU_IRQ_DC_SYNC_EOF; + __raw_writel(IPUIRQ_2_MASK(irq), + IPUIRQ_2_STATREG(irq)); + while ((__raw_readl(IPUIRQ_2_STATREG(irq)) & + IPUIRQ_2_MASK(irq)) == 0) { + msleep(10); + timeout -= 10; + if (timeout <= 0) + break; } } else if (wait_for_stop) { while (idma_is_set(IDMAC_CHA_BUSY, in_dma) || diff --git a/drivers/mxc/ipu3/ipu_disp.c b/drivers/mxc/ipu3/ipu_disp.c index 14dde404990b..7ce04d8bca9e 100644 --- a/drivers/mxc/ipu3/ipu_disp.c +++ b/drivers/mxc/ipu3/ipu_disp.c @@ -318,34 +318,22 @@ static void _ipu_dc_map_clear(int map) } static void _ipu_dc_write_tmpl(int word, u32 opcode, u32 operand, int map, - int wave, int glue, int sync, int stop) + int wave, int glue, int sync) { u32 reg; - - if (opcode == WRG) { - reg = sync; - reg |= (glue << 4); - reg |= (++wave << 11); - reg |= ((operand & 0x1FFFF) << 15); - __raw_writel(reg, ipu_dc_tmpl_reg + word * 2); - - reg = (operand >> 17); - reg |= opcode << 7; - reg |= (stop << 9); - __raw_writel(reg, ipu_dc_tmpl_reg + word * 2 + 1); - } else { - reg = sync; - reg |= (glue << 4); - reg |= (++wave << 11); - reg |= (++map << 15); - reg |= (operand << 20) & 0xFFF00000; - __raw_writel(reg, ipu_dc_tmpl_reg + word * 2); - - reg = (operand >> 12); - reg |= opcode << 4; - reg |= (stop << 9); - __raw_writel(reg, ipu_dc_tmpl_reg + word * 2 + 1); - } + int stop = 1; + + reg = sync; + reg |= (glue << 4); + reg |= (++wave << 11); + reg |= (++map << 15); + reg |= (operand << 20) & 0xFFF00000; + __raw_writel(reg, ipu_dc_tmpl_reg + word * 2); + + reg = (operand >> 12); + reg |= opcode << 4; + reg |= (stop << 9); + __raw_writel(reg, ipu_dc_tmpl_reg + word * 2 + 1); } static void _ipu_dc_link_event(int chan, int event, int addr, int priority) @@ -735,26 +723,6 @@ static bool dc_swap; static irqreturn_t dc_irq_handler(int irq, void *dev_id) { struct completion *comp = dev_id; - uint32_t reg; - uint32_t dc_chan; - - if (irq == IPU_IRQ_DC_FC_1) - dc_chan = 1; - else - dc_chan = 5; - - if (!dc_swap) { - reg = __raw_readl(DC_WR_CH_CONF(dc_chan)); - reg &= ~DC_WR_CH_CONF_PROG_TYPE_MASK; - __raw_writel(reg, DC_WR_CH_CONF(dc_chan)); - - reg = __raw_readl(IPU_DISP_GEN); - if (g_dc_di_assignment[dc_chan]) - reg &= ~DI1_COUNTER_RELEASE; - else - reg &= ~DI0_COUNTER_RELEASE; - __raw_writel(reg, IPU_DISP_GEN); - } complete(comp); return IRQ_HANDLED; @@ -838,6 +806,19 @@ void _ipu_dp_dc_disable(ipu_channel_t channel, bool swap) __raw_writel(reg, DC_WR_CH_CONF(dc_chan)); spin_unlock_irqrestore(&ipu_lock, lock_flags); } else { + spin_lock_irqsave(&ipu_lock, lock_flags); + reg = __raw_readl(DC_WR_CH_CONF(dc_chan)); + reg &= ~DC_WR_CH_CONF_PROG_TYPE_MASK; + __raw_writel(reg, DC_WR_CH_CONF(dc_chan)); + + reg = __raw_readl(IPU_DISP_GEN); + if (g_dc_di_assignment[dc_chan]) + reg &= ~DI1_COUNTER_RELEASE; + else + reg &= ~DI0_COUNTER_RELEASE; + __raw_writel(reg, IPU_DISP_GEN); + + spin_unlock_irqrestore(&ipu_lock, lock_flags); /* Clock is already off because it must be done quickly, but we need to fix the ref count */ clk_disable(g_pixel_clk[g_dc_di_assignment[dc_chan]]); @@ -1062,13 +1043,9 @@ int32_t ipu_init_sync_panel(int disp, uint32_t pixel_clk, dev_dbg(g_ipu_dev, "pixel clk = %d\n", pixel_clk); if (sig.ext_clk) { - /* - * Set the PLL to be an even multiple of the pixel clock. - * Not round div for tvout and ldb. - * Did not consider both DI come from the same ext clk, if - * meet such case, ext clk rate should be set specially. - */ - if (clk_get_usecount(g_pixel_clk[disp]) == 0) { + /* Set the PLL to be an even multiple of the pixel clock. not round div for tvout*/ + if ((clk_get_usecount(g_pixel_clk[0]) == 0) && + (clk_get_usecount(g_pixel_clk[1]) == 0)) { di_parent = clk_get_parent(g_di_clk[disp]); if (strcmp(di_parent->name, "tve_clk") != 0 && strcmp(di_parent->name, "ldb_di0_clk") != 0 && @@ -1117,7 +1094,7 @@ int32_t ipu_init_sync_panel(int disp, uint32_t pixel_clk, di_gen = __raw_readl(DI_GENERAL(disp)); if (sig.interlaced) { - if (g_ipu_hw_rev >= 2) { + if (cpu_is_mx51_rev(CHIP_REV_2_0)) { /* Setup internal HSYNC waveform */ _ipu_di_sync_config( disp, /* display */ @@ -1357,7 +1334,7 @@ int32_t ipu_init_sync_panel(int disp, uint32_t pixel_clk, } /* Init template microcode */ - _ipu_dc_write_tmpl(0, WROD(0), 0, map, SYNC_WAVE, 0, 8, 1); + _ipu_dc_write_tmpl(0, WROD(0), 0, map, SYNC_WAVE, 0, 8); if (sig.Hsync_pol) di_gen |= DI_GEN_POLARITY_3; @@ -1424,27 +1401,27 @@ int32_t ipu_init_sync_panel(int disp, uint32_t pixel_clk, (pixel_fmt == IPU_PIX_FMT_UYVY) || (pixel_fmt == IPU_PIX_FMT_YVYU) || (pixel_fmt == IPU_PIX_FMT_VYUY)) { - _ipu_dc_write_tmpl(8, WROD(0), 0, (map - 1), SYNC_WAVE, 0, 5, 1); - _ipu_dc_write_tmpl(9, WROD(0), 0, map, SYNC_WAVE, 0, 5, 1); + _ipu_dc_write_tmpl(8, WROD(0), 0, (map - 1), SYNC_WAVE, 0, 5); + _ipu_dc_write_tmpl(9, WROD(0), 0, map, SYNC_WAVE, 0, 5); /* configure user events according to DISP NUM */ __raw_writel((width - 1), DC_UGDE_3(disp)); } - _ipu_dc_write_tmpl(2, WROD(0), 0, map, SYNC_WAVE, 8, 5, 1); - _ipu_dc_write_tmpl(3, WRG, 0, map, SYNC_WAVE, 4, 5, 1); - _ipu_dc_write_tmpl(4, WROD(0), 0, map, SYNC_WAVE, 0, 5, 1); + _ipu_dc_write_tmpl(2, WROD(0), 0, map, SYNC_WAVE, 8, 5); + _ipu_dc_write_tmpl(3, WROD(0), 0, map, SYNC_WAVE, 4, 5); + _ipu_dc_write_tmpl(4, WROD(0), 0, map, SYNC_WAVE, 0, 5); } else { if ((pixel_fmt == IPU_PIX_FMT_YUYV) || (pixel_fmt == IPU_PIX_FMT_UYVY) || (pixel_fmt == IPU_PIX_FMT_YVYU) || (pixel_fmt == IPU_PIX_FMT_VYUY)) { - _ipu_dc_write_tmpl(10, WROD(0), 0, (map - 1), SYNC_WAVE, 0, 5, 1); - _ipu_dc_write_tmpl(11, WROD(0), 0, map, SYNC_WAVE, 0, 5, 1); + _ipu_dc_write_tmpl(10, WROD(0), 0, (map - 1), SYNC_WAVE, 0, 5); + _ipu_dc_write_tmpl(11, WROD(0), 0, map, SYNC_WAVE, 0, 5); /* configure user events according to DISP NUM */ __raw_writel(width - 1, DC_UGDE_3(disp)); } - _ipu_dc_write_tmpl(5, WROD(0), 0, map, SYNC_WAVE, 8, 5, 1); - _ipu_dc_write_tmpl(6, WRG, 0, map, SYNC_WAVE, 4, 5, 1); - _ipu_dc_write_tmpl(7, WROD(0), 0, map, SYNC_WAVE, 0, 5, 1); + _ipu_dc_write_tmpl(5, WROD(0), 0, map, SYNC_WAVE, 8, 5); + _ipu_dc_write_tmpl(6, WROD(0), 0, map, SYNC_WAVE, 4, 5); + _ipu_dc_write_tmpl(7, WROD(0), 0, map, SYNC_WAVE, 0, 5); } if (sig.Hsync_pol) @@ -1531,7 +1508,7 @@ int ipu_init_async_panel(int disp, int type, uint32_t cycle_time, _ipu_di_data_pin_config(disp, ASYNC_SER_WAVE, DI_PIN_SER_RS, 2, 0, 0); - _ipu_dc_write_tmpl(0x64, WROD(0), 0, map, ASYNC_SER_WAVE, 0, 0, 1); + _ipu_dc_write_tmpl(0x64, WROD(0), 0, map, ASYNC_SER_WAVE, 0, 0); /* Configure DC for serial panel */ __raw_writel(0x14, DC_DISP_CONF1(DC_DISP_ID_SERIAL)); @@ -1808,39 +1785,6 @@ int32_t ipu_disp_set_window_pos(ipu_channel_t channel, int16_t x_pos, } EXPORT_SYMBOL(ipu_disp_set_window_pos); -int32_t ipu_disp_get_window_pos(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) - flow = DP_SYNC; - else if (channel == MEM_FG_ASYNC0) - flow = DP_ASYNC0; - else if (channel == MEM_FG_ASYNC1) - flow = DP_ASYNC1; - else - return -EINVAL; - - if (!g_ipu_clk_enabled) - clk_enable(g_ipu_clk); - spin_lock_irqsave(&ipu_lock, lock_flags); - - reg = __raw_readl(DP_FG_POS(flow)); - - *x_pos = (reg >> 16) & 0x7FF; - *y_pos = reg & 0x7FF; - - spin_unlock_irqrestore(&ipu_lock, lock_flags); - if (!g_ipu_clk_enabled) - clk_disable(g_ipu_clk); - - return 0; -} -EXPORT_SYMBOL(ipu_disp_get_window_pos); - void ipu_disp_direct_write(ipu_channel_t channel, u32 value, u32 offset) { if (channel == DIRECT_ASYNC0) diff --git a/drivers/mxc/ipu3/ipu_regs.h b/drivers/mxc/ipu3/ipu_regs.h index 4a78e14df560..19fde8846aa7 100644 --- a/drivers/mxc/ipu3/ipu_regs.h +++ b/drivers/mxc/ipu3/ipu_regs.h @@ -664,6 +664,5 @@ enum di_sync_wave { /* DC template opcodes */ #define WROD(lf) (0x18 | (lf << 1)) -#define WRG (0x01) #endif |