summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorAndrzej Hajda <a.hajda@samsung.com>2015-07-08 11:16:24 +0200
committerSeung-Woo Kim <sw0312.kim@samsung.com>2016-12-14 13:46:38 +0900
commit0238d6991bb7afc650e63b6370d042f5b4de72c8 (patch)
tree9991b8f0b6e26d5f62ed8df7d4fcc9ade994c604 /drivers
parent0ca2a8c1b191a36a89b2fc69bed56efeaebbfa32 (diff)
drm/exynos/hdmi: add MHL bridge support
Signed-off-by: Andrzej Hajda <a.hajda@samsung.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/exynos/exynos_hdmi.c51
1 files changed, 42 insertions, 9 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c
index 61922fe7a46f..a834feefc93d 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
@@ -34,6 +34,7 @@
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_gpio.h>
+#include <linux/of_graph.h>
#include <linux/hdmi.h>
#include <linux/component.h>
#include <linux/mfd/syscon.h>
@@ -236,6 +237,7 @@ struct hdmi_context {
struct regmap *sysreg;
enum hdmi_type type;
struct hdmi_driver_data *drv_data;
+ struct drm_bridge *bridge;
};
static inline struct hdmi_context *display_to_hdmi(struct exynos_drm_display *d)
@@ -1298,7 +1300,15 @@ static int hdmi_create_connector(struct exynos_drm_display *display,
drm_connector_register(connector);
drm_mode_connector_attach_encoder(connector, encoder);
- return 0;
+ if (hdata->bridge) {
+ encoder->bridge = hdata->bridge;
+ hdata->bridge->encoder = encoder;
+ ret = drm_bridge_attach(encoder->dev, hdata->bridge);
+ if (ret)
+ DRM_ERROR("Failed to attach bridge\n");
+ }
+
+ return ret;
}
static void hdmi_mode_fixup(struct exynos_drm_display *display,
@@ -2446,6 +2456,33 @@ static int hdmi_clk_init(struct hdmi_context *hdata)
return ret;
}
+static int hdmi_bridge_init(struct hdmi_context *hdata)
+{
+ struct device *dev = hdata->dev;
+ struct device_node *ep, *np;
+
+ ep = of_graph_get_endpoint_by_regs(dev->of_node, 1, -1);
+ if (!ep)
+ return 0;
+ dev_err(dev, "ep=%s\n", ep->full_name);
+
+ np = of_graph_get_remote_port_parent(ep);
+ of_node_put(ep);
+ if (!np) {
+ DRM_ERROR("failed to get remote port parent");
+ return -EINVAL;
+ }
+
+ dev_err(dev, "np=%s\n", np->full_name);
+ hdata->bridge = of_drm_find_bridge(np);
+ of_node_put(np);
+
+ if (!hdata->bridge)
+ return -EPROBE_DEFER;
+
+ return 0;
+}
+
static int hdmi_resources_init(struct hdmi_context *hdata)
{
struct device *dev = hdata->dev;
@@ -2465,10 +2502,9 @@ static int hdmi_resources_init(struct hdmi_context *hdata)
res->regul_bulk = devm_kzalloc(dev, ARRAY_SIZE(supply) *
sizeof(res->regul_bulk[0]), GFP_KERNEL);
- if (!res->regul_bulk) {
- ret = -ENOMEM;
- goto fail;
- }
+ if (!res->regul_bulk)
+ return -ENOMEM;
+
for (i = 0; i < ARRAY_SIZE(supply); ++i) {
res->regul_bulk[i].supply = supply[i];
res->regul_bulk[i].consumer = NULL;
@@ -2494,10 +2530,7 @@ static int hdmi_resources_init(struct hdmi_context *hdata)
} else
res->reg_hdmi_en = NULL;
- return 0;
-fail:
- DRM_ERROR("HDMI resource init - failed\n");
- return ret;
+ return hdmi_bridge_init(hdata);
}
static struct s5p_hdmi_platform_data *drm_hdmi_dt_parse_pdata