diff --git a/drivers/video/fbdev/msm/Makefile b/drivers/video/fbdev/msm/Makefile index 65bc506dabbb..ffe14659ddec 100644 --- a/drivers/video/fbdev/msm/Makefile +++ b/drivers/video/fbdev/msm/Makefile @@ -46,5 +46,5 @@ mdss-qpic-objs := mdss_qpic.o mdss_fb.o mdss_qpic_panel.o obj-$(CONFIG_FB_MSM_QPIC) += mdss-qpic.o obj-$(CONFIG_FB_MSM_QPIC_ILI_QVGA_PANEL) += qpic_panel_ili_qvga.o -obj-$(CONFIG_FB_MSM_MDSS) += mdss_fb.o +obj-$(CONFIG_FB_MSM_MDSS) += mdss_fb.o mdss_util.o obj-$(CONFIG_COMPAT) += mdss_compat_utils.o diff --git a/drivers/video/fbdev/msm/mdss.h b/drivers/video/fbdev/msm/mdss.h index f6bd82ed6f55..952b251ded52 100644 --- a/drivers/video/fbdev/msm/mdss.h +++ b/drivers/video/fbdev/msm/mdss.h @@ -115,6 +115,7 @@ struct mdss_data_type { bool batfet_required; struct regulator *batfet; u32 max_mdp_clk_rate; + struct mdss_util_intf *mdss_util; struct platform_device *pdev; struct dss_io_data mdss_io; @@ -257,15 +258,21 @@ struct mdss_hw { irqreturn_t (*irq_handler)(int irq, void *ptr); }; -int mdss_register_irq(struct mdss_hw *hw); -void mdss_enable_irq(struct mdss_hw *hw); -void mdss_disable_irq(struct mdss_hw *hw); -void mdss_disable_irq_nosync(struct mdss_hw *hw); void mdss_bus_bandwidth_ctrl(int enable); int mdss_iommu_ctrl(int enable); int mdss_bus_scale_set_quota(int client, u64 ab_quota_rt, u64 ab_quota_nrt, u64 ib_quota); +struct mdss_util_intf { + int (*register_irq)(struct mdss_hw *hw); + void (*enable_irq)(struct mdss_hw *hw); + void (*disable_irq)(struct mdss_hw *hw); + void (*disable_irq_nosync)(struct mdss_hw *hw); + int (*irq_dispatch)(u32 hw_ndx, int irq, void *ptr); +}; + +struct mdss_util_intf *mdss_get_util_intf(void); + static inline struct ion_client *mdss_get_ionclient(void) { if (!mdss_res) diff --git a/drivers/video/fbdev/msm/mdss_dsi.c b/drivers/video/fbdev/msm/mdss_dsi.c index d0b64e60837c..50112f767c24 100644 --- a/drivers/video/fbdev/msm/mdss_dsi.c +++ b/drivers/video/fbdev/msm/mdss_dsi.c @@ -1278,6 +1278,13 @@ static int mdss_dsi_ctrl_probe(struct platform_device *pdev) platform_set_drvdata(pdev, ctrl_pdata); } + ctrl_pdata->mdss_util = mdss_get_util_intf(); + if (ctrl_pdata->mdss_util == NULL) { + pr_err("Failed to get mdss utility functions\n"); + rc = -ENODEV; + goto error_no_mem; + } + ctrl_name = of_get_property(pdev->dev.of_node, "label", NULL); if (!ctrl_name) pr_info("%s:%d, DSI Ctrl name not specified\n", diff --git a/drivers/video/fbdev/msm/mdss_dsi.h b/drivers/video/fbdev/msm/mdss_dsi.h index 16f2ceeeb1c4..d2f4f55c945a 100644 --- a/drivers/video/fbdev/msm/mdss_dsi.h +++ b/drivers/video/fbdev/msm/mdss_dsi.h @@ -364,6 +364,7 @@ struct mdss_dsi_ctrl_pdata { int horizontal_idle_cnt; struct panel_horizontal_idle *line_idle; + struct mdss_util_intf *mdss_util; }; struct dsi_status_data { diff --git a/drivers/video/fbdev/msm/mdss_dsi_host.c b/drivers/video/fbdev/msm/mdss_dsi_host.c index acbf8a12cd83..64a2f46fbed2 100644 --- a/drivers/video/fbdev/msm/mdss_dsi_host.c +++ b/drivers/video/fbdev/msm/mdss_dsi_host.c @@ -85,7 +85,7 @@ void mdss_dsi_ctrl_init(struct device *ctrl_dev, ctrl_list[ctrl->ndx] = ctrl; /* keep it */ - if (mdss_register_irq(ctrl->dsi_hw)) + if (ctrl->mdss_util->register_irq(ctrl->dsi_hw)) pr_err("%s: mdss_register_irq failed.\n", __func__); pr_debug("%s: ndx=%d base=%p\n", __func__, ctrl->ndx, ctrl->ctrl_base); @@ -155,7 +155,7 @@ void mdss_dsi_enable_irq(struct mdss_dsi_ctrl_pdata *ctrl, u32 term) } if (ctrl->dsi_irq_mask == 0) { MDSS_XLOG(ctrl->ndx, term); - mdss_enable_irq(ctrl->dsi_hw); + ctrl->mdss_util->enable_irq(ctrl->dsi_hw); pr_debug("%s: IRQ Enable, ndx=%d mask=%x term=%x\n", __func__, ctrl->ndx, (int)ctrl->dsi_irq_mask, (int)term); } @@ -175,7 +175,7 @@ void mdss_dsi_disable_irq(struct mdss_dsi_ctrl_pdata *ctrl, u32 term) ctrl->dsi_irq_mask &= ~term; if (ctrl->dsi_irq_mask == 0) { MDSS_XLOG(ctrl->ndx, term); - mdss_disable_irq(ctrl->dsi_hw); + ctrl->mdss_util->disable_irq(ctrl->dsi_hw); pr_debug("%s: IRQ Disable, ndx=%d mask=%x term=%x\n", __func__, ctrl->ndx, (int)ctrl->dsi_irq_mask, (int)term); } @@ -196,7 +196,7 @@ void mdss_dsi_disable_irq_nosync(struct mdss_dsi_ctrl_pdata *ctrl, u32 term) ctrl->dsi_irq_mask &= ~term; if (ctrl->dsi_irq_mask == 0) { MDSS_XLOG(ctrl->ndx, term); - mdss_disable_irq_nosync(ctrl->dsi_hw); + ctrl->mdss_util->disable_irq_nosync(ctrl->dsi_hw); pr_debug("%s: IRQ Disable, ndx=%d mask=%x term=%x\n", __func__, ctrl->ndx, (int)ctrl->dsi_irq_mask, (int)term); } diff --git a/drivers/video/fbdev/msm/mdss_edp.c b/drivers/video/fbdev/msm/mdss_edp.c index 4031a6442e13..988cd8fa7d69 100644 --- a/drivers/video/fbdev/msm/mdss_edp.c +++ b/drivers/video/fbdev/msm/mdss_edp.c @@ -1011,7 +1011,7 @@ static void mdss_edp_irq_enable(struct mdss_edp_drv_pdata *edp_drv) edp_write(edp_drv->base + 0x30c, edp_drv->mask2); spin_unlock_irqrestore(&edp_drv->lock, flags); - mdss_enable_irq(&mdss_edp_hw); + edp_drv->mdss_util->enable_irq(&mdss_edp_hw); } static void mdss_edp_irq_disable(struct mdss_edp_drv_pdata *edp_drv) @@ -1023,7 +1023,7 @@ static void mdss_edp_irq_disable(struct mdss_edp_drv_pdata *edp_drv) edp_write(edp_drv->base + 0x30c, 0x0); spin_unlock_irqrestore(&edp_drv->lock, flags); - mdss_disable_irq(&mdss_edp_hw); + edp_drv->mdss_util->disable_irq(&mdss_edp_hw); } static int mdss_edp_irq_setup(struct mdss_edp_drv_pdata *edp_drv) @@ -1070,7 +1070,7 @@ static int mdss_edp_irq_setup(struct mdss_edp_drv_pdata *edp_drv) mdss_edp_hw.ptr = (void *)(edp_drv); - if (mdss_register_irq(&mdss_edp_hw)) + if (edp_drv->mdss_util->register_irq(&mdss_edp_hw)) pr_err("%s: mdss_register_irq failed.\n", __func__); @@ -1116,6 +1116,12 @@ static int mdss_edp_probe(struct platform_device *pdev) return -ENOMEM; } + edp_drv->mdss_util = mdss_get_util_intf(); + if (edp_drv->mdss_util == NULL) { + pr_err("Failed to get mdss utility functions\n"); + return -ENODEV; + } + edp_drv->pdev = pdev; edp_drv->pdev->id = 1; edp_drv->clk_on = 0; diff --git a/drivers/video/fbdev/msm/mdss_edp.h b/drivers/video/fbdev/msm/mdss_edp.h index 7ce525c4e191..cd83c382a227 100644 --- a/drivers/video/fbdev/msm/mdss_edp.h +++ b/drivers/video/fbdev/msm/mdss_edp.h @@ -273,6 +273,7 @@ struct mdss_edp_drv_pdata { u32 mask2; struct mdss_panel_data panel_data; + struct mdss_util_intf *mdss_util; int edp_on_cnt; int edp_off_cnt; diff --git a/drivers/video/fbdev/msm/mdss_hdmi_tx.c b/drivers/video/fbdev/msm/mdss_hdmi_tx.c index 28a09318d4ce..6777a16463ca 100644 --- a/drivers/video/fbdev/msm/mdss_hdmi_tx.c +++ b/drivers/video/fbdev/msm/mdss_hdmi_tx.c @@ -2920,7 +2920,7 @@ static void hdmi_tx_hpd_off(struct hdmi_tx_ctrl *hdmi_ctrl) /* Turn off HPD interrupts */ DSS_REG_W(io, HDMI_HPD_INT_CTRL, 0); - mdss_disable_irq(&hdmi_tx_hw); + hdmi_ctrl->mdss_util->disable_irq(&hdmi_tx_hw); hdmi_tx_set_mode(hdmi_ctrl, false); @@ -2979,7 +2979,7 @@ static int hdmi_tx_hpd_on(struct hdmi_tx_ctrl *hdmi_ctrl) DSS_REG_W(io, HDMI_USEC_REFTIMER, 0x0001001B); - mdss_enable_irq(&hdmi_tx_hw); + hdmi_ctrl->mdss_util->enable_irq(&hdmi_tx_hw); hdmi_ctrl->hpd_initialized = true; @@ -3420,7 +3420,7 @@ static int hdmi_tx_register_panel(struct hdmi_tx_ctrl *hdmi_ctrl) return rc; } - rc = mdss_register_irq(&hdmi_tx_hw); + rc = hdmi_ctrl->mdss_util->register_irq(&hdmi_tx_hw); if (rc) DEV_ERR("%s: mdss_register_irq failed.\n", __func__); @@ -4021,6 +4021,13 @@ static int hdmi_tx_probe(struct platform_device *pdev) hdmi_ctrl->video_resolution = vic; } + hdmi_ctrl->mdss_util = mdss_get_util_intf(); + if (hdmi_ctrl->mdss_util == NULL) { + pr_err("Failed to get mdss utility functions\n"); + rc = -ENODEV; + goto failed_res_init; + } + rc = hdmi_tx_init_resource(hdmi_ctrl); if (rc) { DEV_ERR("%s: FAILED: resource init. rc=%d\n", diff --git a/drivers/video/fbdev/msm/mdss_hdmi_tx.h b/drivers/video/fbdev/msm/mdss_hdmi_tx.h index 73658fd6d370..2bab0eeb8c55 100644 --- a/drivers/video/fbdev/msm/mdss_hdmi_tx.h +++ b/drivers/video/fbdev/msm/mdss_hdmi_tx.h @@ -62,6 +62,8 @@ struct hdmi_tx_ctrl { struct platform_device *pdev; struct hdmi_tx_platform_data pdata; struct mdss_panel_data panel_data; + struct mdss_util_intf *mdss_util; + struct hdmi_tx_pinctrl pin_res; struct hdmi_audio audio_data; diff --git a/drivers/video/fbdev/msm/mdss_mdp.c b/drivers/video/fbdev/msm/mdss_mdp.c index 0ac0779f5679..b472597930d6 100644 --- a/drivers/video/fbdev/msm/mdss_mdp.c +++ b/drivers/video/fbdev/msm/mdss_mdp.c @@ -151,9 +151,6 @@ static struct msm_bus_scale_pdata mdp_reg_bus_scale_table = { .name = "mdss_reg", }; -static DEFINE_SPINLOCK(mdss_lock); -struct mdss_hw *mdss_irq_handlers[MDSS_MAX_HW_BLK]; - 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); @@ -229,21 +226,6 @@ u32 mdss_mdp_fb_stride(u32 fb_index, u32 xres, int bpp) return xres * bpp; } -static inline int mdss_irq_dispatch(u32 hw_ndx, int irq, void *ptr) -{ - struct mdss_hw *hw; - int rc = -ENODEV; - - spin_lock(&mdss_lock); - hw = mdss_irq_handlers[hw_ndx]; - spin_unlock(&mdss_lock); - - if (hw) - rc = hw->irq_handler(irq, hw->ptr); - - return rc; -} - static irqreturn_t mdss_irq_handler(int irq, void *ptr) { struct mdss_data_type *mdata = ptr; @@ -256,140 +238,27 @@ static irqreturn_t mdss_irq_handler(int irq, void *ptr) if (intr & MDSS_INTR_MDP) { spin_lock(&mdp_lock); - mdss_irq_dispatch(MDSS_HW_MDP, irq, ptr); + mdata->mdss_util->irq_dispatch(MDSS_HW_MDP, irq, ptr); spin_unlock(&mdp_lock); } if (intr & MDSS_INTR_DSI0) - mdss_irq_dispatch(MDSS_HW_DSI0, irq, ptr); + mdata->mdss_util->irq_dispatch(MDSS_HW_DSI0, irq, ptr); if (intr & MDSS_INTR_DSI1) - mdss_irq_dispatch(MDSS_HW_DSI1, irq, ptr); + mdata->mdss_util->irq_dispatch(MDSS_HW_DSI1, irq, ptr); if (intr & MDSS_INTR_EDP) - mdss_irq_dispatch(MDSS_HW_EDP, irq, ptr); + mdata->mdss_util->irq_dispatch(MDSS_HW_EDP, irq, ptr); if (intr & MDSS_INTR_HDMI) - mdss_irq_dispatch(MDSS_HW_HDMI, irq, ptr); + mdata->mdss_util->irq_dispatch(MDSS_HW_HDMI, irq, ptr); mdata->irq_buzy = false; return IRQ_HANDLED; } -int mdss_register_irq(struct mdss_hw *hw) -{ - unsigned long irq_flags; - u32 ndx_bit; - - if (!hw || hw->hw_ndx >= MDSS_MAX_HW_BLK) - return -EINVAL; - - ndx_bit = BIT(hw->hw_ndx); - - spin_lock_irqsave(&mdss_lock, irq_flags); - if (!mdss_irq_handlers[hw->hw_ndx]) - mdss_irq_handlers[hw->hw_ndx] = hw; - else - pr_err("panel %d's irq at %p is already registered\n", - hw->hw_ndx, hw->irq_handler); - spin_unlock_irqrestore(&mdss_lock, irq_flags); - - return 0; -} /* mdss_regsiter_irq */ -EXPORT_SYMBOL(mdss_register_irq); - -void mdss_enable_irq(struct mdss_hw *hw) -{ - unsigned long irq_flags; - u32 ndx_bit; - - if (hw->hw_ndx >= MDSS_MAX_HW_BLK) - return; - - if (!mdss_irq_handlers[hw->hw_ndx]) { - pr_err("failed. First register the irq then enable it.\n"); - return; - } - - ndx_bit = BIT(hw->hw_ndx); - - pr_debug("Enable HW=%d irq ena=%d mask=%x\n", hw->hw_ndx, - mdss_res->irq_ena, mdss_res->irq_mask); - - spin_lock_irqsave(&mdss_lock, irq_flags); - if (mdss_res->irq_mask & ndx_bit) { - pr_debug("MDSS HW ndx=%d is already set, mask=%x\n", - hw->hw_ndx, mdss_res->irq_mask); - } else { - mdss_res->irq_mask |= ndx_bit; - if (!mdss_res->irq_ena) { - mdss_res->irq_ena = true; - enable_irq(mdss_res->irq); - } - } - spin_unlock_irqrestore(&mdss_lock, irq_flags); -} -EXPORT_SYMBOL(mdss_enable_irq); - -void mdss_disable_irq(struct mdss_hw *hw) -{ - unsigned long irq_flags; - u32 ndx_bit; - - if (hw->hw_ndx >= MDSS_MAX_HW_BLK) - return; - - ndx_bit = BIT(hw->hw_ndx); - - pr_debug("Disable HW=%d irq ena=%d mask=%x\n", hw->hw_ndx, - mdss_res->irq_ena, mdss_res->irq_mask); - - spin_lock_irqsave(&mdss_lock, irq_flags); - if (!(mdss_res->irq_mask & ndx_bit)) { - pr_warn("MDSS HW ndx=%d is NOT set, mask=%x, hist mask=%x\n", - hw->hw_ndx, mdss_res->mdp_irq_mask, - mdss_res->mdp_hist_irq_mask); - } else { - mdss_res->irq_mask &= ~ndx_bit; - if (mdss_res->irq_mask == 0) { - mdss_res->irq_ena = false; - disable_irq_nosync(mdss_res->irq); - } - } - spin_unlock_irqrestore(&mdss_lock, irq_flags); -} -EXPORT_SYMBOL(mdss_disable_irq); - -/* called from interrupt context */ -void mdss_disable_irq_nosync(struct mdss_hw *hw) -{ - u32 ndx_bit; - - if (hw->hw_ndx >= MDSS_MAX_HW_BLK) - return; - - ndx_bit = BIT(hw->hw_ndx); - - pr_debug("Disable HW=%d irq ena=%d mask=%x\n", hw->hw_ndx, - mdss_res->irq_ena, mdss_res->irq_mask); - - spin_lock(&mdss_lock); - if (!(mdss_res->irq_mask & ndx_bit)) { - pr_warn("MDSS HW ndx=%d is NOT set, mask=%x, hist mask=%x\n", - hw->hw_ndx, mdss_res->mdp_irq_mask, - mdss_res->mdp_hist_irq_mask); - } else { - mdss_res->irq_mask &= ~ndx_bit; - if (mdss_res->irq_mask == 0) { - mdss_res->irq_ena = false; - disable_irq_nosync(mdss_res->irq); - } - } - spin_unlock(&mdss_lock); -} -EXPORT_SYMBOL(mdss_disable_irq_nosync); - static int mdss_mdp_bus_scale_register(struct mdss_data_type *mdata) { struct msm_bus_scale_pdata *reg_bus_pdata; @@ -577,7 +446,7 @@ int mdss_mdp_irq_enable(u32 intr_type, u32 intf_num) MDSS_MDP_REG_INTR_CLEAR); writel_relaxed(mdata->mdp_irq_mask, mdata->mdp_base + MDSS_MDP_REG_INTR_EN); - mdss_enable_irq(&mdss_mdp_hw); + mdata->mdss_util->enable_irq(&mdss_mdp_hw); } spin_unlock_irqrestore(&mdp_lock, irq_flags); @@ -602,7 +471,7 @@ int mdss_mdp_hist_irq_enable(u32 irq) MDSS_MDP_REG_HIST_INTR_CLEAR); writel_relaxed(mdata->mdp_hist_irq_mask, mdata->mdp_base + MDSS_MDP_REG_HIST_INTR_EN); - mdss_enable_irq(&mdss_mdp_hw); + mdata->mdss_util->enable_irq(&mdss_mdp_hw); } spin_unlock_irqrestore(&mdp_lock, irq_flags); @@ -628,7 +497,7 @@ void mdss_mdp_irq_disable(u32 intr_type, u32 intf_num) MDSS_MDP_REG_INTR_EN); if ((mdata->mdp_irq_mask == 0) && (mdata->mdp_hist_irq_mask == 0)) - mdss_disable_irq(&mdss_mdp_hw); + mdata->mdss_util->disable_irq(&mdss_mdp_hw); } spin_unlock_irqrestore(&mdp_lock, irq_flags); } @@ -648,7 +517,7 @@ void mdss_mdp_hist_irq_disable(u32 irq) MDSS_MDP_REG_HIST_INTR_EN); if ((mdata->mdp_irq_mask == 0) && (mdata->mdp_hist_irq_mask == 0)) - mdss_disable_irq(&mdss_mdp_hw); + mdata->mdss_util->disable_irq(&mdss_mdp_hw); } spin_unlock_irqrestore(&mdp_lock, irq_flags); } @@ -679,7 +548,7 @@ void mdss_mdp_irq_disable_nosync(u32 intr_type, u32 intf_num) MDSS_MDP_REG_INTR_EN); if ((mdata->mdp_irq_mask == 0) && (mdata->mdp_hist_irq_mask == 0)) - mdss_disable_irq_nosync(&mdss_mdp_hw); + mdata->mdss_util->disable_irq_nosync(&mdss_mdp_hw); } } @@ -1514,6 +1383,12 @@ static int mdss_mdp_probe(struct platform_device *pdev) atomic_set(&mdata->sd_client_count, 0); atomic_set(&mdata->active_intf_cnt, 0); + mdss_res->mdss_util = mdss_get_util_intf(); + if (mdss_res->mdss_util == NULL) { + pr_err("Failed to get mdss utility functions\n"); + return -ENODEV; + } + rc = msm_dss_ioremap_byname(pdev, &mdata->mdss_io, "mdp_phys"); if (rc) { pr_err("unable to map MDP base\n"); @@ -1596,7 +1471,7 @@ static int mdss_mdp_probe(struct platform_device *pdev) if (rc) pr_err("unable to register mdp instance\n"); - rc = mdss_register_irq(&mdss_mdp_hw); + rc = mdss_res->mdss_util->register_irq(&mdss_mdp_hw); if (rc) pr_err("mdss_register_irq failed.\n"); diff --git a/drivers/video/fbdev/msm/mdss_util.c b/drivers/video/fbdev/msm/mdss_util.c new file mode 100644 index 000000000000..f09bbd0da87b --- /dev/null +++ b/drivers/video/fbdev/msm/mdss_util.c @@ -0,0 +1,158 @@ + +/* Copyright (c) 2007-2014, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#define pr_fmt(fmt) "%s: " fmt, __func__ + +#include +#include "mdss_mdp.h" + +struct mdss_hw *mdss_irq_handlers[MDSS_MAX_HW_BLK]; +static DEFINE_SPINLOCK(mdss_lock); + +int mdss_register_irq(struct mdss_hw *hw) +{ + unsigned long irq_flags; + u32 ndx_bit; + + if (!hw || hw->hw_ndx >= MDSS_MAX_HW_BLK) + return -EINVAL; + + ndx_bit = BIT(hw->hw_ndx); + + spin_lock_irqsave(&mdss_lock, irq_flags); + if (!mdss_irq_handlers[hw->hw_ndx]) + mdss_irq_handlers[hw->hw_ndx] = hw; + else + pr_err("panel %d's irq at %p is already registered\n", + hw->hw_ndx, hw->irq_handler); + spin_unlock_irqrestore(&mdss_lock, irq_flags); + + return 0; +} + +void mdss_enable_irq(struct mdss_hw *hw) +{ + unsigned long irq_flags; + u32 ndx_bit; + + if (hw->hw_ndx >= MDSS_MAX_HW_BLK) + return; + + if (!mdss_irq_handlers[hw->hw_ndx]) { + pr_err("failed. First register the irq then enable it.\n"); + return; + } + + ndx_bit = BIT(hw->hw_ndx); + + pr_debug("Enable HW=%d irq ena=%d mask=%x\n", hw->hw_ndx, + mdss_res->irq_ena, mdss_res->irq_mask); + + spin_lock_irqsave(&mdss_lock, irq_flags); + if (mdss_res->irq_mask & ndx_bit) { + pr_debug("MDSS HW ndx=%d is already set, mask=%x\n", + hw->hw_ndx, mdss_res->irq_mask); + } else { + mdss_res->irq_mask |= ndx_bit; + if (!mdss_res->irq_ena) { + mdss_res->irq_ena = true; + enable_irq(mdss_res->irq); + } + } + spin_unlock_irqrestore(&mdss_lock, irq_flags); +} + +void mdss_disable_irq(struct mdss_hw *hw) +{ + unsigned long irq_flags; + u32 ndx_bit; + + if (hw->hw_ndx >= MDSS_MAX_HW_BLK) + return; + + ndx_bit = BIT(hw->hw_ndx); + + pr_debug("Disable HW=%d irq ena=%d mask=%x\n", hw->hw_ndx, + mdss_res->irq_ena, mdss_res->irq_mask); + + spin_lock_irqsave(&mdss_lock, irq_flags); + if (!(mdss_res->irq_mask & ndx_bit)) { + pr_warn("MDSS HW ndx=%d is NOT set, mask=%x, hist mask=%x\n", + hw->hw_ndx, mdss_res->mdp_irq_mask, + mdss_res->mdp_hist_irq_mask); + } else { + mdss_res->irq_mask &= ~ndx_bit; + if (mdss_res->irq_mask == 0) { + mdss_res->irq_ena = false; + disable_irq_nosync(mdss_res->irq); + } + } + spin_unlock_irqrestore(&mdss_lock, irq_flags); +} + +/* called from interrupt context */ +void mdss_disable_irq_nosync(struct mdss_hw *hw) +{ + u32 ndx_bit; + + if (hw->hw_ndx >= MDSS_MAX_HW_BLK) + return; + + ndx_bit = BIT(hw->hw_ndx); + + pr_debug("Disable HW=%d irq ena=%d mask=%x\n", hw->hw_ndx, + mdss_res->irq_ena, mdss_res->irq_mask); + + spin_lock(&mdss_lock); + if (!(mdss_res->irq_mask & ndx_bit)) { + pr_warn("MDSS HW ndx=%d is NOT set, mask=%x, hist mask=%x\n", + hw->hw_ndx, mdss_res->mdp_irq_mask, + mdss_res->mdp_hist_irq_mask); + } else { + mdss_res->irq_mask &= ~ndx_bit; + if (mdss_res->irq_mask == 0) { + mdss_res->irq_ena = false; + disable_irq_nosync(mdss_res->irq); + } + } + spin_unlock(&mdss_lock); +} + +int mdss_irq_dispatch(u32 hw_ndx, int irq, void *ptr) +{ + struct mdss_hw *hw; + int rc = -ENODEV; + + spin_lock(&mdss_lock); + hw = mdss_irq_handlers[hw_ndx]; + spin_unlock(&mdss_lock); + + if (hw) + rc = hw->irq_handler(irq, hw->ptr); + + return rc; +} + +struct mdss_util_intf mdss_util = { + mdss_register_irq, + mdss_enable_irq, + mdss_disable_irq, + mdss_disable_irq_nosync, + mdss_irq_dispatch +}; + +struct mdss_util_intf *mdss_get_util_intf() +{ + return &mdss_util; +} +EXPORT_SYMBOL(mdss_get_util_intf);