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>
config DRM_IMX_PARALLEL_DISPLAY
tristate "Support for parallel displays"
config DRM_IMX_PARALLEL_DISPLAY
tristate "Support for parallel displays"
depends on DRM_IMX
select VIDEOMODE_HELPERS
depends on DRM_IMX
select VIDEOMODE_HELPERS
#include <drm/drmP.h>
#include <drm/drm_fb_helper.h>
#include <drm/drm_crtc_helper.h>
#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>
#include <linux/videodev2.h>
#include <video/of_display_timing.h>
u32 interface_pix_fmt;
int mode_valid;
struct drm_display_mode mode;
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(
};
static enum drm_connector_status imx_pd_connector_detect(
struct device_node *np = imxpd->dev->of_node;
int num_modes = 0;
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);
if (imxpd->edid) {
drm_mode_connector_update_edid_property(connector, imxpd->edid);
num_modes = drm_add_edid_modes(connector, imxpd->edid);
static void imx_pd_encoder_dpms(struct drm_encoder *encoder, int mode)
{
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,
}
static bool imx_pd_encoder_mode_fixup(struct drm_encoder *encoder,
drm_connector_init(drm, &imxpd->connector, &imx_pd_connector_funcs,
DRM_MODE_CONNECTOR_VGA);
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;
drm_mode_connector_attach_encoder(&imxpd->connector, &imxpd->encoder);
imxpd->connector.encoder = &imxpd->encoder;
{
struct drm_device *drm = data;
struct device_node *np = dev->of_node;
{
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;
const u8 *edidp;
struct imx_parallel_display *imxpd;
int ret;
imxpd->interface_pix_fmt = V4L2_PIX_FMT_BGR666;
}
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);
imxpd->dev = dev;
ret = imx_pd_register(drm, imxpd);