Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 852c8bf6 authored by Alan Kwong's avatar Alan Kwong Committed by Gerrit - the friendly Code Review server
Browse files

msm: mdss: Enable export of mdss interrupt to external driver



Add linear irq domain to export top level mdss interrupts.
External driver can connect to exported interrupt specified
in device tree.  The exported interrupt will be routed via
irq domain in mdss interrupt handler.

CRs-Fixed: 972833
Change-Id: Id47aa5629fd0e1343a067d589642bba07f351d05
Signed-off-by: default avatarAlan Kwong <akwong@codeaurora.org>
parent 1c10389d
Loading
Loading
Loading
Loading
+3 −0
Original line number Original line Diff line number Diff line
@@ -20,6 +20,7 @@
#include <linux/types.h>
#include <linux/types.h>
#include <linux/workqueue.h>
#include <linux/workqueue.h>
#include <linux/irqreturn.h>
#include <linux/irqreturn.h>
#include <linux/irqdomain.h>
#include <linux/mdss_io_util.h>
#include <linux/mdss_io_util.h>


#include <linux/msm-bus.h>
#include <linux/msm-bus.h>
@@ -128,6 +129,7 @@ enum mdss_hw_index {
	MDSS_HW_DSI1,
	MDSS_HW_DSI1,
	MDSS_HW_HDMI,
	MDSS_HW_HDMI,
	MDSS_HW_EDP,
	MDSS_HW_EDP,
	MDSS_HW_MISC,
	MDSS_MAX_HW_BLK
	MDSS_MAX_HW_BLK
};
};


@@ -292,6 +294,7 @@ struct mdss_data_type {
	u32 default_ot_rd_limit;
	u32 default_ot_rd_limit;
	u32 default_ot_wr_limit;
	u32 default_ot_wr_limit;


	struct irq_domain *irq_domain;
	u32 mdp_irq_mask;
	u32 mdp_irq_mask;
	u32 mdp_hist_irq_mask;
	u32 mdp_hist_irq_mask;


+101 −4
Original line number Original line Diff line number Diff line
@@ -40,6 +40,8 @@
#include <linux/semaphore.h>
#include <linux/semaphore.h>
#include <linux/uaccess.h>
#include <linux/uaccess.h>
#include <linux/clk/msm-clk.h>
#include <linux/clk/msm-clk.h>
#include <linux/irqdomain.h>
#include <linux/irq.h>


#include <linux/msm-bus.h>
#include <linux/msm-bus.h>
#include <linux/msm-bus-board.h>
#include <linux/msm-bus-board.h>
@@ -108,6 +110,13 @@ struct mdss_hw mdss_mdp_hw = {
	.irq_handler = mdss_mdp_isr,
	.irq_handler = mdss_mdp_isr,
};
};


/* define for h/w block with external driver */
struct mdss_hw mdss_misc_hw = {
	.hw_ndx = MDSS_HW_MISC,
	.ptr = NULL,
	.irq_handler = NULL,
};

#define MDP_REG_BUS_VECTOR_ENTRY(ab_val, ib_val)	\
#define MDP_REG_BUS_VECTOR_ENTRY(ab_val, ib_val)	\
	{						\
	{						\
		.src = MSM_BUS_MASTER_AMPSS_M0,		\
		.src = MSM_BUS_MASTER_AMPSS_M0,		\
@@ -174,6 +183,62 @@ u32 mdss_mdp_fb_stride(u32 fb_index, u32 xres, int bpp)
		return xres * bpp;
		return xres * bpp;
}
}


static void mdss_irq_mask(struct irq_data *data)
{
	struct mdss_data_type *mdata = irq_data_get_irq_chip_data(data);
	unsigned long irq_flags;

	if (!mdata)
		return;

	pr_debug("irq_domain_mask %lu\n", data->hwirq);

	if (data->hwirq < 32) {
		spin_lock_irqsave(&mdp_lock, irq_flags);
		mdata->mdss_util->disable_irq(&mdss_misc_hw);
		spin_unlock_irqrestore(&mdp_lock, irq_flags);
	}
}

static void mdss_irq_unmask(struct irq_data *data)
{
	struct mdss_data_type *mdata = irq_data_get_irq_chip_data(data);
	unsigned long irq_flags;

	if (!mdata)
		return;

	pr_debug("irq_domain_unmask %lu\n", data->hwirq);

	if (data->hwirq < 32) {
		spin_lock_irqsave(&mdp_lock, irq_flags);
		mdata->mdss_util->enable_irq(&mdss_misc_hw);
		spin_unlock_irqrestore(&mdp_lock, irq_flags);
	}
}

static struct irq_chip mdss_irq_chip = {
	.name		= "mdss",
	.irq_mask	= mdss_irq_mask,
	.irq_unmask	= mdss_irq_unmask,
};

static int mdss_irq_domain_map(struct irq_domain *d,
		unsigned int virq, irq_hw_number_t hw)
{
	struct mdss_data_type *mdata = d->host_data;
	/* check here if virq is a valid interrupt line */
	irq_set_chip_and_handler(virq, &mdss_irq_chip, handle_level_irq);
	irq_set_chip_data(virq, mdata);
	set_irq_flags(virq, IRQF_VALID);
	return 0;
}

static struct irq_domain_ops mdss_irq_domain_ops = {
	.map = mdss_irq_domain_map,
	.xlate = irq_domain_xlate_onecell,
};

static irqreturn_t mdss_irq_handler(int irq, void *ptr)
static irqreturn_t mdss_irq_handler(int irq, void *ptr)
{
{
	struct mdss_data_type *mdata = ptr;
	struct mdss_data_type *mdata = ptr;
@@ -192,19 +257,37 @@ static irqreturn_t mdss_irq_handler(int irq, void *ptr)
		spin_lock(&mdp_lock);
		spin_lock(&mdp_lock);
		mdata->mdss_util->irq_dispatch(MDSS_HW_MDP, irq, ptr);
		mdata->mdss_util->irq_dispatch(MDSS_HW_MDP, irq, ptr);
		spin_unlock(&mdp_lock);
		spin_unlock(&mdp_lock);
		intr &= ~MDSS_INTR_MDP;
	}
	}


	if (intr & MDSS_INTR_DSI0)
	if (intr & MDSS_INTR_DSI0) {
		mdata->mdss_util->irq_dispatch(MDSS_HW_DSI0, irq, ptr);
		mdata->mdss_util->irq_dispatch(MDSS_HW_DSI0, irq, ptr);
		intr &= ~MDSS_INTR_DSI0;
	}


	if (intr & MDSS_INTR_DSI1)
	if (intr & MDSS_INTR_DSI1) {
		mdata->mdss_util->irq_dispatch(MDSS_HW_DSI1, irq, ptr);
		mdata->mdss_util->irq_dispatch(MDSS_HW_DSI1, irq, ptr);
		intr &= ~MDSS_INTR_DSI1;
	}


	if (intr & MDSS_INTR_EDP)
	if (intr & MDSS_INTR_EDP) {
		mdata->mdss_util->irq_dispatch(MDSS_HW_EDP, irq, ptr);
		mdata->mdss_util->irq_dispatch(MDSS_HW_EDP, irq, ptr);
		intr &= ~MDSS_INTR_EDP;
	}


	if (intr & MDSS_INTR_HDMI)
	if (intr & MDSS_INTR_HDMI) {
		mdata->mdss_util->irq_dispatch(MDSS_HW_HDMI, irq, ptr);
		mdata->mdss_util->irq_dispatch(MDSS_HW_HDMI, irq, ptr);
		intr &= ~MDSS_INTR_HDMI;
	}

	/* route misc. interrupts to external drivers */
	while (intr) {
		irq_hw_number_t hwirq = fls(intr) - 1;

		generic_handle_irq(irq_find_mapping(
				mdata->irq_domain, hwirq));
		intr &= ~(1 << hwirq);
	}


	mdss_mdp_hw.irq_info->irq_buzy = false;
	mdss_mdp_hw.irq_info->irq_buzy = false;


@@ -1959,6 +2042,20 @@ static int mdss_mdp_probe(struct platform_device *pdev)
	mdss_mdp_hw.irq_info->irq = res->start;
	mdss_mdp_hw.irq_info->irq = res->start;
	mdss_mdp_hw.ptr = mdata;
	mdss_mdp_hw.ptr = mdata;


	/* export misc. interrupts to external driver */
	mdata->irq_domain = irq_domain_add_linear(pdev->dev.of_node, 32,
			&mdss_irq_domain_ops, mdata);
	if (!mdata->irq_domain) {
		pr_err("unable to add linear domain\n");
		rc = -ENOMEM;
		goto probe_done;
	}

	mdss_misc_hw.irq_info = mdss_intr_line();
	rc = mdss_res->mdss_util->register_irq(&mdss_misc_hw);
	if (rc)
		pr_err("mdss_register_irq failed.\n");

	/*populate hw iomem base info from device tree*/
	/*populate hw iomem base info from device tree*/
	rc = mdss_mdp_parse_dt(pdev);
	rc = mdss_mdp_parse_dt(pdev);
	if (rc) {
	if (rc) {