Commit 29efdc29 authored by Dmitry Osipenko's avatar Dmitry Osipenko Committed by Thierry Reding
Browse files

drm/tegra: output: rgb: Support LVDS encoder bridge



Newer Tegra device-trees will specify a video output graph, which involves
LVDS encoder bridge. This patch adds support for the LVDS encoder bridge
to the RGB output, allowing us to model the display hardware properly.

Reviewed-by: default avatarLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Acked-by: default avatarSam Ravnborg <sam@ravnborg.org>
Signed-off-by: default avatarDmitry Osipenko <digetx@gmail.com>
Signed-off-by: default avatarThierry Reding <treding@nvidia.com>
parent f00b9dd5
Loading
Loading
Loading
Loading
+49 −9
Original line number Diff line number Diff line
@@ -7,6 +7,7 @@
#include <linux/clk.h>

#include <drm/drm_atomic_helper.h>
#include <drm/drm_bridge_connector.h>
#include <drm/drm_panel.h>
#include <drm/drm_simple_kms_helper.h>

@@ -267,24 +268,63 @@ int tegra_dc_rgb_remove(struct tegra_dc *dc)
int tegra_dc_rgb_init(struct drm_device *drm, struct tegra_dc *dc)
{
	struct tegra_output *output = dc->rgb;
	struct drm_connector *connector;
	int err;

	if (!dc->rgb)
		return -ENODEV;

	drm_connector_init(drm, &output->connector, &tegra_rgb_connector_funcs,
	drm_simple_encoder_init(drm, &output->encoder, DRM_MODE_ENCODER_LVDS);
	drm_encoder_helper_add(&output->encoder,
			       &tegra_rgb_encoder_helper_funcs);

	/*
	 * Tegra devices that have LVDS panel utilize LVDS encoder bridge
	 * for converting up to 28 LCD LVTTL lanes into 5/4 LVDS lanes that
	 * go to display panel's receiver.
	 *
	 * Encoder usually have a power-down control which needs to be enabled
	 * in order to transmit data to the panel.  Historically devices that
	 * use an older device-tree version didn't model the bridge, assuming
	 * that encoder is turned ON by default, while today's DRM allows us
	 * to model LVDS encoder properly.
	 *
	 * Newer device-trees utilize LVDS encoder bridge, which provides
	 * us with a connector and handles the display panel.
	 *
	 * For older device-trees we fall back to our own connector and use
	 * nvidia,panel phandle.
	 */
	if (output->bridge) {
		err = drm_bridge_attach(&output->encoder, output->bridge,
					NULL, DRM_BRIDGE_ATTACH_NO_CONNECTOR);
		if (err) {
			dev_err(output->dev, "failed to attach bridge: %d\n",
				err);
			return err;
		}

		connector = drm_bridge_connector_init(drm, &output->encoder);
		if (IS_ERR(connector)) {
			dev_err(output->dev,
				"failed to initialize bridge connector: %pe\n",
				connector);
			return PTR_ERR(connector);
		}

		drm_connector_attach_encoder(connector, &output->encoder);
	} else {
		drm_connector_init(drm, &output->connector,
				   &tegra_rgb_connector_funcs,
				   DRM_MODE_CONNECTOR_LVDS);
		drm_connector_helper_add(&output->connector,
					 &tegra_rgb_connector_helper_funcs);
		output->connector.dpms = DRM_MODE_DPMS_OFF;

	drm_simple_encoder_init(drm, &output->encoder, DRM_MODE_ENCODER_LVDS);
	drm_encoder_helper_add(&output->encoder,
			       &tegra_rgb_encoder_helper_funcs);

		drm_connector_attach_encoder(&output->connector,
					     &output->encoder);
		drm_connector_register(&output->connector);
	}

	err = tegra_output_init(drm, output);
	if (err < 0) {