drm/rockchip: add loader protect ops to drm connector
authorMark Yao <mark.yao@rock-chips.com>
Thu, 1 Dec 2016 02:25:49 +0000 (10:25 +0800)
committerHuang, Tao <huangtao@rock-chips.com>
Fri, 2 Dec 2016 09:06:56 +0000 (17:06 +0800)
Change-Id: Iae26ac5c994727b98db045ae00c62d641f31c4b1
Signed-off-by: Mark Yao <mark.yao@rock-chips.com>
drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
drivers/gpu/drm/rockchip/rockchip_drm_drv.c
include/drm/drm_crtc.h
include/drm/drm_crtc_helper.h

index d051ae4e96803bf74946d7f8cba4146c6bfa03ca..58f0d294f8c1419f73e2c1d9b0224bf5faca016c 100644 (file)
@@ -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;
 }
index 22183397259e8fdf4372530355735a7b796ac123..13ccdc0c9bba8c7b06e8a3c77465d1ec5d13362f 100644 (file)
@@ -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,
index dd5dc4e4b60f4102dc29e25912a60e829bb5dd9d..fe202ef8f82116dec513f979a15fb67a6bee7deb 100644 (file)
@@ -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];
index 3febb4b9fce9243793fbaf3e8dbb331fe6adf81d..49c731031d6c636a6342702b63fd74b85a86c22b 100644 (file)
@@ -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);