diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c index 379b43521853..6c9dd2848e5f 100644 --- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c +++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c @@ -240,18 +240,18 @@ int mdp4_enable(struct mdp4_kms *mdp4_kms) return 0; } -static struct drm_panel *detect_panel(struct drm_device *dev) +static struct device_node *mdp4_detect_lcdc_panel(struct drm_device *dev) { struct device_node *endpoint, *panel_node; struct device_node *np = dev->dev->of_node; - struct drm_panel *panel = NULL; endpoint = of_graph_get_next_endpoint(np, NULL); if (!endpoint) { - dev_err(dev->dev, "no valid endpoint\n"); - return ERR_PTR(-ENODEV); + DBG("no endpoint in MDP4 to fetch LVDS panel\n"); + return NULL; } + /* don't proceed if we have an endpoint but no panel_node tied to it */ panel_node = of_graph_get_remote_port_parent(endpoint); if (!panel_node) { dev_err(dev->dev, "no valid panel node\n"); @@ -261,13 +261,7 @@ static struct drm_panel *detect_panel(struct drm_device *dev) of_node_put(endpoint); - panel = of_drm_find_panel(panel_node); - if (!panel) { - of_node_put(panel_node); - return ERR_PTR(-EPROBE_DEFER); - } - - return panel; + return panel_node; } static int mdp4_modeset_init_intf(struct mdp4_kms *mdp4_kms, @@ -277,18 +271,22 @@ static int mdp4_modeset_init_intf(struct mdp4_kms *mdp4_kms, struct msm_drm_private *priv = dev->dev_private; struct drm_encoder *encoder; struct drm_connector *connector; - struct drm_panel *panel; + struct device_node *panel_node; int ret; switch (intf_type) { case DRM_MODE_ENCODER_LVDS: - panel = detect_panel(dev); - if (IS_ERR(panel)) { - dev_err(dev->dev, "failed to detect LVDS panel\n"); - return PTR_ERR(panel); - } + /* + * bail out early if: + * - there is no panel node (no need to initialize lcdc + * encoder and lvds connector), or + * - panel node is a bad pointer + */ + panel_node = mdp4_detect_lcdc_panel(dev); + if (IS_ERR_OR_NULL(panel_node)) + return PTR_ERR(panel_node); - encoder = mdp4_lcdc_encoder_init(dev, panel); + encoder = mdp4_lcdc_encoder_init(dev, panel_node); if (IS_ERR(encoder)) { dev_err(dev->dev, "failed to construct LCDC encoder\n"); return PTR_ERR(encoder); @@ -297,7 +295,7 @@ static int mdp4_modeset_init_intf(struct mdp4_kms *mdp4_kms, /* LCDC can be hooked to DMA_P (TODO: Add DMA_S later?) */ encoder->possible_crtcs = 1 << DMA_P; - connector = mdp4_lvds_connector_init(dev, panel, encoder); + connector = mdp4_lvds_connector_init(dev, panel_node, encoder); if (IS_ERR(connector)) { dev_err(dev->dev, "failed to initialize LVDS connector\n"); return PTR_ERR(connector); diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h index 8a7f6e1e2bca..7d03585424f7 100644 --- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h +++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h @@ -212,10 +212,10 @@ struct drm_encoder *mdp4_dtv_encoder_init(struct drm_device *dev); long mdp4_lcdc_round_pixclk(struct drm_encoder *encoder, unsigned long rate); struct drm_encoder *mdp4_lcdc_encoder_init(struct drm_device *dev, - struct drm_panel *panel); + struct device_node *panel_node); struct drm_connector *mdp4_lvds_connector_init(struct drm_device *dev, - struct drm_panel *panel, struct drm_encoder *encoder); + struct device_node *panel_node, struct drm_encoder *encoder); #ifdef CONFIG_COMMON_CLK struct clk *mpd4_lvds_pll_init(struct drm_device *dev); diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_lcdc_encoder.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_lcdc_encoder.c index 4cd6e721aa0a..1bda2de20334 100644 --- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_lcdc_encoder.c +++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_lcdc_encoder.c @@ -23,6 +23,7 @@ struct mdp4_lcdc_encoder { struct drm_encoder base; + struct device_node *panel_node; struct drm_panel *panel; struct clk *lcdc_clk; unsigned long int pixclock; @@ -338,7 +339,7 @@ static void mdp4_lcdc_encoder_disable(struct drm_encoder *encoder) struct mdp4_lcdc_encoder *mdp4_lcdc_encoder = to_mdp4_lcdc_encoder(encoder); struct mdp4_kms *mdp4_kms = get_kms(encoder); - struct drm_panel *panel = mdp4_lcdc_encoder->panel; + struct drm_panel *panel; int i, ret; if (WARN_ON(!mdp4_lcdc_encoder->enabled)) @@ -346,6 +347,7 @@ static void mdp4_lcdc_encoder_disable(struct drm_encoder *encoder) mdp4_write(mdp4_kms, REG_MDP4_LCDC_ENABLE, 0); + panel = of_drm_find_panel(mdp4_lcdc_encoder->panel_node); if (panel) { drm_panel_disable(panel); drm_panel_unprepare(panel); @@ -381,7 +383,7 @@ static void mdp4_lcdc_encoder_enable(struct drm_encoder *encoder) to_mdp4_lcdc_encoder(encoder); unsigned long pc = mdp4_lcdc_encoder->pixclock; struct mdp4_kms *mdp4_kms = get_kms(encoder); - struct drm_panel *panel = mdp4_lcdc_encoder->panel; + struct drm_panel *panel; int i, ret; if (WARN_ON(mdp4_lcdc_encoder->enabled)) @@ -414,6 +416,7 @@ static void mdp4_lcdc_encoder_enable(struct drm_encoder *encoder) if (ret) dev_err(dev->dev, "failed to enable lcdc_clk: %d\n", ret); + panel = of_drm_find_panel(mdp4_lcdc_encoder->panel_node); if (panel) { drm_panel_prepare(panel); drm_panel_enable(panel); @@ -442,7 +445,7 @@ long mdp4_lcdc_round_pixclk(struct drm_encoder *encoder, unsigned long rate) /* initialize encoder */ struct drm_encoder *mdp4_lcdc_encoder_init(struct drm_device *dev, - struct drm_panel *panel) + struct device_node *panel_node) { struct drm_encoder *encoder = NULL; struct mdp4_lcdc_encoder *mdp4_lcdc_encoder; @@ -455,7 +458,7 @@ struct drm_encoder *mdp4_lcdc_encoder_init(struct drm_device *dev, goto fail; } - mdp4_lcdc_encoder->panel = panel; + mdp4_lcdc_encoder->panel_node = panel_node; encoder = &mdp4_lcdc_encoder->base; diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_lvds_connector.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_lvds_connector.c index 921185133d38..e73e1742b250 100644 --- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_lvds_connector.c +++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_lvds_connector.c @@ -23,6 +23,7 @@ struct mdp4_lvds_connector { struct drm_connector base; struct drm_encoder *encoder; + struct device_node *panel_node; struct drm_panel *panel; }; #define to_mdp4_lvds_connector(x) container_of(x, struct mdp4_lvds_connector, base) @@ -33,6 +34,10 @@ static enum drm_connector_status mdp4_lvds_connector_detect( struct mdp4_lvds_connector *mdp4_lvds_connector = to_mdp4_lvds_connector(connector); + if (!mdp4_lvds_connector->panel) + mdp4_lvds_connector->panel = + of_drm_find_panel(mdp4_lvds_connector->panel_node); + return mdp4_lvds_connector->panel ? connector_status_connected : connector_status_disconnected; @@ -42,10 +47,6 @@ static void mdp4_lvds_connector_destroy(struct drm_connector *connector) { struct mdp4_lvds_connector *mdp4_lvds_connector = to_mdp4_lvds_connector(connector); - struct drm_panel *panel = mdp4_lvds_connector->panel; - - if (panel) - drm_panel_detach(panel); drm_connector_unregister(connector); drm_connector_cleanup(connector); @@ -60,9 +61,14 @@ static int mdp4_lvds_connector_get_modes(struct drm_connector *connector) struct drm_panel *panel = mdp4_lvds_connector->panel; int ret = 0; - if (panel) + if (panel) { + drm_panel_attach(panel, connector); + ret = panel->funcs->get_modes(panel); + drm_panel_detach(panel); + } + return ret; } @@ -111,7 +117,7 @@ static const struct drm_connector_helper_funcs mdp4_lvds_connector_helper_funcs /* initialize connector */ struct drm_connector *mdp4_lvds_connector_init(struct drm_device *dev, - struct drm_panel *panel, struct drm_encoder *encoder) + struct device_node *panel_node, struct drm_encoder *encoder) { struct drm_connector *connector = NULL; struct mdp4_lvds_connector *mdp4_lvds_connector; @@ -124,7 +130,7 @@ struct drm_connector *mdp4_lvds_connector_init(struct drm_device *dev, } mdp4_lvds_connector->encoder = encoder; - mdp4_lvds_connector->panel = panel; + mdp4_lvds_connector->panel_node = panel_node; connector = &mdp4_lvds_connector->base; @@ -141,9 +147,6 @@ struct drm_connector *mdp4_lvds_connector_init(struct drm_device *dev, drm_mode_connector_attach_encoder(connector, encoder); - if (panel) - drm_panel_attach(panel, connector); - return connector; fail: