From c69d9335f31d5ea128cfe82d8b9a49b145b1a1ec Mon Sep 17 00:00:00 2001 From: Mark Yao Date: Thu, 1 Dec 2016 10:25:49 +0800 Subject: [PATCH] drm/rockchip: add loader protect ops to drm connector Change-Id: Iae26ac5c994727b98db045ae00c62d641f31c4b1 Signed-off-by: Mark Yao --- .../drm/bridge/analogix/analogix_dp_core.c | 25 +++++++++++++ drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 35 +++++++++++++------ include/drm/drm_crtc.h | 1 + include/drm/drm_crtc_helper.h | 2 ++ 4 files changed, 53 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index d051ae4e9680..58f0d294f8c1 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -955,7 +955,28 @@ analogix_dp_best_encoder(struct drm_connector *connector) return dp->encoder; } +static int analogix_dp_loader_protect(struct drm_connector *connector, bool on) +{ + struct analogix_dp_device *dp = to_dp(connector); + + if (on == connector->loader_protect) + return 0; + + if (on) { + pm_runtime_get_sync(dp->dev); + + connector->loader_protect = true; + } else { + pm_runtime_put(dp->dev); + + connector->loader_protect = false; + } + + return 0; +} + static const struct drm_connector_helper_funcs analogix_dp_connector_helper_funcs = { + .loader_protect = analogix_dp_loader_protect, .get_modes = analogix_dp_get_modes, .best_encoder = analogix_dp_best_encoder, }; @@ -1086,6 +1107,10 @@ static void analogix_dp_bridge_disable(struct drm_bridge *bridge) dp->plat_data->power_off(dp->plat_data); pm_runtime_put_sync(dp->dev); + if (dp->connector.loader_protect) { + pm_runtime_put_sync(dp->dev); + dp->connector.loader_protect = false; + } dp->dpms_mode = DRM_MODE_DPMS_OFF; } diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c index 22183397259e..13ccdc0c9bba 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c @@ -296,11 +296,14 @@ int setup_initial_state(struct drm_device *drm_dev, funcs = connector->helper_private; conn_state->best_encoder = funcs->best_encoder(connector); + if (funcs->loader_protect) + funcs->loader_protect(connector, true); num_modes = connector->funcs->fill_modes(connector, 4096, 4096); if (!num_modes) { dev_err(drm_dev->dev, "connector[%s] can't found any modes\n", connector->name); - return -EINVAL; + ret = -EINVAL; + goto error; } list_for_each_entry(mode, &connector->modes, head) { @@ -327,15 +330,18 @@ int setup_initial_state(struct drm_device *drm_dev, head); if (!mode) { pr_err("failed to find available modes\n"); - return -EINVAL; + ret = -EINVAL; + goto error; } } } set->mode = mode; crtc_state = drm_atomic_get_crtc_state(state, crtc); - if (IS_ERR(crtc_state)) - return PTR_ERR(crtc_state); + if (IS_ERR(crtc_state)) { + ret = PTR_ERR(crtc_state); + goto error; + } drm_mode_copy(&crtc_state->adjusted_mode, mode); if (!match || !is_crtc_enabled) { @@ -343,20 +349,24 @@ int setup_initial_state(struct drm_device *drm_dev, } else { ret = drm_atomic_set_crtc_for_connector(conn_state, crtc); if (ret) - return ret; + goto error; ret = drm_atomic_set_mode_for_crtc(crtc_state, mode); if (ret) - return ret; + goto error; crtc_state->active = true; } - if (!set->fb) - return 0; + if (!set->fb) { + ret = 0; + goto error; + } primary_state = drm_atomic_get_plane_state(state, crtc->primary); - if (IS_ERR(primary_state)) - return PTR_ERR(primary_state); + if (IS_ERR(primary_state)) { + ret = PTR_ERR(primary_state); + goto error; + } hdisplay = mode->hdisplay; vdisplay = mode->vdisplay; @@ -392,6 +402,11 @@ int setup_initial_state(struct drm_device *drm_dev, } return 0; + +error: + if (funcs->loader_protect) + funcs->loader_protect(connector, false); + return ret; } static int update_state(struct drm_device *drm_dev, diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index dd5dc4e4b60f..fe202ef8f821 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -708,6 +708,7 @@ struct drm_connector { bool override_edid; uint32_t encoder_ids[DRM_CONNECTOR_MAX_ENCODER]; struct drm_encoder *encoder; /* currently active encoder */ + bool loader_protect; /* EDID bits */ uint8_t eld[MAX_ELD_BYTES]; diff --git a/include/drm/drm_crtc_helper.h b/include/drm/drm_crtc_helper.h index 3febb4b9fce9..49c731031d6c 100644 --- a/include/drm/drm_crtc_helper.h +++ b/include/drm/drm_crtc_helper.h @@ -167,6 +167,7 @@ struct drm_encoder_helper_funcs { /** * struct drm_connector_helper_funcs - helper operations for connectors + * @loader_protect: protect loader logo connector's power * @get_modes: get mode list for this connector * @mode_valid: is this mode valid on the given connector? (optional) * @best_encoder: return the preferred encoder for this connector @@ -175,6 +176,7 @@ struct drm_encoder_helper_funcs { * The helper operations are called by the mid-layer CRTC helper. */ struct drm_connector_helper_funcs { + int (*loader_protect)(struct drm_connector *connector, bool on); int (*get_modes)(struct drm_connector *connector); enum drm_mode_status (*mode_valid)(struct drm_connector *connector, struct drm_display_mode *mode); -- 2.34.1