diff options
author | Maxime Ripard <maxime.ripard@free-electrons.com> | 2015-10-29 11:37:32 +0300 |
---|---|---|
committer | Maxime Ripard <maxime.ripard@free-electrons.com> | 2016-04-28 11:30:05 +0300 |
commit | 29e57fab97fcdac9bf04db5f8f59ee63ab11b866 (patch) | |
tree | df1e390b767f303376ef30aab4a4ae568962319e /drivers/gpu/drm/sun4i/sun4i_tcon.c | |
parent | 9026e0d122ac87d329b76a9b631622b03941af64 (diff) | |
download | linux-29e57fab97fcdac9bf04db5f8f59ee63ab11b866.tar.xz |
drm: sun4i: Add RGB output
One of the A10 display pipeline possible output is an RGB interface to
drive LCD panels directly. This is done through the first channel of the
TCON that will output our video signals directly.
Reviewed-by: Boris Brezillon <boris.brezillon@free-electrons.com>
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Diffstat (limited to 'drivers/gpu/drm/sun4i/sun4i_tcon.c')
-rw-r--r-- | drivers/gpu/drm/sun4i/sun4i_tcon.c | 61 |
1 files changed, 60 insertions, 1 deletions
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c index 5fbd3ce9d651..9f19b0e08560 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c @@ -15,10 +15,12 @@ #include <drm/drm_crtc.h> #include <drm/drm_crtc_helper.h> #include <drm/drm_modes.h> +#include <drm/drm_panel.h> #include <linux/component.h> #include <linux/ioport.h> #include <linux/of_address.h> +#include <linux/of_graph.h> #include <linux/of_irq.h> #include <linux/regmap.h> #include <linux/reset.h> @@ -26,6 +28,7 @@ #include "sun4i_crtc.h" #include "sun4i_dotclock.h" #include "sun4i_drv.h" +#include "sun4i_rgb.h" #include "sun4i_tcon.h" void sun4i_tcon_disable(struct sun4i_tcon *tcon) @@ -395,6 +398,40 @@ static int sun4i_tcon_init_regmap(struct device *dev, return 0; } +static struct drm_panel *sun4i_tcon_find_panel(struct device_node *node) +{ + struct device_node *port, *remote, *child; + struct device_node *end_node = NULL; + + /* Inputs are listed first, then outputs */ + port = of_graph_get_port_by_id(node, 1); + + /* + * Our first output is the RGB interface where the panel will + * be connected. + */ + for_each_child_of_node(port, child) { + u32 reg; + + of_property_read_u32(child, "reg", ®); + if (reg == 0) + end_node = child; + } + + if (!end_node) { + DRM_DEBUG_DRIVER("Missing panel endpoint\n"); + return ERR_PTR(-ENODEV); + } + + remote = of_graph_get_remote_port_parent(end_node); + if (!remote) { + DRM_DEBUG_DRIVER("Enable to parse remote node\n"); + return ERR_PTR(-EINVAL); + } + + return of_drm_find_panel(remote); +} + static int sun4i_tcon_bind(struct device *dev, struct device *master, void *data) { @@ -447,7 +484,13 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master, goto err_free_clocks; } - return 0; + tcon->panel = sun4i_tcon_find_panel(dev->of_node); + if (IS_ERR(tcon->panel)) { + dev_info(dev, "No panel found... RGB output disabled\n"); + return 0; + } + + return sun4i_rgb_init(drm); err_free_clocks: sun4i_tcon_free_clocks(tcon); @@ -471,6 +514,22 @@ static struct component_ops sun4i_tcon_ops = { static int sun4i_tcon_probe(struct platform_device *pdev) { + struct device_node *node = pdev->dev.of_node; + struct drm_panel *panel; + + /* + * The panel is not ready. + * Defer the probe. + */ + panel = sun4i_tcon_find_panel(node); + if (IS_ERR(panel)) { + /* + * If we don't have a panel endpoint, just go on + */ + if (PTR_ERR(panel) != -ENODEV) + return -EPROBE_DEFER; + } + return component_add(&pdev->dev, &sun4i_tcon_ops); } |