OSDN Git Service

drm: msm: reserve drm resource for early RVC
authorGuchun Chen <guchunc@codeaurora.org>
Thu, 12 Apr 2018 09:33:09 +0000 (17:33 +0800)
committerGuchun Chen <guchunc@codeaurora.org>
Sat, 21 Apr 2018 14:40:19 +0000 (22:40 +0800)
When early RVC is enabled in bootloader, the pipes on the display
which RVC is on should not be available to uers' Apps. That means,
user should not touch and allocate the pipe for other Apps before
RVC exits. For this purpose, this patch reads the reserved pipe
information from device tree, and reports pipe availability to
user from kernel side.
In additional, user's layer mixer stage will decrease by 1 to
let RVC's layer stays on top before it exits.

CRs-Fixed: 2225630
Change-Id: Id4530afb82da52aecdf5aa48c8fbd59313da236b
Signed-off-by: Guchun Chen <guchunc@codeaurora.org>
drivers/gpu/drm/msm/sde/sde_crtc.c
drivers/gpu/drm/msm/sde/sde_kms.c
drivers/gpu/drm/msm/sde/sde_plane.c
drivers/gpu/drm/msm/sde/sde_plane.h
drivers/gpu/drm/msm/sde/sde_splash.c
drivers/gpu/drm/msm/sde/sde_splash.h

index ea3f138..829cb11 100644 (file)
@@ -1625,8 +1625,18 @@ static void sde_crtc_install_properties(struct drm_crtc *crtc,
        sde_kms_info_add_keyint(info, "hw_version", catalog->hwversion);
        sde_kms_info_add_keyint(info, "max_linewidth",
                        catalog->max_mixer_width);
-       sde_kms_info_add_keyint(info, "max_blendstages",
-                       catalog->max_mixer_blendstages);
+
+       /* till now, we can't know which display early RVC will run on.
+        * Not to impact early RVC's layer, we decrease all lm's blend stage.
+        * This should be restored after handoff is done.
+        */
+       if (sde_kms->splash_info.handoff)
+               sde_kms_info_add_keyint(info, "max_blendstages",
+                               catalog->max_mixer_blendstages - 1);
+       else
+               sde_kms_info_add_keyint(info, "max_blendstages",
+                               catalog->max_mixer_blendstages);
+
        if (catalog->qseed_type == SDE_SSPP_SCALER_QSEED2)
                sde_kms_info_add_keystr(info, "qseed_type", "qseed2");
        if (catalog->qseed_type == SDE_SSPP_SCALER_QSEED3)
index a94de55..554bfd3 100644 (file)
@@ -812,6 +812,7 @@ static int _sde_kms_drm_obj_init(struct sde_kms *sde_kms)
 
        struct msm_drm_private *priv;
        struct sde_mdss_cfg *catalog;
+       struct sde_splash_info *sinfo;
 
        int primary_planes_idx, i, ret;
        int max_crtc_count, max_plane_count;
@@ -824,6 +825,7 @@ static int _sde_kms_drm_obj_init(struct sde_kms *sde_kms)
        dev = sde_kms->dev;
        priv = dev->dev_private;
        catalog = sde_kms->catalog;
+       sinfo = &sde_kms->splash_info;
 
        ret = sde_core_irq_domain_add(sde_kms);
        if (ret)
@@ -851,7 +853,7 @@ static int _sde_kms_drm_obj_init(struct sde_kms *sde_kms)
                                primary = false;
 
                        plane = sde_plane_init(dev, catalog->vp[i].id,
-                                       primary, 1UL << crtc_id, true);
+                                       primary, 1UL << crtc_id, true, false);
                        if (IS_ERR(plane)) {
                                SDE_ERROR("sde_plane_init failed\n");
                                ret = PTR_ERR(plane);
@@ -869,14 +871,22 @@ static int _sde_kms_drm_obj_init(struct sde_kms *sde_kms)
 
                for (i = 0; i < max_plane_count; i++) {
                        bool primary = true;
+                       bool resv_plane = false;
 
                        if (catalog->sspp[i].features & BIT(SDE_SSPP_CURSOR)
                                || primary_planes_idx >= max_crtc_count)
                                primary = false;
 
+                       if (sde_splash_query_plane_is_reserved(sinfo,
+                                                       catalog->sspp[i].id)) {
+                               resv_plane = true;
+                               DRM_INFO("pipe%d is reserved\n",
+                                       catalog->sspp[i].id);
+                       }
+
                        plane = sde_plane_init(dev, catalog->sspp[i].id,
                                        primary, (1UL << max_crtc_count) - 1,
-                                       false);
+                                       false, resv_plane);
                        if (IS_ERR(plane)) {
                                SDE_ERROR("sde_plane_init failed\n");
                                ret = PTR_ERR(plane);
@@ -1337,12 +1347,17 @@ static int sde_kms_hw_init(struct msm_kms *kms)
         */
        sinfo = &sde_kms->splash_info;
        if (sinfo->handoff) {
-               rc = sde_splash_parse_dt(dev);
+               rc = sde_splash_parse_memory_dt(dev);
                if (rc) {
-                       SDE_ERROR("parse dt for splash info failed: %d\n", rc);
+                       SDE_ERROR("parse memory dt failed: %d\n", rc);
                        goto power_error;
                }
 
+               rc = sde_splash_parse_reserved_plane_dt(sinfo,
+                                                       sde_kms->catalog);
+               if (rc)
+                       SDE_ERROR("parse reserved plane dt failed: %d\n", rc);
+
                sde_splash_init(&priv->phandle, kms);
        }
 
index acd5687..ceac5a9 100644 (file)
@@ -1798,7 +1798,7 @@ static void sde_plane_atomic_update(struct drm_plane *plane,
 
 /* helper to install properties which are common to planes and crtcs */
 static void _sde_plane_install_properties(struct drm_plane *plane,
-       struct sde_mdss_cfg *catalog)
+       struct sde_mdss_cfg *catalog, bool plane_reserved)
 {
        static const struct drm_prop_enum_list e_blend_op[] = {
                {SDE_DRM_BLEND_OP_NOT_DEFINED,    "not_defined"},
@@ -1994,6 +1994,16 @@ static void _sde_plane_install_properties(struct drm_plane *plane,
        sde_kms_info_add_keyint(info, "max_downscale", maxdwnscale);
        sde_kms_info_add_keyint(info, "max_horizontal_deci", maxhdeciexp);
        sde_kms_info_add_keyint(info, "max_vertical_deci", maxvdeciexp);
+
+       /* When early RVC is enabled in bootloader and doesn't exit,
+        * user app should not touch the pipe which RVC is on.
+        * So mark the plane_unavailibility to the special pipe's property,
+        * user can parse this property of this pipe and stop this pipe's
+        * allocation after parsing.
+        * plane_reserved is 1, means the pipe is occupied in bootloader.
+        * plane_reserved is 0, means it's not used in bootloader.
+        */
+       sde_kms_info_add_keyint(info, "plane_unavailability", plane_reserved);
        msm_property_set_blob(&psde->property_info, &psde->blob_info,
                        info->data, info->len, PLANE_PROP_INFO);
 
@@ -2731,7 +2741,8 @@ end:
 /* initialize plane */
 struct drm_plane *sde_plane_init(struct drm_device *dev,
                uint32_t pipe, bool primary_plane,
-               unsigned long possible_crtcs, bool vp_enabled)
+               unsigned long possible_crtcs,
+               bool vp_enabled, bool plane_reserved)
 {
        struct drm_plane *plane = NULL;
        struct sde_plane *psde;
@@ -2856,7 +2867,7 @@ struct drm_plane *sde_plane_init(struct drm_device *dev,
                        PLANE_PROP_COUNT, PLANE_PROP_BLOBCOUNT,
                        sizeof(struct sde_plane_state));
 
-       _sde_plane_install_properties(plane, kms->catalog);
+       _sde_plane_install_properties(plane, kms->catalog, plane_reserved);
 
        /* save user friendly pipe name for later */
        snprintf(psde->pipe_name, SDE_NAME_SIZE, "plane%u", plane->base.id);
index 7b91822..8ac5826 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
  * Copyright (C) 2013 Red Hat
  * Author: Rob Clark <robdclark@gmail.com>
  *
@@ -77,10 +77,12 @@ void sde_plane_flush(struct drm_plane *plane);
  * @primary_plane: true if this pipe is primary plane for crtc
  * @possible_crtcs: bitmask of crtc that can be attached to the given pipe
  * @vp_enabled:  Flag indicating if virtual planes enabled
+ * @plane_reserved: Flag indicating the plane is occupied in bootloader
  */
 struct drm_plane *sde_plane_init(struct drm_device *dev,
                uint32_t pipe, bool primary_plane,
-               unsigned long possible_crtcs, bool vp_enabled);
+               unsigned long possible_crtcs,
+               bool vp_enabled, bool plane_reserved);
 
 /**
  * sde_plane_wait_input_fence - wait for input fence object
index 2789ae0..8b1d06c 100644 (file)
@@ -372,12 +372,12 @@ void sde_splash_destroy(struct sde_splash_info *sinfo,
 }
 
 /*
- * sde_splash_parse_dt.
+ * sde_splash_parse_memory_dt.
  * In the function, it will parse and reserve two kinds of memory node.
  * First is to get the reserved memory for display buffers.
- * Second is to get the memory node LK's code stack is running on.
+ * Second is to get the memory node which LK's heap memory is running on.
  */
-int sde_splash_parse_dt(struct drm_device *dev)
+int sde_splash_parse_memory_dt(struct drm_device *dev)
 {
        struct msm_drm_private *priv = dev->dev_private;
        struct sde_kms *sde_kms;
@@ -404,6 +404,79 @@ int sde_splash_parse_dt(struct drm_device *dev)
        return 0;
 }
 
+static inline u32 _sde_splash_parse_sspp_id(struct sde_mdss_cfg *cfg,
+                                       const char *name)
+{
+       int i;
+
+       for (i = 0; i < cfg->sspp_count; i++) {
+               if (!strcmp(cfg->sspp[i].name, name))
+                       return cfg->sspp[i].id;
+       }
+
+       return 0;
+}
+
+int sde_splash_parse_reserved_plane_dt(struct sde_splash_info *splash_info,
+                               struct sde_mdss_cfg *cfg)
+{
+       struct device_node *parent, *node;
+       struct property *prop;
+       const char *cname;
+       int ret = 0, i = 0;
+
+       if (!splash_info || !cfg)
+               return -EINVAL;
+
+       parent = of_find_node_by_path("/qcom,sde-reserved-plane");
+       if (!parent)
+               return -EINVAL;
+
+       for (i = 0; i < MAX_BLOCKS; i++)
+               splash_info->reserved_pipe_info[i] = 0xFFFFFFFF;
+
+       i = 0;
+       for_each_child_of_node(parent, node) {
+               if (i >= MAX_BLOCKS) {
+                       SDE_ERROR("num of nodes(%d) is bigger than max(%d)\n",
+                               i, MAX_BLOCKS);
+                       ret = -EINVAL;
+                       goto parent_node_err;
+               }
+
+               of_property_for_each_string(node, "qcom,plane-name",
+                                       prop, cname)
+               splash_info->reserved_pipe_info[i] =
+                                       _sde_splash_parse_sspp_id(cfg, cname);
+               i++;
+       }
+
+parent_node_err:
+       of_node_put(parent);
+
+       return ret;
+}
+
+bool sde_splash_query_plane_is_reserved(struct sde_splash_info *sinfo,
+                                       uint32_t pipe)
+{
+       int i = 0;
+
+       if (!sinfo)
+               return false;
+
+       /* early return if no splash is enabled */
+       if (!sinfo->handoff)
+               return false;
+
+       for (i = 0; i < MAX_BLOCKS; i++) {
+               if (sinfo->reserved_pipe_info[i] == pipe)
+                       return true;
+       }
+
+       return false;
+}
+
 int sde_splash_get_handoff_status(struct msm_kms *kms)
 {
        uint32_t intf_sel = 0;
index babf883..77dbb38 100644 (file)
@@ -54,6 +54,9 @@ struct sde_splash_info {
 
        /* registered dst connector count */
        uint32_t dsi_connector_cnt;
+
+       /* reserved pipe info for early RVC */
+       uint32_t reserved_pipe_info[MAX_BLOCKS];
 };
 
 /* APIs for early splash handoff functions */
@@ -99,11 +102,27 @@ int sde_splash_clean_up_free_resource(struct msm_kms *kms,
                                int connector_type, void *display);
 
 /**
- * sde_splash_parse_dt.
+ * sde_splash_parse_memory_dt.
  *
  * Parse reserved memory block from DT for early splash.
  */
-int sde_splash_parse_dt(struct drm_device *dev);
+int sde_splash_parse_memory_dt(struct drm_device *dev);
+
+/**
+ * sde_splash_parse_reserved_plane_dt
+ *
+ * Parse reserved plane information from DT for early RVC case.
+ */
+int sde_splash_parse_reserved_plane_dt(struct sde_splash_info *splash_info,
+                                       struct sde_mdss_cfg *cfg);
+
+/*
+ * sde_splash_query_plane_is_reserved
+ *
+ * Query plane is reserved in dt.
+ */
+bool sde_splash_query_plane_is_reserved(struct sde_splash_info *sinfo,
+                                       uint32_t pipe);
 
 /**
  * sde_splash_smmu_map.