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

Commit c11dea5b authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge branch 'for-next' of http://git.agner.ch/git/linux-drm-fsl-dcu into drm-next

This adds drm bridge support for the NXP/Freescale DCU. The patchset
has been discussed on the mailing list since quite some time...
Plus there is a small fix provided by Peter.

* 'for-next' of http://git.agner.ch/git/linux-drm-fsl-dcu:
  drm/fsl-dcu: add support for drm bridge
  drm/fsl-dcu: rework codes to support of_graph dt binding for panel
  drm/fsl-dcu: add missing of_node_put after calling of_parse_phandle
parents c8c21231 c4a304d3
Loading
Loading
Loading
Loading
+7 −2
Original line number Original line Diff line number Diff line
@@ -12,7 +12,7 @@ Required properties:
- clock-names:		Should be "dcu" and "pix"
- clock-names:		Should be "dcu" and "pix"
			See ../clocks/clock-bindings.txt for details.
			See ../clocks/clock-bindings.txt for details.
- big-endian		Boolean property, LS1021A DCU registers are big-endian.
- big-endian		Boolean property, LS1021A DCU registers are big-endian.
- fsl,panel:		The phandle to panel node.
- port			Video port for the panel output


Optional properties:
Optional properties:
- fsl,tcon:		The phandle to the timing controller node.
- fsl,tcon:		The phandle to the timing controller node.
@@ -24,6 +24,11 @@ dcu: dcu@2ce0000 {
	clocks = <&platform_clk 0>, <&platform_clk 0>;
	clocks = <&platform_clk 0>, <&platform_clk 0>;
	clock-names = "dcu", "pix";
	clock-names = "dcu", "pix";
	big-endian;
	big-endian;
	fsl,panel = <&panel>;
	fsl,tcon = <&tcon>;
	fsl,tcon = <&tcon>;

	port {
		dcu_out: endpoint {
			remote-endpoint = <&panel_out>;
	     };
	};
};
};
+1 −1
Original line number Original line Diff line number Diff line
@@ -43,7 +43,7 @@ int fsl_dcu_drm_modeset_init(struct fsl_dcu_drm_device *fsl_dev)
	if (ret)
	if (ret)
		goto err;
		goto err;


	ret = fsl_dcu_drm_connector_create(fsl_dev, &fsl_dev->encoder);
	ret = fsl_dcu_create_outputs(fsl_dev);
	if (ret)
	if (ret)
		goto err;
		goto err;


+1 −2
Original line number Original line Diff line number Diff line
@@ -25,9 +25,8 @@ to_fsl_dcu_connector(struct drm_connector *con)
		     : NULL;
		     : NULL;
}
}


int fsl_dcu_drm_connector_create(struct fsl_dcu_drm_device *fsl_dev,
				 struct drm_encoder *encoder);
int fsl_dcu_drm_encoder_create(struct fsl_dcu_drm_device *fsl_dev,
int fsl_dcu_drm_encoder_create(struct fsl_dcu_drm_device *fsl_dev,
			       struct drm_crtc *crtc);
			       struct drm_crtc *crtc);
int fsl_dcu_create_outputs(struct fsl_dcu_drm_device *fsl_dev);


#endif /* __FSL_DCU_DRM_CONNECTOR_H__ */
#endif /* __FSL_DCU_DRM_CONNECTOR_H__ */
+58 −20
Original line number Original line Diff line number Diff line
@@ -10,6 +10,7 @@
 */
 */


#include <linux/backlight.h>
#include <linux/backlight.h>
#include <linux/of_graph.h>


#include <drm/drmP.h>
#include <drm/drmP.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_atomic_helper.h>
@@ -132,12 +133,12 @@ static const struct drm_connector_helper_funcs connector_helper_funcs = {
	.mode_valid = fsl_dcu_drm_connector_mode_valid,
	.mode_valid = fsl_dcu_drm_connector_mode_valid,
};
};


int fsl_dcu_drm_connector_create(struct fsl_dcu_drm_device *fsl_dev,
static int fsl_dcu_attach_panel(struct fsl_dcu_drm_device *fsl_dev,
				 struct drm_encoder *encoder)
				 struct drm_panel *panel)
{
{
	struct drm_encoder *encoder = &fsl_dev->encoder;
	struct drm_connector *connector = &fsl_dev->connector.base;
	struct drm_connector *connector = &fsl_dev->connector.base;
	struct drm_mode_config *mode_config = &fsl_dev->drm->mode_config;
	struct drm_mode_config *mode_config = &fsl_dev->drm->mode_config;
	struct device_node *panel_node;
	int ret;
	int ret;


	fsl_dev->connector.encoder = encoder;
	fsl_dev->connector.encoder = encoder;
@@ -161,21 +162,7 @@ int fsl_dcu_drm_connector_create(struct fsl_dcu_drm_device *fsl_dev,
				      mode_config->dpms_property,
				      mode_config->dpms_property,
				      DRM_MODE_DPMS_OFF);
				      DRM_MODE_DPMS_OFF);


	panel_node = of_parse_phandle(fsl_dev->np, "fsl,panel", 0);
	ret = drm_panel_attach(panel, connector);
	if (!panel_node) {
		dev_err(fsl_dev->dev, "fsl,panel property not found\n");
		ret = -ENODEV;
		goto err_sysfs;
	}

	fsl_dev->connector.panel = of_drm_find_panel(panel_node);
	if (!fsl_dev->connector.panel) {
		ret = -EPROBE_DEFER;
		goto err_panel;
	}
	of_node_put(panel_node);

	ret = drm_panel_attach(fsl_dev->connector.panel, connector);
	if (ret) {
	if (ret) {
		dev_err(fsl_dev->dev, "failed to attach panel\n");
		dev_err(fsl_dev->dev, "failed to attach panel\n");
		goto err_sysfs;
		goto err_sysfs;
@@ -183,11 +170,62 @@ int fsl_dcu_drm_connector_create(struct fsl_dcu_drm_device *fsl_dev,


	return 0;
	return 0;


err_panel:
	of_node_put(panel_node);
err_sysfs:
err_sysfs:
	drm_connector_unregister(connector);
	drm_connector_unregister(connector);
err_cleanup:
err_cleanup:
	drm_connector_cleanup(connector);
	drm_connector_cleanup(connector);
	return ret;
	return ret;
}
}

static int fsl_dcu_attach_endpoint(struct fsl_dcu_drm_device *fsl_dev,
				   const struct of_endpoint *ep)
{
	struct drm_bridge *bridge;
	struct device_node *np;

	np = of_graph_get_remote_port_parent(ep->local_node);

	fsl_dev->connector.panel = of_drm_find_panel(np);
	if (fsl_dev->connector.panel) {
		of_node_put(np);
		return fsl_dcu_attach_panel(fsl_dev, fsl_dev->connector.panel);
	}

	bridge = of_drm_find_bridge(np);
	of_node_put(np);
	if (!bridge)
		return -ENODEV;

	fsl_dev->encoder.bridge = bridge;
	bridge->encoder = &fsl_dev->encoder;

	return drm_bridge_attach(fsl_dev->drm, bridge);
}

int fsl_dcu_create_outputs(struct fsl_dcu_drm_device *fsl_dev)
{
	struct of_endpoint ep;
	struct device_node *ep_node, *panel_node;
	int ret;

	/* This is for backward compatibility */
	panel_node = of_parse_phandle(fsl_dev->np, "fsl,panel", 0);
	if (panel_node) {
		fsl_dev->connector.panel = of_drm_find_panel(panel_node);
		of_node_put(panel_node);
		if (!fsl_dev->connector.panel)
			return -EPROBE_DEFER;
		return fsl_dcu_attach_panel(fsl_dev, fsl_dev->connector.panel);
	}

	ep_node = of_graph_get_next_endpoint(fsl_dev->np, NULL);
	if (!ep_node)
		return -ENODEV;

	ret = of_graph_parse_endpoint(ep_node, &ep);
	of_node_put(ep_node);
	if (ret)
		return -ENODEV;

	return fsl_dcu_attach_endpoint(fsl_dev, &ep);
}
+1 −0
Original line number Original line Diff line number Diff line
@@ -92,6 +92,7 @@ struct fsl_tcon *fsl_tcon_init(struct device *dev)
		goto err_node_put;
		goto err_node_put;
	}
	}


	of_node_put(np);
	clk_prepare_enable(tcon->ipg_clk);
	clk_prepare_enable(tcon->ipg_clk);


	dev_info(dev, "Using TCON in bypass mode\n");
	dev_info(dev, "Using TCON in bypass mode\n");