MLK-16986-3: drm: mxsfb: fix connector handling
authorRobert Chiras <robert.chiras@nxp.com>
Fri, 24 Nov 2017 12:03:51 +0000 (14:03 +0200)
committerNitin Garg <nitin.garg@nxp.com>
Tue, 20 Mar 2018 19:50:08 +0000 (14:50 -0500)
Since the MXSFB initially was just a simple display pipe using a
drm_panel, the drm_connector was created "in-house", by mxsfb driver.
But, with latest changes, mxsfb also supports a bridge. In case of a
drm_bridge, the the connector is created and initialized by that bridge.
So, for a proper initialization during start-up, we need to take into
consideration that connector, instead of our "in-house" connector.
The connector created and initialized by mxsfb will be used only when
this driver will have a panel.

Signed-off-by: Robert Chiras <robert.chiras@nxp.com>
Reviewed-by: Laurentiu Palcu <laurentiu.palcu@nxp.com>
drivers/gpu/drm/mxsfb/mxsfb_crtc.c
drivers/gpu/drm/mxsfb/mxsfb_drv.c
drivers/gpu/drm/mxsfb/mxsfb_drv.h
drivers/gpu/drm/mxsfb/mxsfb_out.c

index a940e22..1ac0321 100644 (file)
@@ -96,8 +96,11 @@ static void mxsfb_set_bus_fmt(struct mxsfb_drm_private *mxsfb)
 
        reg = readl(mxsfb->base + LCDC_CTRL);
 
-       if (mxsfb->connector.display_info.num_bus_formats)
-               bus_format = mxsfb->connector.display_info.bus_formats[0];
+       if (mxsfb->connector->display_info.num_bus_formats)
+               bus_format = mxsfb->connector->display_info.bus_formats[0];
+
+       DRM_DEV_DEBUG_DRIVER(mxsfb->dev,
+               "Using bus_format: 0x%08X\n", bus_format);
 
        reg &= ~CTRL_BUS_WIDTH_MASK;
        switch (bus_format) {
@@ -174,7 +177,7 @@ static void mxsfb_disable_controller(struct mxsfb_drm_private *mxsfb)
 static void mxsfb_crtc_mode_set_nofb(struct mxsfb_drm_private *mxsfb)
 {
        struct drm_display_mode *m = &mxsfb->pipe.crtc.state->adjusted_mode;
-       const u32 bus_flags = mxsfb->connector.display_info.bus_flags;
+       const u32 bus_flags = mxsfb->connector->display_info.bus_flags;
        u32 hbp = m->crtc_hblank_end - m->crtc_hsync_end;
        u32 vbp = m->crtc_vblank_end - m->crtc_vsync_end;
        u32 vdctrl0, vsync_pulse_len, hsync_pulse_len;
@@ -196,6 +199,11 @@ static void mxsfb_crtc_mode_set_nofb(struct mxsfb_drm_private *mxsfb)
 
        clk_set_rate(mxsfb->clk, m->crtc_clock * 1000);
 
+       DRM_DEV_DEBUG_DRIVER(mxsfb->dev,
+               "Connector bus_flags: 0x%08X\n", bus_flags);
+       DRM_DEV_DEBUG_DRIVER(mxsfb->dev,
+               "Mode flags: 0x%08X\n", m->flags);
+
        writel(TRANSFER_COUNT_SET_VCOUNT(m->crtc_vdisplay) |
               TRANSFER_COUNT_SET_HCOUNT(m->crtc_hdisplay),
               mxsfb->base + mxsfb->devdata->transfer_count);
index 4ec6d31..f37dd51 100644 (file)
@@ -104,8 +104,23 @@ static const struct drm_mode_config_funcs mxsfb_mode_config_funcs = {
 static void mxsfb_pipe_enable(struct drm_simple_display_pipe *pipe,
                              struct drm_crtc_state *crtc_state)
 {
+       struct drm_device *drm = pipe->encoder.dev;
+       struct drm_connector *connector;
        struct mxsfb_drm_private *mxsfb = drm_pipe_to_mxsfb_drm_private(pipe);
 
+       if (!mxsfb->connector) {
+               drm_for_each_connector(connector, drm)
+                       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;
+       }
+
        mxsfb_crtc_enable(mxsfb);
        pm_runtime_get_sync(mxsfb->dev);
 }
@@ -116,6 +131,9 @@ static void mxsfb_pipe_disable(struct drm_simple_display_pipe *pipe)
 
        mxsfb_crtc_disable(mxsfb);
        pm_runtime_put_sync(mxsfb->dev);
+
+       if (mxsfb->connector != &mxsfb->panel_connector)
+               mxsfb->connector = NULL;
 }
 
 static void mxsfb_pipe_update(struct drm_simple_display_pipe *pipe,
@@ -200,15 +218,22 @@ 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),
-                       &mxsfb->connector);
+                       mxsfb->connector);
        if (ret < 0) {
                dev_err(drm->dev, "Cannot setup simple display pipe\n");
                goto err_vblank;
        }
 
-       /* Attach panel only if there is one */
+       /*
+        * 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);
+               ret = drm_panel_attach(mxsfb->panel, mxsfb->connector);
                if (ret) {
                        dev_err(drm->dev, "Cannot connect panel\n");
                        goto err_vblank;
@@ -220,7 +245,6 @@ static int mxsfb_load(struct drm_device *drm, unsigned long flags)
                        dev_err(drm->dev, "Cannot connect bridge\n");
                        goto err_vblank;
                }
-
        }
 
        drm->mode_config.min_width      = MXSFB_MIN_XRES;
index 71e62b0..baf35b3 100644 (file)
@@ -37,7 +37,8 @@ struct mxsfb_drm_private {
        struct clk                      *clk_disp_axi;
 
        struct drm_simple_display_pipe  pipe;
-       struct drm_connector            connector;
+       struct drm_connector            panel_connector;
+       struct drm_connector            *connector;
        struct drm_panel                *panel;
        struct drm_bridge               *bridge;
        struct drm_fbdev_cma            *fbdev;
index cecbd08..5587341 100644 (file)
@@ -29,7 +29,8 @@
 static struct mxsfb_drm_private *
 drm_connector_to_mxsfb_drm_private(struct drm_connector *connector)
 {
-       return container_of(connector, struct mxsfb_drm_private, connector);
+       return container_of(connector, struct mxsfb_drm_private,
+                           panel_connector);
 }
 
 static int mxsfb_panel_get_modes(struct drm_connector *connector)
@@ -99,11 +100,12 @@ static int mxsfb_attach_endpoint(struct drm_device *drm,
                return -EPROBE_DEFER;
 
        if (mxsfb->panel) {
-               mxsfb->connector.dpms = DRM_MODE_DPMS_OFF;
-               mxsfb->connector.polled = 0;
-               drm_connector_helper_add(&mxsfb->connector,
+               mxsfb->connector = &mxsfb->panel_connector;
+               mxsfb->connector->dpms = DRM_MODE_DPMS_OFF;
+               mxsfb->connector->polled = 0;
+               drm_connector_helper_add(mxsfb->connector,
                                &mxsfb_panel_connector_helper_funcs);
-               ret = drm_connector_init(drm, &mxsfb->connector,
+               ret = drm_connector_init(drm, mxsfb->connector,
                                         &mxsfb_panel_connector_funcs,
                                         DRM_MODE_CONNECTOR_Unknown);
        }