summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/mxsfb/mxsfb_drv.c
diff options
context:
space:
mode:
authorRobert Chiras <robert.chiras@nxp.com>2019-08-29 14:30:02 +0300
committerStefan Agner <stefan@agner.ch>2019-10-14 22:19:22 +0200
commitd02340436695cbf6920ae1aaaed8afdc8635468d (patch)
tree6d5737850c7d4120f29693afd2e235c9febcf872 /drivers/gpu/drm/mxsfb/mxsfb_drv.c
parent67c698fc5eb0f7471f28e10cd6960e5cf6426de1 (diff)
drm/mxsfb: Update mxsfb to support a bridge
Currently, the MXSFB DRM driver only supports a panel. But, its output display signal can also be redirected to another encoder, like a DSI controller. In this case, that DSI controller may act like a drm_bridge. In order support this use-case too, this patch adds support for drm_bridge in mxsfb. Signed-off-by: Robert Chiras <robert.chiras@nxp.com> Tested-by: Guido Günther <agx@sigxcpu.org> Signed-off-by: Stefan Agner <stefan@agner.ch> Link: https://patchwork.freedesktop.org/patch/msgid/1567078215-31601-2-git-send-email-robert.chiras@nxp.com
Diffstat (limited to 'drivers/gpu/drm/mxsfb/mxsfb_drv.c')
-rw-r--r--drivers/gpu/drm/mxsfb/mxsfb_drv.c46
1 files changed, 41 insertions, 5 deletions
diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
index e8506335cd15..497cf443a9af 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
@@ -101,9 +101,25 @@ static void mxsfb_pipe_enable(struct drm_simple_display_pipe *pipe,
struct drm_crtc_state *crtc_state,
struct drm_plane_state *plane_state)
{
+ struct drm_connector *connector;
struct mxsfb_drm_private *mxsfb = drm_pipe_to_mxsfb_drm_private(pipe);
struct drm_device *drm = pipe->plane.dev;
+ if (!mxsfb->connector) {
+ list_for_each_entry(connector,
+ &drm->mode_config.connector_list,
+ head)
+ if (connector->encoder == &mxsfb->pipe.encoder) {
+ mxsfb->connector = connector;
+ break;
+ }
+ }
+
+ if (!mxsfb->connector) {
+ dev_warn(drm->dev, "No connector attached, using default\n");
+ mxsfb->connector = &mxsfb->panel_connector;
+ }
+
pm_runtime_get_sync(drm->dev);
drm_panel_prepare(mxsfb->panel);
mxsfb_crtc_enable(mxsfb);
@@ -129,6 +145,9 @@ static void mxsfb_pipe_disable(struct drm_simple_display_pipe *pipe)
drm_crtc_send_vblank_event(crtc, event);
}
spin_unlock_irq(&drm->event_lock);
+
+ if (mxsfb->connector != &mxsfb->panel_connector)
+ mxsfb->connector = NULL;
}
static void mxsfb_pipe_update(struct drm_simple_display_pipe *pipe,
@@ -226,16 +245,33 @@ static int mxsfb_load(struct drm_device *drm, unsigned long flags)
ret = drm_simple_display_pipe_init(drm, &mxsfb->pipe, &mxsfb_funcs,
mxsfb_formats, ARRAY_SIZE(mxsfb_formats), NULL,
- &mxsfb->connector);
+ mxsfb->connector);
if (ret < 0) {
dev_err(drm->dev, "Cannot setup simple display pipe\n");
goto err_vblank;
}
- ret = drm_panel_attach(mxsfb->panel, &mxsfb->connector);
- if (ret) {
- dev_err(drm->dev, "Cannot connect panel\n");
- goto err_vblank;
+ /*
+ * Attach panel only if there is one.
+ * If there is no panel attach, it must be a bridge. In this case, we
+ * need a reference to its connector for a proper initialization.
+ * We will do this check in pipe->enable(), since the connector won't
+ * be attached to an encoder until then.
+ */
+
+ if (mxsfb->panel) {
+ ret = drm_panel_attach(mxsfb->panel, mxsfb->connector);
+ if (ret) {
+ dev_err(drm->dev, "Cannot connect panel: %d\n", ret);
+ goto err_vblank;
+ }
+ } else if (mxsfb->bridge) {
+ ret = drm_simple_display_pipe_attach_bridge(&mxsfb->pipe,
+ mxsfb->bridge);
+ if (ret) {
+ dev_err(drm->dev, "Cannot connect bridge: %d\n", ret);
+ goto err_vblank;
+ }
}
drm->mode_config.min_width = MXSFB_MIN_XRES;