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) {
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;
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);
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);
}
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,
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;
dev_err(drm->dev, "Cannot connect bridge\n");
goto err_vblank;
}
-
}
drm->mode_config.min_width = MXSFB_MIN_XRES;
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;
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)
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);
}