Refactor existing CRC code for layer mixer and add CRC support for interface blocks
Changes since V1: - Create helper methods for collect_misr and setup_misr in dpu_hw_util.c - Move common bitmasks into dpu_hw_util.h - Update copyrights - Create a dynamically allocated crcs array in dpu_crtc_state - Collect CRCs for all drm_encoders connected to the crtc
Changes since V2: - Separate dpu_hw_util changes into a separate patch - Revert back to using a static array and define a macro for MAX_CRC_ENTRIES
Changes since V3: - Move crcs array into block-specific get_crc helper methods - Rename "enc" source string to "encoder"
Jessica Zhang (4): drm/msm/dpu: Move LM CRC code into separate method drm/msm/dpu: Move MISR methods to dpu_hw_util drm/msm/dpu: Add MISR register support for interface drm/msm/dpu: Add interface support for CRC debugfs
drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 111 +++++++++++++++----- drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h | 5 + drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 64 +++++++++++ drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h | 22 ++++ drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c | 19 +++- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h | 8 +- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.c | 42 +------- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.c | 49 ++++++++- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.h | 16 +++ 9 files changed, 269 insertions(+), 67 deletions(-)
Move layer mixer-specific section of dpu_crtc_get_crc() into a separate helper method. This way, we can make it easier to get CRCs from other HW blocks by adding other get_crc helper methods.
Changes since V1: - Move common bitmasks to dpu_hw_util.h - Move common CRC methods to dpu_hw_util.c - Update copyrights - Change crcs array to a dynamically allocated array and added it as a member of crtc_state
Changes since V2: - Put changes for hw_util into a separate commit - Revert crcs array to a static array - Add else case for set_crc_source to return EINVAL if no valid source is selected - Add DPU_CRTC_MAX_CRC_ENTRIES macro
Changes since V3: - Move crcs array into dpu_crtc_get_lm_crc - Remove comment about crcs array in dpu_crtc_state struct - Revert `lm` rename - Remove DPU_CRTC_MAX_CRC_ENTRIES macro - Return EINVAL in dpu_crtc_get_crc if no valid CRC source is set
Signed-off-by: Jessica Zhang quic_jesszhan@quicinc.com --- drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 65 +++++++++++++++--------- drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h | 2 + 2 files changed, 43 insertions(+), 24 deletions(-)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c index b56f777dbd0e..b57140c3671a 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2014-2021 The Linux Foundation. All rights reserved. * Copyright (C) 2013 Red Hat * Author: Rob Clark robdclark@gmail.com @@ -99,17 +100,32 @@ static int dpu_crtc_verify_crc_source(struct drm_crtc *crtc, return 0; }
+static void dpu_crtc_setup_lm_misr(struct dpu_crtc_state *crtc_state) +{ + struct dpu_crtc_mixer *m; + int i; + + for (i = 0; i < crtc_state->num_mixers; ++i) { + m = &crtc_state->mixers[i]; + + if (!m->hw_lm || !m->hw_lm->ops.setup_misr) + continue; + + /* Calculate MISR over 1 frame */ + m->hw_lm->ops.setup_misr(m->hw_lm, true, 1); + } +} + static int dpu_crtc_set_crc_source(struct drm_crtc *crtc, const char *src_name) { enum dpu_crtc_crc_source source = dpu_crtc_parse_crc_source(src_name); enum dpu_crtc_crc_source current_source; struct dpu_crtc_state *crtc_state; struct drm_device *drm_dev = crtc->dev; - struct dpu_crtc_mixer *m;
bool was_enabled; bool enable = false; - int i, ret = 0; + int ret = 0;
if (source < 0) { DRM_DEBUG_DRIVER("Invalid CRC source %s for CRTC%d\n", src_name, crtc->index); @@ -146,16 +162,10 @@ static int dpu_crtc_set_crc_source(struct drm_crtc *crtc, const char *src_name)
crtc_state->crc_frame_skip_count = 0;
- for (i = 0; i < crtc_state->num_mixers; ++i) { - m = &crtc_state->mixers[i]; - - if (!m->hw_lm || !m->hw_lm->ops.setup_misr) - continue; - - /* Calculate MISR over 1 frame */ - m->hw_lm->ops.setup_misr(m->hw_lm, true, 1); - } - + if (source == DPU_CRTC_CRC_SOURCE_LAYER_MIXER) + dpu_crtc_setup_lm_misr(crtc_state); + else + ret = -EINVAL;
cleanup: drm_modeset_unlock(&crtc->mutex); @@ -174,26 +184,17 @@ static u32 dpu_crtc_get_vblank_counter(struct drm_crtc *crtc) return dpu_encoder_get_vsync_count(encoder); }
- -static int dpu_crtc_get_crc(struct drm_crtc *crtc) +static int dpu_crtc_get_lm_crc(struct drm_crtc *crtc, + struct dpu_crtc_state *crtc_state) { - struct dpu_crtc_state *crtc_state; struct dpu_crtc_mixer *m; u32 crcs[CRTC_DUAL_MIXERS];
- int i = 0; int rc = 0; - - crtc_state = to_dpu_crtc_state(crtc->state); + int i;
BUILD_BUG_ON(ARRAY_SIZE(crcs) != ARRAY_SIZE(crtc_state->mixers));
- /* Skip first 2 frames in case of "uncooked" CRCs */ - if (crtc_state->crc_frame_skip_count < 2) { - crtc_state->crc_frame_skip_count++; - return 0; - } - for (i = 0; i < crtc_state->num_mixers; ++i) {
m = &crtc_state->mixers[i]; @@ -214,6 +215,22 @@ static int dpu_crtc_get_crc(struct drm_crtc *crtc) drm_crtc_accurate_vblank_count(crtc), crcs); }
+static int dpu_crtc_get_crc(struct drm_crtc *crtc) +{ + struct dpu_crtc_state *crtc_state = to_dpu_crtc_state(crtc->state); + + /* Skip first 2 frames in case of "uncooked" CRCs */ + if (crtc_state->crc_frame_skip_count < 2) { + crtc_state->crc_frame_skip_count++; + return 0; + } + + if (crtc_state->crc_source == DPU_CRTC_CRC_SOURCE_LAYER_MIXER) + return dpu_crtc_get_lm_crc(crtc, crtc_state); + + return -EINVAL; +} + static bool dpu_crtc_get_scanout_position(struct drm_crtc *crtc, bool in_vblank_irq, int *vpos, int *hpos, diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h index b8785c394fcc..20df23fe74ed 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h @@ -201,6 +201,8 @@ struct dpu_crtc { * @mixers : List of active mixers * @num_ctls : Number of ctl paths in use * @hw_ctls : List of active ctl paths + * @crc_source : CRC source + * @crc_frame_skip_count: Number of frames skipped before getting CRC */ struct dpu_crtc_state { struct drm_crtc_state base;
On 22/06/2022 20:18, Jessica Zhang wrote:
Move layer mixer-specific section of dpu_crtc_get_crc() into a separate helper method. This way, we can make it easier to get CRCs from other HW blocks by adding other get_crc helper methods.
Changes since V1:
- Move common bitmasks to dpu_hw_util.h
- Move common CRC methods to dpu_hw_util.c
- Update copyrights
- Change crcs array to a dynamically allocated array and added it as a member of crtc_state
Changes since V2:
- Put changes for hw_util into a separate commit
- Revert crcs array to a static array
- Add else case for set_crc_source to return EINVAL if no valid source is selected
- Add DPU_CRTC_MAX_CRC_ENTRIES macro
Changes since V3:
- Move crcs array into dpu_crtc_get_lm_crc
- Remove comment about crcs array in dpu_crtc_state struct
- Revert `lm` rename
- Remove DPU_CRTC_MAX_CRC_ENTRIES macro
- Return EINVAL in dpu_crtc_get_crc if no valid CRC source is set
Signed-off-by: Jessica Zhang quic_jesszhan@quicinc.com
Reviewed-by: Dmitry Baryshkov dmitry.baryshkov@linaro.org
drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 65 +++++++++++++++--------- drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h | 2 + 2 files changed, 43 insertions(+), 24 deletions(-)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c index b56f777dbd0e..b57140c3671a 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /*
- Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
- Copyright (c) 2014-2021 The Linux Foundation. All rights reserved.
- Copyright (C) 2013 Red Hat
- Author: Rob Clark robdclark@gmail.com
@@ -99,17 +100,32 @@ static int dpu_crtc_verify_crc_source(struct drm_crtc *crtc, return 0; }
+static void dpu_crtc_setup_lm_misr(struct dpu_crtc_state *crtc_state) +{
- struct dpu_crtc_mixer *m;
- int i;
- for (i = 0; i < crtc_state->num_mixers; ++i) {
m = &crtc_state->mixers[i];
if (!m->hw_lm || !m->hw_lm->ops.setup_misr)
continue;
/* Calculate MISR over 1 frame */
m->hw_lm->ops.setup_misr(m->hw_lm, true, 1);
- }
+}
- static int dpu_crtc_set_crc_source(struct drm_crtc *crtc, const char *src_name) { enum dpu_crtc_crc_source source = dpu_crtc_parse_crc_source(src_name); enum dpu_crtc_crc_source current_source; struct dpu_crtc_state *crtc_state; struct drm_device *drm_dev = crtc->dev;
struct dpu_crtc_mixer *m;
bool was_enabled; bool enable = false;
int i, ret = 0;
int ret = 0;
if (source < 0) { DRM_DEBUG_DRIVER("Invalid CRC source %s for CRTC%d\n", src_name, crtc->index);
@@ -146,16 +162,10 @@ static int dpu_crtc_set_crc_source(struct drm_crtc *crtc, const char *src_name)
crtc_state->crc_frame_skip_count = 0;
- for (i = 0; i < crtc_state->num_mixers; ++i) {
m = &crtc_state->mixers[i];
if (!m->hw_lm || !m->hw_lm->ops.setup_misr)
continue;
/* Calculate MISR over 1 frame */
m->hw_lm->ops.setup_misr(m->hw_lm, true, 1);
- }
if (source == DPU_CRTC_CRC_SOURCE_LAYER_MIXER)
dpu_crtc_setup_lm_misr(crtc_state);
else
ret = -EINVAL;
cleanup: drm_modeset_unlock(&crtc->mutex);
@@ -174,26 +184,17 @@ static u32 dpu_crtc_get_vblank_counter(struct drm_crtc *crtc) return dpu_encoder_get_vsync_count(encoder); }
-static int dpu_crtc_get_crc(struct drm_crtc *crtc) +static int dpu_crtc_get_lm_crc(struct drm_crtc *crtc,
{struct dpu_crtc_state *crtc_state)
struct dpu_crtc_state *crtc_state; struct dpu_crtc_mixer *m; u32 crcs[CRTC_DUAL_MIXERS];
int i = 0; int rc = 0;
crtc_state = to_dpu_crtc_state(crtc->state);
int i;
BUILD_BUG_ON(ARRAY_SIZE(crcs) != ARRAY_SIZE(crtc_state->mixers));
/* Skip first 2 frames in case of "uncooked" CRCs */
if (crtc_state->crc_frame_skip_count < 2) {
crtc_state->crc_frame_skip_count++;
return 0;
}
for (i = 0; i < crtc_state->num_mixers; ++i) {
m = &crtc_state->mixers[i];
@@ -214,6 +215,22 @@ static int dpu_crtc_get_crc(struct drm_crtc *crtc) drm_crtc_accurate_vblank_count(crtc), crcs); }
+static int dpu_crtc_get_crc(struct drm_crtc *crtc) +{
- struct dpu_crtc_state *crtc_state = to_dpu_crtc_state(crtc->state);
- /* Skip first 2 frames in case of "uncooked" CRCs */
- if (crtc_state->crc_frame_skip_count < 2) {
crtc_state->crc_frame_skip_count++;
return 0;
- }
- if (crtc_state->crc_source == DPU_CRTC_CRC_SOURCE_LAYER_MIXER)
return dpu_crtc_get_lm_crc(crtc, crtc_state);
- return -EINVAL;
+}
- static bool dpu_crtc_get_scanout_position(struct drm_crtc *crtc, bool in_vblank_irq, int *vpos, int *hpos,
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h index b8785c394fcc..20df23fe74ed 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h @@ -201,6 +201,8 @@ struct dpu_crtc {
- @mixers : List of active mixers
- @num_ctls : Number of ctl paths in use
- @hw_ctls : List of active ctl paths
- @crc_source : CRC source
*/ struct dpu_crtc_state { struct drm_crtc_state base;
- @crc_frame_skip_count: Number of frames skipped before getting CRC
Move layer mixer specific MISR methods to generalized helper methods. This will make it easier to add CRC support for other blocks in the future.
Changes since V2: - Reordered parameters so that offsets are after hw_blk_reg_map - Fixed mismatched whitespace in bitmask definitions
Signed-off-by: Jessica Zhang quic_jesszhan@quicinc.com Reviewed-by: Dmitry Baryshkov dmitry.baryshkov@linaro.org --- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.c | 42 ++---------------- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.c | 49 ++++++++++++++++++++- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.h | 16 +++++++ 3 files changed, 67 insertions(+), 40 deletions(-)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.c index 462f5082099e..e370dcd76e17 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved. */
@@ -27,11 +28,6 @@
#define LM_MISR_CTRL 0x310 #define LM_MISR_SIGNATURE 0x314 -#define LM_MISR_FRAME_COUNT_MASK 0xFF -#define LM_MISR_CTRL_ENABLE BIT(8) -#define LM_MISR_CTRL_STATUS BIT(9) -#define LM_MISR_CTRL_STATUS_CLEAR BIT(10) -#define LM_MISR_CTRL_FREE_RUN_MASK BIT(31)
static const struct dpu_lm_cfg *_lm_offset(enum dpu_lm mixer, @@ -108,44 +104,12 @@ static void dpu_hw_lm_setup_border_color(struct dpu_hw_mixer *ctx,
static void dpu_hw_lm_setup_misr(struct dpu_hw_mixer *ctx, bool enable, u32 frame_count) { - struct dpu_hw_blk_reg_map *c = &ctx->hw; - u32 config = 0; - - DPU_REG_WRITE(c, LM_MISR_CTRL, LM_MISR_CTRL_STATUS_CLEAR); - - /* Clear old MISR value (in case it's read before a new value is calculated)*/ - wmb(); - - if (enable) { - config = (frame_count & LM_MISR_FRAME_COUNT_MASK) | - LM_MISR_CTRL_ENABLE | LM_MISR_CTRL_FREE_RUN_MASK; - - DPU_REG_WRITE(c, LM_MISR_CTRL, config); - } else { - DPU_REG_WRITE(c, LM_MISR_CTRL, 0); - } - + dpu_hw_setup_misr(&ctx->hw, LM_MISR_CTRL, enable, frame_count); }
static int dpu_hw_lm_collect_misr(struct dpu_hw_mixer *ctx, u32 *misr_value) { - struct dpu_hw_blk_reg_map *c = &ctx->hw; - u32 ctrl = 0; - - if (!misr_value) - return -EINVAL; - - ctrl = DPU_REG_READ(c, LM_MISR_CTRL); - - if (!(ctrl & LM_MISR_CTRL_ENABLE)) - return -ENODATA; - - if (!(ctrl & LM_MISR_CTRL_STATUS)) - return -EINVAL; - - *misr_value = DPU_REG_READ(c, LM_MISR_SIGNATURE); - - return 0; + return dpu_hw_collect_misr(&ctx->hw, LM_MISR_CTRL, LM_MISR_SIGNATURE, misr_value); }
static void dpu_hw_lm_setup_blend_config_sdm845(struct dpu_hw_mixer *ctx, diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.c index 512316f25a51..a679757159e9 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.c @@ -1,5 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only -/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. +/* + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. */ #define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__
@@ -447,3 +449,48 @@ u64 _dpu_hw_get_qos_lut(const struct dpu_qos_lut_tbl *tbl,
return 0; } + +void dpu_hw_setup_misr(struct dpu_hw_blk_reg_map *c, + u32 misr_ctrl_offset, + bool enable, u32 frame_count) +{ + u32 config = 0; + + DPU_REG_WRITE(c, misr_ctrl_offset, MISR_CTRL_STATUS_CLEAR); + + /* Clear old MISR value (in case it's read before a new value is calculated)*/ + wmb(); + + if (enable) { + config = (frame_count & MISR_FRAME_COUNT_MASK) | + MISR_CTRL_ENABLE | MISR_CTRL_FREE_RUN_MASK; + + DPU_REG_WRITE(c, misr_ctrl_offset, config); + } else { + DPU_REG_WRITE(c, misr_ctrl_offset, 0); + } + +} + +int dpu_hw_collect_misr(struct dpu_hw_blk_reg_map *c, + u32 misr_ctrl_offset, + u32 misr_signature_offset, + u32 *misr_value) +{ + u32 ctrl = 0; + + if (!misr_value) + return -EINVAL; + + ctrl = DPU_REG_READ(c, misr_ctrl_offset); + + if (!(ctrl & MISR_CTRL_ENABLE)) + return -ENODATA; + + if (!(ctrl & MISR_CTRL_STATUS)) + return -EINVAL; + + *misr_value = DPU_REG_READ(c, misr_signature_offset); + + return 0; +} diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.h index e4a65eb4f769..98f1be0d2559 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.h @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved. */
@@ -12,6 +13,11 @@ #include "dpu_hw_catalog.h"
#define REG_MASK(n) ((BIT(n)) - 1) +#define MISR_FRAME_COUNT_MASK 0xFF +#define MISR_CTRL_ENABLE BIT(8) +#define MISR_CTRL_STATUS BIT(9) +#define MISR_CTRL_STATUS_CLEAR BIT(10) +#define MISR_CTRL_FREE_RUN_MASK BIT(31)
/* * This is the common struct maintained by each sub block @@ -343,4 +349,14 @@ void dpu_hw_csc_setup(struct dpu_hw_blk_reg_map *c, u64 _dpu_hw_get_qos_lut(const struct dpu_qos_lut_tbl *tbl, u32 total_fl);
+void dpu_hw_setup_misr(struct dpu_hw_blk_reg_map *c, + u32 misr_ctrl_offset, + bool enable, + u32 frame_count); + +int dpu_hw_collect_misr(struct dpu_hw_blk_reg_map *c, + u32 misr_ctrl_offset, + u32 misr_signature_offset, + u32 *misr_value); + #endif /* _DPU_HW_UTIL_H */
Add support for setting MISR registers within the interface
Changes since V1: - Replaced dpu_hw_intf collect_misr and setup_misr implementations with calls to dpu_hw_utils helper methods
Signed-off-by: Jessica Zhang quic_jesszhan@quicinc.com Reviewed-by: Dmitry Baryshkov dmitry.baryshkov@linaro.org --- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c | 19 ++++++++++++++++++- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h | 8 +++++++- 2 files changed, 25 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c index 3f4d2c6e1b45..b37eeea36532 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c @@ -1,5 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only -/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. +/* + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. */
#include "dpu_hwio.h" @@ -67,6 +69,9 @@ #define INTF_CFG2_DATABUS_WIDEN BIT(0) #define INTF_CFG2_DATA_HCTL_EN BIT(4)
+#define INTF_MISR_CTRL 0x180 +#define INTF_MISR_SIGNATURE 0x184 + static const struct dpu_intf_cfg *_intf_offset(enum dpu_intf intf, const struct dpu_mdss_cfg *m, void __iomem *addr, @@ -319,6 +324,16 @@ static u32 dpu_hw_intf_get_line_count(struct dpu_hw_intf *intf) return DPU_REG_READ(c, INTF_LINE_COUNT); }
+static void dpu_hw_intf_setup_misr(struct dpu_hw_intf *intf, bool enable, u32 frame_count) +{ + dpu_hw_setup_misr(&intf->hw, INTF_MISR_CTRL, enable, frame_count); +} + +static int dpu_hw_intf_collect_misr(struct dpu_hw_intf *intf, u32 *misr_value) +{ + return dpu_hw_collect_misr(&intf->hw, INTF_MISR_CTRL, INTF_MISR_SIGNATURE, misr_value); +} + static void _setup_intf_ops(struct dpu_hw_intf_ops *ops, unsigned long cap) { @@ -329,6 +344,8 @@ static void _setup_intf_ops(struct dpu_hw_intf_ops *ops, ops->get_line_count = dpu_hw_intf_get_line_count; if (cap & BIT(DPU_INTF_INPUT_CTRL)) ops->bind_pingpong_blk = dpu_hw_intf_bind_pingpong_blk; + ops->setup_misr = dpu_hw_intf_setup_misr; + ops->collect_misr = dpu_hw_intf_collect_misr; }
struct dpu_hw_intf *dpu_hw_intf_init(enum dpu_intf idx, diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h index 7b2d96ac61e8..8d0e7b509260 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h @@ -1,5 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ -/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. +/* + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. */
#ifndef _DPU_HW_INTF_H @@ -57,6 +59,8 @@ struct intf_status { * @ get_line_count: reads current vertical line counter * @bind_pingpong_blk: enable/disable the connection with pingpong which will * feed pixels to this interface + * @setup_misr: enable/disable MISR + * @collect_misr: read MISR signature */ struct dpu_hw_intf_ops { void (*setup_timing_gen)(struct dpu_hw_intf *intf, @@ -77,6 +81,8 @@ struct dpu_hw_intf_ops { void (*bind_pingpong_blk)(struct dpu_hw_intf *intf, bool enable, const enum dpu_pingpong pp); + void (*setup_misr)(struct dpu_hw_intf *intf, bool enable, u32 frame_count); + int (*collect_misr)(struct dpu_hw_intf *intf, u32 *misr_value); };
struct dpu_hw_intf {
Add support for writing CRC values for the interface block to the debugfs by calling the necessary MISR setup/collect methods.
Changes since V1: - Set values_cnt to only include phys with backing hw_intf - Loop over all drm_encs connected to crtc
Changes since V2: - Remove vblank.h inclusion - Change `pos + i` to `pos + entries` - Initialize values_cnt to 0 for encoder - Change DPU_CRTC_CRC_SOURCE_INTF to DPU_CRTC_CRC_SOURCE_ENCODER (and "intf" to "enc") - Change dpu_encoder_get_num_phys to dpu_encoder_get_num_hw_intfs - Add checks for setup_misr and collect_misr in dpu_encoder_get_num_hw_intfs
Changes since V3: - Remove extra whitespace - Change "enc" to "encoder" - Move crcs array to dpu_crtc_get_encoder_crc - Rename dpu_encoder_get_num_hw_intfs to dpu_encoder_get_crc_values_cnt
Signed-off-by: Jessica Zhang quic_jesszhan@quicinc.com --- drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 46 ++++++++++++++- drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h | 3 + drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 64 +++++++++++++++++++++ drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h | 22 +++++++ 4 files changed, 134 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c index b57140c3671a..4dd0ce09ca74 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c @@ -79,6 +79,8 @@ static enum dpu_crtc_crc_source dpu_crtc_parse_crc_source(const char *src_name) if (!strcmp(src_name, "auto") || !strcmp(src_name, "lm")) return DPU_CRTC_CRC_SOURCE_LAYER_MIXER; + if (!strcmp(src_name, "encoder")) + return DPU_CRTC_CRC_SOURCE_ENCODER;
return DPU_CRTC_CRC_SOURCE_INVALID; } @@ -94,8 +96,16 @@ static int dpu_crtc_verify_crc_source(struct drm_crtc *crtc, return -EINVAL; }
- if (source == DPU_CRTC_CRC_SOURCE_LAYER_MIXER) + if (source == DPU_CRTC_CRC_SOURCE_LAYER_MIXER) { *values_cnt = crtc_state->num_mixers; + } else if (source == DPU_CRTC_CRC_SOURCE_ENCODER) { + struct drm_encoder *drm_enc; + + *values_cnt = 0; + + drm_for_each_encoder_mask(drm_enc, crtc->dev, crtc->state->encoder_mask) + *values_cnt += dpu_encoder_get_crc_values_cnt(drm_enc); + }
return 0; } @@ -116,6 +126,14 @@ static void dpu_crtc_setup_lm_misr(struct dpu_crtc_state *crtc_state) } }
+static void dpu_crtc_setup_encoder_misr(struct drm_crtc *crtc) +{ + struct drm_encoder *drm_enc; + + drm_for_each_encoder_mask(drm_enc, crtc->dev, crtc->state->encoder_mask) + dpu_encoder_setup_misr(drm_enc); +} + static int dpu_crtc_set_crc_source(struct drm_crtc *crtc, const char *src_name) { enum dpu_crtc_crc_source source = dpu_crtc_parse_crc_source(src_name); @@ -164,6 +182,8 @@ static int dpu_crtc_set_crc_source(struct drm_crtc *crtc, const char *src_name)
if (source == DPU_CRTC_CRC_SOURCE_LAYER_MIXER) dpu_crtc_setup_lm_misr(crtc_state); + else if (source == DPU_CRTC_CRC_SOURCE_ENCODER) + dpu_crtc_setup_encoder_misr(crtc); else ret = -EINVAL;
@@ -215,6 +235,28 @@ static int dpu_crtc_get_lm_crc(struct drm_crtc *crtc, drm_crtc_accurate_vblank_count(crtc), crcs); }
+static int dpu_crtc_get_encoder_crc(struct drm_crtc *crtc) +{ + struct drm_encoder *drm_enc; + int rc, pos = 0; + u32 crcs[INTF_MAX]; + + drm_for_each_encoder_mask(drm_enc, crtc->dev, crtc->state->encoder_mask) { + rc = dpu_encoder_get_crc(drm_enc, crcs, pos); + if (rc < 0) { + if (rc != -ENODATA) + DRM_DEBUG_DRIVER("MISR read failed\n"); + + return rc; + } + + pos += rc; + } + + return drm_crtc_add_crc_entry(crtc, true, + drm_crtc_accurate_vblank_count(crtc), crcs); +} + static int dpu_crtc_get_crc(struct drm_crtc *crtc) { struct dpu_crtc_state *crtc_state = to_dpu_crtc_state(crtc->state); @@ -227,6 +269,8 @@ static int dpu_crtc_get_crc(struct drm_crtc *crtc)
if (crtc_state->crc_source == DPU_CRTC_CRC_SOURCE_LAYER_MIXER) return dpu_crtc_get_lm_crc(crtc, crtc_state); + else if (crtc_state->crc_source == DPU_CRTC_CRC_SOURCE_ENCODER) + return dpu_crtc_get_encoder_crc(crtc);
return -EINVAL; } diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h index 20df23fe74ed..af03277a3e5a 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2015-2021 The Linux Foundation. All rights reserved. * Copyright (C) 2013 Red Hat * Author: Rob Clark robdclark@gmail.com @@ -73,11 +74,13 @@ struct dpu_crtc_smmu_state_data { * enum dpu_crtc_crc_source: CRC source * @DPU_CRTC_CRC_SOURCE_NONE: no source set * @DPU_CRTC_CRC_SOURCE_LAYER_MIXER: CRC in layer mixer + * @DPU_CRTC_CRC_SOURCE_ENCODER: CRC in encoder * @DPU_CRTC_CRC_SOURCE_INVALID: Invalid source */ enum dpu_crtc_crc_source { DPU_CRTC_CRC_SOURCE_NONE = 0, DPU_CRTC_CRC_SOURCE_LAYER_MIXER, + DPU_CRTC_CRC_SOURCE_ENCODER, DPU_CRTC_CRC_SOURCE_MAX, DPU_CRTC_CRC_SOURCE_INVALID = -1 }; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index 52516eb20cb8..e00c788db14c 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -225,6 +225,70 @@ bool dpu_encoder_is_widebus_enabled(const struct drm_encoder *drm_enc) return dpu_enc->wide_bus_en; }
+int dpu_encoder_get_crc_values_cnt(const struct drm_encoder *drm_enc) +{ + struct dpu_encoder_virt *dpu_enc; + int i, num_intf = 0; + + dpu_enc = to_dpu_encoder_virt(drm_enc); + + for (i = 0; i < dpu_enc->num_phys_encs; i++) { + struct dpu_encoder_phys *phys = dpu_enc->phys_encs[i]; + + if (phys->hw_intf && phys->hw_intf->ops.setup_misr + && phys->hw_intf->ops.collect_misr) + num_intf++; + } + + return num_intf; +} + +void dpu_encoder_setup_misr(const struct drm_encoder *drm_enc) +{ + struct dpu_encoder_virt *dpu_enc; + + int i; + + dpu_enc = to_dpu_encoder_virt(drm_enc); + + for (i = 0; i < dpu_enc->num_phys_encs; i++) { + struct dpu_encoder_phys *phys = dpu_enc->phys_encs[i]; + + if (!phys->hw_intf || !phys->hw_intf->ops.setup_misr) + continue; + + phys->hw_intf->ops.setup_misr(phys->hw_intf, true, 1); + } +} + +int dpu_encoder_get_crc(const struct drm_encoder *drm_enc, u32 *crcs, int pos) +{ + struct dpu_encoder_virt *dpu_enc; + + int i, rc = 0, entries_added = 0; + + if (!drm_enc->crtc) { + DRM_ERROR("no crtc found for encoder %d\n", drm_enc->index); + return -EINVAL; + } + + dpu_enc = to_dpu_encoder_virt(drm_enc); + + for (i = 0; i < dpu_enc->num_phys_encs; i++) { + struct dpu_encoder_phys *phys = dpu_enc->phys_encs[i]; + + if (!phys->hw_intf || !phys->hw_intf->ops.collect_misr) + continue; + + rc = phys->hw_intf->ops.collect_misr(phys->hw_intf, &crcs[pos + entries_added]); + if (rc) + return rc; + entries_added++; + } + + return entries_added; +} + static void _dpu_encoder_setup_dither(struct dpu_hw_pingpong *hw_pp, unsigned bpc) { struct dpu_hw_dither_cfg dither_cfg = { 0 }; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h index 781d41c91994..a78971670024 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. * Copyright (C) 2013 Red Hat * Author: Rob Clark robdclark@gmail.com @@ -174,6 +175,27 @@ int dpu_encoder_get_vsync_count(struct drm_encoder *drm_enc);
bool dpu_encoder_is_widebus_enabled(const struct drm_encoder *drm_enc);
+/** + * dpu_encoder_get_crc_values_cnt - get number of physical encoders contained + * in virtual encoder that can collect CRC values + * @drm_enc: Pointer to previously created drm encoder structure + * Returns: Number of physical encoders for given drm encoder + */ +int dpu_encoder_get_crc_values_cnt(const struct drm_encoder *drm_enc); + +/** + * dpu_encoder_setup_misr - enable misr calculations + * @drm_enc: Pointer to previously created drm encoder structure + */ +void dpu_encoder_setup_misr(const struct drm_encoder *drm_encoder); + +/** + * dpu_encoder_get_crc - get the crc value from interface blocks + * @drm_enc: Pointer to previously created drm encoder structure + * Returns: 0 on success, error otherwise + */ +int dpu_encoder_get_crc(const struct drm_encoder *drm_enc, u32 *crcs, int pos); + /** * dpu_encoder_use_dsc_merge - returns true if the encoder uses DSC merge topology. * @drm_enc: Pointer to previously created drm encoder structure
On 22/06/2022 20:18, Jessica Zhang wrote:
Add support for writing CRC values for the interface block to the debugfs by calling the necessary MISR setup/collect methods.
Changes since V1:
- Set values_cnt to only include phys with backing hw_intf
- Loop over all drm_encs connected to crtc
Changes since V2:
- Remove vblank.h inclusion
- Change `pos + i` to `pos + entries`
- Initialize values_cnt to 0 for encoder
- Change DPU_CRTC_CRC_SOURCE_INTF to DPU_CRTC_CRC_SOURCE_ENCODER (and "intf" to "enc")
- Change dpu_encoder_get_num_phys to dpu_encoder_get_num_hw_intfs
- Add checks for setup_misr and collect_misr in dpu_encoder_get_num_hw_intfs
Changes since V3:
- Remove extra whitespace
- Change "enc" to "encoder"
- Move crcs array to dpu_crtc_get_encoder_crc
- Rename dpu_encoder_get_num_hw_intfs to dpu_encoder_get_crc_values_cnt
Signed-off-by: Jessica Zhang quic_jesszhan@quicinc.com
Reviewed-by: Dmitry Baryshkov dmitry.baryshkov@linaro.org
drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 46 ++++++++++++++- drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h | 3 + drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 64 +++++++++++++++++++++ drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h | 22 +++++++ 4 files changed, 134 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c index b57140c3671a..4dd0ce09ca74 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c @@ -79,6 +79,8 @@ static enum dpu_crtc_crc_source dpu_crtc_parse_crc_source(const char *src_name) if (!strcmp(src_name, "auto") || !strcmp(src_name, "lm")) return DPU_CRTC_CRC_SOURCE_LAYER_MIXER;
if (!strcmp(src_name, "encoder"))
return DPU_CRTC_CRC_SOURCE_ENCODER;
return DPU_CRTC_CRC_SOURCE_INVALID; }
@@ -94,8 +96,16 @@ static int dpu_crtc_verify_crc_source(struct drm_crtc *crtc, return -EINVAL; }
- if (source == DPU_CRTC_CRC_SOURCE_LAYER_MIXER)
if (source == DPU_CRTC_CRC_SOURCE_LAYER_MIXER) { *values_cnt = crtc_state->num_mixers;
} else if (source == DPU_CRTC_CRC_SOURCE_ENCODER) {
struct drm_encoder *drm_enc;
*values_cnt = 0;
drm_for_each_encoder_mask(drm_enc, crtc->dev, crtc->state->encoder_mask)
*values_cnt += dpu_encoder_get_crc_values_cnt(drm_enc);
}
return 0; }
@@ -116,6 +126,14 @@ static void dpu_crtc_setup_lm_misr(struct dpu_crtc_state *crtc_state) } }
+static void dpu_crtc_setup_encoder_misr(struct drm_crtc *crtc) +{
- struct drm_encoder *drm_enc;
- drm_for_each_encoder_mask(drm_enc, crtc->dev, crtc->state->encoder_mask)
dpu_encoder_setup_misr(drm_enc);
+}
- static int dpu_crtc_set_crc_source(struct drm_crtc *crtc, const char *src_name) { enum dpu_crtc_crc_source source = dpu_crtc_parse_crc_source(src_name);
@@ -164,6 +182,8 @@ static int dpu_crtc_set_crc_source(struct drm_crtc *crtc, const char *src_name)
if (source == DPU_CRTC_CRC_SOURCE_LAYER_MIXER) dpu_crtc_setup_lm_misr(crtc_state);
- else if (source == DPU_CRTC_CRC_SOURCE_ENCODER)
else ret = -EINVAL;dpu_crtc_setup_encoder_misr(crtc);
@@ -215,6 +235,28 @@ static int dpu_crtc_get_lm_crc(struct drm_crtc *crtc, drm_crtc_accurate_vblank_count(crtc), crcs); }
+static int dpu_crtc_get_encoder_crc(struct drm_crtc *crtc) +{
- struct drm_encoder *drm_enc;
- int rc, pos = 0;
- u32 crcs[INTF_MAX];
- drm_for_each_encoder_mask(drm_enc, crtc->dev, crtc->state->encoder_mask) {
rc = dpu_encoder_get_crc(drm_enc, crcs, pos);
if (rc < 0) {
if (rc != -ENODATA)
DRM_DEBUG_DRIVER("MISR read failed\n");
return rc;
}
pos += rc;
- }
- return drm_crtc_add_crc_entry(crtc, true,
drm_crtc_accurate_vblank_count(crtc), crcs);
+}
- static int dpu_crtc_get_crc(struct drm_crtc *crtc) { struct dpu_crtc_state *crtc_state = to_dpu_crtc_state(crtc->state);
@@ -227,6 +269,8 @@ static int dpu_crtc_get_crc(struct drm_crtc *crtc)
if (crtc_state->crc_source == DPU_CRTC_CRC_SOURCE_LAYER_MIXER) return dpu_crtc_get_lm_crc(crtc, crtc_state);
else if (crtc_state->crc_source == DPU_CRTC_CRC_SOURCE_ENCODER)
return dpu_crtc_get_encoder_crc(crtc);
return -EINVAL; }
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h index 20df23fe74ed..af03277a3e5a 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /*
- Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
- Copyright (c) 2015-2021 The Linux Foundation. All rights reserved.
- Copyright (C) 2013 Red Hat
- Author: Rob Clark robdclark@gmail.com
@@ -73,11 +74,13 @@ struct dpu_crtc_smmu_state_data {
- enum dpu_crtc_crc_source: CRC source
- @DPU_CRTC_CRC_SOURCE_NONE: no source set
- @DPU_CRTC_CRC_SOURCE_LAYER_MIXER: CRC in layer mixer
*/ enum dpu_crtc_crc_source { DPU_CRTC_CRC_SOURCE_NONE = 0, DPU_CRTC_CRC_SOURCE_LAYER_MIXER,
- @DPU_CRTC_CRC_SOURCE_ENCODER: CRC in encoder
- @DPU_CRTC_CRC_SOURCE_INVALID: Invalid source
- DPU_CRTC_CRC_SOURCE_ENCODER, DPU_CRTC_CRC_SOURCE_MAX, DPU_CRTC_CRC_SOURCE_INVALID = -1 };
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index 52516eb20cb8..e00c788db14c 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -225,6 +225,70 @@ bool dpu_encoder_is_widebus_enabled(const struct drm_encoder *drm_enc) return dpu_enc->wide_bus_en; }
+int dpu_encoder_get_crc_values_cnt(const struct drm_encoder *drm_enc) +{
- struct dpu_encoder_virt *dpu_enc;
- int i, num_intf = 0;
- dpu_enc = to_dpu_encoder_virt(drm_enc);
- for (i = 0; i < dpu_enc->num_phys_encs; i++) {
struct dpu_encoder_phys *phys = dpu_enc->phys_encs[i];
if (phys->hw_intf && phys->hw_intf->ops.setup_misr
&& phys->hw_intf->ops.collect_misr)
num_intf++;
- }
- return num_intf;
+}
+void dpu_encoder_setup_misr(const struct drm_encoder *drm_enc) +{
- struct dpu_encoder_virt *dpu_enc;
- int i;
- dpu_enc = to_dpu_encoder_virt(drm_enc);
- for (i = 0; i < dpu_enc->num_phys_encs; i++) {
struct dpu_encoder_phys *phys = dpu_enc->phys_encs[i];
if (!phys->hw_intf || !phys->hw_intf->ops.setup_misr)
continue;
phys->hw_intf->ops.setup_misr(phys->hw_intf, true, 1);
- }
+}
+int dpu_encoder_get_crc(const struct drm_encoder *drm_enc, u32 *crcs, int pos) +{
- struct dpu_encoder_virt *dpu_enc;
- int i, rc = 0, entries_added = 0;
- if (!drm_enc->crtc) {
DRM_ERROR("no crtc found for encoder %d\n", drm_enc->index);
return -EINVAL;
- }
- dpu_enc = to_dpu_encoder_virt(drm_enc);
- for (i = 0; i < dpu_enc->num_phys_encs; i++) {
struct dpu_encoder_phys *phys = dpu_enc->phys_encs[i];
if (!phys->hw_intf || !phys->hw_intf->ops.collect_misr)
continue;
rc = phys->hw_intf->ops.collect_misr(phys->hw_intf, &crcs[pos + entries_added]);
if (rc)
return rc;
entries_added++;
- }
- return entries_added;
+}
- static void _dpu_encoder_setup_dither(struct dpu_hw_pingpong *hw_pp, unsigned bpc) { struct dpu_hw_dither_cfg dither_cfg = { 0 };
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h index 781d41c91994..a78971670024 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /*
- Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
- Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
- Copyright (C) 2013 Red Hat
- Author: Rob Clark robdclark@gmail.com
@@ -174,6 +175,27 @@ int dpu_encoder_get_vsync_count(struct drm_encoder *drm_enc);
bool dpu_encoder_is_widebus_enabled(const struct drm_encoder *drm_enc);
+/**
- dpu_encoder_get_crc_values_cnt - get number of physical encoders contained
- in virtual encoder that can collect CRC values
- @drm_enc: Pointer to previously created drm encoder structure
- Returns: Number of physical encoders for given drm encoder
- */
+int dpu_encoder_get_crc_values_cnt(const struct drm_encoder *drm_enc);
+/**
- dpu_encoder_setup_misr - enable misr calculations
- @drm_enc: Pointer to previously created drm encoder structure
- */
+void dpu_encoder_setup_misr(const struct drm_encoder *drm_encoder);
+/**
- dpu_encoder_get_crc - get the crc value from interface blocks
- @drm_enc: Pointer to previously created drm encoder structure
- Returns: 0 on success, error otherwise
- */
+int dpu_encoder_get_crc(const struct drm_encoder *drm_enc, u32 *crcs, int pos);
- /**
- dpu_encoder_use_dsc_merge - returns true if the encoder uses DSC merge topology.
- @drm_enc: Pointer to previously created drm encoder structure
dri-devel@lists.freedesktop.org