コード例 #1
0
static int exynos_dp_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct device_node *np = NULL, *endpoint = NULL;
	struct exynos_dp_device *dp;

	dp = devm_kzalloc(&pdev->dev, sizeof(struct exynos_dp_device),
			  GFP_KERNEL);
	if (!dp)
		return -ENOMEM;

	/*
	 * We just use the drvdata until driver run into component
	 * add function, and then we would set drvdata to null, so
	 * that analogix dp driver would take charge of the drvdata.
	 */
	platform_set_drvdata(pdev, dp);

	/* This is for the backward compatibility. */
	np = of_parse_phandle(dev->of_node, "panel", 0);
	if (np) {
		dp->plat_data.panel = of_drm_find_panel(np);
		of_node_put(np);
		if (!dp->plat_data.panel)
			return -EPROBE_DEFER;
		goto out;
	}

	endpoint = of_graph_get_next_endpoint(dev->of_node, NULL);
	if (endpoint) {
		np = of_graph_get_remote_port_parent(endpoint);
		if (np) {
			/* The remote port can be either a panel or a bridge */
			dp->plat_data.panel = of_drm_find_panel(np);
			if (!dp->plat_data.panel) {
				dp->ptn_bridge = of_drm_find_bridge(np);
				if (!dp->ptn_bridge) {
					of_node_put(np);
					return -EPROBE_DEFER;
				}
			}
			of_node_put(np);
		} else {
			DRM_ERROR("no remote endpoint device node found.\n");
			return -EINVAL;
		}
	} else {
		DRM_ERROR("no port endpoint subnode found.\n");
		return -EINVAL;
	}

out:
	return component_add(&pdev->dev, &exynos_dp_ops);
}
コード例 #2
0
ファイル: exynos_dp_core.c プロジェクト: 19Dan01/linux
static int exynos_dp_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct device_node *panel_node, *bridge_node, *endpoint;
	struct exynos_dp_device *dp;
	int ret;

	dp = devm_kzalloc(&pdev->dev, sizeof(struct exynos_dp_device),
				GFP_KERNEL);
	if (!dp)
		return -ENOMEM;

	dp->display.type = EXYNOS_DISPLAY_TYPE_LCD;
	dp->display.ops = &exynos_dp_display_ops;
	platform_set_drvdata(pdev, dp);

	ret = exynos_drm_component_add(&pdev->dev, EXYNOS_DEVICE_TYPE_CONNECTOR,
					dp->display.type);
	if (ret)
		return ret;

	panel_node = of_parse_phandle(dev->of_node, "panel", 0);
	if (panel_node) {
		dp->panel = of_drm_find_panel(panel_node);
		of_node_put(panel_node);
		if (!dp->panel)
			return -EPROBE_DEFER;
	}

	endpoint = of_graph_get_next_endpoint(dev->of_node, NULL);
	if (endpoint) {
		bridge_node = of_graph_get_remote_port_parent(endpoint);
		if (bridge_node) {
			dp->bridge = of_drm_find_bridge(bridge_node);
			of_node_put(bridge_node);
			if (!dp->bridge)
				return -EPROBE_DEFER;
		} else
			return -EPROBE_DEFER;
	}

	ret = component_add(&pdev->dev, &exynos_dp_ops);
	if (ret)
		exynos_drm_component_del(&pdev->dev,
						EXYNOS_DEVICE_TYPE_CONNECTOR);

	return ret;
}
コード例 #3
0
int rcar_du_hdmienc_init(struct rcar_du_device *rcdu,
			 struct rcar_du_encoder *renc, struct device_node *np)
{
	struct drm_encoder *encoder = rcar_encoder_to_drm_encoder(renc);
	struct drm_bridge *bridge;
	struct rcar_du_hdmienc *hdmienc;
	int ret;

	hdmienc = devm_kzalloc(rcdu->dev, sizeof(*hdmienc), GFP_KERNEL);
	if (hdmienc == NULL)
		return -ENOMEM;

	/* Locate the DRM bridge from the HDMI encoder DT node. */
	bridge = of_drm_find_bridge(np);
	if (!bridge)
		return -EPROBE_DEFER;

	ret = drm_encoder_init(rcdu->ddev, encoder, &encoder_funcs,
			       DRM_MODE_ENCODER_TMDS, NULL);
	if (ret < 0)
		return ret;

	drm_encoder_helper_add(encoder, &encoder_helper_funcs);

	renc->hdmi = hdmienc;
	hdmienc->renc = renc;

	/* Link the bridge to the encoder. */
	bridge->encoder = encoder;
	encoder->bridge = bridge;

	ret = drm_bridge_attach(rcdu->ddev, bridge);
	if (ret) {
		drm_encoder_cleanup(encoder);
		return ret;
	}

	return 0;
}
コード例 #4
0
int tilcdc_attach_external_device(struct drm_device *ddev)
{
	struct tilcdc_drm_private *priv = ddev->dev_private;
	struct device_node *remote_node;
	struct drm_bridge *bridge;
	int ret;

	remote_node = tilcdc_get_remote_node(ddev->dev->of_node);
	if (!remote_node)
		return 0;

	bridge = of_drm_find_bridge(remote_node);
	of_node_put(remote_node);
	if (!bridge)
		return -EPROBE_DEFER;

	priv->external_encoder = devm_kzalloc(ddev->dev,
					      sizeof(*priv->external_encoder),
					      GFP_KERNEL);
	if (!priv->external_encoder)
		return -ENOMEM;

	ret = drm_encoder_init(ddev, priv->external_encoder,
			       &tilcdc_external_encoder_funcs,
			       DRM_MODE_ENCODER_NONE, NULL);
	if (ret) {
		dev_err(ddev->dev, "drm_encoder_init() failed %d\n", ret);
		return ret;
	}

	ret = tilcdc_attach_bridge(ddev, bridge);
	if (ret)
		drm_encoder_cleanup(priv->external_encoder);

	return ret;
}
コード例 #5
0
ファイル: fsl_dcu_drm_rgb.c プロジェクト: AK101111/linux
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);
}
コード例 #6
0
ファイル: rcar_lvds.c プロジェクト: lumag/linux
static int rcar_lvds_parse_dt(struct rcar_lvds *lvds)
{
	struct device_node *local_output = NULL;
	struct device_node *remote_input = NULL;
	struct device_node *remote = NULL;
	struct device_node *node;
	bool is_bridge = false;
	int ret = 0;

	local_output = of_graph_get_endpoint_by_regs(lvds->dev->of_node, 1, 0);
	if (!local_output) {
		dev_dbg(lvds->dev, "unconnected port@1\n");
		return -ENODEV;
	}

	/*
	 * Locate the connected entity and infer its type from the number of
	 * endpoints.
	 */
	remote = of_graph_get_remote_port_parent(local_output);
	if (!remote) {
		dev_dbg(lvds->dev, "unconnected endpoint %pOF\n", local_output);
		ret = -ENODEV;
		goto done;
	}

	if (!of_device_is_available(remote)) {
		dev_dbg(lvds->dev, "connected entity %pOF is disabled\n",
			remote);
		ret = -ENODEV;
		goto done;
	}

	remote_input = of_graph_get_remote_endpoint(local_output);

	for_each_endpoint_of_node(remote, node) {
		if (node != remote_input) {
			/*
			 * We've found one endpoint other than the input, this
			 * must be a bridge.
			 */
			is_bridge = true;
			of_node_put(node);
			break;
		}
	}

	if (is_bridge) {
		lvds->next_bridge = of_drm_find_bridge(remote);
		if (!lvds->next_bridge)
			ret = -EPROBE_DEFER;
	} else {
		lvds->panel = of_drm_find_panel(remote);
		if (!lvds->panel)
			ret = -EPROBE_DEFER;
	}

done:
	of_node_put(local_output);
	of_node_put(remote_input);
	of_node_put(remote);

	return ret;
}
コード例 #7
0
static int exynos_dp_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct device_node *np = NULL, *endpoint = NULL;
	struct exynos_dp_device *dp;
	int ret;

	dp = devm_kzalloc(&pdev->dev, sizeof(struct exynos_dp_device),
				GFP_KERNEL);
	if (!dp)
		return -ENOMEM;

	platform_set_drvdata(pdev, dp);

	/* This is for the backward compatibility. */
	np = of_parse_phandle(dev->of_node, "panel", 0);
	if (np) {
		dp->panel = of_drm_find_panel(np);
		of_node_put(np);
		if (!dp->panel)
			return -EPROBE_DEFER;
		goto out;
	}

	endpoint = of_graph_get_next_endpoint(dev->of_node, NULL);
	if (endpoint) {
		np = of_graph_get_remote_port_parent(endpoint);
		if (np) {
			/* The remote port can be either a panel or a bridge */
			dp->panel = of_drm_find_panel(np);
			if (!dp->panel) {
				dp->ptn_bridge = of_drm_find_bridge(np);
				if (!dp->ptn_bridge) {
					of_node_put(np);
					return -EPROBE_DEFER;
				}
			}
			of_node_put(np);
		} else {
			DRM_ERROR("no remote endpoint device node found.\n");
			return -EINVAL;
		}
	} else {
		DRM_ERROR("no port endpoint subnode found.\n");
		return -EINVAL;
	}

out:
	pm_runtime_enable(dev);

	ret = component_add(&pdev->dev, &exynos_dp_ops);
	if (ret)
		goto err_disable_pm_runtime;

	return ret;

err_disable_pm_runtime:
	pm_runtime_disable(dev);

	return ret;
}