drm/msm/dpu: add support for color processing blocks in dpu driver
authorKalyan Thota <kalyan_t@codeaurora.org>
Tue, 24 Mar 2020 10:01:18 +0000 (15:31 +0530)
committerRob Clark <robdclark@chromium.org>
Mon, 18 May 2020 16:26:32 +0000 (09:26 -0700)
This change adds support to configure dspp blocks in
the dpu driver.

Macro description of the changes coming in this patch.
1) Add dspp definitions in the hw catalog.
2) Add capability to reserve dspp blocks in the display data path.
3) Attach the reserved block to the encoder.

Signed-off-by: Kalyan Thota <kalyan_t@codeaurora.org>
Tested-by: Fritz Koenig <frkoenig@google.com>
Signed-off-by: Rob Clark <robdclark@chromium.org>
14 files changed:
drivers/gpu/drm/msm/Makefile
drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.c [new file with mode: 0644]
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.h [new file with mode: 0644]
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
drivers/gpu/drm/msm/msm_drv.h

index 1579cf0d828f80b776c52930a539fb48cb59dff1..42f8aae28b31d0e0f2268f6df7b67c7cbd1be27f 100644 (file)
@@ -65,6 +65,7 @@ msm-y := \
        disp/dpu1/dpu_hw_lm.o \
        disp/dpu1/dpu_hw_pingpong.o \
        disp/dpu1/dpu_hw_sspp.o \
+       disp/dpu1/dpu_hw_dspp.o \
        disp/dpu1/dpu_hw_top.o \
        disp/dpu1/dpu_hw_util.o \
        disp/dpu1/dpu_hw_vbif.o \
index 5174e86124cc4df70c343c8d2de763f6a9f422c1..cec3474340e80ff18839a953668d16a17a273bf9 100644 (file)
@@ -73,12 +73,14 @@ struct dpu_crtc_smmu_state_data {
  * struct dpu_crtc_mixer: stores the map for each virtual pipeline in the CRTC
  * @hw_lm:     LM HW Driver context
  * @lm_ctl:    CTL Path HW driver context
+ * @lm_dspp:   DSPP HW driver context
  * @mixer_op_mode:     mixer blending operation mode
  * @flush_mask:        mixer flush mask for ctl, mixer and pipe
  */
 struct dpu_crtc_mixer {
        struct dpu_hw_mixer *hw_lm;
        struct dpu_hw_ctl *lm_ctl;
+       struct dpu_hw_dspp *hw_dspp;
        u32 mixer_op_mode;
        u32 flush_mask;
 };
index a1b79ee2bd9d574f6a17ff617f95360b07ff1806..63976dcd2ac87fc18293331b1a9ed82fdb3c1e40 100644 (file)
@@ -20,6 +20,7 @@
 #include "dpu_hw_catalog.h"
 #include "dpu_hw_intf.h"
 #include "dpu_hw_ctl.h"
+#include "dpu_hw_dspp.h"
 #include "dpu_formats.h"
 #include "dpu_encoder_phys.h"
 #include "dpu_crtc.h"
@@ -536,6 +537,7 @@ static struct msm_display_topology dpu_encoder_get_topology(
         * 1 LM, 1 INTF
         * 2 LM, 1 INTF (stream merge to support high resolution interfaces)
         *
+        * Adding color blocks only to primary interface
         */
        if (intf_count == 2)
                topology.num_lm = 2;
@@ -544,6 +546,9 @@ static struct msm_display_topology dpu_encoder_get_topology(
        else
                topology.num_lm = (mode->hdisplay > MAX_HDISPLAY_SPLIT) ? 2 : 1;
 
+       if (dpu_enc->disp_info.intf_type == DRM_MODE_ENCODER_DSI)
+               topology.num_dspp = topology.num_lm;
+
        topology.num_enc = 0;
        topology.num_intf = intf_count;
 
@@ -959,7 +964,8 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc,
        struct dpu_hw_blk *hw_pp[MAX_CHANNELS_PER_ENC];
        struct dpu_hw_blk *hw_ctl[MAX_CHANNELS_PER_ENC];
        struct dpu_hw_blk *hw_lm[MAX_CHANNELS_PER_ENC];
-       int num_lm, num_ctl, num_pp;
+       struct dpu_hw_blk *hw_dspp[MAX_CHANNELS_PER_ENC] = { NULL };
+       int num_lm, num_ctl, num_pp, num_dspp;
        int i, j;
 
        if (!drm_enc) {
@@ -1008,6 +1014,9 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc,
                drm_enc->base.id, DPU_HW_BLK_CTL, hw_ctl, ARRAY_SIZE(hw_ctl));
        num_lm = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
                drm_enc->base.id, DPU_HW_BLK_LM, hw_lm, ARRAY_SIZE(hw_lm));
+       num_dspp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
+               drm_enc->base.id, DPU_HW_BLK_DSPP, hw_dspp,
+               ARRAY_SIZE(hw_dspp));
 
        for (i = 0; i < MAX_CHANNELS_PER_ENC; i++)
                dpu_enc->hw_pp[i] = i < num_pp ? to_dpu_hw_pingpong(hw_pp[i])
@@ -1020,6 +1029,7 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc,
 
                cstate->mixers[i].hw_lm = to_dpu_hw_mixer(hw_lm[i]);
                cstate->mixers[i].lm_ctl = to_dpu_hw_ctl(hw_ctl[ctl_idx]);
+               cstate->mixers[i].hw_dspp = to_dpu_hw_dspp(hw_dspp[i]);
        }
 
        cstate->num_mixers = num_lm;
index c567917541e8b596496b44499d334a0724a65199..19d065ad0b25dfba7bc1e5b3cdf51964b481fc6d 100644 (file)
@@ -41,6 +41,8 @@
 #define PINGPONG_SDM845_SPLIT_MASK \
        (PINGPONG_SDM845_MASK | BIT(DPU_PINGPONG_TE2))
 
+#define DSPP_SC7180_MASK 0
+
 #define DEFAULT_PIXEL_RAM_SIZE         (50 * 1024)
 #define DEFAULT_DPU_LINE_WIDTH         2048
 #define DEFAULT_DPU_OUTPUT_LINE_WIDTH  2560
@@ -291,29 +293,30 @@ static const struct dpu_lm_sub_blks sdm845_lm_sblk = {
        },
 };
 
-#define LM_BLK(_name, _id, _base, _fmask, _sblk, _pp, _lmpair) \
+#define LM_BLK(_name, _id, _base, _fmask, _sblk, _pp, _lmpair, _dspp) \
        { \
        .name = _name, .id = _id, \
        .base = _base, .len = 0x320, \
        .features = _fmask, \
        .sblk = _sblk, \
        .pingpong = _pp, \
-       .lm_pair_mask = (1 << _lmpair) \
+       .lm_pair_mask = (1 << _lmpair), \
+       .dspp = _dspp \
        }
 
 static const struct dpu_lm_cfg sdm845_lm[] = {
        LM_BLK("lm_0", LM_0, 0x44000, MIXER_SDM845_MASK,
-               &sdm845_lm_sblk, PINGPONG_0, LM_1),
+               &sdm845_lm_sblk, PINGPONG_0, LM_1, 0),
        LM_BLK("lm_1", LM_1, 0x45000, MIXER_SDM845_MASK,
-               &sdm845_lm_sblk, PINGPONG_1, LM_0),
+               &sdm845_lm_sblk, PINGPONG_1, LM_0, 0),
        LM_BLK("lm_2", LM_2, 0x46000, MIXER_SDM845_MASK,
-               &sdm845_lm_sblk, PINGPONG_2, LM_5),
+               &sdm845_lm_sblk, PINGPONG_2, LM_5, 0),
        LM_BLK("lm_3", LM_3, 0x0, MIXER_SDM845_MASK,
-               &sdm845_lm_sblk, PINGPONG_MAX, 0),
+               &sdm845_lm_sblk, PINGPONG_MAX, 0, 0),
        LM_BLK("lm_4", LM_4, 0x0, MIXER_SDM845_MASK,
-               &sdm845_lm_sblk, PINGPONG_MAX, 0),
+               &sdm845_lm_sblk, PINGPONG_MAX, 0, 0),
        LM_BLK("lm_5", LM_5, 0x49000, MIXER_SDM845_MASK,
-               &sdm845_lm_sblk, PINGPONG_3, LM_2),
+               &sdm845_lm_sblk, PINGPONG_3, LM_2, 0),
 };
 
 /* SC7180 */
@@ -328,11 +331,25 @@ static const struct dpu_lm_sub_blks sc7180_lm_sblk = {
 
 static const struct dpu_lm_cfg sc7180_lm[] = {
        LM_BLK("lm_0", LM_0, 0x44000, MIXER_SC7180_MASK,
-               &sc7180_lm_sblk, PINGPONG_0, LM_1),
+               &sc7180_lm_sblk, PINGPONG_0, LM_1, DSPP_0),
        LM_BLK("lm_1", LM_1, 0x45000, MIXER_SC7180_MASK,
-               &sc7180_lm_sblk, PINGPONG_1, LM_0),
+               &sc7180_lm_sblk, PINGPONG_1, LM_0, 0),
 };
 
+/*************************************************************
+ * DSPP sub blocks config
+ *************************************************************/
+#define DSPP_BLK(_name, _id, _base) \
+               {\
+               .name = _name, .id = _id, \
+               .base = _base, .len = 0x1800, \
+               .features = DSPP_SC7180_MASK, \
+               .sblk = NULL, \
+               }
+
+static const struct dpu_dspp_cfg sc7180_dspp[] = {
+       DSPP_BLK("dspp_0", DSPP_0, 0x54000),
+};
 /*************************************************************
  * PINGPONG sub blocks config
  *************************************************************/
@@ -587,6 +604,8 @@ static void sc7180_cfg_init(struct dpu_mdss_cfg *dpu_cfg)
                .sspp = sc7180_sspp,
                .mixer_count = ARRAY_SIZE(sc7180_lm),
                .mixer = sc7180_lm,
+               .dspp_count = ARRAY_SIZE(sc7180_dspp),
+               .dspp = sc7180_dspp,
                .pingpong_count = ARRAY_SIZE(sc7180_pp),
                .pingpong = sc7180_pp,
                .intf_count = ARRAY_SIZE(sc7180_intf),
index 09df7d87dd43f3fe56e0b80b0d0ad3a5bc0a74c6..f7de43838c69cbad996b509784fd512b409f0d15 100644 (file)
@@ -145,6 +145,17 @@ enum {
        DPU_MIXER_MAX
 };
 
+/**
+ * DSPP sub-blocks
+ * @DPU_DSPP_PCC             Panel color correction block
+ * @DPU_DSPP_GC              Gamma correction block
+ */
+enum {
+       DPU_DSPP_PCC = 0x1,
+       DPU_DSPP_GC,
+       DPU_DSPP_MAX
+};
+
 /**
  * PINGPONG sub-blocks
  * @DPU_PINGPONG_TE         Tear check block
@@ -377,6 +388,16 @@ struct dpu_lm_sub_blks {
        struct dpu_pp_blk gc;
 };
 
+/**
+ * struct dpu_dspp_sub_blks: Information of DSPP block
+ * @gc : gamma correction block
+ * @pcc: pixel color correction block
+ */
+struct dpu_dspp_sub_blks {
+       struct dpu_pp_blk gc;
+       struct dpu_pp_blk pcc;
+};
+
 struct dpu_pingpong_sub_blks {
        struct dpu_pp_blk te;
        struct dpu_pp_blk te2;
@@ -471,9 +492,23 @@ struct dpu_lm_cfg {
        DPU_HW_BLK_INFO;
        const struct dpu_lm_sub_blks *sblk;
        u32 pingpong;
+       u32 dspp;
        unsigned long lm_pair_mask;
 };
 
+/**
+ * struct dpu_dspp_cfg - information of DSPP blocks
+ * @id                 enum identifying this block
+ * @base               register offset of this block
+ * @features           bit mask identifying sub-blocks/features
+ *                     supported by this block
+ * @sblk               sub-blocks information
+ */
+struct dpu_dspp_cfg  {
+       DPU_HW_BLK_INFO;
+       const struct dpu_dspp_sub_blks *sblk;
+};
+
 /**
  * struct dpu_pingpong_cfg - information of PING-PONG blocks
  * @id                 enum identifying this block
@@ -688,6 +723,9 @@ struct dpu_mdss_cfg {
 
        u32 ad_count;
 
+       u32 dspp_count;
+       const struct dpu_dspp_cfg *dspp;
+
        /* Add additional block data structures here */
 
        struct dpu_perf_cfg perf;
@@ -716,6 +754,7 @@ struct dpu_mdss_hw_cfg_handler {
 #define BLK_PINGPONG(s) ((s)->pingpong)
 #define BLK_INTF(s) ((s)->intf)
 #define BLK_AD(s) ((s)->ad)
+#define BLK_DSPP(s) ((s)->dspp)
 
 /**
  * dpu_hw_catalog_init - dpu hardware catalog init API retrieves
index 831e5f7a9b7f0ed676377aa3dc145af7756e627a..613ae8f0cfcdedd11b6628d693f54dc3b0a6d1fc 100644 (file)
@@ -272,6 +272,31 @@ static int dpu_hw_ctl_active_get_bitmask_intf(struct dpu_hw_ctl *ctx,
        return 0;
 }
 
+static uint32_t dpu_hw_ctl_get_bitmask_dspp(struct dpu_hw_ctl *ctx,
+       enum dpu_dspp dspp)
+{
+       uint32_t flushbits = 0;
+
+       switch (dspp) {
+       case DSPP_0:
+               flushbits = BIT(13);
+               break;
+       case DSPP_1:
+               flushbits = BIT(14);
+               break;
+       case DSPP_2:
+               flushbits = BIT(15);
+               break;
+       case DSPP_3:
+               flushbits = BIT(21);
+               break;
+       default:
+               return 0;
+       }
+
+       return flushbits;
+}
+
 static u32 dpu_hw_ctl_poll_reset_status(struct dpu_hw_ctl *ctx, u32 timeout_us)
 {
        struct dpu_hw_blk_reg_map *c = &ctx->hw;
@@ -548,6 +573,7 @@ static void _setup_ctl_ops(struct dpu_hw_ctl_ops *ops,
        ops->setup_blendstage = dpu_hw_ctl_setup_blendstage;
        ops->get_bitmask_sspp = dpu_hw_ctl_get_bitmask_sspp;
        ops->get_bitmask_mixer = dpu_hw_ctl_get_bitmask_mixer;
+       ops->get_bitmask_dspp = dpu_hw_ctl_get_bitmask_dspp;
 };
 
 static struct dpu_hw_blk_ops dpu_hw_ops;
index 09e1263c72e241c4e1b035522ae357ece5fe0905..ec579b470a8033b3375c9064f9dadec978298c1d 100644 (file)
@@ -139,6 +139,9 @@ struct dpu_hw_ctl_ops {
        uint32_t (*get_bitmask_mixer)(struct dpu_hw_ctl *ctx,
                enum dpu_lm blk);
 
+       uint32_t (*get_bitmask_dspp)(struct dpu_hw_ctl *ctx,
+               enum dpu_dspp blk);
+
        /**
         * Query the value of the intf flush mask
         * No effect on hardware
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.c
new file mode 100644 (file)
index 0000000..75c82e9
--- /dev/null
@@ -0,0 +1,82 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+ */
+
+#include "dpu_hwio.h"
+#include "dpu_hw_catalog.h"
+#include "dpu_hw_lm.h"
+#include "dpu_hw_dspp.h"
+#include "dpu_kms.h"
+
+
+static void _setup_dspp_ops(struct dpu_hw_dspp *c,
+               unsigned long features)
+{
+       return;
+}
+
+static const struct dpu_dspp_cfg *_dspp_offset(enum dpu_dspp dspp,
+               const struct dpu_mdss_cfg *m,
+               void __iomem *addr,
+               struct dpu_hw_blk_reg_map *b)
+{
+       int i;
+
+       if (!m || !addr || !b)
+               return ERR_PTR(-EINVAL);
+
+       for (i = 0; i < m->dspp_count; i++) {
+               if (dspp == m->dspp[i].id) {
+                       b->base_off = addr;
+                       b->blk_off = m->dspp[i].base;
+                       b->length = m->dspp[i].len;
+                       b->hwversion = m->hwversion;
+                       b->log_mask = DPU_DBG_MASK_DSPP;
+                       return &m->dspp[i];
+               }
+       }
+
+       return ERR_PTR(-EINVAL);
+}
+
+static struct dpu_hw_blk_ops dpu_hw_ops;
+
+struct dpu_hw_dspp *dpu_hw_dspp_init(enum dpu_dspp idx,
+                       void __iomem *addr,
+                       const struct dpu_mdss_cfg *m)
+{
+       struct dpu_hw_dspp *c;
+       const struct dpu_dspp_cfg *cfg;
+
+       if (!addr || !m)
+               return ERR_PTR(-EINVAL);
+
+       c = kzalloc(sizeof(*c), GFP_KERNEL);
+       if (!c)
+               return ERR_PTR(-ENOMEM);
+
+       cfg = _dspp_offset(idx, m, addr, &c->hw);
+       if (IS_ERR_OR_NULL(cfg)) {
+               kfree(c);
+               return ERR_PTR(-EINVAL);
+       }
+
+       /* Assign ops */
+       c->idx = idx;
+       c->cap = cfg;
+       _setup_dspp_ops(c, c->cap->features);
+
+       dpu_hw_blk_init(&c->base, DPU_HW_BLK_DSPP, idx, &dpu_hw_ops);
+
+       return c;
+}
+
+void dpu_hw_dspp_destroy(struct dpu_hw_dspp *dspp)
+{
+       if (dspp)
+               dpu_hw_blk_destroy(&dspp->base);
+
+       kfree(dspp);
+}
+
+
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.h
new file mode 100644 (file)
index 0000000..09807ea
--- /dev/null
@@ -0,0 +1,69 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+ */
+
+#ifndef _DPU_HW_DSPP_H
+#define _DPU_HW_DSPP_H
+
+#include "dpu_hw_blk.h"
+
+struct dpu_hw_dspp;
+
+/**
+ * struct dpu_hw_dspp_ops - interface to the dspp hardware driver functions
+ * Caller must call the init function to get the dspp context for each dspp
+ * Assumption is these functions will be called after clocks are enabled
+ */
+struct dpu_hw_dspp_ops {
+
+       void (*dummy)(struct dpu_hw_dspp *ctx);
+};
+
+/**
+ * struct dpu_hw_dspp - dspp description
+ * @base: Hardware block base structure
+ * @hw: Block hardware details
+ * @idx: DSPP index
+ * @cap: Pointer to layer_cfg
+ * @ops: Pointer to operations possible for this DSPP
+ */
+struct dpu_hw_dspp {
+       struct dpu_hw_blk base;
+       struct dpu_hw_blk_reg_map hw;
+
+       /* dspp */
+       int idx;
+       const struct dpu_dspp_cfg *cap;
+
+       /* Ops */
+       struct dpu_hw_dspp_ops ops;
+};
+
+/**
+ * dpu_hw_dspp - convert base object dpu_hw_base to container
+ * @hw: Pointer to base hardware block
+ * return: Pointer to hardware block container
+ */
+static inline struct dpu_hw_dspp *to_dpu_hw_dspp(struct dpu_hw_blk *hw)
+{
+       return container_of(hw, struct dpu_hw_dspp, base);
+}
+
+/**
+ * dpu_hw_dspp_init - initializes the dspp hw driver object.
+ * should be called once before accessing every dspp.
+ * @idx:  DSPP index for which driver object is required
+ * @addr: Mapped register io address of MDP
+ * @Return: pointer to structure or ERR_PTR
+ */
+struct dpu_hw_dspp *dpu_hw_dspp_init(enum dpu_dspp idx,
+       void __iomem *addr, const struct dpu_mdss_cfg *m);
+
+/**
+ * dpu_hw_dspp_destroy(): Destroys DSPP driver context
+ * @dspp: Pointer to DSPP driver context
+ */
+void dpu_hw_dspp_destroy(struct dpu_hw_dspp *dspp);
+
+#endif /*_DPU_HW_DSPP_H */
+
index 686882132bf66a4281cb0286a24aa721a56a380b..402dc583236185f1432ba0c76b56f3d3f3a21198 100644 (file)
@@ -95,6 +95,7 @@ enum dpu_hw_blk_type {
        DPU_HW_BLK_PINGPONG,
        DPU_HW_BLK_INTF,
        DPU_HW_BLK_WB,
+       DPU_HW_BLK_DSPP,
        DPU_HW_BLK_MAX,
 };
 
@@ -425,5 +426,6 @@ struct dpu_mdss_color {
 #define DPU_DBG_MASK_TOP      (1 << 7)
 #define DPU_DBG_MASK_VBIF     (1 << 8)
 #define DPU_DBG_MASK_ROT      (1 << 9)
+#define DPU_DBG_MASK_DSPP     (1 << 10)
 
 #endif  /* _DPU_HW_MDSS_H */
index 211f5de99a441b020e8001be040d0238c5dd2ddf..4e32d040f1e6fe561845eea9cfedff9805065ebc 100644 (file)
@@ -158,6 +158,7 @@ struct dpu_global_state {
        uint32_t mixer_to_enc_id[LM_MAX - LM_0];
        uint32_t ctl_to_enc_id[CTL_MAX - CTL_0];
        uint32_t intf_to_enc_id[INTF_MAX - INTF_0];
+       uint32_t dspp_to_enc_id[DSPP_MAX - DSPP_0];
 };
 
 struct dpu_global_state
index 9b62451b01eeebc2a79f0f3cf0bcbd3c772ab298..9b2b5044e8e05490003f534a6d34f10204304d22 100644 (file)
@@ -9,6 +9,7 @@
 #include "dpu_hw_ctl.h"
 #include "dpu_hw_pingpong.h"
 #include "dpu_hw_intf.h"
+#include "dpu_hw_dspp.h"
 #include "dpu_encoder.h"
 #include "dpu_trace.h"
 
@@ -174,6 +175,23 @@ int dpu_rm_init(struct dpu_rm *rm,
                rm->ctl_blks[ctl->id - CTL_0] = &hw->base;
        }
 
+       for (i = 0; i < cat->dspp_count; i++) {
+               struct dpu_hw_dspp *hw;
+               const struct dpu_dspp_cfg *dspp = &cat->dspp[i];
+
+               if (dspp->id < DSPP_0 || dspp->id >= DSPP_MAX) {
+                       DPU_ERROR("skip dspp %d with invalid id\n", dspp->id);
+                       continue;
+               }
+               hw = dpu_hw_dspp_init(dspp->id, mmio, cat);
+               if (IS_ERR_OR_NULL(hw)) {
+                       rc = PTR_ERR(hw);
+                       DPU_ERROR("failed dspp object creation: err %d\n", rc);
+                       goto fail;
+               }
+               rm->dspp_blks[dspp->id - DSPP_0] = &hw->base;
+       }
+
        return 0;
 
 fail:
@@ -222,12 +240,17 @@ static bool _dpu_rm_check_lm_peer(struct dpu_rm *rm, int primary_idx,
  *      if lm, and all other hardwired blocks connected to the lm (pp) is
  *      available and appropriate
  * @pp_idx: output parameter, index of pingpong block attached to the layer
- *      mixer in rm->pongpong_blks[].
+ *      mixer in rm->pingpong_blks[].
+ * @dspp_idx: output parameter, index of dspp block attached to the layer
+ *      mixer in rm->dspp_blks[].
+ * @reqs: input parameter, rm requirements for HW blocks needed in the
+ *      datapath.
  * @Return: true if lm matches all requirements, false otherwise
  */
 static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm,
                struct dpu_global_state *global_state,
-               uint32_t enc_id, int lm_idx, int *pp_idx)
+               uint32_t enc_id, int lm_idx, int *pp_idx, int *dspp_idx,
+               struct dpu_rm_requirements *reqs)
 {
        const struct dpu_lm_cfg *lm_cfg;
        int idx;
@@ -251,6 +274,23 @@ static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm,
                return false;
        }
        *pp_idx = idx;
+
+       if (!reqs->topology.num_dspp)
+               return true;
+
+       idx = lm_cfg->dspp - DSPP_0;
+       if (idx < 0 || idx >= ARRAY_SIZE(rm->dspp_blks)) {
+               DPU_ERROR("failed to get dspp on lm %d\n", lm_cfg->dspp);
+               return false;
+       }
+
+       if (reserved_by_other(global_state->dspp_to_enc_id, idx, enc_id)) {
+               DPU_DEBUG("lm %d dspp %d already reserved\n", lm_cfg->id,
+                               lm_cfg->dspp);
+               return false;
+       }
+       *dspp_idx = idx;
+
        return true;
 }
 
@@ -262,6 +302,7 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
 {
        int lm_idx[MAX_BLOCKS];
        int pp_idx[MAX_BLOCKS];
+       int dspp_idx[MAX_BLOCKS] = {0};
        int i, j, lm_count = 0;
 
        if (!reqs->topology.num_lm) {
@@ -279,7 +320,8 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
                lm_idx[lm_count] = i;
 
                if (!_dpu_rm_check_lm_and_get_connected_blks(rm, global_state,
-                               enc_id, i, &pp_idx[lm_count])) {
+                               enc_id, i, &pp_idx[lm_count],
+                               &dspp_idx[lm_count], reqs)) {
                        continue;
                }
 
@@ -299,7 +341,8 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
 
                        if (!_dpu_rm_check_lm_and_get_connected_blks(rm,
                                        global_state, enc_id, j,
-                                       &pp_idx[lm_count])) {
+                                       &pp_idx[lm_count], &dspp_idx[lm_count],
+                                       reqs)) {
                                continue;
                        }
 
@@ -316,6 +359,8 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
        for (i = 0; i < lm_count; i++) {
                global_state->mixer_to_enc_id[lm_idx[i]] = enc_id;
                global_state->pingpong_to_enc_id[pp_idx[i]] = enc_id;
+               global_state->dspp_to_enc_id[dspp_idx[i]] =
+                       reqs->topology.num_dspp ? enc_id : 0;
 
                trace_dpu_rm_reserve_lms(lm_idx[i] + LM_0, enc_id,
                                         pp_idx[i] + PINGPONG_0);
@@ -560,6 +605,11 @@ int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
                hw_to_enc_id = global_state->intf_to_enc_id;
                max_blks = ARRAY_SIZE(rm->intf_blks);
                break;
+       case DPU_HW_BLK_DSPP:
+               hw_blks = rm->dspp_blks;
+               hw_to_enc_id = global_state->dspp_to_enc_id;
+               max_blks = ARRAY_SIZE(rm->dspp_blks);
+               break;
        default:
                DPU_ERROR("blk type %d not managed by rm\n", type);
                return 0;
index 6d2b04f306f09b9409c7107aa54f23163fb329fd..08726bb1063aadf487dd22507b66fa05191eae61 100644 (file)
@@ -19,6 +19,7 @@ struct dpu_global_state;
  * @mixer_blks: array of layer mixer hardware resources
  * @ctl_blks: array of ctl hardware resources
  * @intf_blks: array of intf hardware resources
+ * @dspp_blks: array of dspp hardware resources
  * @lm_max_width: cached layer mixer maximum width
  * @rm_lock: resource manager mutex
  */
@@ -27,6 +28,7 @@ struct dpu_rm {
        struct dpu_hw_blk *mixer_blks[LM_MAX - LM_0];
        struct dpu_hw_blk *ctl_blks[CTL_MAX - CTL_0];
        struct dpu_hw_blk *intf_blks[INTF_MAX - INTF_0];
+       struct dpu_hw_blk *dspp_blks[DSPP_MAX - DSPP_0];
 
        uint32_t lm_max_width;
 };
index 194d900a460e6e664756e8d9232de17b55a2b628..0ab49aa781a3199574cab6751c90eb2025598d7e 100644 (file)
@@ -105,6 +105,7 @@ struct msm_display_topology {
        u32 num_lm;
        u32 num_enc;
        u32 num_intf;
+       u32 num_dspp;
 };
 
 /**