drm/msm/mdp5: use irqdomains
For mdp5, the irqs of hdmi/eDP/dsi0/dsi1 blocks get routed through the mdp block. In order to decouple hdmi/eDP/etc, register an irq domain in mdp5. When hdmi/dsi/etc are used with mdp4, they can directly setup their irqs in their DT nodes as normal. When used with mdp5, instead set the mdp device as the interrupt-parent, as in: mdp: qcom,mdss_mdp@fd900000 { compatible = "qcom,mdss_mdp"; interrupt-controller; #interrupt-cells = <1>; ... }; hdmi: qcom,hdmi_tx@fd922100 { compatible = "qcom,hdmi-tx-8074"; interrupt-parent = <&mdp>; interrupts = <8 0>; /* MDP5_HW_INTR_STATUS.INTR_HDMI */ ... }; There is a slight awkwardness, in that we cannot disable child irqs at the mdp level, they can only be cleared in the child block. So you must not use threaded irq handlers in the child. I'm not sure if there is a better way to deal with that. Signed-off-by: Rob Clark <robdclark@gmail.com>
This commit is contained in:
@@ -15,6 +15,7 @@
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <linux/of_irq.h>
|
||||
#include "hdmi.h"
|
||||
|
||||
void hdmi_set_mode(struct hdmi *hdmi, bool power_on)
|
||||
@@ -39,7 +40,7 @@ void hdmi_set_mode(struct hdmi *hdmi, bool power_on)
|
||||
power_on ? "Enable" : "Disable", ctrl);
|
||||
}
|
||||
|
||||
irqreturn_t hdmi_irq(int irq, void *dev_id)
|
||||
static irqreturn_t hdmi_irq(int irq, void *dev_id)
|
||||
{
|
||||
struct hdmi *hdmi = dev_id;
|
||||
|
||||
@@ -200,7 +201,6 @@ int hdmi_modeset_init(struct hdmi *hdmi,
|
||||
{
|
||||
struct msm_drm_private *priv = dev->dev_private;
|
||||
struct platform_device *pdev = hdmi->pdev;
|
||||
struct hdmi_platform_config *config = pdev->dev.platform_data;
|
||||
int ret;
|
||||
|
||||
hdmi->dev = dev;
|
||||
@@ -224,22 +224,20 @@ int hdmi_modeset_init(struct hdmi *hdmi,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!config->shared_irq) {
|
||||
hdmi->irq = platform_get_irq(pdev, 0);
|
||||
if (hdmi->irq < 0) {
|
||||
ret = hdmi->irq;
|
||||
dev_err(dev->dev, "failed to get irq: %d\n", ret);
|
||||
goto fail;
|
||||
}
|
||||
hdmi->irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
|
||||
if (hdmi->irq < 0) {
|
||||
ret = hdmi->irq;
|
||||
dev_err(dev->dev, "failed to get irq: %d\n", ret);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = devm_request_threaded_irq(&pdev->dev, hdmi->irq,
|
||||
NULL, hdmi_irq, IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
|
||||
"hdmi_isr", hdmi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev->dev, "failed to request IRQ%u: %d\n",
|
||||
hdmi->irq, ret);
|
||||
goto fail;
|
||||
}
|
||||
ret = devm_request_irq(&pdev->dev, hdmi->irq,
|
||||
hdmi_irq, IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
|
||||
"hdmi_isr", hdmi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev->dev, "failed to request IRQ%u: %d\n",
|
||||
hdmi->irq, ret);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
encoder->bridge = hdmi->bridge;
|
||||
@@ -318,7 +316,6 @@ static int hdmi_bind(struct device *dev, struct device *master, void *data)
|
||||
config.hpd_clk_cnt = ARRAY_SIZE(hpd_clk_names);
|
||||
config.pwr_clk_names = pwr_clk_names;
|
||||
config.pwr_clk_cnt = ARRAY_SIZE(pwr_clk_names);
|
||||
config.shared_irq = true;
|
||||
} else if (of_device_is_compatible(of_node, "qcom,hdmi-tx-8960")) {
|
||||
static const char *hpd_clk_names[] = {"core_clk", "master_iface_clk", "slave_iface_clk"};
|
||||
static const char *hpd_reg_names[] = {"core-vdda", "hdmi-mux"};
|
||||
|
Reference in New Issue
Block a user