From 1e1bf68fa5da6cfa19fd06faaea13b37aa0ace12 Mon Sep 17 00:00:00 2001 From: Jeykumar Sankaran Date: Wed, 9 Mar 2016 15:03:00 -0800 Subject: [PATCH] msm: mdss: handle multiple MDP interrupt register sets This change enhances the existing MDP ISR routine handlers to handle multiple MDP register sets. Maintain IRQ handlers and callbacks in a single file. Change-Id: Iea6e77be1eaab5ccf2fd89f7c98e2dd328af7de0 Signed-off-by: Jeykumar Sankaran --- drivers/video/fbdev/msm/mdss.h | 2 +- drivers/video/fbdev/msm/mdss_mdp.c | 387 +++++++++++++++--- drivers/video/fbdev/msm/mdss_mdp.h | 1 + drivers/video/fbdev/msm/mdss_mdp_hwio.h | 23 +- drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c | 81 ++-- drivers/video/fbdev/msm/mdss_mdp_intf_video.c | 31 +- .../video/fbdev/msm/mdss_mdp_intf_writeback.c | 12 +- drivers/video/fbdev/msm/mdss_mdp_util.c | 268 ------------ 8 files changed, 417 insertions(+), 388 deletions(-) diff --git a/drivers/video/fbdev/msm/mdss.h b/drivers/video/fbdev/msm/mdss.h index d9397cc5614d..06f7438814aa 100644 --- a/drivers/video/fbdev/msm/mdss.h +++ b/drivers/video/fbdev/msm/mdss.h @@ -338,7 +338,7 @@ struct mdss_data_type { u32 default_ot_wr_limit; struct irq_domain *irq_domain; - u32 mdp_irq_mask; + u32 *mdp_irq_mask; u32 mdp_hist_irq_mask; int suspend_fs_ena; diff --git a/drivers/video/fbdev/msm/mdss_mdp.c b/drivers/video/fbdev/msm/mdss_mdp.c index 4fad99d5617c..e247596ff782 100644 --- a/drivers/video/fbdev/msm/mdss_mdp.c +++ b/drivers/video/fbdev/msm/mdss_mdp.c @@ -89,6 +89,7 @@ struct msm_mdp_interface mdp5 = { #define MEM_PROTECT_SD_CTRL_FLAT 0x14 static DEFINE_SPINLOCK(mdp_lock); +static DEFINE_SPINLOCK(mdss_mdp_intr_lock); static DEFINE_MUTEX(mdp_clk_lock); static DEFINE_MUTEX(mdp_iommu_ref_cnt_lock); static DEFINE_MUTEX(mdp_fs_idle_pc_lock); @@ -149,6 +150,83 @@ u32 invalid_mdp107_wb_output_fmts[] = { MDP_BGRX_8888, }; +/* + * struct intr_call - array of intr handlers + * @func: intr handler + * @arg: requested argument to the handler + */ +struct intr_callback { + void (*func)(void *); + void *arg; +}; + +/* + * struct mdss_mdp_intr_reg - array of MDP intr register sets + * @clr_off: offset to CLEAR reg + * @en_off: offset to ENABLE reg + * @status_off: offset to STATUS reg + */ +struct mdss_mdp_intr_reg { + u32 clr_off; + u32 en_off; + u32 status_off; +}; + +/* + * struct mdss_mdp_irq - maps each irq with i/f + * @intr_type: type of interface + * @intf_num: i/f the irq is associated with + * @irq_mask: corresponding bit in the reg set + * @reg_idx: which reg set to program + */ +struct mdss_mdp_irq { + u32 intr_type; + u32 intf_num; + u32 irq_mask; + u32 reg_idx; +}; + +static struct mdss_mdp_intr_reg mdp_intr_reg[] = { + { MDSS_MDP_REG_INTR_CLEAR, MDSS_MDP_REG_INTR_EN, + MDSS_MDP_REG_INTR_STATUS }, + { MDSS_MDP_REG_INTR2_CLEAR, MDSS_MDP_REG_INTR2_EN, + MDSS_MDP_REG_INTR2_STATUS } +}; + +static struct mdss_mdp_irq mdp_irq_map[] = { + { MDSS_MDP_IRQ_TYPE_INTF_UNDER_RUN, 1, MDSS_MDP_INTR_INTF_0_UNDERRUN, 0}, + { MDSS_MDP_IRQ_TYPE_INTF_UNDER_RUN, 2, MDSS_MDP_INTR_INTF_1_UNDERRUN, 0}, + { MDSS_MDP_IRQ_TYPE_INTF_UNDER_RUN, 3, MDSS_MDP_INTR_INTF_2_UNDERRUN, 0}, + { MDSS_MDP_IRQ_TYPE_INTF_UNDER_RUN, 4, MDSS_MDP_INTR_INTF_3_UNDERRUN, 0}, + { MDSS_MDP_IRQ_TYPE_INTF_VSYNC, 1, MDSS_MDP_INTR_INTF_0_VSYNC, 0}, + { MDSS_MDP_IRQ_TYPE_INTF_VSYNC, 2, MDSS_MDP_INTR_INTF_1_VSYNC, 0}, + { MDSS_MDP_IRQ_TYPE_INTF_VSYNC, 3, MDSS_MDP_INTR_INTF_2_VSYNC, 0}, + { MDSS_MDP_IRQ_TYPE_INTF_VSYNC, 4, MDSS_MDP_INTR_INTF_3_VSYNC, 0}, + { MDSS_MDP_IRQ_TYPE_PING_PONG_COMP, 0, MDSS_MDP_INTR_PING_PONG_0_DONE, 0}, + { MDSS_MDP_IRQ_TYPE_PING_PONG_COMP, 1, MDSS_MDP_INTR_PING_PONG_1_DONE, 0}, + { MDSS_MDP_IRQ_TYPE_PING_PONG_COMP, 2, MDSS_MDP_INTR_PING_PONG_2_DONE, 0}, + { MDSS_MDP_IRQ_TYPE_PING_PONG_COMP, 3, MDSS_MDP_INTR_PING_PONG_3_DONE, 0}, + { MDSS_MDP_IRQ_TYPE_PING_PONG_RD_PTR, 0, MDSS_MDP_INTR_PING_PONG_0_RD_PTR, 0}, + { MDSS_MDP_IRQ_TYPE_PING_PONG_RD_PTR, 1, MDSS_MDP_INTR_PING_PONG_1_RD_PTR, 0}, + { MDSS_MDP_IRQ_TYPE_PING_PONG_RD_PTR, 2, MDSS_MDP_INTR_PING_PONG_2_RD_PTR, 0}, + { MDSS_MDP_IRQ_TYPE_PING_PONG_RD_PTR, 3, MDSS_MDP_INTR_PING_PONG_3_RD_PTR, 0}, + { MDSS_MDP_IRQ_TYPE_PING_PONG_WR_PTR, 0, MDSS_MDP_INTR_PING_PONG_0_WR_PTR, 0}, + { MDSS_MDP_IRQ_TYPE_PING_PONG_WR_PTR, 1, MDSS_MDP_INTR_PING_PONG_1_WR_PTR, 0}, + { MDSS_MDP_IRQ_TYPE_PING_PONG_WR_PTR, 2, MDSS_MDP_INTR_PING_PONG_2_WR_PTR, 0}, + { MDSS_MDP_IRQ_TYPE_PING_PONG_WR_PTR, 3, MDSS_MDP_INTR_PING_PONG_3_WR_PTR, 0}, + { MDSS_MDP_IRQ_TYPE_WB_ROT_COMP, 0, MDSS_MDP_INTR_WB_0_DONE, 0}, + { MDSS_MDP_IRQ_TYPE_WB_ROT_COMP, 1, MDSS_MDP_INTR_WB_1_DONE, 0}, + { MDSS_MDP_IRQ_TYPE_WB_WFD_COMP, 0, MDSS_MDP_INTR_WB_2_DONE, 0}, + { MDSS_MDP_IRQ_TYPE_PING_PONG_AUTO_REF, 0, MDSS_MDP_INTR_PING_PONG_0_AUTOREFRESH_DONE, 0}, + { MDSS_MDP_IRQ_TYPE_PING_PONG_AUTO_REF, 1, MDSS_MDP_INTR_PING_PONG_1_AUTOREFRESH_DONE, 0}, + { MDSS_MDP_IRQ_TYPE_PING_PONG_AUTO_REF, 2, MDSS_MDP_INTR_PING_PONG_2_AUTOREFRESH_DONE, 0}, + { MDSS_MDP_IRQ_TYPE_PING_PONG_AUTO_REF, 3, MDSS_MDP_INTR_PING_PONG_3_AUTOREFRESH_DONE, 0}, + { MDSS_MDP_IRQ_TYPE_CWB_OVERFLOW, 2, MDSS_MDP_INTR2_PING_PONG_2_CWB_OVERFLOW, 1}, + { MDSS_MDP_IRQ_TYPE_CWB_OVERFLOW, 3, MDSS_MDP_INTR2_PING_PONG_2_CWB_OVERFLOW, 1} +}; + +static struct intr_callback *mdp_intr_cb; + static void mdss_mdp_footswitch_ctrl(struct mdss_data_type *mdata, int on); static int mdss_mdp_parse_dt(struct platform_device *pdev); static int mdss_mdp_parse_dt_pipe(struct platform_device *pdev); @@ -157,9 +235,9 @@ static int mdss_mdp_parse_dt_wb(struct platform_device *pdev); static int mdss_mdp_parse_dt_ctl(struct platform_device *pdev); static int mdss_mdp_parse_dt_video_intf(struct platform_device *pdev); static int mdss_mdp_parse_dt_handler(struct platform_device *pdev, - char *prop_name, u32 *offsets, int len); + char *prop_name, u32 *offsets, int len); static int mdss_mdp_parse_dt_prop_len(struct platform_device *pdev, - char *prop_name); + char *prop_name); static int mdss_mdp_parse_dt_smp(struct platform_device *pdev); static int mdss_mdp_parse_dt_prefill(struct platform_device *pdev); static int mdss_mdp_parse_dt_misc(struct platform_device *pdev); @@ -168,6 +246,21 @@ static int mdss_mdp_parse_dt_ppb_off(struct platform_device *pdev); static int mdss_mdp_parse_dt_cdm(struct platform_device *pdev); static int mdss_mdp_parse_dt_dsc(struct platform_device *pdev); +static inline u32 is_mdp_irq_enabled(void) +{ + struct mdss_data_type *mdata = mdss_mdp_get_mdata(); + int i; + + for (i = 0; i < ARRAY_SIZE(mdp_intr_reg); i++) + if (mdata->mdp_irq_mask[i] != 0) + return 1; + + if (mdata->mdp_hist_irq_mask) + return 1; + + return 0; +} + u32 mdss_mdp_fb_stride(u32 fb_index, u32 xres, int bpp) { /* The adreno GPU hardware requires that the pitch be aligned to @@ -612,12 +705,23 @@ int mdss_update_reg_bus_vote(struct reg_bus_client *bus_client, u32 usecase_ndx) #endif -static inline u32 mdss_mdp_irq_mask(u32 intr_type, u32 intf_num) +static int mdss_mdp_intr2index(u32 intr_type, u32 intf_num) { - if (intr_type == MDSS_MDP_IRQ_INTF_UNDER_RUN || - intr_type == MDSS_MDP_IRQ_INTF_VSYNC) - intf_num = (intf_num - MDSS_MDP_INTF0) * 2; - return 1 << (intr_type + intf_num); + int i; + + for (i = 0; i < ARRAY_SIZE(mdp_irq_map); i++) { + if (intr_type == mdp_irq_map[i].intr_type && + intf_num == mdp_irq_map[i].intf_num) + return i; + } + return -EINVAL; +} + +u32 mdss_mdp_get_irq_mask(u32 intr_type, u32 intf_num) +{ + int idx = mdss_mdp_intr2index(intr_type, intf_num); + + return (idx < 0) ? 0 : mdp_irq_map[idx].irq_mask; } /* function assumes that mdp is clocked to access hw registers */ @@ -625,38 +729,55 @@ void mdss_mdp_irq_clear(struct mdss_data_type *mdata, u32 intr_type, u32 intf_num) { unsigned long irq_flags; - u32 irq; + int irq_idx; + struct mdss_mdp_intr_reg reg; + struct mdss_mdp_irq irq; - irq = mdss_mdp_irq_mask(intr_type, intf_num); + irq_idx = mdss_mdp_intr2index(intr_type, intf_num); + if (irq_idx < 0) { + pr_err("invalid irq request\n"); + return; + } - pr_debug("clearing mdp irq mask=%x\n", irq); + irq = mdp_irq_map[irq_idx]; + reg = mdp_intr_reg[irq.reg_idx]; + + pr_debug("clearing mdp irq mask=%x\n", irq.irq_mask); spin_lock_irqsave(&mdp_lock, irq_flags); - writel_relaxed(irq, mdata->mdp_base + MDSS_MDP_REG_INTR_CLEAR); + writel_relaxed(irq.irq_mask, mdata->mdp_base + reg.clr_off); spin_unlock_irqrestore(&mdp_lock, irq_flags); } int mdss_mdp_irq_enable(u32 intr_type, u32 intf_num) { - u32 irq; + int irq_idx, idx; unsigned long irq_flags; int ret = 0; struct mdss_data_type *mdata = mdss_mdp_get_mdata(); + struct mdss_mdp_intr_reg reg; + struct mdss_mdp_irq irq; - irq = mdss_mdp_irq_mask(intr_type, intf_num); + irq_idx = mdss_mdp_intr2index(intr_type, intf_num); + if (irq_idx < 0) { + pr_err("invalid irq request\n"); + return -EINVAL; + } + + irq = mdp_irq_map[irq_idx]; + reg = mdp_intr_reg[irq.reg_idx]; spin_lock_irqsave(&mdp_lock, irq_flags); - if (mdata->mdp_irq_mask & irq) { + if (mdata->mdp_irq_mask[irq.reg_idx] & irq.irq_mask) { pr_warn("MDSS MDP IRQ-0x%x is already set, mask=%x\n", - irq, mdata->mdp_irq_mask); + irq.irq_mask, mdata->mdp_irq_mask[idx]); ret = -EBUSY; } else { pr_debug("MDP IRQ mask old=%x new=%x\n", - mdata->mdp_irq_mask, irq); - mdata->mdp_irq_mask |= irq; - writel_relaxed(irq, mdata->mdp_base + - MDSS_MDP_REG_INTR_CLEAR); - writel_relaxed(mdata->mdp_irq_mask, mdata->mdp_base + - MDSS_MDP_REG_INTR_EN); + mdata->mdp_irq_mask[irq.reg_idx], irq.irq_mask); + mdata->mdp_irq_mask[irq.reg_idx] |= irq.irq_mask; + writel_relaxed(irq.irq_mask, mdata->mdp_base + reg.clr_off); + writel_relaxed(mdata->mdp_irq_mask[irq.reg_idx], + mdata->mdp_base + reg.en_off); mdata->mdss_util->enable_irq(&mdss_mdp_hw); } spin_unlock_irqrestore(&mdp_lock, irq_flags); @@ -673,7 +794,7 @@ int mdss_mdp_hist_irq_enable(u32 irq) irq, mdata->mdp_hist_irq_mask); ret = -EBUSY; } else { - pr_debug("MDP IRQ mask old=%x new=%x\n", + pr_debug("mask old=%x new=%x\n", mdata->mdp_hist_irq_mask, irq); mdata->mdp_hist_irq_mask |= irq; writel_relaxed(irq, mdata->mdp_base + @@ -688,47 +809,61 @@ int mdss_mdp_hist_irq_enable(u32 irq) void mdss_mdp_irq_disable(u32 intr_type, u32 intf_num) { - u32 irq; + int irq_idx; unsigned long irq_flags; struct mdss_data_type *mdata = mdss_mdp_get_mdata(); + struct mdss_mdp_intr_reg reg; + struct mdss_mdp_irq irq; - irq = mdss_mdp_irq_mask(intr_type, intf_num); + irq_idx = mdss_mdp_intr2index(intr_type, intf_num); + if (irq_idx < 0) { + pr_err("invalid irq request\n"); + return; + } + + irq = mdp_irq_map[irq_idx]; + reg = mdp_intr_reg[irq.reg_idx]; spin_lock_irqsave(&mdp_lock, irq_flags); - if (!(mdata->mdp_irq_mask & irq)) { + if (!(mdata->mdp_irq_mask[irq.reg_idx] & irq.irq_mask)) { pr_warn("MDSS MDP IRQ-%x is NOT set, mask=%x\n", - irq, mdata->mdp_irq_mask); + irq.irq_mask, mdata->mdp_irq_mask[irq.reg_idx]); } else { - mdata->mdp_irq_mask &= ~irq; - - writel_relaxed(mdata->mdp_irq_mask, mdata->mdp_base + - MDSS_MDP_REG_INTR_EN); - if ((mdata->mdp_irq_mask == 0) && - (mdata->mdp_hist_irq_mask == 0)) + mdata->mdp_irq_mask[irq.reg_idx] &= ~irq.irq_mask; + writel_relaxed(mdata->mdp_irq_mask[irq.reg_idx], + mdata->mdp_base + reg.en_off); + if (!is_mdp_irq_enabled()) mdata->mdss_util->disable_irq(&mdss_mdp_hw); } spin_unlock_irqrestore(&mdp_lock, irq_flags); } -/* - * This function is used to check and clear the status of - * INTR and does not handle INTR2 and HIST_INTR - */ +/* This function is used to check and clear the status of MDP interrupts */ void mdss_mdp_intr_check_and_clear(u32 intr_type, u32 intf_num) { - u32 status, irq; + u32 status; + int irq_idx; unsigned long irq_flags; struct mdss_data_type *mdata = mdss_mdp_get_mdata(); + struct mdss_mdp_intr_reg reg; + struct mdss_mdp_irq irq; - irq = mdss_mdp_irq_mask(intr_type, intf_num); + irq_idx = mdss_mdp_intr2index(intr_type, intf_num); + if (irq_idx < 0) { + pr_err("invalid irq request\n"); + return; + } + + irq = mdp_irq_map[irq_idx]; + reg = mdp_intr_reg[irq.reg_idx]; spin_lock_irqsave(&mdp_lock, irq_flags); - status = irq & readl_relaxed(mdata->mdp_base + - MDSS_MDP_REG_INTR_STATUS); + status = irq.irq_mask & readl_relaxed(mdata->mdp_base + + reg.status_off); if (status) { pr_debug("clearing irq: intr_type:%d, intf_num:%d\n", intr_type, intf_num); - writel_relaxed(irq, mdata->mdp_base + MDSS_MDP_REG_INTR_CLEAR); + writel_relaxed(irq.irq_mask, mdata->mdp_base + reg.clr_off); } spin_unlock_irqrestore(&mdp_lock, irq_flags); } @@ -744,8 +879,7 @@ void mdss_mdp_hist_irq_disable(u32 irq) mdata->mdp_hist_irq_mask &= ~irq; writel_relaxed(mdata->mdp_hist_irq_mask, mdata->mdp_base + MDSS_MDP_REG_HIST_INTR_EN); - if ((mdata->mdp_irq_mask == 0) && - (mdata->mdp_hist_irq_mask == 0)) + if (!is_mdp_irq_enabled()) mdata->mdss_util->disable_irq(&mdss_mdp_hw); } } @@ -762,24 +896,163 @@ void mdss_mdp_hist_irq_disable(u32 irq) */ void mdss_mdp_irq_disable_nosync(u32 intr_type, u32 intf_num) { - u32 irq; + int irq_idx; struct mdss_data_type *mdata = mdss_mdp_get_mdata(); + struct mdss_mdp_intr_reg reg; + struct mdss_mdp_irq irq; - irq = mdss_mdp_irq_mask(intr_type, intf_num); + irq_idx = mdss_mdp_intr2index(intr_type, intf_num); + if (irq_idx < 0) { + pr_err("invalid irq request\n"); + return; + } - if (!(mdata->mdp_irq_mask & irq)) { + irq = mdp_irq_map[irq_idx]; + reg = mdp_intr_reg[irq.reg_idx]; + + if (!(mdata->mdp_irq_mask[irq.reg_idx] & irq.irq_mask)) { pr_warn("MDSS MDP IRQ-%x is NOT set, mask=%x\n", - irq, mdata->mdp_irq_mask); + irq.irq_mask, mdata->mdp_irq_mask[irq.reg_idx]); } else { - mdata->mdp_irq_mask &= ~irq; - writel_relaxed(mdata->mdp_irq_mask, mdata->mdp_base + - MDSS_MDP_REG_INTR_EN); - if ((mdata->mdp_irq_mask == 0) && - (mdata->mdp_hist_irq_mask == 0)) + mdata->mdp_irq_mask[irq.reg_idx] &= ~irq.irq_mask; + writel_relaxed(mdata->mdp_irq_mask[irq.reg_idx], + mdata->mdp_base + reg.en_off); + if (!is_mdp_irq_enabled()) mdata->mdss_util->disable_irq_nosync(&mdss_mdp_hw); } } +int mdss_mdp_set_intr_callback(u32 intr_type, u32 intf_num, + void (*fnc_ptr)(void *), void *arg) +{ + unsigned long flags; + int index; + + index = mdss_mdp_intr2index(intr_type, intf_num); + if (index < 0) { + pr_warn("invalid intr type=%u intf_numf_num=%u\n", + intr_type, intf_num); + return -EINVAL; + } + + spin_lock_irqsave(&mdss_mdp_intr_lock, flags); + WARN(mdp_intr_cb[index].func && fnc_ptr, + "replacing current intr callback for ndx=%d\n", index); + mdp_intr_cb[index].func = fnc_ptr; + mdp_intr_cb[index].arg = arg; + spin_unlock_irqrestore(&mdss_mdp_intr_lock, flags); + + return 0; +} + +int mdss_mdp_set_intr_callback_nosync(u32 intr_type, u32 intf_num, + void (*fnc_ptr)(void *), void *arg) +{ + int index; + + index = mdss_mdp_intr2index(intr_type, intf_num); + if (index < 0) { + pr_warn("invalid intr Typee=%u intf_num=%u\n", + intr_type, intf_num); + return -EINVAL; + } + + WARN(mdp_intr_cb[index].func && fnc_ptr, + "replacing current intr callbackack for ndx=%d\n", + index); + mdp_intr_cb[index].func = fnc_ptr; + mdp_intr_cb[index].arg = arg; + + return 0; +} + +static inline void mdss_mdp_intr_done(int index) +{ + void (*fnc)(void *); + void *arg; + + spin_lock(&mdss_mdp_intr_lock); + fnc = mdp_intr_cb[index].func; + arg = mdp_intr_cb[index].arg; + spin_unlock(&mdss_mdp_intr_lock); + if (fnc) + fnc(arg); +} + +irqreturn_t mdss_mdp_isr(int irq, void *ptr) +{ + struct mdss_data_type *mdata = ptr; + u32 isr, mask, hist_isr, hist_mask; + int i, j; + + if (!mdata->clk_ena) + return IRQ_HANDLED; + + for (i = 0; i < ARRAY_SIZE(mdp_intr_reg); i++) { + struct mdss_mdp_intr_reg reg = mdp_intr_reg[i]; + + isr = readl_relaxed(mdata->mdp_base + reg.status_off); + if (isr == 0) + continue; + + mask = readl_relaxed(mdata->mdp_base + reg.en_off); + writel_relaxed(isr, mdata->mdp_base + reg.clr_off); + + pr_debug("%s: reg:%d isr=%x mask=%x\n", + __func__, i+1, isr, mask); + + isr &= mask; + if (isr == 0) + continue; + + for (j = 0; j < ARRAY_SIZE(mdp_irq_map); j++) + if (mdp_irq_map[j].reg_idx == i && + (isr & mdp_irq_map[j].irq_mask)) + mdss_mdp_intr_done(j); + if (!i) { + if (isr & MDSS_MDP_INTR_PING_PONG_0_DONE) + mdss_misr_crc_collect(mdata, DISPLAY_MISR_DSI0, false); + + if (isr & MDSS_MDP_INTR_PING_PONG_1_DONE) + mdss_misr_crc_collect(mdata, DISPLAY_MISR_DSI1, false); + + if (isr & MDSS_MDP_INTR_INTF_0_VSYNC) + mdss_misr_crc_collect(mdata, DISPLAY_MISR_EDP, true); + + if (isr & MDSS_MDP_INTR_INTF_1_VSYNC) + mdss_misr_crc_collect(mdata, DISPLAY_MISR_DSI0, true); + + if (isr & MDSS_MDP_INTR_INTF_2_VSYNC) + mdss_misr_crc_collect(mdata, DISPLAY_MISR_DSI1, true); + + if (isr & MDSS_MDP_INTR_INTF_3_VSYNC) + mdss_misr_crc_collect(mdata, DISPLAY_MISR_HDMI, true); + + if (isr & MDSS_MDP_INTR_WB_0_DONE) + mdss_misr_crc_collect(mdata, DISPLAY_MISR_MDP, true); + + if (isr & MDSS_MDP_INTR_WB_1_DONE) + mdss_misr_crc_collect(mdata, DISPLAY_MISR_MDP, true); + + if (isr & MDSS_MDP_INTR_WB_2_DONE) + mdss_misr_crc_collect(mdata, DISPLAY_MISR_MDP, true); + } + } + + hist_isr = readl_relaxed(mdata->mdp_base + + MDSS_MDP_REG_HIST_INTR_STATUS); + if (hist_isr != 0) { + hist_mask = readl_relaxed(mdata->mdp_base + + MDSS_MDP_REG_HIST_INTR_EN); + writel_relaxed(hist_isr, mdata->mdp_base + + MDSS_MDP_REG_HIST_INTR_CLEAR); + hist_isr &= hist_mask; + if (hist_isr != 0) + mdss_mdp_hist_intr_done(hist_isr); + } + return IRQ_HANDLED; +} + static int mdss_mdp_clk_update(u32 clk_idx, u32 enable) { int ret = -ENODEV; @@ -2366,6 +2639,16 @@ static int mdss_mdp_probe(struct platform_device *pdev) if (!display_on) mdss_mdp_footswitch_ctrl_splash(false); + mdp_intr_cb = kcalloc(ARRAY_SIZE(mdp_irq_map), + sizeof(struct intr_callback), GFP_KERNEL); + if (mdp_intr_cb == NULL) + return -ENOMEM; + + mdss_res->mdp_irq_mask = kcalloc(ARRAY_SIZE(mdp_intr_reg), + sizeof(u32), GFP_KERNEL); + if (mdss_res->mdp_irq_mask == NULL) + return -ENOMEM; + pr_info("mdss version = 0x%x, bootloader display is %s\n", mdata->mdp_rev, display_on ? "on" : "off"); diff --git a/drivers/video/fbdev/msm/mdss_mdp.h b/drivers/video/fbdev/msm/mdss_mdp.h index 30b2e4be940c..a91c8df4fc89 100644 --- a/drivers/video/fbdev/msm/mdss_mdp.h +++ b/drivers/video/fbdev/msm/mdss_mdp.h @@ -1388,6 +1388,7 @@ int mdss_mdp_set_intr_callback(u32 intr_type, u32 intf_num, void (*fnc_ptr)(void *), void *arg); int mdss_mdp_set_intr_callback_nosync(u32 intr_type, u32 intf_num, void (*fnc_ptr)(void *), void *arg); +u32 mdss_mdp_get_irq_mask(u32 intr_type, u32 intf_num); void mdss_mdp_footswitch_ctrl_splash(int on); void mdss_mdp_batfet_ctrl(struct mdss_data_type *mdata, int enable); diff --git a/drivers/video/fbdev/msm/mdss_mdp_hwio.h b/drivers/video/fbdev/msm/mdss_mdp_hwio.h index d98896435d98..27ed5246649f 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_hwio.h +++ b/drivers/video/fbdev/msm/mdss_mdp_hwio.h @@ -60,6 +60,9 @@ static inline u32 mdss_mdp_hwio_mask(struct mdss_mdp_hwio_cfg *cfg, u32 val) #define MDSS_MDP_REG_HW_VERSION 0x0 #define MDSS_MDP_REG_DISP_INTF_SEL 0x00004 +#define MDSS_MDP_REG_INTR2_EN 0x00008 +#define MDSS_MDP_REG_INTR2_STATUS 0x0000C +#define MDSS_MDP_REG_INTR2_CLEAR 0x0002C #define MDSS_MDP_REG_INTR_EN 0x00010 #define MDSS_MDP_REG_INTR_STATUS 0x00014 #define MDSS_MDP_REG_INTR_CLEAR 0x00018 @@ -115,6 +118,9 @@ static inline u32 mdss_mdp_hwio_mask(struct mdss_mdp_hwio_cfg *cfg, u32 val) #define MDSS_MDP_INTR_INTF_3_UNDERRUN BIT(30) #define MDSS_MDP_INTR_INTF_3_VSYNC BIT(31) +#define MDSS_MDP_INTR2_PING_PONG_2_CWB_OVERFLOW BIT(14) +#define MDSS_MDP_INTR2_PING_PONG_3_CWB_OVERFLOW BIT(15) + #define MDSS_MDP_HIST_INTR_VIG_0_DONE BIT(0) #define MDSS_MDP_HIST_INTR_VIG_0_RESET_DONE BIT(1) #define MDSS_MDP_HIST_INTR_VIG_1_DONE BIT(4) @@ -133,14 +139,15 @@ static inline u32 mdss_mdp_hwio_mask(struct mdss_mdp_hwio_cfg *cfg, u32 val) #define MDSS_MDP_HIST_INTR_DSPP_3_RESET_DONE BIT(23) enum mdss_mdp_intr_type { - MDSS_MDP_IRQ_WB_ROT_COMP = 0, - MDSS_MDP_IRQ_WB_WFD = 4, - MDSS_MDP_IRQ_PING_PONG_COMP = 8, - MDSS_MDP_IRQ_PING_PONG_RD_PTR = 12, - MDSS_MDP_IRQ_PING_PONG_WR_PTR = 16, - MDSS_MDP_IRQ_PING_PONG_AUTO_REF = 20, - MDSS_MDP_IRQ_INTF_UNDER_RUN = 24, - MDSS_MDP_IRQ_INTF_VSYNC = 25, + MDSS_MDP_IRQ_TYPE_WB_ROT_COMP, + MDSS_MDP_IRQ_TYPE_WB_WFD_COMP, + MDSS_MDP_IRQ_TYPE_PING_PONG_COMP, + MDSS_MDP_IRQ_TYPE_PING_PONG_RD_PTR, + MDSS_MDP_IRQ_TYPE_PING_PONG_WR_PTR, + MDSS_MDP_IRQ_TYPE_PING_PONG_AUTO_REF, + MDSS_MDP_IRQ_TYPE_INTF_UNDER_RUN, + MDSS_MDP_IRQ_TYPE_INTF_VSYNC, + MDSS_MDP_IRQ_TYPE_CWB_OVERFLOW, }; #define MDSS_MDP_REG_IGC_VIG_BASE 0x200 diff --git a/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c b/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c index 58e84eb7a141..4874e055b274 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c +++ b/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c @@ -1124,10 +1124,11 @@ static void mdss_mdp_cmd_intf_recovery(void *data, int event) spin_lock_irqsave(&ctx->koff_lock, flags); if (reset_done && atomic_add_unless(&ctx->koff_cnt, -1, 0)) { pr_debug("%s: intf_num=%d\n", __func__, ctx->ctl->intf_num); - mdss_mdp_irq_disable_nosync(MDSS_MDP_IRQ_PING_PONG_COMP, + mdss_mdp_irq_disable_nosync(MDSS_MDP_IRQ_TYPE_PING_PONG_COMP, ctx->current_pp_num); - mdss_mdp_set_intr_callback_nosync(MDSS_MDP_IRQ_PING_PONG_COMP, - ctx->current_pp_num, NULL, NULL); + mdss_mdp_set_intr_callback_nosync( + MDSS_MDP_IRQ_TYPE_PING_PONG_COMP, + ctx->current_pp_num, NULL, NULL); if (mdss_mdp_cmd_do_notifier(ctx)) notify_frame_timeout = true; } @@ -1163,9 +1164,9 @@ static void mdss_mdp_cmd_pingpong_done(void *arg) spin_lock(&ctx->koff_lock); - mdss_mdp_irq_disable_nosync(MDSS_MDP_IRQ_PING_PONG_COMP, + mdss_mdp_irq_disable_nosync(MDSS_MDP_IRQ_TYPE_PING_PONG_COMP, ctx->current_pp_num); - mdss_mdp_set_intr_callback_nosync(MDSS_MDP_IRQ_PING_PONG_COMP, + mdss_mdp_set_intr_callback_nosync(MDSS_MDP_IRQ_TYPE_PING_PONG_COMP, ctx->current_pp_num, NULL, NULL); MDSS_XLOG(ctl->num, atomic_read(&ctx->koff_cnt), ctx->current_pp_num); @@ -1237,18 +1238,18 @@ static int mdss_mdp_setup_lineptr(struct mdss_mdp_cmd_ctx *ctx, if (enable) { /* enable clocks and irq */ mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON); - mdss_mdp_irq_enable(MDSS_MDP_IRQ_PING_PONG_WR_PTR, + mdss_mdp_irq_enable(MDSS_MDP_IRQ_TYPE_PING_PONG_WR_PTR, ctx->default_pp_num); } else { /* disable clocks and irq */ - mdss_mdp_irq_disable(MDSS_MDP_IRQ_PING_PONG_WR_PTR, + mdss_mdp_irq_disable(MDSS_MDP_IRQ_TYPE_PING_PONG_WR_PTR, ctx->default_pp_num); /* * check the intr status and clear the irq before * disabling the clocks */ mdss_mdp_intr_check_and_clear( - MDSS_MDP_IRQ_PING_PONG_WR_PTR, + MDSS_MDP_IRQ_TYPE_PING_PONG_WR_PTR, ctx->default_pp_num); mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF); @@ -1392,9 +1393,9 @@ static void mdss_mdp_cmd_autorefresh_pp_done(void *arg) return; } - mdss_mdp_irq_disable_nosync(MDSS_MDP_IRQ_PING_PONG_COMP, + mdss_mdp_irq_disable_nosync(MDSS_MDP_IRQ_TYPE_PING_PONG_COMP, ctx->current_pp_num); - mdss_mdp_set_intr_callback_nosync(MDSS_MDP_IRQ_PING_PONG_COMP, + mdss_mdp_set_intr_callback_nosync(MDSS_MDP_IRQ_TYPE_PING_PONG_COMP, ctx->current_pp_num, NULL, NULL); MDSS_XLOG(ctl->num, atomic_read(&ctx->koff_cnt), ctx->current_pp_num); @@ -1688,18 +1689,18 @@ static int mdss_mdp_setup_vsync(struct mdss_mdp_cmd_ctx *ctx, if (enable) { /* enable clocks and irq */ mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON); - mdss_mdp_irq_enable(MDSS_MDP_IRQ_PING_PONG_RD_PTR, + mdss_mdp_irq_enable(MDSS_MDP_IRQ_TYPE_PING_PONG_RD_PTR, ctx->default_pp_num); } else { /* disable clocks and irq */ - mdss_mdp_irq_disable(MDSS_MDP_IRQ_PING_PONG_RD_PTR, + mdss_mdp_irq_disable(MDSS_MDP_IRQ_TYPE_PING_PONG_RD_PTR, ctx->default_pp_num); /* * check the intr status and clear the irq before * disabling the clocks */ mdss_mdp_intr_check_and_clear( - MDSS_MDP_IRQ_PING_PONG_RD_PTR, + MDSS_MDP_IRQ_TYPE_PING_PONG_RD_PTR, ctx->default_pp_num); mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF); @@ -1864,14 +1865,15 @@ static int mdss_mdp_cmd_wait4pingpong(struct mdss_mdp_ctl *ctl, void *arg) if (rc <= 0) { u32 status, mask; - mask = BIT(MDSS_MDP_IRQ_PING_PONG_COMP + ctx->current_pp_num); + mask = mdss_mdp_get_irq_mask(MDSS_MDP_IRQ_TYPE_PING_PONG_COMP, + ctx->current_pp_num); status = mask & readl_relaxed(ctl->mdata->mdp_base + MDSS_MDP_REG_INTR_STATUS); MDSS_XLOG(status, rc, atomic_read(&ctx->koff_cnt)); if (status) { pr_warn("pp done but irq not triggered\n"); mdss_mdp_irq_clear(ctl->mdata, - MDSS_MDP_IRQ_PING_PONG_COMP, + MDSS_MDP_IRQ_TYPE_PING_PONG_COMP, ctx->current_pp_num); local_irq_save(flags); mdss_mdp_cmd_pingpong_done(ctl); @@ -1902,10 +1904,11 @@ static int mdss_mdp_cmd_wait4pingpong(struct mdss_mdp_ctl *ctl, void *arg) ctx->pp_timeout_report_cnt++; rc = -EPERM; - mdss_mdp_irq_disable_nosync(MDSS_MDP_IRQ_PING_PONG_COMP, + mdss_mdp_irq_disable_nosync(MDSS_MDP_IRQ_TYPE_PING_PONG_COMP, ctx->current_pp_num); - mdss_mdp_set_intr_callback_nosync(MDSS_MDP_IRQ_PING_PONG_COMP, - ctx->current_pp_num, NULL, NULL); + mdss_mdp_set_intr_callback_nosync( + MDSS_MDP_IRQ_TYPE_PING_PONG_COMP, + ctx->current_pp_num, NULL, NULL); if (atomic_add_unless(&ctx->koff_cnt, -1, 0) && mdss_mdp_cmd_do_notifier(ctx)) mdss_mdp_ctl_notify(ctl, MDP_NOTIFY_FRAME_TIMEOUT); @@ -2277,7 +2280,7 @@ static void mdss_mdp_cmd_post_programming(struct mdss_mdp_ctl *mctl) static void mdss_mdp_cmd_wait4_autorefresh_pp(struct mdss_mdp_ctl *ctl) { int rc; - u32 val, line_out, intr_type = MDSS_MDP_IRQ_PING_PONG_COMP; + u32 val, line_out, intr_type = MDSS_MDP_IRQ_TYPE_PING_PONG_COMP; char __iomem *pp_base = ctl->mixer_left->pingpong_base; struct mdss_mdp_cmd_ctx *ctx = ctl->intf_ctx[MASTER_CTX]; @@ -2301,7 +2304,7 @@ static void mdss_mdp_cmd_wait4_autorefresh_pp(struct mdss_mdp_ctl *ctl) MDSS_MDP_REG_PP_LINE_COUNT); if (val == ctl->mixer_left->roi.h) { mdss_mdp_irq_clear(ctl->mdata, - MDSS_MDP_IRQ_PING_PONG_COMP, + MDSS_MDP_IRQ_TYPE_PING_PONG_COMP, ctx->current_pp_num); mdss_mdp_irq_disable_nosync(intr_type, ctx->current_pp_num); @@ -2329,9 +2332,9 @@ static void mdss_mdp_cmd_autorefresh_done(void *arg) return; } - mdss_mdp_irq_disable_nosync(MDSS_MDP_IRQ_PING_PONG_AUTO_REF, + mdss_mdp_irq_disable_nosync(MDSS_MDP_IRQ_TYPE_PING_PONG_AUTO_REF, ctx->current_pp_num); - mdss_mdp_set_intr_callback_nosync(MDSS_MDP_IRQ_PING_PONG_AUTO_REF, + mdss_mdp_set_intr_callback_nosync(MDSS_MDP_IRQ_TYPE_PING_PONG_AUTO_REF, ctx->current_pp_num, NULL, NULL); MDSS_XLOG(ctl->num, atomic_read(&ctx->koff_cnt), ctx->current_pp_num); @@ -2400,9 +2403,9 @@ static void mdss_mdp_cmd_wait4_autorefresh_done(struct mdss_mdp_ctl *ctl) reinit_completion(&ctx->autorefresh_done); /* enable autorefresh done */ - mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_PING_PONG_AUTO_REF, + mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_TYPE_PING_PONG_AUTO_REF, ctx->current_pp_num, mdss_mdp_cmd_autorefresh_done, ctl); - mdss_mdp_irq_enable(MDSS_MDP_IRQ_PING_PONG_AUTO_REF, + mdss_mdp_irq_enable(MDSS_MDP_IRQ_TYPE_PING_PONG_AUTO_REF, ctx->current_pp_num); /* @@ -2420,22 +2423,23 @@ static void mdss_mdp_cmd_wait4_autorefresh_done(struct mdss_mdp_ctl *ctl) if (rc <= 0) { u32 status, mask; - mask = BIT(MDSS_MDP_IRQ_PING_PONG_AUTO_REF + - ctx->current_pp_num); + mask = mdss_mdp_get_irq_mask( + MDSS_MDP_IRQ_TYPE_PING_PONG_AUTO_REF, + ctx->current_pp_num); status = mask & readl_relaxed(ctl->mdata->mdp_base + MDSS_MDP_REG_INTR_STATUS); if (status) { pr_warn("autorefresh done but irq not triggered\n"); mdss_mdp_irq_clear(ctl->mdata, - MDSS_MDP_IRQ_PING_PONG_AUTO_REF, + MDSS_MDP_IRQ_TYPE_PING_PONG_AUTO_REF, ctx->current_pp_num); local_irq_save(flags); mdss_mdp_irq_disable_nosync( - MDSS_MDP_IRQ_PING_PONG_AUTO_REF, + MDSS_MDP_IRQ_TYPE_PING_PONG_AUTO_REF, ctx->current_pp_num); mdss_mdp_set_intr_callback_nosync( - MDSS_MDP_IRQ_PING_PONG_AUTO_REF, + MDSS_MDP_IRQ_TYPE_PING_PONG_AUTO_REF, ctx->current_pp_num, NULL, NULL); local_irq_restore(flags); rc = 1; @@ -2663,13 +2667,14 @@ static int mdss_mdp_cmd_kickoff(struct mdss_mdp_ctl *ctl, void *arg) mdss_mdp_disable_autorefresh(ctl, sctl); } - mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_PING_PONG_COMP, + mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_TYPE_PING_PONG_COMP, ctx->current_pp_num, mdss_mdp_cmd_pingpong_done, ctl); - mdss_mdp_irq_enable(MDSS_MDP_IRQ_PING_PONG_COMP, ctx->current_pp_num); + mdss_mdp_irq_enable(MDSS_MDP_IRQ_TYPE_PING_PONG_COMP, + ctx->current_pp_num); if (sctx) { - mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_PING_PONG_COMP, + mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_TYPE_PING_PONG_COMP, sctx->current_pp_num, mdss_mdp_cmd_pingpong_done, sctl); - mdss_mdp_irq_enable(MDSS_MDP_IRQ_PING_PONG_COMP, + mdss_mdp_irq_enable(MDSS_MDP_IRQ_TYPE_PING_PONG_COMP, sctx->current_pp_num); } @@ -2805,11 +2810,11 @@ int mdss_mdp_cmd_ctx_stop(struct mdss_mdp_ctl *ctl, return 0; } - mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_PING_PONG_RD_PTR, + mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_TYPE_PING_PONG_RD_PTR, ctx->default_pp_num, NULL, NULL); - mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_PING_PONG_WR_PTR, + mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_TYPE_PING_PONG_WR_PTR, ctx->default_pp_num, NULL, NULL); - mdss_mdp_set_intr_callback_nosync(MDSS_MDP_IRQ_PING_PONG_COMP, + mdss_mdp_set_intr_callback_nosync(MDSS_MDP_IRQ_TYPE_PING_PONG_COMP, ctx->default_pp_num, NULL, NULL); memset(ctx, 0, sizeof(*ctx)); @@ -3140,10 +3145,10 @@ static int mdss_mdp_cmd_ctx_setup(struct mdss_mdp_ctl *ctl, default_pp_num, aux_pp_num); MDSS_XLOG(ctl->num, atomic_read(&ctx->koff_cnt)); - mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_PING_PONG_RD_PTR, + mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_TYPE_PING_PONG_RD_PTR, ctx->default_pp_num, mdss_mdp_cmd_readptr_done, ctl); - mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_PING_PONG_WR_PTR, + mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_TYPE_PING_PONG_WR_PTR, ctx->default_pp_num, mdss_mdp_cmd_writeptr_done, ctl); ret = mdss_mdp_cmd_tearcheck_setup(ctx, false); diff --git a/drivers/video/fbdev/msm/mdss_mdp_intf_video.c b/drivers/video/fbdev/msm/mdss_mdp_intf_video.c index 9eae668526e4..4e4caf98ea9f 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_intf_video.c +++ b/drivers/video/fbdev/msm/mdss_mdp_intf_video.c @@ -34,9 +34,6 @@ /* Filter out input events for 1 vsync time after receiving an input event*/ #define INPUT_EVENT_HANDLER_DELAY_USECS 16000 -#define MDP_INTR_MASK_INTF_VSYNC(intf_num) \ - (1 << (2 * (intf_num - MDSS_MDP_INTF0) + MDSS_MDP_IRQ_INTF_VSYNC)) - /* intf timing settings */ struct intf_timing_params { u32 width; @@ -354,9 +351,10 @@ static inline void video_vsync_irq_enable(struct mdss_mdp_ctl *ctl, bool clear) mutex_lock(&ctx->vsync_mtx); if (atomic_inc_return(&ctx->vsync_ref) == 1) - mdss_mdp_irq_enable(MDSS_MDP_IRQ_INTF_VSYNC, ctl->intf_num); + mdss_mdp_irq_enable(MDSS_MDP_IRQ_TYPE_INTF_VSYNC, + ctl->intf_num); else if (clear) - mdss_mdp_irq_clear(ctl->mdata, MDSS_MDP_IRQ_INTF_VSYNC, + mdss_mdp_irq_clear(ctl->mdata, MDSS_MDP_IRQ_TYPE_INTF_VSYNC, ctl->intf_num); mutex_unlock(&ctx->vsync_mtx); } @@ -367,7 +365,8 @@ static inline void video_vsync_irq_disable(struct mdss_mdp_ctl *ctl) mutex_lock(&ctx->vsync_mtx); if (atomic_dec_return(&ctx->vsync_ref) == 0) - mdss_mdp_irq_disable(MDSS_MDP_IRQ_INTF_VSYNC, ctl->intf_num); + mdss_mdp_irq_disable(MDSS_MDP_IRQ_TYPE_INTF_VSYNC, + ctl->intf_num); mutex_unlock(&ctx->vsync_mtx); } @@ -450,11 +449,11 @@ void mdss_mdp_turn_off_time_engine(struct mdss_mdp_ctl *ctl, mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF); ctx->timegen_en = false; - mdss_mdp_irq_disable(MDSS_MDP_IRQ_INTF_UNDER_RUN, ctl->intf_num); + mdss_mdp_irq_disable(MDSS_MDP_IRQ_TYPE_INTF_UNDER_RUN, ctl->intf_num); sctl = mdss_mdp_get_split_ctl(ctl); if (sctl) - mdss_mdp_irq_disable(MDSS_MDP_IRQ_INTF_UNDER_RUN, + mdss_mdp_irq_disable(MDSS_MDP_IRQ_TYPE_INTF_UNDER_RUN, sctl->intf_num); } @@ -489,9 +488,9 @@ static int mdss_mdp_video_ctx_stop(struct mdss_mdp_ctl *ctl, mdss_bus_bandwidth_ctrl(false); } - mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_INTF_VSYNC, + mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_TYPE_INTF_VSYNC, ctx->intf_num, NULL, NULL); - mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_INTF_UNDER_RUN, + mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_TYPE_INTF_UNDER_RUN, ctx->intf_num, NULL, NULL); ctx->ref_cnt--; @@ -614,7 +613,8 @@ static int mdss_mdp_video_pollwait(struct mdss_mdp_ctl *ctl) u32 mask, status; int rc; - mask = MDP_INTR_MASK_INTF_VSYNC(ctl->intf_num); + mask = mdss_mdp_get_irq_mask(MDSS_MDP_IRQ_TYPE_INTF_VSYNC, + ctl->intf_num); mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON); rc = readl_poll_timeout(ctl->mdata->mdp_base + MDSS_MDP_REG_INTR_STATUS, @@ -1140,10 +1140,11 @@ static int mdss_mdp_video_display(struct mdss_mdp_ctl *ctl, void *arg) mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON); - mdss_mdp_irq_enable(MDSS_MDP_IRQ_INTF_UNDER_RUN, ctl->intf_num); + mdss_mdp_irq_enable(MDSS_MDP_IRQ_TYPE_INTF_UNDER_RUN, + ctl->intf_num); sctl = mdss_mdp_get_split_ctl(ctl); if (sctl) - mdss_mdp_irq_enable(MDSS_MDP_IRQ_INTF_UNDER_RUN, + mdss_mdp_irq_enable(MDSS_MDP_IRQ_TYPE_INTF_UNDER_RUN, sctl->intf_num); mdss_bus_bandwidth_ctrl(true); @@ -1447,10 +1448,10 @@ static int mdss_mdp_video_ctx_setup(struct mdss_mdp_ctl *ctl, if (pinfo->compression_mode == COMPRESSION_DSC) dsc = &pinfo->dsc; - mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_INTF_VSYNC, + mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_TYPE_INTF_VSYNC, ctx->intf_num, mdss_mdp_video_vsync_intr_done, ctl); - mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_INTF_UNDER_RUN, + mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_TYPE_INTF_UNDER_RUN, ctx->intf_num, mdss_mdp_video_underrun_intr_done, ctl); diff --git a/drivers/video/fbdev/msm/mdss_mdp_intf_writeback.c b/drivers/video/fbdev/msm/mdss_mdp_intf_writeback.c index e019bcf6eeaf..5d9d8f45a965 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_intf_writeback.c +++ b/drivers/video/fbdev/msm/mdss_mdp_intf_writeback.c @@ -76,7 +76,7 @@ struct mdss_mdp_writeback_ctx { static struct mdss_mdp_writeback_ctx wb_ctx_list[MDSS_MDP_MAX_WRITEBACK] = { { .type = MDSS_MDP_WRITEBACK_TYPE_ROTATOR, - .intr_type = MDSS_MDP_IRQ_WB_ROT_COMP, + .intr_type = MDSS_MDP_IRQ_TYPE_WB_ROT_COMP, .intf_num = 0, .xin_id = 3, .clk_ctrl.reg_off = 0x2BC, @@ -84,7 +84,7 @@ static struct mdss_mdp_writeback_ctx wb_ctx_list[MDSS_MDP_MAX_WRITEBACK] = { }, { .type = MDSS_MDP_WRITEBACK_TYPE_ROTATOR, - .intr_type = MDSS_MDP_IRQ_WB_ROT_COMP, + .intr_type = MDSS_MDP_IRQ_TYPE_WB_ROT_COMP, .intf_num = 1, .xin_id = 11, .clk_ctrl.reg_off = 0x2BC, @@ -92,7 +92,7 @@ static struct mdss_mdp_writeback_ctx wb_ctx_list[MDSS_MDP_MAX_WRITEBACK] = { }, { .type = MDSS_MDP_WRITEBACK_TYPE_LINE, - .intr_type = MDSS_MDP_IRQ_WB_ROT_COMP, + .intr_type = MDSS_MDP_IRQ_TYPE_WB_ROT_COMP, .intf_num = 0, .xin_id = 3, .clk_ctrl.reg_off = 0x2BC, @@ -100,7 +100,7 @@ static struct mdss_mdp_writeback_ctx wb_ctx_list[MDSS_MDP_MAX_WRITEBACK] = { }, { .type = MDSS_MDP_WRITEBACK_TYPE_LINE, - .intr_type = MDSS_MDP_IRQ_WB_ROT_COMP, + .intr_type = MDSS_MDP_IRQ_TYPE_WB_ROT_COMP, .intf_num = 1, .xin_id = 11, .clk_ctrl.reg_off = 0x2BC, @@ -108,7 +108,7 @@ static struct mdss_mdp_writeback_ctx wb_ctx_list[MDSS_MDP_MAX_WRITEBACK] = { }, { .type = MDSS_MDP_WRITEBACK_TYPE_WFD, - .intr_type = MDSS_MDP_IRQ_WB_WFD, + .intr_type = MDSS_MDP_IRQ_TYPE_WB_WFD_COMP, .intf_num = 0, .xin_id = 6, .clk_ctrl.reg_off = 0x2BC, @@ -889,7 +889,7 @@ int mdss_mdp_writeback_start(struct mdss_mdp_ctl *ctl) /* WB2 Intr Enable is BIT(2) in MDSS 1.8.0 */ if (ctl->mdata->mdp_rev == MDSS_MDP_HW_REV_108) { - ctx->intr_type = MDSS_MDP_IRQ_WB_ROT_COMP; + ctx->intr_type = MDSS_MDP_IRQ_TYPE_WB_ROT_COMP; ctx->intf_num = 2; } } diff --git a/drivers/video/fbdev/msm/mdss_mdp_util.c b/drivers/video/fbdev/msm/mdss_mdp_util.c index 2d173647422b..20bbfcedaad4 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_util.c +++ b/drivers/video/fbdev/msm/mdss_mdp_util.c @@ -32,274 +32,6 @@ #define PHY_ADDR_4G (1ULL<<32) -enum { - MDP_INTR_VSYNC_INTF_0, - MDP_INTR_VSYNC_INTF_1, - MDP_INTR_VSYNC_INTF_2, - MDP_INTR_VSYNC_INTF_3, - MDP_INTR_UNDERRUN_INTF_0, - MDP_INTR_UNDERRUN_INTF_1, - MDP_INTR_UNDERRUN_INTF_2, - MDP_INTR_UNDERRUN_INTF_3, - MDP_INTR_PING_PONG_0, - MDP_INTR_PING_PONG_1, - MDP_INTR_PING_PONG_2, - MDP_INTR_PING_PONG_3, - MDP_INTR_PING_PONG_0_RD_PTR, - MDP_INTR_PING_PONG_1_RD_PTR, - MDP_INTR_PING_PONG_2_RD_PTR, - MDP_INTR_PING_PONG_3_RD_PTR, - MDP_INTR_PING_PONG_0_WR_PTR, - MDP_INTR_PING_PONG_1_WR_PTR, - MDP_INTR_PING_PONG_2_WR_PTR, - MDP_INTR_PING_PONG_3_WR_PTR, - MDP_INTR_WB_0, - MDP_INTR_WB_1, - MDP_INTR_WB_2, - MDP_INTR_PING_PONG_0_AUTO_REF, - MDP_INTR_PING_PONG_1_AUTO_REF, - MDP_INTR_PING_PONG_2_AUTO_REF, - MDP_INTR_PING_PONG_3_AUTO_REF, - MDP_INTR_MAX, -}; - -struct intr_callback { - void (*func)(void *); - void *arg; -}; - -struct intr_callback mdp_intr_cb[MDP_INTR_MAX]; -static DEFINE_SPINLOCK(mdss_mdp_intr_lock); - -static int mdss_mdp_intr2index(u32 intr_type, u32 intf_num) -{ - int index = -1; - switch (intr_type) { - case MDSS_MDP_IRQ_INTF_UNDER_RUN: - index = MDP_INTR_UNDERRUN_INTF_0 + (intf_num - MDSS_MDP_INTF0); - break; - case MDSS_MDP_IRQ_INTF_VSYNC: - index = MDP_INTR_VSYNC_INTF_0 + (intf_num - MDSS_MDP_INTF0); - break; - case MDSS_MDP_IRQ_PING_PONG_COMP: - index = MDP_INTR_PING_PONG_0 + intf_num; - break; - case MDSS_MDP_IRQ_PING_PONG_RD_PTR: - index = MDP_INTR_PING_PONG_0_RD_PTR + intf_num; - break; - case MDSS_MDP_IRQ_PING_PONG_WR_PTR: - index = MDP_INTR_PING_PONG_0_WR_PTR + intf_num; - break; - case MDSS_MDP_IRQ_WB_ROT_COMP: - index = MDP_INTR_WB_0 + intf_num; - break; - case MDSS_MDP_IRQ_WB_WFD: - index = MDP_INTR_WB_2 + intf_num; - break; - case MDSS_MDP_IRQ_PING_PONG_AUTO_REF: - index = MDP_INTR_PING_PONG_0_AUTO_REF + intf_num; - break; - } - - return index; -} - -int mdss_mdp_set_intr_callback(u32 intr_type, u32 intf_num, - void (*fnc_ptr)(void *), void *arg) -{ - unsigned long flags; - int index; - - index = mdss_mdp_intr2index(intr_type, intf_num); - if (index < 0) { - pr_warn("invalid intr type=%u intf_num=%u\n", - intr_type, intf_num); - return -EINVAL; - } - - spin_lock_irqsave(&mdss_mdp_intr_lock, flags); - WARN(mdp_intr_cb[index].func && fnc_ptr, - "replacing current intr callback for ndx=%d\n", index); - mdp_intr_cb[index].func = fnc_ptr; - mdp_intr_cb[index].arg = arg; - spin_unlock_irqrestore(&mdss_mdp_intr_lock, flags); - - return 0; -} - -int mdss_mdp_set_intr_callback_nosync(u32 intr_type, u32 intf_num, - void (*fnc_ptr)(void *), void *arg) -{ - int index; - - index = mdss_mdp_intr2index(intr_type, intf_num); - if (index < 0) { - pr_warn("invalid intr type=%u intf_num=%u\n", - intr_type, intf_num); - return -EINVAL; - } - - WARN(mdp_intr_cb[index].func && fnc_ptr, - "replacing current intr callback for ndx=%d\n", index); - mdp_intr_cb[index].func = fnc_ptr; - mdp_intr_cb[index].arg = arg; - - return 0; -} - -static inline void mdss_mdp_intr_done(int index) -{ - void (*fnc)(void *); - void *arg; - - spin_lock(&mdss_mdp_intr_lock); - fnc = mdp_intr_cb[index].func; - arg = mdp_intr_cb[index].arg; - spin_unlock(&mdss_mdp_intr_lock); - if (fnc) - fnc(arg); -} - -irqreturn_t mdss_mdp_isr(int irq, void *ptr) -{ - struct mdss_data_type *mdata = ptr; - u32 isr, mask, hist_isr, hist_mask; - - if (!mdata->clk_ena) - return IRQ_HANDLED; - - isr = readl_relaxed(mdata->mdp_base + MDSS_MDP_REG_INTR_STATUS); - - if (isr == 0) - goto mdp_isr_done; - - - mask = readl_relaxed(mdata->mdp_base + MDSS_MDP_REG_INTR_EN); - writel_relaxed(isr, mdata->mdp_base + MDSS_MDP_REG_INTR_CLEAR); - - pr_debug("%s: isr=%x mask=%x\n", __func__, isr, mask); - - isr &= mask; - if (isr == 0) - goto mdp_isr_done; - - if (isr & MDSS_MDP_INTR_INTF_0_UNDERRUN) - mdss_mdp_intr_done(MDP_INTR_UNDERRUN_INTF_0); - - if (isr & MDSS_MDP_INTR_INTF_1_UNDERRUN) - mdss_mdp_intr_done(MDP_INTR_UNDERRUN_INTF_1); - - if (isr & MDSS_MDP_INTR_INTF_2_UNDERRUN) - mdss_mdp_intr_done(MDP_INTR_UNDERRUN_INTF_2); - - if (isr & MDSS_MDP_INTR_INTF_3_UNDERRUN) - mdss_mdp_intr_done(MDP_INTR_UNDERRUN_INTF_3); - - if (isr & MDSS_MDP_INTR_PING_PONG_0_DONE) { - mdss_mdp_intr_done(MDP_INTR_PING_PONG_0); - mdss_misr_crc_collect(mdata, DISPLAY_MISR_DSI0, false); - } - - if (isr & MDSS_MDP_INTR_PING_PONG_1_DONE) { - mdss_mdp_intr_done(MDP_INTR_PING_PONG_1); - mdss_misr_crc_collect(mdata, DISPLAY_MISR_DSI1, false); - } - - if (isr & MDSS_MDP_INTR_PING_PONG_2_DONE) - mdss_mdp_intr_done(MDP_INTR_PING_PONG_2); - - if (isr & MDSS_MDP_INTR_PING_PONG_3_DONE) - mdss_mdp_intr_done(MDP_INTR_PING_PONG_3); - - if (isr & MDSS_MDP_INTR_PING_PONG_0_RD_PTR) - mdss_mdp_intr_done(MDP_INTR_PING_PONG_0_RD_PTR); - - if (isr & MDSS_MDP_INTR_PING_PONG_1_RD_PTR) - mdss_mdp_intr_done(MDP_INTR_PING_PONG_1_RD_PTR); - - if (isr & MDSS_MDP_INTR_PING_PONG_2_RD_PTR) - mdss_mdp_intr_done(MDP_INTR_PING_PONG_2_RD_PTR); - - if (isr & MDSS_MDP_INTR_PING_PONG_3_RD_PTR) - mdss_mdp_intr_done(MDP_INTR_PING_PONG_3_RD_PTR); - - if (isr & MDSS_MDP_INTR_PING_PONG_0_WR_PTR) - mdss_mdp_intr_done(MDP_INTR_PING_PONG_0_WR_PTR); - - if (isr & MDSS_MDP_INTR_PING_PONG_1_WR_PTR) - mdss_mdp_intr_done(MDP_INTR_PING_PONG_1_WR_PTR); - - if (isr & MDSS_MDP_INTR_PING_PONG_2_WR_PTR) - mdss_mdp_intr_done(MDP_INTR_PING_PONG_2_WR_PTR); - - if (isr & MDSS_MDP_INTR_PING_PONG_3_WR_PTR) - mdss_mdp_intr_done(MDP_INTR_PING_PONG_3_WR_PTR); - - if (isr & MDSS_MDP_INTR_INTF_0_VSYNC) { - mdss_mdp_intr_done(MDP_INTR_VSYNC_INTF_0); - mdss_misr_crc_collect(mdata, DISPLAY_MISR_EDP, true); - } - - if (isr & MDSS_MDP_INTR_INTF_1_VSYNC) { - mdss_mdp_intr_done(MDP_INTR_VSYNC_INTF_1); - mdss_misr_crc_collect(mdata, DISPLAY_MISR_DSI0, true); - } - - if (isr & MDSS_MDP_INTR_INTF_2_VSYNC) { - mdss_mdp_intr_done(MDP_INTR_VSYNC_INTF_2); - mdss_misr_crc_collect(mdata, DISPLAY_MISR_DSI1, true); - } - - if (isr & MDSS_MDP_INTR_INTF_3_VSYNC) { - mdss_mdp_intr_done(MDP_INTR_VSYNC_INTF_3); - mdss_misr_crc_collect(mdata, DISPLAY_MISR_HDMI, true); - } - - if (isr & MDSS_MDP_INTR_WB_0_DONE) { - mdss_mdp_intr_done(MDP_INTR_WB_0); - mdss_misr_crc_collect(mdata, DISPLAY_MISR_MDP, true); - } - - if (isr & MDSS_MDP_INTR_WB_1_DONE) { - mdss_mdp_intr_done(MDP_INTR_WB_1); - mdss_misr_crc_collect(mdata, DISPLAY_MISR_MDP, true); - } - - if (isr & ((mdata->mdp_rev == MDSS_MDP_HW_REV_108) ? - MDSS_MDP_INTR_WB_2_DONE >> 2 : MDSS_MDP_INTR_WB_2_DONE)) { - mdss_mdp_intr_done(MDP_INTR_WB_2); - mdss_misr_crc_collect(mdata, DISPLAY_MISR_MDP, true); - } - - if (isr & MDSS_MDP_INTR_PING_PONG_0_AUTOREFRESH_DONE) - mdss_mdp_intr_done(MDP_INTR_PING_PONG_0_AUTO_REF); - - if (isr & MDSS_MDP_INTR_PING_PONG_1_AUTOREFRESH_DONE) - mdss_mdp_intr_done(MDP_INTR_PING_PONG_1_AUTO_REF); - - if (isr & MDSS_MDP_INTR_PING_PONG_2_AUTOREFRESH_DONE) - mdss_mdp_intr_done(MDP_INTR_PING_PONG_2_AUTO_REF); - - if (isr & MDSS_MDP_INTR_PING_PONG_3_AUTOREFRESH_DONE) - mdss_mdp_intr_done(MDP_INTR_PING_PONG_3_AUTO_REF); - -mdp_isr_done: - hist_isr = readl_relaxed(mdata->mdp_base + - MDSS_MDP_REG_HIST_INTR_STATUS); - if (hist_isr == 0) - goto hist_isr_done; - hist_mask = readl_relaxed(mdata->mdp_base + - MDSS_MDP_REG_HIST_INTR_EN); - writel_relaxed(hist_isr, mdata->mdp_base + - MDSS_MDP_REG_HIST_INTR_CLEAR); - hist_isr &= hist_mask; - if (hist_isr == 0) - goto hist_isr_done; - mdss_mdp_hist_intr_done(hist_isr); -hist_isr_done: - return IRQ_HANDLED; -} - void mdss_mdp_format_flag_removal(u32 *table, u32 num, u32 remove_bits) { struct mdss_mdp_format_params *fmt = NULL;