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

Commit bf7149f3 authored by Laurent Pinchart's avatar Laurent Pinchart
Browse files

drm: rcar-du: Use the DRM panel API



Instead of parsing the panel device tree node manually, use the panel
API to delegate panel handling to a panel driver.

Signed-off-by: default avatarLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
parent 06711e63
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ config DRM_RCAR_HDMI
config DRM_RCAR_LVDS
	bool "R-Car DU LVDS Encoder Support"
	depends on DRM_RCAR_DU
	select DRM_PANEL
	help
	  Enable support for the R-Car Display Unit embedded LVDS encoders.

+22 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@
#include <drm/drmP.h>
#include <drm/drm_crtc.h>
#include <drm/drm_crtc_helper.h>
#include <drm/drm_panel.h>

#include "rcar_du_drv.h"
#include "rcar_du_encoder.h"
@@ -33,6 +34,11 @@ static void rcar_du_encoder_disable(struct drm_encoder *encoder)
{
	struct rcar_du_encoder *renc = to_rcar_encoder(encoder);

	if (renc->connector && renc->connector->panel) {
		drm_panel_disable(renc->connector->panel);
		drm_panel_unprepare(renc->connector->panel);
	}

	if (renc->lvds)
		rcar_du_lvdsenc_enable(renc->lvds, encoder->crtc, false);
}
@@ -43,6 +49,11 @@ static void rcar_du_encoder_enable(struct drm_encoder *encoder)

	if (renc->lvds)
		rcar_du_lvdsenc_enable(renc->lvds, encoder->crtc, true);

	if (renc->connector && renc->connector->panel) {
		drm_panel_prepare(renc->connector->panel);
		drm_panel_enable(renc->connector->panel);
	}
}

static int rcar_du_encoder_atomic_check(struct drm_encoder *encoder,
@@ -89,6 +100,17 @@ static void rcar_du_encoder_mode_set(struct drm_encoder *encoder,
	struct rcar_du_encoder *renc = to_rcar_encoder(encoder);

	rcar_du_crtc_route_output(crtc_state->crtc, renc->output);

	if (!renc->lvds) {
		/*
		 * The DU driver creates connectors only for the outputs of the
		 * internal LVDS encoders.
		 */
		renc->connector = NULL;
		return;
	}

	renc->connector = to_rcar_connector(conn_state->connector);
}

static const struct drm_encoder_helper_funcs encoder_helper_funcs = {
+3 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
#include <drm/drm_crtc.h>
#include <drm/drm_encoder.h>

struct drm_panel;
struct rcar_du_device;
struct rcar_du_hdmienc;
struct rcar_du_lvdsenc;
@@ -32,6 +33,7 @@ enum rcar_du_encoder_type {
struct rcar_du_encoder {
	struct drm_encoder base;
	enum rcar_du_output output;
	struct rcar_du_connector *connector;
	struct rcar_du_hdmienc *hdmi;
	struct rcar_du_lvdsenc *lvds;
};
@@ -44,6 +46,7 @@ struct rcar_du_encoder {
struct rcar_du_connector {
	struct drm_connector connector;
	struct rcar_du_encoder *encoder;
	struct drm_panel *panel;
};

#define to_rcar_connector(c) \
+24 −44
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_crtc.h>
#include <drm/drm_crtc_helper.h>
#include <drm/drm_panel.h>

#include <video/display_timing.h>
#include <video/of_display_timing.h>
@@ -25,47 +26,30 @@
#include "rcar_du_kms.h"
#include "rcar_du_lvdscon.h"

struct rcar_du_lvds_connector {
	struct rcar_du_connector connector;

	struct {
		unsigned int width_mm;		/* Panel width in mm */
		unsigned int height_mm;		/* Panel height in mm */
		struct videomode mode;
	} panel;
};

#define to_rcar_lvds_connector(c) \
	container_of(c, struct rcar_du_lvds_connector, connector.connector)

static int rcar_du_lvds_connector_get_modes(struct drm_connector *connector)
{
	struct rcar_du_lvds_connector *lvdscon =
		to_rcar_lvds_connector(connector);
	struct drm_display_mode *mode;

	mode = drm_mode_create(connector->dev);
	if (mode == NULL)
		return 0;

	mode->type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER;

	drm_display_mode_from_videomode(&lvdscon->panel.mode, mode);
	struct rcar_du_connector *rcon = to_rcar_connector(connector);

	drm_mode_probed_add(connector, mode);

	return 1;
	return drm_panel_get_modes(rcon->panel);
}

static const struct drm_connector_helper_funcs connector_helper_funcs = {
	.get_modes = rcar_du_lvds_connector_get_modes,
};

static void rcar_du_lvds_connector_destroy(struct drm_connector *connector)
{
	struct rcar_du_connector *rcon = to_rcar_connector(connector);

	drm_panel_detach(rcon->panel);
	drm_connector_cleanup(connector);
}

static const struct drm_connector_funcs connector_funcs = {
	.dpms = drm_atomic_helper_connector_dpms,
	.reset = drm_atomic_helper_connector_reset,
	.fill_modes = drm_helper_probe_single_connector_modes,
	.destroy = drm_connector_cleanup,
	.destroy = rcar_du_lvds_connector_destroy,
	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
};
@@ -75,27 +59,19 @@ int rcar_du_lvds_connector_init(struct rcar_du_device *rcdu,
				const struct device_node *np)
{
	struct drm_encoder *encoder = rcar_encoder_to_drm_encoder(renc);
	struct rcar_du_lvds_connector *lvdscon;
	struct rcar_du_connector *rcon;
	struct drm_connector *connector;
	struct display_timing timing;
	int ret;

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

	ret = of_get_display_timing(np, "panel-timing", &timing);
	if (ret < 0)
		return ret;

	videomode_from_timing(&timing, &lvdscon->panel.mode);

	of_property_read_u32(np, "width-mm", &lvdscon->panel.width_mm);
	of_property_read_u32(np, "height-mm", &lvdscon->panel.height_mm);
	connector = &rcon->connector;

	connector = &lvdscon->connector.connector;
	connector->display_info.width_mm = lvdscon->panel.width_mm;
	connector->display_info.height_mm = lvdscon->panel.height_mm;
	rcon->panel = of_drm_find_panel(np);
	if (!rcon->panel)
		return -EPROBE_DEFER;

	ret = drm_connector_init(rcdu->ddev, connector, &connector_funcs,
				 DRM_MODE_CONNECTOR_LVDS);
@@ -112,7 +88,11 @@ int rcar_du_lvds_connector_init(struct rcar_du_device *rcdu,
	if (ret < 0)
		return ret;

	lvdscon->connector.encoder = renc;
	ret = drm_panel_attach(rcon->panel, connector);
	if (ret < 0)
		return ret;

	rcon->encoder = renc;

	return 0;
}