summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c49
-rw-r--r--drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h3
2 files changed, 51 insertions, 1 deletions
diff --git a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c
index c377f3759e67..4c70472bd338 100644
--- a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c
+++ b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c
@@ -23,6 +23,7 @@
#include <linux/gpio.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
+#include <linux/irqdomain.h>
#include "sde_kms.h"
#include "sde_connector.h"
@@ -967,6 +968,18 @@ static void _sde_hdmi_connector_irq(struct sde_hdmi *sde_hdmi)
}
}
+static void _sde_hdmi_cec_irq(struct sde_hdmi *sde_hdmi)
+{
+ struct hdmi *hdmi = sde_hdmi->ctrl.ctrl;
+ u32 cec_intr = hdmi_read(hdmi, REG_HDMI_CEC_INT);
+
+ /* Routing interrupt to external CEC drivers */
+ if (cec_intr)
+ generic_handle_irq(irq_find_mapping(
+ sde_hdmi->irq_domain, 1));
+}
+
+
static irqreturn_t _sde_hdmi_irq(int irq, void *dev_id)
{
struct sde_hdmi *sde_hdmi = dev_id;
@@ -987,7 +1000,8 @@ static irqreturn_t _sde_hdmi_irq(int irq, void *dev_id)
if (hdmi->hdcp_ctrl && hdmi->is_hdcp_supported)
hdmi_hdcp_ctrl_irq(hdmi->hdcp_ctrl);
- /* TODO audio.. */
+ /* Process CEC: */
+ _sde_hdmi_cec_irq(sde_hdmi);
return IRQ_HANDLED;
}
@@ -2017,6 +2031,29 @@ static struct platform_driver sde_hdmi_driver = {
},
};
+static int sde_hdmi_irqdomain_map(struct irq_domain *domain,
+ unsigned int irq, irq_hw_number_t hwirq)
+{
+ struct sde_hdmi *display;
+ int rc;
+
+ if (!domain || !domain->host_data) {
+ pr_err("invalid parameters domain\n");
+ return -EINVAL;
+ }
+ display = domain->host_data;
+
+ irq_set_chip_and_handler(irq, &dummy_irq_chip, handle_level_irq);
+ rc = irq_set_chip_data(irq, display);
+
+ return rc;
+}
+
+static const struct irq_domain_ops sde_hdmi_irqdomain_ops = {
+ .map = sde_hdmi_irqdomain_map,
+ .xlate = irq_domain_xlate_onecell,
+};
+
int sde_hdmi_drm_init(struct sde_hdmi *display, struct drm_encoder *enc)
{
int rc = 0;
@@ -2071,6 +2108,13 @@ int sde_hdmi_drm_init(struct sde_hdmi *display, struct drm_encoder *enc)
goto error;
}
+ display->irq_domain = irq_domain_add_linear(pdev->dev.of_node, 8,
+ &sde_hdmi_irqdomain_ops, display);
+ if (!display->irq_domain) {
+ SDE_ERROR("failed to create IRQ domain\n");
+ goto error;
+ }
+
enc->bridge = hdmi->bridge;
priv->bridges[priv->num_bridges++] = hdmi->bridge;
@@ -2096,6 +2140,9 @@ int sde_hdmi_drm_deinit(struct sde_hdmi *display)
return -EINVAL;
}
+ if (display->irq_domain)
+ irq_domain_remove(display->irq_domain);
+
return rc;
}
diff --git a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h
index ffa9a27e7dfe..54506da4f9b0 100644
--- a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h
+++ b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h
@@ -86,6 +86,7 @@ struct sde_hdmi_ctrl {
* @hpd_work: HPD work structure.
* @codec_ready: If audio codec is ready.
* @client_notify_pending: If there is client notification pending.
+ * @irq_domain: IRQ domain structure.
* @root: Debug fs root entry.
*/
struct sde_hdmi {
@@ -114,6 +115,8 @@ struct sde_hdmi {
bool codec_ready;
bool client_notify_pending;
+ struct irq_domain *irq_domain;
+
/* DEBUG FS */
struct dentry *root;
};