summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Chen <b02280@freescale.com>2011-08-22 11:06:02 +0800
committerJason Chen <b02280@freescale.com>2011-09-08 12:49:09 +0800
commitad19aef4a80094221b1b826185aea924627e8642 (patch)
tree3d9685df8994f7c85faf4217e137de8dfb4bb015
parent0613f87ecb234aa2f0ba3c392ce6c33fad3601fd (diff)
ENGR00155140 ipuv3: add support of power suspend/resume
add support of power suspend/resume. because IPU has issue of restore current buffer register, this code only work for single buffer mode. Signed-off-by: Jason Chen <b02280@freescale.com>
-rw-r--r--drivers/mxc/ipu3/ipu_common.c199
-rw-r--r--drivers/mxc/ipu3/ipu_prv.h9
2 files changed, 86 insertions, 122 deletions
diff --git a/drivers/mxc/ipu3/ipu_common.c b/drivers/mxc/ipu3/ipu_common.c
index 4ee5d97d6a0e..3e099d9e0f1d 100644
--- a/drivers/mxc/ipu3/ipu_common.c
+++ b/drivers/mxc/ipu3/ipu_common.c
@@ -43,17 +43,6 @@
static struct ipu_soc ipu_array[MXC_IPU_MAX_NUM];
int g_ipu_hw_rev;
-/* for power gating */
-static uint32_t ipu_conf_reg;
-static uint32_t ic_conf_reg;
-static uint32_t ipu_cha_db_mode_reg[4];
-static uint32_t ipu_cha_trb_mode_reg[2];
-static uint32_t ipu_cha_cur_buf_reg[4];
-static uint32_t ipu_cha_triple_cur_buf_reg[4];
-static uint32_t idma_sub_addr_reg[5];
-static uint32_t idma_enable_reg[2];
-static uint32_t buf_ready_reg[10];
-
/* Static functions */
static irqreturn_t ipu_irq_handler(int irq, void *desc);
@@ -2846,90 +2835,74 @@ 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 0
- if (g_ipu_clk_enabled) {
+ if (ipu->ipu_use_count) {
/* save and disable enabled channels*/
- idma_enable_reg[0] = __raw_readl(IDMAC_CHA_EN(0));
- idma_enable_reg[1] = __raw_readl(IDMAC_CHA_EN(32));
- while ((__raw_readl(IDMAC_CHA_BUSY(0)) & idma_enable_reg[0])
- || (__raw_readl(IDMAC_CHA_BUSY(32)) &
- idma_enable_reg[1])) {
+ 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));
+ while ((ipu_idmac_read(ipu, IDMAC_CHA_BUSY(0))
+ & ipu->idma_enable_reg[0])
+ || (ipu_idmac_read(ipu, IDMAC_CHA_BUSY(32))
+ & ipu->idma_enable_reg[1])) {
/* disable channel not busy already */
uint32_t chan_should_disable, timeout = 1000, time = 0;
chan_should_disable =
- __raw_readl(IDMAC_CHA_BUSY(0))
- ^ idma_enable_reg[0];
- __raw_writel((~chan_should_disable) &
- idma_enable_reg[0], IDMAC_CHA_EN(0));
+ ipu_idmac_read(ipu, IDMAC_CHA_BUSY(0))
+ ^ ipu->idma_enable_reg[0];
+ ipu_idmac_write(ipu, (~chan_should_disable) &
+ ipu->idma_enable_reg[0], IDMAC_CHA_EN(0));
chan_should_disable =
- __raw_readl(IDMAC_CHA_BUSY(1))
- ^ idma_enable_reg[1];
- __raw_writel((~chan_should_disable) &
- idma_enable_reg[1], IDMAC_CHA_EN(32));
+ ipu_idmac_read(ipu, IDMAC_CHA_BUSY(1))
+ ^ ipu->idma_enable_reg[1];
+ ipu_idmac_write(ipu, (~chan_should_disable) &
+ ipu->idma_enable_reg[1], IDMAC_CHA_EN(32));
msleep(2);
time += 2;
if (time >= timeout)
return -1;
}
- __raw_writel(0, IDMAC_CHA_EN(0));
- __raw_writel(0, IDMAC_CHA_EN(32));
+ ipu_idmac_write(ipu, 0, IDMAC_CHA_EN(0));
+ ipu_idmac_write(ipu, 0, IDMAC_CHA_EN(32));
/* save double buffer select regs */
- ipu_cha_db_mode_reg[0] = __raw_readl(IPU_CHA_DB_MODE_SEL(0));
- ipu_cha_db_mode_reg[1] = __raw_readl(IPU_CHA_DB_MODE_SEL(32));
- ipu_cha_db_mode_reg[2] =
- __raw_readl(IPU_ALT_CHA_DB_MODE_SEL(0));
- ipu_cha_db_mode_reg[3] =
- __raw_readl(IPU_ALT_CHA_DB_MODE_SEL(32));
+ ipu->cha_db_mode_reg[0] = ipu_cm_read(ipu, IPU_CHA_DB_MODE_SEL(0));
+ ipu->cha_db_mode_reg[1] = ipu_cm_read(ipu, IPU_CHA_DB_MODE_SEL(32));
+ ipu->cha_db_mode_reg[2] =
+ ipu_cm_read(ipu, IPU_ALT_CHA_DB_MODE_SEL(0));
+ ipu->cha_db_mode_reg[3] =
+ ipu_cm_read(ipu, IPU_ALT_CHA_DB_MODE_SEL(32));
/* save triple buffer select regs */
- ipu_cha_trb_mode_reg[0] = __raw_readl(IPU_CHA_TRB_MODE_SEL(0));
- ipu_cha_trb_mode_reg[1] = __raw_readl(IPU_CHA_TRB_MODE_SEL(32));
-
- /* save current buffer regs */
- ipu_cha_cur_buf_reg[0] = __raw_readl(IPU_CHA_CUR_BUF(0));
- ipu_cha_cur_buf_reg[1] = __raw_readl(IPU_CHA_CUR_BUF(32));
- ipu_cha_cur_buf_reg[2] = __raw_readl(IPU_ALT_CUR_BUF0);
- ipu_cha_cur_buf_reg[3] = __raw_readl(IPU_ALT_CUR_BUF1);
-
- /* save current triple buffer regs */
- ipu_cha_triple_cur_buf_reg[0] =
- __raw_readl(IPU_CHA_TRIPLE_CUR_BUF(0));
- ipu_cha_triple_cur_buf_reg[1] =
- __raw_readl(IPU_CHA_TRIPLE_CUR_BUF(32));
- ipu_cha_triple_cur_buf_reg[2] =
- __raw_readl(IPU_CHA_TRIPLE_CUR_BUF(64));
- ipu_cha_triple_cur_buf_reg[3] =
- __raw_readl(IPU_CHA_TRIPLE_CUR_BUF(96));
+ ipu->cha_trb_mode_reg[0] = ipu_cm_read(ipu, IPU_CHA_TRB_MODE_SEL(0));
+ ipu->cha_trb_mode_reg[1] = ipu_cm_read(ipu, IPU_CHA_TRB_MODE_SEL(32));
/* save idamc sub addr regs */
- idma_sub_addr_reg[0] = __raw_readl(IDMAC_SUB_ADDR_0);
- idma_sub_addr_reg[1] = __raw_readl(IDMAC_SUB_ADDR_1);
- idma_sub_addr_reg[2] = __raw_readl(IDMAC_SUB_ADDR_2);
- idma_sub_addr_reg[3] = __raw_readl(IDMAC_SUB_ADDR_3);
- idma_sub_addr_reg[4] = __raw_readl(IDMAC_SUB_ADDR_4);
+ ipu->idma_sub_addr_reg[0] = ipu_idmac_read(ipu, IDMAC_SUB_ADDR_0);
+ ipu->idma_sub_addr_reg[1] = ipu_idmac_read(ipu, IDMAC_SUB_ADDR_1);
+ ipu->idma_sub_addr_reg[2] = ipu_idmac_read(ipu, IDMAC_SUB_ADDR_2);
+ ipu->idma_sub_addr_reg[3] = ipu_idmac_read(ipu, IDMAC_SUB_ADDR_3);
+ ipu->idma_sub_addr_reg[4] = ipu_idmac_read(ipu, IDMAC_SUB_ADDR_4);
/* save sub-modules status and disable all */
- ic_conf_reg = __raw_readl(IC_CONF);
- __raw_writel(0, IC_CONF);
- ipu_conf_reg = __raw_readl(IPU_CONF);
- __raw_writel(0, IPU_CONF);
+ ipu->ic_conf_reg = ipu_ic_read(ipu, IC_CONF);
+ ipu_ic_write(ipu, 0, IC_CONF);
+ ipu->ipu_conf_reg = ipu_cm_read(ipu, IPU_CONF);
+ ipu_cm_write(ipu, 0, IPU_CONF);
/* save buf ready regs */
- buf_ready_reg[0] = __raw_readl(IPU_CHA_BUF0_RDY(0));
- buf_ready_reg[1] = __raw_readl(IPU_CHA_BUF0_RDY(32));
- buf_ready_reg[2] = __raw_readl(IPU_CHA_BUF1_RDY(0));
- buf_ready_reg[3] = __raw_readl(IPU_CHA_BUF1_RDY(32));
- buf_ready_reg[4] = __raw_readl(IPU_ALT_CHA_BUF0_RDY(0));
- buf_ready_reg[5] = __raw_readl(IPU_ALT_CHA_BUF0_RDY(32));
- buf_ready_reg[6] = __raw_readl(IPU_ALT_CHA_BUF1_RDY(0));
- buf_ready_reg[7] = __raw_readl(IPU_ALT_CHA_BUF1_RDY(32));
- buf_ready_reg[8] = __raw_readl(IPU_CHA_BUF2_RDY(0));
- buf_ready_reg[9] = __raw_readl(IPU_CHA_BUF2_RDY(32));
+ ipu->buf_ready_reg[0] = ipu_cm_read(ipu, IPU_CHA_BUF0_RDY(0));
+ ipu->buf_ready_reg[1] = ipu_cm_read(ipu, IPU_CHA_BUF0_RDY(32));
+ ipu->buf_ready_reg[2] = ipu_cm_read(ipu, IPU_CHA_BUF1_RDY(0));
+ ipu->buf_ready_reg[3] = ipu_cm_read(ipu, IPU_CHA_BUF1_RDY(32));
+ ipu->buf_ready_reg[4] = ipu_cm_read(ipu, IPU_ALT_CHA_BUF0_RDY(0));
+ ipu->buf_ready_reg[5] = ipu_cm_read(ipu, IPU_ALT_CHA_BUF0_RDY(32));
+ ipu->buf_ready_reg[6] = ipu_cm_read(ipu, IPU_ALT_CHA_BUF1_RDY(0));
+ ipu->buf_ready_reg[7] = ipu_cm_read(ipu, IPU_ALT_CHA_BUF1_RDY(32));
+ ipu->buf_ready_reg[8] = ipu_cm_read(ipu, IPU_CHA_BUF2_RDY(0));
+ ipu->buf_ready_reg[9] = ipu_cm_read(ipu, IPU_CHA_BUF2_RDY(32));
}
-#endif
if (plat_data->pg)
plat_data->pg(1);
@@ -2940,77 +2913,59 @@ static int ipu_suspend(struct platform_device *pdev, pm_message_t state)
static int ipu_resume(struct platform_device *pdev)
{
struct imx_ipuv3_platform_data *plat_data = pdev->dev.platform_data;
+ struct ipu_soc *ipu = platform_get_drvdata(pdev);
if (plat_data->pg)
plat_data->pg(0);
-#if 0
- if (g_ipu_clk_enabled) {
+ if (ipu->ipu_use_count) {
/* restore buf ready regs */
- __raw_writel(buf_ready_reg[0], IPU_CHA_BUF0_RDY(0));
- __raw_writel(buf_ready_reg[1], IPU_CHA_BUF0_RDY(32));
- __raw_writel(buf_ready_reg[2], IPU_CHA_BUF1_RDY(0));
- __raw_writel(buf_ready_reg[3], IPU_CHA_BUF1_RDY(32));
- __raw_writel(buf_ready_reg[4], IPU_ALT_CHA_BUF0_RDY(0));
- __raw_writel(buf_ready_reg[5], IPU_ALT_CHA_BUF0_RDY(32));
- __raw_writel(buf_ready_reg[6], IPU_ALT_CHA_BUF1_RDY(0));
- __raw_writel(buf_ready_reg[7], IPU_ALT_CHA_BUF1_RDY(32));
- __raw_writel(buf_ready_reg[8], IPU_CHA_BUF2_RDY(0));
- __raw_writel(buf_ready_reg[9], IPU_CHA_BUF2_RDY(32));
+ 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));
+ ipu_cm_write(ipu, ipu->buf_ready_reg[2], IPU_CHA_BUF1_RDY(0));
+ ipu_cm_write(ipu, ipu->buf_ready_reg[3], IPU_CHA_BUF1_RDY(32));
+ ipu_cm_write(ipu, ipu->buf_ready_reg[4], IPU_ALT_CHA_BUF0_RDY(0));
+ ipu_cm_write(ipu, ipu->buf_ready_reg[5], IPU_ALT_CHA_BUF0_RDY(32));
+ ipu_cm_write(ipu, ipu->buf_ready_reg[6], IPU_ALT_CHA_BUF1_RDY(0));
+ ipu_cm_write(ipu, ipu->buf_ready_reg[7], IPU_ALT_CHA_BUF1_RDY(32));
+ ipu_cm_write(ipu, ipu->buf_ready_reg[8], IPU_CHA_BUF2_RDY(0));
+ ipu_cm_write(ipu, ipu->buf_ready_reg[9], IPU_CHA_BUF2_RDY(32));
/* re-enable sub-modules*/
- __raw_writel(ipu_conf_reg, IPU_CONF);
- __raw_writel(ic_conf_reg, IC_CONF);
+ ipu_cm_write(ipu, ipu->ipu_conf_reg, IPU_CONF);
+ ipu_ic_write(ipu, ipu->ic_conf_reg, IC_CONF);
/* restore double buffer select regs */
- __raw_writel(ipu_cha_db_mode_reg[0], IPU_CHA_DB_MODE_SEL(0));
- __raw_writel(ipu_cha_db_mode_reg[1], IPU_CHA_DB_MODE_SEL(32));
- __raw_writel(ipu_cha_db_mode_reg[2],
+ ipu_cm_write(ipu, ipu->cha_db_mode_reg[0], IPU_CHA_DB_MODE_SEL(0));
+ ipu_cm_write(ipu, ipu->cha_db_mode_reg[1], IPU_CHA_DB_MODE_SEL(32));
+ ipu_cm_write(ipu, ipu->cha_db_mode_reg[2],
IPU_ALT_CHA_DB_MODE_SEL(0));
- __raw_writel(ipu_cha_db_mode_reg[3],
+ ipu_cm_write(ipu, ipu->cha_db_mode_reg[3],
IPU_ALT_CHA_DB_MODE_SEL(32));
/* restore triple buffer select regs */
- __raw_writel(ipu_cha_trb_mode_reg[0], IPU_CHA_TRB_MODE_SEL(0));
- __raw_writel(ipu_cha_trb_mode_reg[1], IPU_CHA_TRB_MODE_SEL(32));
-
- /* restore current buffer select regs */
- __raw_writel(~(ipu_cha_cur_buf_reg[0]), IPU_CHA_CUR_BUF(0));
- __raw_writel(~(ipu_cha_cur_buf_reg[1]), IPU_CHA_CUR_BUF(32));
- __raw_writel(~(ipu_cha_cur_buf_reg[2]), IPU_ALT_CUR_BUF0);
- __raw_writel(~(ipu_cha_cur_buf_reg[3]), IPU_ALT_CUR_BUF1);
-
- /* restore triple current buffer select regs */
- __raw_writel(~(ipu_cha_triple_cur_buf_reg[0]),
- IPU_CHA_TRIPLE_CUR_BUF(0));
- __raw_writel(~(ipu_cha_triple_cur_buf_reg[1]),
- IPU_CHA_TRIPLE_CUR_BUF(32));
- __raw_writel(~(ipu_cha_triple_cur_buf_reg[2]),
- IPU_CHA_TRIPLE_CUR_BUF(64));
- __raw_writel(~(ipu_cha_triple_cur_buf_reg[3]),
- IPU_CHA_TRIPLE_CUR_BUF(96));
+ ipu_cm_write(ipu, ipu->cha_trb_mode_reg[0], IPU_CHA_TRB_MODE_SEL(0));
+ ipu_cm_write(ipu, ipu->cha_trb_mode_reg[1], IPU_CHA_TRB_MODE_SEL(32));
/* restore idamc sub addr regs */
- __raw_writel(idma_sub_addr_reg[0], IDMAC_SUB_ADDR_0);
- __raw_writel(idma_sub_addr_reg[1], IDMAC_SUB_ADDR_1);
- __raw_writel(idma_sub_addr_reg[2], IDMAC_SUB_ADDR_2);
- __raw_writel(idma_sub_addr_reg[3], IDMAC_SUB_ADDR_3);
- __raw_writel(idma_sub_addr_reg[4], IDMAC_SUB_ADDR_4);
+ ipu_idmac_write(ipu, ipu->idma_sub_addr_reg[0], IDMAC_SUB_ADDR_0);
+ ipu_idmac_write(ipu, ipu->idma_sub_addr_reg[1], IDMAC_SUB_ADDR_1);
+ ipu_idmac_write(ipu, ipu->idma_sub_addr_reg[2], IDMAC_SUB_ADDR_2);
+ ipu_idmac_write(ipu, ipu->idma_sub_addr_reg[3], IDMAC_SUB_ADDR_3);
+ ipu_idmac_write(ipu, ipu->idma_sub_addr_reg[4], IDMAC_SUB_ADDR_4);
/* restart idma channel*/
- __raw_writel(idma_enable_reg[0], IDMAC_CHA_EN(0));
- __raw_writel(idma_enable_reg[1], IDMAC_CHA_EN(32));
+ ipu_idmac_write(ipu, ipu->idma_enable_reg[0], IDMAC_CHA_EN(0));
+ ipu_idmac_write(ipu, ipu->idma_enable_reg[1], IDMAC_CHA_EN(32));
} else {
- clk_enable(g_ipu_clk);
- _ipu_dmfc_init(dmfc_type_setup, 1);
- _ipu_init_dc_mappings();
-
+ _ipu_get(ipu);
+ _ipu_dmfc_init(ipu, dmfc_type_setup, 1);
+ _ipu_init_dc_mappings(ipu);
/* Set sync refresh channels as high priority */
- __raw_writel(0x18800001L, IDMAC_CHA_PRI(0));
- clk_disable(g_ipu_clk);
+ ipu_idmac_write(ipu, 0x18800001L, IDMAC_CHA_PRI(0));
+ _ipu_put(ipu);
}
-#endif
return 0;
}
diff --git a/drivers/mxc/ipu3/ipu_prv.h b/drivers/mxc/ipu3/ipu_prv.h
index e0d03fa2b7c7..dfb7b38bc44c 100644
--- a/drivers/mxc/ipu3/ipu_prv.h
+++ b/drivers/mxc/ipu3/ipu_prv.h
@@ -111,6 +111,15 @@ struct ipu_soc {
bool dc_swap;
struct completion dc_comp;
+ /* for power gating */
+ u32 ipu_conf_reg;
+ u32 ic_conf_reg;
+ u32 cha_db_mode_reg[4];
+ u32 cha_trb_mode_reg[2];
+ u32 idma_sub_addr_reg[5];
+ u32 idma_enable_reg[2];
+ u32 buf_ready_reg[10];
+
/*ipu processing driver*/
struct list_head task_list[2];
struct mutex task_lock[2];