imx-drm: parallel-display: Add drm_panel support

This patch allows to optionally attach the parallel-display to a panel
supported by a drm_panel driver instead of supplying the modes via
device tree.

Before:
	parallel-display {
		compatible = "fsl,imx-parallel-display";
		...

		display-timings {
			native-timing = <&timing1>;
			timing1: etm0700g0dh6 {
				hactive = <800>;
				vactive = <480>;
				clock-frequency = <33260000>;
				hsync-len = <128>;
				hback-porch = <88>;
				hfront-porch = <40>;
				vsync-len = <2>;
				vback-porch = <33>;
				vfront-porch = <10>;
				hsync-active = <0>;
				vsync-active = <0>;
				...
			};
		};
		...
	};

After:
	parallel-display {
		compatible = "fsl,imx-parallel-display";
		fsl,panel = <&panel>;
		...
	};

	panel: panel {
		compatible = "edt,etm0700g0dh6", "simple-panel";
	};

Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Philipp Zabel 2014-02-25 11:55:04 +01:00 committed by Greg Kroah-Hartman
parent 1f15b69b59
commit 628f435be4
2 changed files with 24 additions and 0 deletions

View File

@ -20,6 +20,7 @@ config DRM_IMX_FB_HELPER
config DRM_IMX_PARALLEL_DISPLAY
tristate "Support for parallel displays"
select DRM_PANEL
depends on DRM_IMX
select VIDEOMODE_HELPERS

View File

@ -23,6 +23,7 @@
#include <drm/drmP.h>
#include <drm/drm_fb_helper.h>
#include <drm/drm_crtc_helper.h>
#include <drm/drm_panel.h>
#include <linux/videodev2.h>
#include <video/of_display_timing.h>
@ -40,6 +41,7 @@ struct imx_parallel_display {
u32 interface_pix_fmt;
int mode_valid;
struct drm_display_mode mode;
struct drm_panel *panel;
};
static enum drm_connector_status imx_pd_connector_detect(
@ -54,6 +56,13 @@ static int imx_pd_connector_get_modes(struct drm_connector *connector)
struct device_node *np = imxpd->dev->of_node;
int num_modes = 0;
if (imxpd->panel && imxpd->panel->funcs &&
imxpd->panel->funcs->get_modes) {
num_modes = imxpd->panel->funcs->get_modes(imxpd->panel);
if (num_modes > 0)
return num_modes;
}
if (imxpd->edid) {
drm_mode_connector_update_edid_property(connector, imxpd->edid);
num_modes = drm_add_edid_modes(connector, imxpd->edid);
@ -89,6 +98,12 @@ static struct drm_encoder *imx_pd_connector_best_encoder(
static void imx_pd_encoder_dpms(struct drm_encoder *encoder, int mode)
{
struct imx_parallel_display *imxpd = enc_to_imxpd(encoder);
if (mode != DRM_MODE_DPMS_ON)
drm_panel_disable(imxpd->panel);
else
drm_panel_enable(imxpd->panel);
}
static bool imx_pd_encoder_mode_fixup(struct drm_encoder *encoder,
@ -164,6 +179,9 @@ static int imx_pd_register(struct drm_device *drm,
drm_connector_init(drm, &imxpd->connector, &imx_pd_connector_funcs,
DRM_MODE_CONNECTOR_VGA);
if (imxpd->panel)
drm_panel_attach(imxpd->panel, &imxpd->connector);
drm_mode_connector_attach_encoder(&imxpd->connector, &imxpd->encoder);
imxpd->connector.encoder = &imxpd->encoder;
@ -175,6 +193,7 @@ static int imx_pd_bind(struct device *dev, struct device *master, void *data)
{
struct drm_device *drm = data;
struct device_node *np = dev->of_node;
struct device_node *panel_node;
const u8 *edidp;
struct imx_parallel_display *imxpd;
int ret;
@ -198,6 +217,10 @@ static int imx_pd_bind(struct device *dev, struct device *master, void *data)
imxpd->interface_pix_fmt = V4L2_PIX_FMT_BGR666;
}
panel_node = of_parse_phandle(np, "fsl,panel", 0);
if (panel_node)
imxpd->panel = of_drm_find_panel(panel_node);
imxpd->dev = dev;
ret = imx_pd_register(drm, imxpd);